diff --git a/CHANGELOG b/CHANGELOG index 353214b6d..7a75c56e3 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -65,7 +65,16 @@ - Added Advance Save - Added swing distance weapons - Added support to Critical hits + - Added System Quest + - Added function blockDoors this is for cumstom servs + - Added Script AdvanceSave for save and regenerate on increase level + - Added new options automatic for save/clean map on globalevents + - Added custom commands /save /addons /mounts /gotopos + - Added missing elementdeath elementholy on weapons + - Changes on config + - Check two-handed weapons on equip - Enable monster passive behavior + - Fix shovel - Fix editing house - Fix effect debug - Fix spells on 8.x @@ -75,12 +84,19 @@ - Fix correct calculation method for skill spells - Fix mounts and outfits names - atributes - Fix bug with pvp zone - - Fix groups.xml - Fix limit outfits - Fix Shovel + - Fix swimming and citizen portal now show descrition + - Fix and tunes on spells + - Fix spell and item descriptions + - Fixed loginWindows for 10.9x - Fix https://www.youtube.com/watch?v=ube4b-q4Ncg - - Update items.xml - - Support 10.82 - 10.90 + - Update items.xml / items.otb + - Update firstitems scripts // missing vocation + - Update monsters is more complete + - Update outfits and mounts to lasted Tibia + - Removed unnused variables + - Support 10.90 ] [ OTX Server 3.1 Version - "BOOM" diff --git a/path_10_8/.editorconfig b/path_10_8/.editorconfig deleted file mode 100644 index 26b3599ca..000000000 --- a/path_10_8/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -root = true - -# General configuration -[*] -charset = utf-8 -end_of_line = lf -indent_style = tab -insert_final_newline = true -trim_trailing_whitespace = true - -[**.{.cpp,.h}] -# Options not ubiquitous, but useful -indent_brace_style = K&R -spaces_around_brackets = none - -[.travis.yml] -indent_style = spaces -indent_size = 2 diff --git a/path_10_8/.gitattributes b/path_10_8/.gitattributes deleted file mode 100644 index 109adf08d..000000000 --- a/path_10_8/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -# Auto detect text files and perform LF normalization -* text=auto - -# Custom for Visual Studio -*.sln merge=union -*.vcxproj merge=union diff --git a/path_10_8/.gitignore b/path_10_8/.gitignore deleted file mode 100644 index bf2b4e1e8..000000000 --- a/path_10_8/.gitignore +++ /dev/null @@ -1,171 +0,0 @@ -################# -## Visual Studio -################# - -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. - -# User-specific files -*.suo -*.user -*.sln.docstates - -# Build results - -[Dd]ebug/ -[Rr]elease/ -x64/ -build/ -[Bb]in/ -[Oo]bj/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -*_i.c -*_p.c -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.log -*.scc - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -*.ncrunch* -.*crunch*.local.xml - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.Publish.xml -*.pubxml - -# NuGet Packages Directory -## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ - -# Windows Azure Build Output -csx -*.build.csdef - -# Windows Store app package directory -AppPackages/ - -# Others -sql/ -*.Cache -ClientBin/ -[Ss]tyle[Cc]op.* -~$* -*~ -*.dbmdl -*.[Pp]ublish.xml -*.pfx -*.publishsettings - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file to a newer -# Visual Studio version. Backup files are not needed, because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -App_Data/*.mdf -App_Data/*.ldf - -############# -## Windows detritus -############# - -# Windows image file caches -Thumbs.db -ehthumbs.db - -# Folder config file -Desktop.ini - -# Recycle Bin used on file shares -$RECYCLE.BIN/ - -# Mac crap -.DS_Store - -# Installer logs -pip-log.txt - -# Unit test / coverage reports -.coverage -.tox - -#Translations -*.mo - -#Mr Developer -.mr.developer.cfg - -# Vim files -*~ -.*.swp -.*.swo - diff --git a/path_10_8/.travis.yml b/path_10_8/.travis.yml deleted file mode 100644 index 571f37424..000000000 --- a/path_10_8/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -sudo: required -dist: trusty -language: cpp -compiler: - - clang - - gcc -env: - - LUAJIT=OFF - - LUAJIT=ON -cache: apt -addons: - apt: - packages: - - libboost-dev - - libboost-system-dev - - liblua5.2-dev - - libluajit-5.1-dev - - libmysqlclient-dev -before_script: - - mkdir build && cd build - - cmake -DCMAKE_BUILD_TYPE=Release -DUSE_LUAJIT=${LUAJIT} .. -script: make -j2 diff --git a/path_10_8/CMakeLists.txt b/path_10_8/CMakeLists.txt deleted file mode 100644 index 0044b0cde..000000000 --- a/path_10_8/CMakeLists.txt +++ /dev/null @@ -1,52 +0,0 @@ -cmake_minimum_required(VERSION 2.8) - -set(CMAKE_DISABLE_SOURCE_CHANGES ON) -set(CMAKE_DISABLE_IN_SOURCE_BUILD ON) - -project(tfs) - -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) - -include(cotire) - -# Initialize CXXFLAGS. -set(CMAKE_CXX_FLAGS "-Wall -Werror -pipe") -set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") -set(CMAKE_CXX_FLAGS_MINSIZEREL "-Os -DNDEBUG") -set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -march=native -DNDEBUG") -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g") - -if (CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing") -endif() - -include(FindCXX11) - -# Find packages. -find_package(GMP REQUIRED) -find_package(LuaJIT) -find_package(MySQL) -find_package(Threads) - -option(USE_LUAJIT "Use LuaJIT" ${LUAJIT_FOUND}) - -if(USE_LUAJIT) - find_package(LuaJIT REQUIRED) - if(APPLE) - set(CMAKE_EXE_LINKER_FLAGS "-pagezero_size 10000 -image_base 100000000") - endif() -else() - find_package(Lua) -endif() - -find_package(Boost 1.53.0 COMPONENTS system REQUIRED) - -include(src/CMakeLists.txt) -add_executable(tfs ${tfs_SRC}) - -include_directories(${MYSQL_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${Boost_INCLUDE_DIRS} ${GMP_INCLUDE_DIR}) -target_link_libraries(tfs ${MYSQL_CLIENT_LIBS} ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${GMP_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) - -set_target_properties(tfs PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "src/otpch.h") -set_target_properties(tfs PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE) -cotire(tfs) diff --git a/path_10_8/cmake/FindCXX11.cmake b/path_10_8/cmake/FindCXX11.cmake deleted file mode 100644 index 1702e8dfb..000000000 --- a/path_10_8/cmake/FindCXX11.cmake +++ /dev/null @@ -1,26 +0,0 @@ -if(__FIND_CXX11_CMAKE__) - return() -endif() -set(__FIND_CXX11_CMAKE__ TRUE) - -include(CheckCXXCompilerFlag) -enable_language(CXX) - -check_cxx_compiler_flag("-std=c++11" COMPILER_KNOWS_CXX11) -if(COMPILER_KNOWS_CXX11) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - - # Tested on Mac OS X 10.8.2 with XCode 4.6 Command Line Tools - # Clang requires this to find the correct c++11 headers - check_cxx_compiler_flag("-stdlib=libc++" COMPILER_KNOWS_STDLIB) - if(APPLE AND COMPILER_KNOWS_STDLIB) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - endif() -else() - check_cxx_compiler_flag("-std=c++0x" COMPILER_KNOWS_CXX0X) - if(COMPILER_KNOWS_CXX0X) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") - else() - message(FATAL_ERROR "Your C++ compiler does not support C++11.") - endif() -endif() diff --git a/path_10_8/cmake/FindGMP.cmake b/path_10_8/cmake/FindGMP.cmake deleted file mode 100644 index 80805443f..000000000 --- a/path_10_8/cmake/FindGMP.cmake +++ /dev/null @@ -1,14 +0,0 @@ -# Locate GMP library -# This module defines -# GMP_FOUND -# GMP_INCLUDE_DIR -# GMP_LIBRARIES - -find_path(GMP_INCLUDE_DIR NAMES gmp.h) -find_library(GMP_LIBRARIES NAMES gmp libgmp) -find_library(GMPXX_LIBRARIES NAMES gmpxx libgmpxx) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMP DEFAULT_MSG GMP_INCLUDE_DIR GMP_LIBRARIES GMPXX_LIBRARIES) - -mark_as_advanced(GMP_INCLUDE_DIR GMP_LIBRARIES GMPXX_LIBRARIES) diff --git a/path_10_8/cmake/FindLua.cmake b/path_10_8/cmake/FindLua.cmake deleted file mode 100644 index 57a48ebca..000000000 --- a/path_10_8/cmake/FindLua.cmake +++ /dev/null @@ -1,118 +0,0 @@ -# Locate Lua library -# This module defines -# LUA_EXECUTABLE, if found -# LUA_FOUND, if false, do not try to link to Lua -# LUA_LIBRARIES -# LUA_INCLUDE_DIR, where to find lua.h -# LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8) -# -# Note that the expected include convention is -# #include "lua.h" -# and not -# #include -# This is because, the lua location is not standardized and may exist -# in locations other than lua/ - -#============================================================================= -# Copyright 2007-2009 Kitware, Inc. -# Modified to support Lua 5.2 by LuaDist 2012 -# -# Distributed under the OSI-approved BSD License (the "License"); -# see accompanying file Copyright.txt for details. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= -# (To distribute this file outside of CMake, substitute the full -# License text for the above reference.) -# -# The required version of Lua can be specified using the -# standard syntax, e.g. FIND_PACKAGE(Lua 5.1) -# Otherwise the module will search for any available Lua implementation - -# Always search for non-versioned lua first (recommended) -SET(_POSSIBLE_LUA_INCLUDE include include/lua) -SET(_POSSIBLE_LUA_EXECUTABLE lua) -SET(_POSSIBLE_LUA_LIBRARY lua) - -# Determine possible naming suffixes (there is no standard for this) -IF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) - SET(_POSSIBLE_SUFFIXES "${Lua_FIND_VERSION_MAJOR}${Lua_FIND_VERSION_MINOR}" "${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}" "-${Lua_FIND_VERSION_MAJOR}.${Lua_FIND_VERSION_MINOR}") -ELSE(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) - SET(_POSSIBLE_SUFFIXES "52" "5.2" "-5.2" "51" "5.1" "-5.1") -ENDIF(Lua_FIND_VERSION_MAJOR AND Lua_FIND_VERSION_MINOR) - -# Set up possible search names and locations -FOREACH(_SUFFIX ${_POSSIBLE_SUFFIXES}) - LIST(APPEND _POSSIBLE_LUA_INCLUDE "include/lua${_SUFFIX}") - LIST(APPEND _POSSIBLE_LUA_EXECUTABLE "lua${_SUFFIX}") - LIST(APPEND _POSSIBLE_LUA_LIBRARY "lua${_SUFFIX}") -ENDFOREACH(_SUFFIX) - -# Find the lua executable -FIND_PROGRAM(LUA_EXECUTABLE - NAMES ${_POSSIBLE_LUA_EXECUTABLE} -) - -# Find the lua header -FIND_PATH(LUA_INCLUDE_DIR lua.h - HINTS - $ENV{LUA_DIR} - PATH_SUFFIXES ${_POSSIBLE_LUA_INCLUDE} - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -# Find the lua library -FIND_LIBRARY(LUA_LIBRARY - NAMES ${_POSSIBLE_LUA_LIBRARY} - HINTS - $ENV{LUA_DIR} - PATH_SUFFIXES lib64 lib - PATHS - ~/Library/Frameworks - /Library/Frameworks - /usr/local - /usr - /sw - /opt/local - /opt/csw - /opt -) - -IF(LUA_LIBRARY) - # include the math library for Unix - IF(UNIX AND NOT APPLE) - FIND_LIBRARY(LUA_MATH_LIBRARY m) - SET( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") - # For Windows and Mac, don't need to explicitly include the math library - ELSE(UNIX AND NOT APPLE) - SET( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") - ENDIF(UNIX AND NOT APPLE) -ENDIF(LUA_LIBRARY) - -# Determine Lua version -IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/lua.h") - FILE(STRINGS "${LUA_INCLUDE_DIR}/lua.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua .+\"") - - STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"Lua ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}") - UNSET(lua_version_str) -ENDIF() - -INCLUDE(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if -# all listed variables are TRUE -FIND_PACKAGE_HANDLE_STANDARD_ARGS(Lua - REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR - VERSION_VAR LUA_VERSION_STRING) - -MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY LUA_EXECUTABLE) - diff --git a/path_10_8/cmake/FindLuaJIT.cmake b/path_10_8/cmake/FindLuaJIT.cmake deleted file mode 100644 index e626a5a1d..000000000 --- a/path_10_8/cmake/FindLuaJIT.cmake +++ /dev/null @@ -1,63 +0,0 @@ -# Locate LuaJIT library -# This module defines -# LUAJIT_FOUND, if false, do not try to link to Lua -# LUA_LIBRARIES -# LUA_INCLUDE_DIR, where to find lua.h -# LUAJIT_VERSION_STRING, the version of Lua found (since CMake 2.8.8) - -## Copied from default CMake FindLua51.cmake - -find_path(LUA_INCLUDE_DIR luajit.h - HINTS - ENV LUA_DIR - PATH_SUFFIXES include/luajit-2.0 include - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw # Fink - /opt/local # DarwinPorts - /opt/csw # Blastwave - /opt -) - -find_library(LUA_LIBRARY - NAMES luajit-5.1 - HINTS - ENV LUA_DIR - PATH_SUFFIXES lib - PATHS - ~/Library/Frameworks - /Library/Frameworks - /sw - /opt/local - /opt/csw - /opt -) - -if(LUA_LIBRARY) - # include the math library for Unix - if(UNIX AND NOT APPLE) - find_library(LUA_MATH_LIBRARY m) - set( LUA_LIBRARIES "${LUA_LIBRARY};${LUA_MATH_LIBRARY}" CACHE STRING "Lua Libraries") - # For Windows and Mac, don't need to explicitly include the math library - else() - set( LUA_LIBRARIES "${LUA_LIBRARY}" CACHE STRING "Lua Libraries") - endif() -endif() - -if(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h") - file(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" luajit_version_str REGEX "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT .+\"") - - string(REGEX REPLACE "^#define[ \t]+LUAJIT_VERSION[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUAJIT_VERSION_STRING "${luajit_version_str}") - unset(luajit_version_str) -endif() - -include(FindPackageHandleStandardArgs) -# handle the QUIETLY and REQUIRED arguments and set LUA_FOUND to TRUE if -# all listed variables are TRUE -FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJIT - REQUIRED_VARS LUA_LIBRARIES LUA_INCLUDE_DIR - VERSION_VAR LUAJIT_VERSION_STRING) - -mark_as_advanced(LUA_INCLUDE_DIR LUA_LIBRARIES LUA_LIBRARY LUA_MATH_LIBRARY) - diff --git a/path_10_8/cmake/FindMySQL.cmake b/path_10_8/cmake/FindMySQL.cmake deleted file mode 100644 index 5e378d5b4..000000000 --- a/path_10_8/cmake/FindMySQL.cmake +++ /dev/null @@ -1,118 +0,0 @@ -#-------------------------------------------------------- -# Copyright (C) 1995-2007 MySQL AB -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of version 2 of the GNU General Public License as -# published by the Free Software Foundation. -# -# There are special exceptions to the terms and conditions of the GPL -# as it is applied to this software. View the full text of the exception -# in file LICENSE.exceptions in the top-level directory of this software -# distribution. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# -# The MySQL Connector/ODBC is licensed under the terms of the -# GPL, like most MySQL Connectors. There are special exceptions -# to the terms and conditions of the GPL as it is applied to -# this software, see the FLOSS License Exception available on -# mysql.com. - -########################################################################## - - -#-------------- FIND MYSQL_INCLUDE_DIR ------------------ -FIND_PATH(MYSQL_INCLUDE_DIR mysql.h - $ENV{MYSQL_INCLUDE_DIR} - $ENV{MYSQL_DIR}/include - /usr/include/mysql - /usr/local/include/mysql - /opt/mysql/mysql/include - /opt/mysql/mysql/include/mysql - /opt/mysql/include - /opt/local/include/mysql5 - /usr/local/mysql/include - /usr/local/mysql/include/mysql - $ENV{ProgramFiles}/MySQL/*/include - $ENV{SystemDrive}/MySQL/*/include) - -#----------------- FIND MYSQL_LIB_DIR ------------------- -IF (WIN32) - # Set lib path suffixes - # dist = for mysql binary distributions - # build = for custom built tree - IF (CMAKE_BUILD_TYPE STREQUAL Debug) - SET(libsuffixDist debug) - SET(libsuffixBuild Debug) - ELSE (CMAKE_BUILD_TYPE STREQUAL Debug) - SET(libsuffixDist opt) - SET(libsuffixBuild Release) - ADD_DEFINITIONS(-DDBUG_OFF) - ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug) - - FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient - PATHS - $ENV{MYSQL_DIR}/lib/${libsuffixDist} - $ENV{MYSQL_DIR}/libmysql - $ENV{MYSQL_DIR}/libmysql/${libsuffixBuild} - $ENV{MYSQL_DIR}/client/${libsuffixBuild} - $ENV{MYSQL_DIR}/libmysql/${libsuffixBuild} - $ENV{ProgramFiles}/MySQL/*/lib/${libsuffixDist} - $ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist}) -ELSE (WIN32) - FIND_LIBRARY(MYSQL_LIB NAMES mysqlclient - PATHS - $ENV{MYSQL_DIR}/libmysql/.libs - $ENV{MYSQL_DIR}/lib - $ENV{MYSQL_DIR}/lib/mysql - /usr/lib/mysql - /usr/local/lib/mysql - /usr/local/mysql/lib - /usr/local/mysql/lib/mysql - /opt/local/mysql5/lib - /opt/local/lib/mysql5/mysql - /opt/mysql/mysql/lib/mysql - /opt/mysql/lib/mysql) -ENDIF (WIN32) - -IF(MYSQL_LIB) - GET_FILENAME_COMPONENT(MYSQL_LIB_DIR ${MYSQL_LIB} PATH) -ENDIF(MYSQL_LIB) - -IF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR) - SET(MYSQL_FOUND TRUE) - - INCLUDE_DIRECTORIES(${MYSQL_INCLUDE_DIR}) - LINK_DIRECTORIES(${MYSQL_LIB_DIR}) - - FIND_LIBRARY(MYSQL_ZLIB zlib PATHS ${MYSQL_LIB_DIR}) - FIND_LIBRARY(MYSQL_YASSL yassl PATHS ${MYSQL_LIB_DIR}) - FIND_LIBRARY(MYSQL_TAOCRYPT taocrypt PATHS ${MYSQL_LIB_DIR}) - SET(MYSQL_CLIENT_LIBS mysqlclient) - IF (MYSQL_ZLIB) - SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} zlib) - ENDIF (MYSQL_ZLIB) - IF (MYSQL_YASSL) - SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} yassl) - ENDIF (MYSQL_YASSL) - IF (MYSQL_TAOCRYPT) - SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} taocrypt) - ENDIF (MYSQL_TAOCRYPT) - # Added needed mysqlclient dependencies on Windows - IF (WIN32) - SET(MYSQL_CLIENT_LIBS ${MYSQL_CLIENT_LIBS} ws2_32) - ENDIF (WIN32) - - MESSAGE(STATUS "MySQL Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}") - MESSAGE(STATUS "MySQL client libraries: ${MYSQL_CLIENT_LIBS}") -ELSE (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR) - MESSAGE(FATAL_ERROR "Cannot find MySQL. Include dir: ${MYSQL_INCLUDE_DIR} library dir: ${MYSQL_LIB_DIR}") -ENDIF (MYSQL_INCLUDE_DIR AND MYSQL_LIB_DIR) - diff --git a/path_10_8/cmake/cotire.cmake b/path_10_8/cmake/cotire.cmake deleted file mode 100644 index a4fb533c6..000000000 --- a/path_10_8/cmake/cotire.cmake +++ /dev/null @@ -1,3827 +0,0 @@ -# - cotire (compile time reducer) -# -# See the cotire manual for usage hints. -# -#============================================================================= -# Copyright 2012-2015 Sascha Kratky -# -# 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. -#============================================================================= - -if(__COTIRE_INCLUDED) - return() -endif() -set(__COTIRE_INCLUDED TRUE) - -# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode -# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(PUSH) -endif() -cmake_minimum_required(VERSION 2.8.12) -if (NOT CMAKE_SCRIPT_MODE_FILE) - cmake_policy(POP) -endif() - -set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}") -set (COTIRE_CMAKE_MODULE_VERSION "1.7.6") - -# activate select policies -if (POLICY CMP0025) - # Compiler id for Apple Clang is now AppleClang - cmake_policy(SET CMP0025 NEW) -endif() - -if (POLICY CMP0026) - # disallow use of the LOCATION target property - cmake_policy(SET CMP0026 NEW) -endif() - -if (POLICY CMP0038) - # targets may not link directly to themselves - cmake_policy(SET CMP0038 NEW) -endif() - -if (POLICY CMP0039) - # utility targets may not have link dependencies - cmake_policy(SET CMP0039 NEW) -endif() - -if (POLICY CMP0040) - # target in the TARGET signature of add_custom_command() must exist - cmake_policy(SET CMP0040 NEW) -endif() - -if (POLICY CMP0045) - # error on non-existent target in get_target_property - cmake_policy(SET CMP0045 NEW) -endif() - -if (POLICY CMP0046) - # error on non-existent dependency in add_dependencies - cmake_policy(SET CMP0046 NEW) -endif() - -if (POLICY CMP0049) - # do not expand variables in target source entries - cmake_policy(SET CMP0049 NEW) -endif() - -if (POLICY CMP0050) - # disallow add_custom_command SOURCE signatures - cmake_policy(SET CMP0050 NEW) -endif() - -if (POLICY CMP0051) - # include TARGET_OBJECTS expressions in a target's SOURCES property - cmake_policy(SET CMP0051 NEW) -endif() - -if (POLICY CMP0053) - # simplify variable reference and escape sequence evaluation - cmake_policy(SET CMP0053 NEW) -endif() - -if (POLICY CMP0054) - # only interpret if() arguments as variables or keywords when unquoted - cmake_policy(SET CMP0054 NEW) -endif() - -include(CMakeParseArguments) -include(ProcessorCount) - -function (cotire_get_configuration_types _configsVar) - set (_configs "") - if (CMAKE_CONFIGURATION_TYPES) - list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES}) - endif() - if (CMAKE_BUILD_TYPE) - list (APPEND _configs "${CMAKE_BUILD_TYPE}") - endif() - if (_configs) - list (REMOVE_DUPLICATES _configs) - set (${_configsVar} ${_configs} PARENT_SCOPE) - else() - set (${_configsVar} "None" PARENT_SCOPE) - endif() -endfunction() - -function (cotire_get_source_file_extension _sourceFile _extVar) - # get_filename_component returns extension from first occurrence of . in file name - # this function computes the extension from last occurrence of . in file name - string (FIND "${_sourceFile}" "." _index REVERSE) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt) - else() - set (_sourceExt "") - endif() - set (${_extVar} "${_sourceExt}" PARENT_SCOPE) -endfunction() - -macro (cotire_check_is_path_relative_to _path _isRelativeVar) - set (${_isRelativeVar} FALSE) - if (IS_ABSOLUTE "${_path}") - foreach (_dir ${ARGN}) - file (RELATIVE_PATH _relPath "${_dir}" "${_path}") - if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")) - set (${_isRelativeVar} TRUE) - break() - endif() - endforeach() - endif() -endmacro() - -function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar) - if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}") - else() - set (_languageExtensions "") - endif() - if (CMAKE_${_language}_IGNORE_EXTENSIONS) - set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}") - else() - set (_ignoreExtensions "") - endif() - if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS) - set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}") - else() - set (_excludeExtensions "") - endif() - if (COTIRE_DEBUG AND _languageExtensions) - message (STATUS "${_language} source file extensions: ${_languageExtensions}") - endif() - if (COTIRE_DEBUG AND _ignoreExtensions) - message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}") - endif() - if (COTIRE_DEBUG AND _excludeExtensions) - message (STATUS "${_language} exclude extensions: ${_excludeExtensions}") - endif() - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_allSourceFiles ${ARGN}) - else() - # as of CMake 3.1 target sources may contain generator expressions - # since we cannot obtain required property information about source files added - # through generator expressions at configure time, we filter them out - string (GENEX_STRIP "${ARGN}" _allSourceFiles) - endif() - set (_filteredSourceFiles "") - set (_excludedSourceFiles "") - foreach (_sourceFile ${_allSourceFiles}) - get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY) - get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT) - get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC) - if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic) - cotire_get_source_file_extension("${_sourceFile}" _sourceExt) - if (_sourceExt) - list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex) - if (_ignoreIndex LESS 0) - list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex) - if (_excludeIndex GREATER -1) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (FIND _languageExtensions "${_sourceExt}" _sourceIndex) - if (_sourceIndex GREATER -1) - # consider source file unless it is excluded explicitly - get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED) - if (_sourceIsExcluded) - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _filteredSourceFiles "${_sourceFile}") - endif() - else() - get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE) - if ("${_sourceLanguage}" STREQUAL "${_language}") - # add to excluded sources, if file is not ignored and has correct language without having the correct extension - list (APPEND _excludedSourceFiles "${_sourceFile}") - endif() - endif() - endif() - endif() - endif() - endif() - endforeach() - # separate filtered source files from already cotired ones - # the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire - set (_sourceFiles "") - set (_cotiredSourceFiles "") - foreach (_sourceFile ${_filteredSourceFiles}) - get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET) - if (_sourceIsCotired) - list (APPEND _cotiredSourceFiles "${_sourceFile}") - else() - get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS) - if (_sourceCompileFlags) - # add to excluded sources, if file has custom compile flags - list (APPEND _excludedSourceFiles "${_sourceFile}") - else() - list (APPEND _sourceFiles "${_sourceFile}") - endif() - endif() - endforeach() - if (COTIRE_DEBUG) - if (_sourceFiles) - message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}") - endif() - if (_excludedSourceFiles) - message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}") - endif() - if (_cotiredSourceFiles) - message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}") - endif() - endif() - set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE) - set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE) - set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type) - set (_filteredObjects "") - foreach (_object ${ARGN}) - get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (NOT _propertyValue) - list (APPEND _filteredObjects "${_object}") - endif() - endif() - endforeach() - set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_file_property_values _valuesVar _property) - set (_values "") - foreach (_sourceFile ${ARGN}) - get_source_file_property(_propertyValue "${_sourceFile}" ${_property}) - if (_propertyValue) - list (APPEND _values "${_propertyValue}") - endif() - endforeach() - set (${_valuesVar} ${_values} PARENT_SCOPE) -endfunction() - -function (cotire_resolve_config_properites _configurations _propertiesVar) - set (_properties "") - foreach (_property ${ARGN}) - if ("${_property}" MATCHES "") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - string (REPLACE "" "${_upperConfig}" _configProperty "${_property}") - list (APPEND _properties ${_configProperty}) - endforeach() - else() - list (APPEND _properties ${_property}) - endif() - endforeach() - set (${_propertiesVar} ${_properties} PARENT_SCOPE) -endfunction() - -function (cotire_copy_set_properites _configurations _type _source _target) - cotire_resolve_config_properites("${_configurations}" _properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET) - if (_isSet) - get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property}) - set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}") - endif() - endforeach() -endfunction() - -function (cotire_get_target_usage_requirements _target _targetRequirementsVar) - set (_targetRequirements "") - get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES) - while (_librariesToProcess) - # remove from head - list (GET _librariesToProcess 0 _library) - list (REMOVE_AT _librariesToProcess 0) - if (TARGET ${_library}) - list (FIND _targetRequirements ${_library} _index) - if (_index LESS 0) - list (APPEND _targetRequirements ${_library}) - # process transitive libraries - get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES) - if (_libraries) - list (APPEND _librariesToProcess ${_libraries}) - list (REMOVE_DUPLICATES _librariesToProcess) - endif() - endif() - endif() - endwhile() - set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE) -endfunction() - -function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - set (_flagPrefix "[/-]") - else() - set (_flagPrefix "--?") - endif() - set (_optionFlag "") - set (_matchedOptions "") - set (_unmatchedOptions "") - foreach (_compileFlag ${ARGN}) - if (_compileFlag) - if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}") - # option with separate argument - list (APPEND _matchedOptions "${_compileFlag}") - set (_optionFlag "") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$") - # remember option - set (_optionFlag "${CMAKE_MATCH_2}") - elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$") - # option with joined argument - list (APPEND _matchedOptions "${CMAKE_MATCH_3}") - set (_optionFlag "") - else() - # flush remembered option - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - set (_optionFlag "") - endif() - # add to unfiltered options - list (APPEND _unmatchedOptions "${_compileFlag}") - endif() - endif() - endforeach() - if (_optionFlag) - list (APPEND _matchedOptions "${_optionFlag}") - endif() - if (COTIRE_DEBUG AND _matchedOptions) - message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}") - endif() - if (COTIRE_DEBUG AND _unmatchedOptions) - message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}") - endif() - set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE) - set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_flags _config _language _target _flagsVar) - string (TOUPPER "${_config}" _upperConfig) - # collect options from CMake language variables - set (_compileFlags "") - if (CMAKE_${_language}_FLAGS) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}") - endif() - if (CMAKE_${_language}_FLAGS_${_upperConfig}) - set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}") - endif() - if (_target) - # add target compile flags - get_target_property(_targetflags ${_target} COMPILE_FLAGS) - if (_targetflags) - set (_compileFlags "${_compileFlags} ${_targetflags}") - endif() - endif() - if (UNIX) - separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}") - elseif(WIN32) - separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}") - else() - separate_arguments(_compileFlags) - endif() - # target compile options - if (_target) - get_target_property(_targetOptions ${_target} COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endif() - # interface compile options from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS) - if (_targetOptions) - list (APPEND _compileFlags ${_targetOptions}) - endif() - endforeach() - endif() - # handle language standard properties - if (_target) - get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD) - get_target_property(_targetLanguageExtensions ${_target} ${_language}_EXTENSIONS) - get_target_property(_targetLanguageStandardRequired ${_target} ${_language}_STANDARD_REQUIRED) - if (_targetLanguageExtensions) - if (CMAKE_${_language}${_targetLanguageExtensions}_EXTENSION_COMPILE_OPTION) - list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageExtensions}_EXTENSION_COMPILE_OPTION}") - endif() - elseif (_targetLanguageStandard) - if (_targetLanguageStandardRequired) - if (CMAKE_${_language}${_targetLanguageStandard}_STANDARD_COMPILE_OPTION) - list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_STANDARD_COMPILE_OPTION}") - endif() - else() - if (CMAKE_${_language}${_targetLanguageStandard}_EXTENSION_COMPILE_OPTION) - list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_EXTENSION_COMPILE_OPTION}") - endif() - endif() - endif() - endif() - # handle the POSITION_INDEPENDENT_CODE target property - if (_target) - get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE) - if (_targetPIC) - get_target_property(_targetType ${_target} TYPE) - if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}") - elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}") - endif() - endif() - endif() - # handle visibility target properties - if (_target) - get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET) - if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}") - endif() - get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN) - if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN) - list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}") - endif() - endif() - # platform specific flags - if (APPLE) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig}) - if (NOT _architectures) - get_target_property(_architectures ${_target} OSX_ARCHITECTURES) - endif() - if (_architectures) - foreach (_arch ${_architectures}) - list (APPEND _compileFlags "-arch" "${_arch}") - endforeach() - endif() - if (CMAKE_OSX_SYSROOT) - if (CMAKE_${_language}_SYSROOT_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}") - else() - list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}") - endif() - endif() - if (CMAKE_OSX_DEPLOYMENT_TARGET) - if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG) - list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}") - else() - list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - endif() - endif() - endif() - if (COTIRE_DEBUG AND _compileFlags) - message (STATUS "Target ${_target} compile flags: ${_compileFlags}") - endif() - set (${_flagsVar} ${_compileFlags} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar) - set (_includeDirs "") - set (_systemIncludeDirs "") - # default include dirs - if (CMAKE_INCLUDE_CURRENT_DIR) - list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}") - list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}") - endif() - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - # parse additional include directories from target compile flags - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _includeDirs ${_dirs}) - endif() - endif() - endif() - # parse additional system include directories from target compile flags - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_dirs "") - cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags}) - if (_dirs) - list (APPEND _systemIncludeDirs ${_dirs}) - endif() - endif() - endif() - # target include directories - get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES) - if (_target) - get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endif() - # interface include directories from linked library targets - if (_target) - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _dirs ${_targetDirs}) - endif() - get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) - if (_targetDirs) - list (APPEND _systemIncludeDirs ${_targetDirs}) - endif() - endforeach() - endif() - if (dirs) - list (REMOVE_DUPLICATES _dirs) - endif() - list (LENGTH _includeDirs _projectInsertIndex) - foreach (_dir ${_dirs}) - if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE) - cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}") - if (_isRelative) - list (LENGTH _includeDirs _len) - if (_len EQUAL _projectInsertIndex) - list (APPEND _includeDirs "${_dir}") - else() - list (INSERT _includeDirs _projectInsertIndex "${_dir}") - endif() - math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1") - else() - list (APPEND _includeDirs "${_dir}") - endif() - else() - list (APPEND _includeDirs "${_dir}") - endif() - endforeach() - list (REMOVE_DUPLICATES _includeDirs) - list (REMOVE_DUPLICATES _systemIncludeDirs) - if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES) - list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES}) - endif() - if (COTIRE_DEBUG AND _includeDirs) - message (STATUS "Target ${_target} include dirs: ${_includeDirs}") - endif() - set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE) - if (COTIRE_DEBUG AND _systemIncludeDirs) - message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}") - endif() - set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_export_symbol _target _exportSymbolVar) - set (_exportSymbol "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_enableExports ${_target} ENABLE_EXPORTS) - if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR - (_targetType STREQUAL "EXECUTABLE" AND _enableExports)) - get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL) - if (NOT _exportSymbol) - set (_exportSymbol "${_target}_EXPORTS") - endif() - string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol) - endif() - set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compile_definitions _config _language _target _definitionsVar) - string (TOUPPER "${_config}" _upperConfig) - set (_configDefinitions "") - # CMAKE_INTDIR for multi-configuration build systems - if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".") - list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"") - endif() - # target export define symbol - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - list (APPEND _configDefinitions "${_defineSymbol}") - endif() - # directory compile definitions - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # target compile definitions - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - # interface compile definitions from linked library targets - set (_linkedTargets "") - cotire_get_target_usage_requirements(${_target} _linkedTargets) - foreach (_linkedTarget ${_linkedTargets}) - get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - endforeach() - # parse additional compile definitions from target compile flags - # and don't look at directory compile definitions, which we already handled - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags}) - if (_definitions) - list (APPEND _configDefinitions ${_definitions}) - endif() - list (REMOVE_DUPLICATES _configDefinitions) - if (COTIRE_DEBUG AND _configDefinitions) - message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}") - endif() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar) - # parse target compile flags omitting compile definitions and include directives - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - set (_flagFilter "D") - if (CMAKE_INCLUDE_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language}) - string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag) - string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}") - if (_includeFlag) - set (_flagFilter "${_flagFilter}|${_includeFlag}") - endif() - endif() - set (_compilerFlags "") - cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags}) - if (COTIRE_DEBUG AND _compilerFlags) - message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}") - endif() - set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE) -endfunction() - -function (cotire_add_sys_root_paths _pathsVar) - if (APPLE) - if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT) - foreach (_path IN LISTS ${_pathsVar}) - if (IS_ABSOLUTE "${_path}") - get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE) - if (EXISTS "${_path}") - list (APPEND ${_pathsVar} "${_path}") - endif() - endif() - endforeach() - endif() - endif() - set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar) - set (_extraProperties ${ARGN}) - set (_result "") - if (_extraProperties) - list (FIND _extraProperties "${_sourceFile}" _index) - if (_index GREATER -1) - math (EXPR _index "${_index} + 1") - list (LENGTH _extraProperties _len) - math (EXPR _len "${_len} - 1") - foreach (_index RANGE ${_index} ${_len}) - list (GET _extraProperties ${_index} _value) - if (_value MATCHES "${_pattern}") - list (APPEND _result "${_value}") - else() - break() - endif() - endforeach() - endif() - endif() - set (${_resultVar} ${_result} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar) - set (_compileDefinitions "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - string (TOUPPER "${_config}" _upperConfig) - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN}) - if (_definitions) - list (APPEND _compileDefinitions ${_definitions}) - endif() - if (COTIRE_DEBUG AND _compileDefinitions) - message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}") - endif() - set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_compile_definitions _config _language _definitionsVar) - set (_configDefinitions "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions) - if (_sourceDefinitions) - list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-") - endif() - endforeach() - set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar) - set (_sourceUndefs "") - if (NOT CMAKE_SCRIPT_MODE_FILE) - get_source_file_property(_undefs "${_sourceFile}" ${_property}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - endif() - cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN}) - if (_undefs) - list (APPEND _sourceUndefs ${_undefs}) - endif() - if (COTIRE_DEBUG AND _sourceUndefs) - message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}") - endif() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -function (cotire_get_source_files_undefs _property _sourceUndefsVar) - set (_sourceUndefs "") - foreach (_sourceFile ${ARGN}) - cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs) - if (_undefs) - list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-") - endif() - endforeach() - set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE) -endfunction() - -macro (cotire_set_cmd_to_prologue _cmdVar) - set (${_cmdVar} "${CMAKE_COMMAND}") - if (COTIRE_DEBUG) - list (APPEND ${_cmdVar} "--warn-uninitialized") - endif() - list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$") - if (COTIRE_VERBOSE) - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON") - elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles") - list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)") - endif() -endmacro() - -function (cotire_init_compile_cmd _cmdVar _language _compilerExe _compilerArg1) - if (NOT _compilerExe) - set (_compilerExe "${CMAKE_${_language}_COMPILER}") - endif() - if (NOT _compilerArg1) - set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1}) - endif() - string (STRIP "${_compilerArg1}" _compilerArg1) - set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE) -endfunction() - -macro (cotire_add_definitions_to_cmd _cmdVar _language) - foreach (_definition ${ARGN}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - list (APPEND ${_cmdVar} "/D${_definition}") - else() - list (APPEND ${_cmdVar} "-D${_definition}") - endif() - endforeach() -endmacro() - -function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}}) - if (_includeDirs) - list (REMOVE_DUPLICATES _includeDirs) - foreach (_include ${_includeDirs}) - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - file (TO_NATIVE_PATH "${_include}" _include) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}") - else() - set (_index -1) - if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+") - list (FIND ${_systemIncludesVar} "${_include}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${_include}") - else() - list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}") - endif() - endif() - endforeach() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar) - if (APPLE) - set (_frameworkDirs "") - foreach (_include ${${_includesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _frameworkDirs "${_frameworkDir}") - endif() - endforeach() - set (_systemFrameworkDirs "") - foreach (_include ${${_systemIncludesVar}}) - if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$") - get_filename_component(_frameworkDir "${_include}" DIRECTORY) - list (APPEND _systemFrameworkDirs "${_frameworkDir}") - endif() - endforeach() - if (_systemFrameworkDirs) - list (APPEND _frameworkDirs ${_systemFrameworkDirs}) - endif() - if (_frameworkDirs) - list (REMOVE_DUPLICATES _frameworkDirs) - foreach (_frameworkDir ${_frameworkDirs}) - set (_index -1) - if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+") - list (FIND _systemFrameworkDirs "${_frameworkDir}" _index) - endif() - if (_index GREATER -1) - list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - else() - list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}") - endif() - endforeach() - endif() - endif() - set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE) -endfunction() - -macro (cotire_add_compile_flags_to_cmd _cmdVar) - foreach (_flag ${ARGN}) - list (APPEND ${_cmdVar} "${_flag}") - endforeach() -endmacro() - -function (cotire_check_file_up_to_date _fileIsUpToDateVar _file) - if (EXISTS "${_file}") - set (_triggerFile "") - foreach (_dependencyFile ${ARGN}) - if (EXISTS "${_dependencyFile}") - # IS_NEWER_THAN returns TRUE if both files have the same timestamp - # thus we do the comparison in both directions to exclude ties - if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND - NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}") - set (_triggerFile "${_dependencyFile}") - break() - endif() - endif() - endforeach() - if (_triggerFile) - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} update triggered by ${_triggerFile} change.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} is up-to-date.") - endif() - set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE) - endif() - else() - if (COTIRE_VERBOSE) - get_filename_component(_fileName "${_file}" NAME) - message (STATUS "${_fileName} does not exist yet.") - endif() - set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar) - set (${_relPathVar} "") - foreach (_includeDir ${_includeDirs}) - if (IS_DIRECTORY "${_includeDir}") - file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}") - if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.") - string (LENGTH "${${_relPathVar}}" _closestLen) - string (LENGTH "${_relPath}" _relLen) - if (_closestLen EQUAL 0 OR _relLen LESS _closestLen) - set (${_relPathVar} "${_relPath}") - endif() - endif() - elseif ("${_includeDir}" STREQUAL "${_headerFile}") - # if path matches exactly, return short non-empty string - set (${_relPathVar} "1") - break() - endif() - endforeach() -endmacro() - -macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside) - # check header path against ignored and honored include directories - cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath) - if (_insideRelPath) - # header is inside, but could be become outside if there is a shorter outside match - cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath) - if (_outsideRelPath) - string (LENGTH "${_insideRelPath}" _insideRelPathLen) - string (LENGTH "${_outsideRelPath}" _outsideRelPathLen) - if (_outsideRelPathLen LESS _insideRelPathLen) - set (${_headerIsInside} FALSE) - else() - set (${_headerIsInside} TRUE) - endif() - else() - set (${_headerIsInside} TRUE) - endif() - else() - # header is outside - set (${_headerIsInside} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar) - if (NOT EXISTS "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif (IS_DIRECTORY "${_headerFile}") - set (${_headerIsIgnoredVar} TRUE) - elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$") - # heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path - # these often stem from using GCC #include_next tricks, which may break the precompiled header compilation - # with the error message "error: no include path in which to search for header.h" - set (${_headerIsIgnoredVar} TRUE) - else() - set (${_headerIsIgnoredVar} FALSE) - endif() -endmacro() - -macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar) - # check header file extension - cotire_get_source_file_extension("${_headerFile}" _headerFileExt) - set (${_headerIsIgnoredVar} FALSE) - if (_headerFileExt) - list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index) - if (_index GREATER -1) - set (${_headerIsIgnoredVar} TRUE) - endif() - endif() -endmacro() - -macro (cotire_parse_line _line _headerFileVar _headerDepthVar) - if (MSVC) - # cl.exe /showIncludes output looks different depending on the language pack used, e.g.: - # English: "Note: including file: C:\directory\file" - # German: "Hinweis: Einlesen der Datei: C:\directory\file" - # We use a very general regular expression, relying on the presence of the : characters - if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$") - # Visual Studio compiler output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE) - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - else() - if (_line MATCHES "^(\\.+) (.*)$") - # GCC like output - string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar}) - if (IS_ABSOLUTE "${CMAKE_MATCH_2}") - set (${_headerFileVar} "${CMAKE_MATCH_2}") - else() - get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH) - endif() - else() - set (${_headerFileVar} "") - set (${_headerDepthVar} 0) - endif() - endif() -endmacro() - -function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar) - if (WIN32) - # prevent CMake macro invocation errors due to backslash characters in Windows paths - string (REPLACE "\\" "/" _scanOutput "${_scanOutput}") - endif() - # canonize slashes - string (REPLACE "//" "/" _scanOutput "${_scanOutput}") - # prevent semicolon from being interpreted as a line separator - string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}") - # then separate lines - string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}") - list (LENGTH _scanOutput _len) - # remove duplicate lines to speed up parsing - list (REMOVE_DUPLICATES _scanOutput) - list (LENGTH _scanOutput _uniqueLen) - if (COTIRE_VERBOSE OR COTIRE_DEBUG) - message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes") - if (_ignoredExtensions) - message (STATUS "Ignored extensions: ${_ignoredExtensions}") - endif() - if (_ignoredIncludeDirs) - message (STATUS "Ignored paths: ${_ignoredIncludeDirs}") - endif() - if (_honoredIncludeDirs) - message (STATUS "Included paths: ${_honoredIncludeDirs}") - endif() - endif() - set (_sourceFiles ${ARGN}) - set (_selectedIncludes "") - set (_unparsedLines "") - # stack keeps track of inside/outside project status of processed header files - set (_headerIsInsideStack "") - foreach (_line IN LISTS _scanOutput) - if (_line) - cotire_parse_line("${_line}" _headerFile _headerDepth) - if (_headerFile) - cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside) - if (COTIRE_DEBUG) - message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}") - endif() - # update stack - list (LENGTH _headerIsInsideStack _stackLen) - if (_headerDepth GREATER _stackLen) - math (EXPR _stackLen "${_stackLen} + 1") - foreach (_index RANGE ${_stackLen} ${_headerDepth}) - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endforeach() - else() - foreach (_index RANGE ${_headerDepth} ${_stackLen}) - list (REMOVE_AT _headerIsInsideStack -1) - endforeach() - list (APPEND _headerIsInsideStack ${_headerIsInside}) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerIsInsideStack}") - endif() - # header is a candidate if it is outside project - if (NOT _headerIsInside) - # get parent header file's inside/outside status - if (_headerDepth GREATER 1) - math (EXPR _index "${_headerDepth} - 2") - list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside) - else() - set (_parentHeaderIsInside TRUE) - endif() - # select header file if parent header file is inside project - # (e.g., a project header file that includes a standard header file) - if (_parentHeaderIsInside) - cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored) - if (NOT _headerIsIgnored) - cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored) - if (NOT _headerIsIgnored) - list (APPEND _selectedIncludes "${_headerFile}") - else() - # fix header's inside status on stack, it is ignored by extension now - list (REMOVE_AT _headerIsInsideStack -1) - list (APPEND _headerIsInsideStack TRUE) - endif() - endif() - if (COTIRE_DEBUG) - message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}") - endif() - endif() - endif() - else() - if (MSVC) - # for cl.exe do not keep unparsed lines which solely consist of a source file name - string (FIND "${_sourceFiles}" "${_line}" _index) - if (_index LESS 0) - list (APPEND _unparsedLines "${_line}") - endif() - else() - list (APPEND _unparsedLines "${_line}") - endif() - endif() - endif() - endforeach() - list (REMOVE_DUPLICATES _selectedIncludes) - set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE) - set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE) -endfunction() - -function (cotire_scan_includes _includesVar) - set(_options "") - set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_VERSION LANGUAGE UNPARSED_LINES) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES - IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd) - # only consider existing source files for scanning - set (_existingSourceFiles "") - foreach (_sourceFile ${_sourceFiles}) - if (EXISTS "${_sourceFile}") - list (APPEND _existingSourceFiles "${_sourceFile}") - endif() - endforeach() - if (NOT _existingSourceFiles) - set (${_includesVar} "" PARENT_SCOPE) - return() - endif() - list (APPEND _cmd ${_existingSourceFiles}) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (_option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result - OUTPUT_QUIET - ERROR_VARIABLE _output) - if (_result) - message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.") - endif() - cotire_parse_includes( - "${_option_LANGUAGE}" "${_output}" - "${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}" - "${_option_IGNORE_EXTENSIONS}" - _includes _unparsedLines - ${_sourceFiles}) - if (_option_INCLUDE_PRIORITY_PATH) - set (_sortedIncludes "") - foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH}) - foreach (_include ${_includes}) - string (FIND ${_include} ${_priorityPath} _position) - if (_position GREATER -1) - list (APPEND _sortedIncludes ${_include}) - endif() - endforeach() - endforeach() - if (_sortedIncludes) - list (INSERT _includes 0 ${_sortedIncludes}) - list (REMOVE_DUPLICATES _includes) - endif() - endif() - set (${_includesVar} ${_includes} PARENT_SCOPE) - if (_option_UNPARSED_LINES) - set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE) - endif() -endfunction() - -macro (cotire_append_undefs _contentsVar) - set (_undefs ${ARGN}) - if (_undefs) - list (REMOVE_DUPLICATES _undefs) - foreach (_definition ${_undefs}) - list (APPEND ${_contentsVar} "#undef ${_definition}") - endforeach() - endif() -endmacro() - -macro (cotire_comment_str _language _commentText _commentVar) - if ("${_language}" STREQUAL "CMAKE") - set (${_commentVar} "# ${_commentText}") - else() - set (${_commentVar} "/* ${_commentText} */") - endif() -endmacro() - -function (cotire_write_file _language _file _contents _force) - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1) - cotire_comment_str("${_language}" "${_file}" _header2) - set (_contents "${_header1}\n${_header2}\n${_contents}") - if (COTIRE_DEBUG) - message (STATUS "${_contents}") - endif() - if (_force OR NOT EXISTS "${_file}") - file (WRITE "${_file}" "${_contents}") - else() - file (READ "${_file}" _oldContents) - if (NOT "${_oldContents}" STREQUAL "${_contents}") - file (WRITE "${_file}" "${_contents}") - else() - if (COTIRE_DEBUG) - message (STATUS "${_file} unchanged") - endif() - endif() - endif() -endfunction() - -function (cotire_generate_unity_source _unityFile) - set(_options "") - set(_oneValueArgs LANGUAGE) - set(_multiValueArgs - DEPENDS SOURCES_COMPILE_DEFINITIONS - PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (_option_DEPENDS) - cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS}) - if (_unityFileIsUpToDate) - return() - endif() - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - if (NOT _option_PRE_UNDEFS) - set (_option_PRE_UNDEFS "") - endif() - if (NOT _option_SOURCES_PRE_UNDEFS) - set (_option_SOURCES_PRE_UNDEFS "") - endif() - if (NOT _option_POST_UNDEFS) - set (_option_POST_UNDEFS "") - endif() - if (NOT _option_SOURCES_POST_UNDEFS) - set (_option_SOURCES_POST_UNDEFS "") - endif() - set (_contents "") - if (_option_PROLOGUE) - list (APPEND _contents ${_option_PROLOGUE}) - endif() - if (_option_LANGUAGE AND _sourceFiles) - if ("${_option_LANGUAGE}" STREQUAL "CXX") - list (APPEND _contents "#ifdef __cplusplus") - elseif ("${_option_LANGUAGE}" STREQUAL "C") - list (APPEND _contents "#ifndef __cplusplus") - endif() - endif() - set (_compileUndefinitions "") - foreach (_sourceFile ${_sourceFiles}) - cotire_get_source_compile_definitions( - "${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions - ${_option_SOURCES_COMPILE_DEFINITIONS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS}) - cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS}) - if (_option_PRE_UNDEFS) - list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS}) - endif() - if (_sourcePreUndefs) - list (APPEND _compileUndefinitions ${_sourcePreUndefs}) - endif() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_sourcePostUndefs) - list (APPEND _compileUndefinitions ${_sourcePostUndefs}) - endif() - if (_option_POST_UNDEFS) - list (APPEND _compileUndefinitions ${_option_POST_UNDEFS}) - endif() - foreach (_definition ${_compileDefinitions}) - if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$") - list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}") - list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}") - else() - list (APPEND _contents "#define ${_definition}") - list (INSERT _compileUndefinitions 0 "${_definition}") - endif() - endforeach() - # use absolute path as source file location - get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE) - if (WIN32) - file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation) - endif() - list (APPEND _contents "#include \"${_sourceFileLocation}\"") - endforeach() - if (_compileUndefinitions) - cotire_append_undefs(_contents ${_compileUndefinitions}) - set (_compileUndefinitions "") - endif() - if (_option_LANGUAGE AND _sourceFiles) - list (APPEND _contents "#endif") - endif() - if (_option_EPILOGUE) - list (APPEND _contents ${_option_EPILOGUE}) - endif() - list (APPEND _contents "") - string (REPLACE ";" "\n" _contents "${_contents}") - if (COTIRE_VERBOSE) - message ("${_contents}") - endif() - cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE) -endfunction() - -function (cotire_generate_prefix_header _prefixFile) - set(_options "") - set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION) - set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS - INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH - IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - if (_option_DEPENDS) - cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS}) - if (_prefixFileIsUpToDate) - # create empty log file - set (_unparsedLinesFile "${_prefixFile}.log") - file (WRITE "${_unparsedLinesFile}" "") - return() - endif() - endif() - set (_prologue "") - set (_epilogue "") - if (_option_COMPILER_ID MATCHES "Clang") - set (_prologue "#pragma clang system_header") - elseif (_option_COMPILER_ID MATCHES "GNU") - set (_prologue "#pragma GCC system_header") - elseif (_option_COMPILER_ID MATCHES "MSVC") - set (_prologue "#pragma warning(push, 0)") - set (_epilogue "#pragma warning(pop)") - elseif (_option_COMPILER_ID MATCHES "Intel") - # Intel compiler requires hdrstop pragma to stop generating PCH file - set (_epilogue "#pragma hdrstop") - endif() - set (_sourceFiles ${_option_UNPARSED_ARGUMENTS}) - cotire_scan_includes(_selectedHeaders ${_sourceFiles} - LANGUAGE "${_option_LANGUAGE}" - COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}" - COMPILER_ID "${_option_COMPILER_ID}" - COMPILER_VERSION "${_option_COMPILER_VERSION}" - COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS} - COMPILE_FLAGS ${_option_COMPILE_FLAGS} - INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES} - SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES} - IGNORE_PATH ${_option_IGNORE_PATH} - INCLUDE_PATH ${_option_INCLUDE_PATH} - IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS} - INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH} - UNPARSED_LINES _unparsedLines) - cotire_generate_unity_source("${_prefixFile}" - PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders}) - set (_unparsedLinesFile "${_prefixFile}.log") - if (_unparsedLines) - if (COTIRE_VERBOSE OR NOT _selectedHeaders) - list (LENGTH _unparsedLines _skippedLineCount) - message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesFile}") - endif() - string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}") - endif() - file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}") -endfunction() - -function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - # cl.exe options used - # /nologo suppresses display of sign-on banner - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /EP preprocess to stdout without #line directives - # /showIncludes list include files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /showIncludes") - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fdirectives-only do not expand macros, requires GCC >= 4.3 - if (_flags) - # append to list - list (APPEND _flags -H -E) - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - list (APPEND _flags "-fdirectives-only") - endif() - else() - # return as a flag string - set (_flags "-H -E") - if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0") - set (_flags "${_flags} -fdirectives-only") - endif() - endif() - elseif (_compilerID MATCHES "Clang") - # Clang options used - # -H print the name of each header file used - # -E invoke preprocessor - # -fno-color-diagnostics don't prints diagnostics in color - if (_flags) - # append to list - list (APPEND _flags -H -E -fno-color-diagnostics) - else() - # return as a flag string - set (_flags "-H -E -fno-color-diagnostics") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - # Windows Intel options used - # /nologo do not display compiler version information - # /QH display the include file order - # /EP preprocess to stdout, omitting #line directives - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH) - else() - # return as a flag string - set (_flags "${_sourceFileType${_language}} /EP /QH") - endif() - else() - # Linux / Mac OS X Intel options used - # -H print the name of each header file used - # -EP preprocess to stdout, omitting #line directives - # -Kc++ process all source or unrecognized file types as C++ source files - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags -H -EP) - else() - # return as a flag string - if ("${_language}" STREQUAL "CXX") - set (_flags "-Kc++ ") - endif() - set (_flags "${_flags}-H -EP") - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # cl.exe options used - # /Yc creates a precompiled header file - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /TC treat all files named on the command line as C source files - # /TP treat all files named on the command line as C++ source files - # /Zs syntax check only - # /Zm precompiled header memory allocation scaling factor - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - elseif (_compilerID MATCHES "GNU|Clang") - # GCC / Clang options used - # -x specify the source language - # -c compile but do not link - # -o place output in file - # note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may - # alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - list (APPEND _flags "-x" "${_xLanguage_${_language}}" "-c" "${_prefixFile}" -o "${_pchFile}") - else() - # return as a flag string - set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative) - # Windows Intel options used - # /nologo do not display compiler version information - # /Yc create a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /TC process all source or unrecognized file types as C source files - # /TP process all source or unrecognized file types as C++ source files - # /Zs syntax check only - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - set (_sourceFileTypeC "/TC") - set (_sourceFileTypeCXX "/TP") - if (_flags) - # append to list - list (APPEND _flags /nologo "${_sourceFileType${_language}}" - "/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-create name of the precompiled header (PCH) to create - # -Kc++ process all source or unrecognized file types as C++ source files - # -fsyntax-only check only for correct syntax - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - set (_xLanguage_C "c-header") - set (_xLanguage_CXX "c++-header") - if (_flags) - # append to list - if ("${_language}" STREQUAL "CXX") - list (APPEND _flags -Kc++) - endif() - list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-create" "${_pchName}" "-fsyntax-only" "${_hostFile}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "-Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar) - set (_flags ${${_flagsVar}}) - if (_compilerID MATCHES "MSVC") - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # cl.exe options used - # /Yu uses a precompiled header file during build - # /Fp specifies precompiled header binary file name - # /FI forces inclusion of file - # /Zm precompiled header memory allocation scaling factor - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - else() - # return as a flag string - set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - elseif (_compilerID MATCHES "GNU") - # GCC options used - # -include process include file as the first line of the primary source file - # -Winvalid-pch warns if precompiled header is found but cannot be used - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags "-Winvalid-pch" "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Winvalid-pch -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Clang") - # Clang options used - # -include process include file as the first line of the primary source file - # -include-pch include precompiled header file - # -Qunused-arguments don't emit warning for unused driver arguments - # note: ccache requires the -include flag to be used in order to process precompiled header correctly - if (_flags) - # append to list - list (APPEND _flags "-Qunused-arguments" "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-Qunused-arguments -include \"${_prefixFile}\"") - endif() - elseif (_compilerID MATCHES "Intel") - if (WIN32) - file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative) - # Windows Intel options used - # /Yu use a precompiled header (PCH) file - # /Fp specify a path or file name for precompiled header files - # /FI tells the preprocessor to include a specified file name as the header file - # /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative) - if (_flags) - # append to list - list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "/Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} /Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "/FI${_prefixFileNative}") - else() - # return as a flag string - set (_flags "/FI\"${_prefixFileNative}\"") - endif() - endif() - else() - # Linux / Mac OS X Intel options used - # -pch-dir location for precompiled header files - # -pch-use name of the precompiled header (PCH) to use - # -include process include file as the first line of the primary source file - # -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2) - if (_pchFile) - get_filename_component(_pchDir "${_pchFile}" DIRECTORY) - get_filename_component(_pchName "${_pchFile}" NAME) - if (_flags) - # append to list - list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-use" "${_pchName}") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - list (APPEND _flags "-Wpch-messages") - endif() - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"") - if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0") - set (_flags "${_flags} -Wpch-messages") - endif() - endif() - else() - # no precompiled header, force inclusion of prefix header - if (_flags) - # append to list - list (APPEND _flags "-include" "${_prefixFile}") - else() - # return as a flag string - set (_flags "-include \"${_prefixFile}\"") - endif() - endif() - endif() - else() - message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.") - endif() - set (${_flagsVar} ${_flags} PARENT_SCOPE) -endfunction() - -function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile) - set(_options "") - set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ID COMPILER_VERSION LANGUAGE) - set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGE) - set (_option_LANGUAGE "CXX") - endif() - if (NOT _option_COMPILER_ID) - set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}") - endif() - if (NOT _option_COMPILER_VERSION) - set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}") - endif() - cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}") - cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS}) - cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS}) - cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES) - cotire_add_pch_compilation_flags( - "${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd) - if (COTIRE_VERBOSE) - message (STATUS "execute_process: ${_cmd}") - endif() - if (_option_COMPILER_ID MATCHES "MSVC") - # cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared - unset (ENV{VS_UNICODE_OUTPUT}) - endif() - execute_process( - COMMAND ${_cmd} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - RESULT_VARIABLE _result) - if (_result) - message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.") - endif() -endfunction() - -function (cotire_check_precompiled_header_support _language _target _msgVar) - set (_unsupportedCompiler - "Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}") - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # supported since Visual Studio C++ 6.0 - # and CMake does not support an earlier version - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC PCH support requires version >= 3.4 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # all Clang versions have PCH support - set (${_msgVar} "" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel PCH support requires version >= 8.0.0 - if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0") - set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE) - else() - set (${_msgVar} "" PARENT_SCOPE) - endif() - else() - set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE) - endif() - if (CMAKE_${_language}_COMPILER MATCHES "ccache") - if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros|pch_defines") - set (${_msgVar} - "ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"." - PARENT_SCOPE) - endif() - endif() - if (APPLE) - # PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64) - cotire_get_configuration_types(_configs) - foreach (_config ${_configs}) - set (_targetFlags "") - cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags) - cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags}) - list (LENGTH _architectures _numberOfArchitectures) - if (_numberOfArchitectures GREATER 1) - string (REPLACE ";" ", " _architectureStr "${_architectures}") - set (${_msgVar} - "Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})." - PARENT_SCOPE) - break() - endif() - endforeach() - endif() -endfunction() - -macro (cotire_get_intermediate_dir _cotireDir) - # ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types - get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE) -endmacro() - -macro (cotire_setup_file_extension_variables) - set (_unityFileExt_C ".c") - set (_unityFileExt_CXX ".cxx") - set (_prefixFileExt_C ".h") - set (_prefixFileExt_CXX ".hxx") - set (_prefixSourceFileExt_C ".c") - set (_prefixSourceFileExt_CXX ".cxx") -endmacro() - -function (cotire_make_single_unity_source_file_path _language _target _unityFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}") - cotire_get_intermediate_dir(_baseDir) - set (_unityFile "${_baseDir}/${_unityFileName}") - set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_unityFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - cotire_get_intermediate_dir(_baseDir) - set (_startIndex 0) - set (_index 0) - set (_unityFiles "") - set (_sourceFiles ${ARGN}) - foreach (_sourceFile ${_sourceFiles}) - get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE) - math (EXPR _unityFileCount "${_index} - ${_startIndex}") - if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes)) - if (_index GREATER 0) - # start new unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (_startIndex ${_index}) - endif() - math (EXPR _index "${_index} + 1") - endforeach() - list (LENGTH _sourceFiles _numberOfSources) - if (_startIndex EQUAL 0) - # there is only a single unity file - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles) - elseif (_startIndex LESS _numberOfSources) - # end with final unity file segment - math (EXPR _endIndex "${_index} - 1") - set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}") - list (APPEND _unityFiles "${_baseDir}/${_unityFileName}") - endif() - set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE) - if (COTIRE_DEBUG AND _unityFiles) - message (STATUS "unity files: ${_unityFiles}") - endif() -endfunction() - -function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _unityFileExt_${_language}) - set (${_prefixFileVar} "" PARENT_SCOPE) - return() - endif() - set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}") - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}") - string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}") - set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE) -endfunction() - -function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar) - cotire_setup_file_extension_variables() - if (NOT DEFINED _prefixSourceFileExt_${_language}) - set (${_prefixSourceFileVar} "" PARENT_SCOPE) - return() - endif() - string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}") - set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar) - cotire_setup_file_extension_variables() - if (NOT _language) - set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}") - elseif (DEFINED _prefixFileExt_${_language}) - set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}") - set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}") - else() - set (_prefixFileBaseName "") - set (_prefixFileName "") - endif() - set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE) - set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE) -endfunction() - -function (cotire_make_prefix_file_path _language _target _prefixFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_prefixFileVar} "" PARENT_SCOPE) - if (_prefixFileName) - if (NOT _language) - set (_language "C") - endif() - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC") - cotire_get_intermediate_dir(_baseDir) - set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE) - endif() - endif() -endfunction() - -function (cotire_make_pch_file_path _language _target _pchFileVar) - cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName) - set (${_pchFileVar} "" PARENT_SCOPE) - if (_prefixFileBaseName AND _prefixFileName) - cotire_check_precompiled_header_support("${_language}" "${_target}" _msg) - if (NOT _msg) - if (XCODE) - # For Xcode, we completely hand off the compilation of the prefix header to the IDE - return() - endif() - cotire_get_intermediate_dir(_baseDir) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC") - # MSVC uses the extension .pch added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang") - # Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU") - # GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended - set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE) - elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel") - # Intel uses the extension .pchi added to the prefix header base name - set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE) - endif() - endif() - endif() -endfunction() - -function (cotire_select_unity_source_files _unityFile _sourcesVar) - set (_sourceFiles ${ARGN}) - if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)") - set (_startIndex ${CMAKE_MATCH_1}) - set (_endIndex ${CMAKE_MATCH_2}) - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _startIndex LESS _numberOfSources) - math (EXPR _startIndex "${_numberOfSources} - 1") - endif() - if (NOT _endIndex LESS _numberOfSources) - math (EXPR _endIndex "${_numberOfSources} - 1") - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${_endIndex}) - list (GET _sourceFiles ${_index} _file) - list (APPEND _files "${_file}") - endforeach() - else() - set (_files ${_sourceFiles}) - endif() - set (${_sourcesVar} ${_files} PARENT_SCOPE) -endfunction() - -function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target's generated source files - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - # but omit all generated source files that have the COTIRE_EXCLUDED property set to true - cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources}) - if (_excludedGeneratedSources) - list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources}) - endif() - # and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly - cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources}) - if (_excludedNonDependencySources) - list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources}) - endif() - if (_generatedSources) - list (APPEND _dependencySources ${_generatedSources}) - endif() - endif() - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar) - set (_dependencySources "") - # depend on target source files marked with custom COTIRE_DEPENDENCY property - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles}) - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}") - endif() - set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE) -endfunction() - -function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar) - set (_targetSources ${ARGN}) - cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources}) - cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources}) - # set up variables to be configured - set (COTIRE_TARGET_LANGUAGE "${_language}") - get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH) - get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH) - cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH) - get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS) - get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS) - get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources}) - cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources}) - set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}") - foreach (_config ${_configurations}) - string (TOUPPER "${_config}" _upperConfig) - cotire_get_target_include_directories( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}) - cotire_get_target_compile_definitions( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}) - cotire_get_target_compiler_flags( - "${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}) - cotire_get_source_files_compile_definitions( - "${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources}) - endforeach() - # set up COTIRE_TARGET_SOURCES - set (COTIRE_TARGET_SOURCES "") - foreach (_sourceFile ${_targetSources}) - get_source_file_property(_generated "${_sourceFile}" GENERATED) - if (_generated) - # use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}") - else() - list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}") - endif() - endforeach() - # copy variable definitions to cotire target script - get_cmake_property(_vars VARIABLES) - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}") - # omit COTIRE_*_INIT variables - string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}") - if (_initVars) - list (REMOVE_ITEM _matchVars ${_initVars}) - endif() - # omit COTIRE_VERBOSE which is passed as a CMake define on command line - list (REMOVE_ITEM _matchVars COTIRE_VERBOSE) - set (_contents "") - set (_contentsHasGeneratorExpressions FALSE) - foreach (_var IN LISTS _matchVars ITEMS - XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES - CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION - CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1 - CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_${_language}_SEP - CMAKE_INCLUDE_SYSTEM_FLAG_${_language} - CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG - CMAKE_${_language}_SOURCE_FILE_EXTENSIONS) - if (DEFINED ${_var}) - string (REPLACE "\"" "\\\"" _value "${${_var}}") - set (_contents "${_contents}set (${_var} \"${_value}\")\n") - if (NOT _contentsHasGeneratorExpressions) - if ("${_value}" MATCHES "\\$<.*>") - set (_contentsHasGeneratorExpressions TRUE) - endif() - endif() - endif() - endforeach() - # generate target script file - get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME) - set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}") - cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE) - if (_contentsHasGeneratorExpressions) - # use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time - set (_configNameOrNoneGeneratorExpression "$<$:None>$<$>:$>") - set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}") - file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}") - else() - set (_targetCotireConfigScript "${_targetCotireScript}") - endif() - set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE) - set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE) -endfunction() - -function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # for Visual Studio and Intel, we attach the precompiled header compilation to the host file - # the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion - if (_sourceFiles) - set (_flags "") - cotire_add_pch_compilation_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags) - set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}") - # make object file generated from host file depend on prefix header - set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") - # mark host file as cotired to prevent it from being used in another cotired target - set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we add a custom command to precompile the prefix header - if (_targetScript) - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}") - file (RELATIVE_PATH _pchFileRelPath "${CMAKE_BINARY_DIR}" "${_pchFile}") - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} IMPLICIT_DEPENDS ${_language} ${_prefixFile}") - endif() - set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE) - add_custom_command( - OUTPUT "${_pchFile}" - COMMAND ${_cmds} - DEPENDS "${_prefixFile}" - IMPLICIT_DEPENDS ${_language} "${_prefixFile}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Building ${_language} precompiled header ${_pchFileRelPath}" - VERBATIM) - endif() - endif() -endfunction() - -function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile) - if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # for Visual Studio and Intel, we include the precompiled header in all but the host file - # the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation - set (_sourceFiles ${ARGN}) - list (LENGTH _sourceFiles _numberOfSourceFiles) - if (_numberOfSourceFiles GREATER 0) - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - set (_sourceFiles ${_hostFile} ${ARGN}) - if (NOT _wholeTarget) - # for makefile based generator, we force the inclusion of the prefix header for a subset - # of the source files, if this is a multi-language target or has excluded files - set (_flags "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - endif() - # make object files generated from source files depend on precompiled header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}") - endif() -endfunction() - -function (cotire_setup_prefix_file_inclusion _language _target _prefixFile) - set (_sourceFiles ${ARGN}) - # force the inclusion of the prefix header for the given source files - set (_flags "") - set (_pchFile "") - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _flags) - set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ") - # mark sources as cotired to prevent them from being used in another cotired target - set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}") - # make object files generated from source files depend on prefix header - set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}") -endfunction() - -function (cotire_get_first_set_property_value _propertyValueVar _type _object) - set (_properties ${ARGN}) - foreach (_property ${_properties}) - get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property}) - if (_propertyValue) - set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE) - return() - endif() - endforeach() - set (${_propertyValueVar} "" PARENT_SCOPE) -endfunction() - -function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar) - set (_files ${ARGN}) - set (_filesPaths "") - foreach (_file ${_files}) - get_filename_component(_filePath "${_file}" ABSOLUTE) - list (APPEND _filesPaths "${_filePath}") - endforeach() - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine") - if (_targetScript) - list (APPEND _prefixCmd "${_targetScript}") - endif() - list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths}) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}") - endif() - set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE) - file (RELATIVE_PATH _joinedFileRelPath "${CMAKE_BINARY_DIR}" "${_joinedFile}") - get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE) - get_filename_component(_joinedFileExt "${_joinedFile}" EXT) - if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$") - set (_comment "Generating ${_language} unity source ${_joinedFileRelPath}") - elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$") - if (_joinedFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_joinedFileRelPath}") - else() - set (_comment "Generating ${_language} prefix header ${_joinedFileRelPath}") - endif() - else() - set (_comment "Generating ${_joinedFileRelPath}") - endif() - add_custom_command( - OUTPUT "${_joinedFile}" - COMMAND ${_prefixCmd} - DEPENDS ${_files} - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_target_pch_usage _languages _target _wholeTarget) - if (XCODE) - # for Xcode, we attach a pre-build action to generate the unity sources and prefix headers - set (_prefixFiles "") - foreach (_language ${_languages}) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - list (APPEND _prefixFiles "${_prefixFile}") - endif() - endforeach() - set (_cmds ${ARGN}) - list (LENGTH _prefixFiles _numberOfPrefixFiles) - if (_numberOfPrefixFiles GREATER 1) - # we also generate a generic, single prefix header which includes all language specific prefix headers - set (_language "") - set (_targetScript "") - cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader) - cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles}) - else() - set (_prefixHeader "${_prefixFiles}") - endif() - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}") - endif() - # because CMake PRE_BUILD command does not support dependencies, - # we check dependencies explicity in cotire script mode when the pre-build action is run - add_custom_command( - TARGET "${_target}" - PRE_BUILD ${_cmds} - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - COMMENT "Updating target ${_target} prefix headers" - VERBATIM) - # make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++ - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES") - set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}") - elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generator, we force inclusion of the prefix header for all target source files - # if this is a single-language target without any excluded files - if (_wholeTarget) - set (_language "${_languages}") - # for Visual Studio and Intel, precompiled header inclusion is always done on the source file level - # see cotire_setup_pch_file_inclusion - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_prefixFile) - get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER) - set (_options COMPILE_OPTIONS) - cotire_add_prefix_pch_inclusion_flags( - "${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}" - "${_prefixFile}" "${_pchFile}" _options) - set_property(TARGET ${_target} APPEND PROPERTY ${_options}) - endif() - endif() - endif() - endif() -endfunction() - -function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar) - set (_dependencySources "") - cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN}) - foreach (_unityFile ${_unityFiles}) - set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE) - # set up compiled unity source dependencies via OBJECT_DEPENDS - # this ensures that missing source files are generated before the unity file is compiled - if (COTIRE_DEBUG AND _dependencySources) - message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}") - endif() - if (_dependencySources) - # the OBJECT_DEPENDS property requires a list of full paths - set (_objectDependsPaths "") - foreach (_sourceFile ${_dependencySources}) - get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION) - list (APPEND _objectDependsPaths "${_sourceLocation}") - endforeach() - set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths}) - endif() - if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # unity file compilation results in potentially huge object file, thus use /bigobj by default unter MSVC and Windows Intel - set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj") - endif() - cotire_set_cmd_to_prologue(_unityCmd) - list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}") - if (CMAKE_VERSION VERSION_LESS "3.1.0") - set (_unityCmdDepends "${_targetScript}") - else() - # CMake 3.1.0 supports generator expressions in arguments to DEPENDS - set (_unityCmdDepends "${_targetConfigScript}") - endif() - file (RELATIVE_PATH _unityFileRelPath "${CMAKE_BINARY_DIR}" "${_unityFile}") - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}") - endif() - add_custom_command( - OUTPUT "${_unityFile}" - COMMAND ${_unityCmd} - DEPENDS ${_unityCmdDepends} - COMMENT "Generating ${_language} unity source ${_unityFileRelPath}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_unityCmd}) - endforeach() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - set (_dependencySources "") - cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles}) - cotire_set_cmd_to_prologue(_prefixCmd) - list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles}) - set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE) - if (COTIRE_DEBUG) - message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources}") - endif() - file (RELATIVE_PATH _prefixFileRelPath "${CMAKE_BINARY_DIR}" "${_prefixFile}") - get_filename_component(_prefixFileExt "${_prefixFile}" EXT) - if (_prefixFileExt MATCHES "^\\.c") - set (_comment "Generating ${_language} prefix source ${_prefixFileRelPath}") - else() - set (_comment "Generating ${_language} prefix header ${_prefixFileRelPath}") - endif() - # prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist - # we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence - # thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files - set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre") - if (TARGET ${_preTargetName}) - # custom helper target has already been generated while processing a different language - list (APPEND _dependencySources ${_preTargetName}) - else() - get_target_property(_targetSourceFiles ${_target} SOURCES) - cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles}) - if (_generatedSources) - add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources}) - cotire_init_target("${_preTargetName}") - list (APPEND _dependencySources ${_preTargetName}) - endif() - endif() - add_custom_command( - OUTPUT "${_prefixFile}" "${_prefixFile}.log" - COMMAND ${_prefixCmd} - DEPENDS ${_unityFiles} ${_dependencySources} - COMMENT "${_comment}" - WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" - VERBATIM) - list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd}) - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar) - set (_sourceFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_prefix_generation_command( - ${_language} ${_target} "${_targetScript}" - "${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar) - set (_prefixHeaderFiles ${ARGN}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma - cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile) - else() - set (_prefixSourceFile "${_prefixFile}") - endif() - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles}) - if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang") - # set up generation of a prefix source file which includes the prefix header - cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile}) - endif() - set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE) -endfunction() - -function (cotire_init_cotire_target_properties _target) - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE) - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}") - cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}") - if (NOT _isRelative) - set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}") - endif() - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET) - if (NOT _isSet) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY") - endif() - get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET) - if (NOT _isSet) - if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}") - else() - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "") - endif() - endif() -endfunction() - -function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - string (REPLACE ";" " " _languagesStr "${_languages}") - math (EXPR _numberOfExcludedFiles "${ARGC} - 4") - if (_numberOfExcludedFiles EQUAL 0) - set (_excludedStr "") - elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4) - string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}") - else() - set (_excludedStr "excluding ${_numberOfExcludedFiles} files") - endif() - set (_targetMsg "") - if (NOT _languages) - set (_targetMsg "Target ${_target} cannot be cotired.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH AND NOT _targetAddSCU) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.") - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetUsePCH) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.") - endif() - if (_disableMsg) - set (_targetMsg "${_targetMsg} ${_disableMsg}") - endif() - elseif (NOT _targetAddSCU) - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.") - endif() - else() - if (_excludedStr) - set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.") - else() - set (_targetMsg "${_languagesStr} target ${_target} cotired.") - endif() - endif() - set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE) -endfunction() - -function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar) - set (_languages ${ARGN}) - set (_allSourceFiles "") - set (_allExcludedSourceFiles "") - set (_allCotiredSourceFiles "") - set (_targetLanguages "") - set (_pchEligibleTargetLanguages "") - get_target_property(_targetType ${_target} TYPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - set (_disableMsg "") - foreach (_language ${_languages}) - get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER) - get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE) - if (_prefixHeader OR _unityBuildFile) - message (STATUS "cotire: target ${_target} has already been cotired.") - set (${_targetLanguagesVar} "" PARENT_SCOPE) - return() - endif() - if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$") - cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg) - if (_disableMsg) - set (_targetUsePCH FALSE) - endif() - endif() - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _excludedSources OR _cotiredSources) - list (APPEND _targetLanguages ${_language}) - endif() - if (_sourceFiles) - list (APPEND _allSourceFiles ${_sourceFiles}) - endif() - list (LENGTH _sourceFiles _numberOfSources) - if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - list (APPEND _pchEligibleTargetLanguages ${_language}) - endif() - if (_excludedSources) - list (APPEND _allExcludedSourceFiles ${_excludedSources}) - endif() - if (_cotiredSources) - list (APPEND _allCotiredSourceFiles ${_cotiredSources}) - endif() - endforeach() - set (_targetMsgLevel STATUS) - if (NOT _targetLanguages) - string (REPLACE ";" " or " _languagesStr "${_languages}") - set (_disableMsg "No ${_languagesStr} source files.") - set (_targetUsePCH FALSE) - set (_targetAddSCU FALSE) - endif() - if (_targetUsePCH) - if (_allCotiredSourceFiles) - cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles}) - list (REMOVE_DUPLICATES _cotireTargets) - string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}") - set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.") - set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},") - set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.") - set (_targetMsgLevel SEND_ERROR) - set (_targetUsePCH FALSE) - elseif (NOT _pchEligibleTargetLanguages) - set (_disableMsg "Too few applicable sources.") - set (_targetUsePCH FALSE) - elseif (XCODE AND _allExcludedSourceFiles) - # for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target - set (_disableMsg "Exclusion of source files not supported for generator Xcode.") - set (_targetUsePCH FALSE) - elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY") - # for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target - set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.") - set (_targetUsePCH FALSE) - endif() - endif() - set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH}) - set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU}) - cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles}) - if (_targetMsg) - if (NOT DEFINED COTIREMSG_${_target}) - set (COTIREMSG_${_target} "") - endif() - if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR - NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}") - # cache message to avoid redundant messages on re-configure - set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.") - message (${_targetMsgLevel} "${_targetMsg}") - endif() - endif() - list (LENGTH _targetLanguages _numberOfLanguages) - if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles) - set (${_wholeTargetVar} FALSE PARENT_SCOPE) - else() - set (${_wholeTargetVar} TRUE PARENT_SCOPE) - endif() - set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE) -endfunction() - -function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar) - set (_sourceFiles ${ARGN}) - get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES) - if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)") - set (_numberOfThreads "${CMAKE_MATCH_2}") - if (NOT _numberOfThreads) - # use all available cores - ProcessorCount(_numberOfThreads) - endif() - list (LENGTH _sourceFiles _numberOfSources) - math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}") - elseif (NOT _maxIncludes MATCHES "[0-9]+") - set (_maxIncludes 0) - endif() - if (COTIRE_DEBUG) - message (STATUS "${_target} unity source max includes: ${_maxIncludes}") - endif() - set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE) -endfunction() - -function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar) - set (${_cmdsVar} "" PARENT_SCOPE) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (NOT _sourceFiles AND NOT _cotiredSources) - return() - endif() - set (_cmds "") - # check for user provided unity source file list - get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT) - if (NOT _unitySourceFiles) - set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources}) - endif() - cotire_generate_target_script( - ${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles}) - # set up unity files for parallel compilation - cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles}) - cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles}) - list (LENGTH _unityFiles _numberOfUnityFiles) - if (_numberOfUnityFiles EQUAL 0) - return() - elseif (_numberOfUnityFiles GREATER 1) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles}) - endif() - # set up single unity file for prefix header generation - cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile) - cotire_setup_unity_generation_commands( - ${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles}) - cotire_make_prefix_file_path(${_language} ${_target} _prefixFile) - # set up prefix header - if (_prefixFile) - # check for user provided prefix header files - get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - if (_prefixHeaderFiles) - cotire_setup_prefix_generation_from_provided_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles}) - else() - cotire_setup_prefix_generation_from_unity_command( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles}) - endif() - # check if selected language has enough sources at all - list (LENGTH _sourceFiles _numberOfSources) - if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES}) - set (_targetUsePCH FALSE) - else() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - endif() - if (_targetUsePCH) - cotire_make_pch_file_path(${_language} ${_target} _pchFile) - if (_pchFile) - # first file in _sourceFiles is passed as the host file - cotire_setup_pch_file_compilation( - ${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - cotire_setup_pch_file_inclusion( - ${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles}) - endif() - elseif (_prefixHeaderFiles) - # user provided prefix header must be included unconditionally - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles}) - endif() - endif() - # mark target as cotired for language - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}") - if (_prefixFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}") - if (_targetUsePCH AND _pchFile) - set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}") - endif() - endif() - set (${_cmdsVar} ${_cmds} PARENT_SCOPE) -endfunction() - -function (cotire_setup_clean_target _target) - set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}") - if (NOT TARGET "${_cleanTargetName}") - cotire_set_cmd_to_prologue(_cmds) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}") - add_custom_target(${_cleanTargetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up target ${_target} cotire generated files" - VERBATIM) - cotire_init_target("${_cleanTargetName}") - endif() -endfunction() - -function (cotire_setup_pch_target _languages _configurations _target) - if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja") - # for makefile based generators, we add a custom target to trigger the generation of the cotire related files - set (_dependsFiles "") - foreach (_language ${_languages}) - set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE) - if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel") - # Visual Studio and Intel only create precompiled header as a side effect - list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER) - endif() - cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props}) - if (_dependsFile) - list (APPEND _dependsFiles "${_dependsFile}") - endif() - endforeach() - if (_dependsFiles) - set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}") - add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles}) - cotire_init_target("${_pchTargetName}") - cotire_add_to_pch_all_target(${_pchTargetName}) - endif() - else() - # for other generators, we add the "clean all" target to clean up the precompiled header - cotire_setup_clean_all_target() - endif() -endfunction() - -function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar) - get_target_property(_targetSourceFiles ${_target} SOURCES) - set (_unityTargetSources ${_targetSourceFiles}) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - # remove source files that are included in the unity source - set (_sourceFiles "") - set (_excludedSources "") - set (_cotiredSources "") - cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles}) - if (_sourceFiles OR _cotiredSources) - list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources}) - endif() - # add unity source files instead - list (APPEND _unityTargetSources ${_unityFiles}) - endif() - endforeach() - set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE) -endfunction() - -function (cotire_setup_unity_target_pch_usage _languages _target) - foreach (_language ${_languages}) - get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE) - if (_unityFiles) - get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT) - get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER) - if (_userPrefixFile AND _prefixFile) - # user provided prefix header must be included unconditionally by unity sources - cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles}) - endif() - endif() - endforeach() -endfunction() - -function (cotire_setup_unity_build_target _languages _configurations _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (NOT _unityTargetName) - set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}") - endif() - # determine unity target sub type - get_target_property(_targetType ${_target} TYPE) - if ("${_targetType}" STREQUAL "EXECUTABLE") - set (_unityTargetSubType "") - elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY") - set (_unityTargetSubType "${CMAKE_MATCH_1}") - else() - message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.") - return() - endif() - # determine unity target sources - set (_unityTargetSources "") - cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources) - # handle automatic Qt processing - get_target_property(_targetAutoMoc ${_target} AUTOMOC) - get_target_property(_targetAutoUic ${_target} AUTOUIC) - get_target_property(_targetAutoRcc ${_target} AUTORCC) - if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) - # if the original target sources are subject to CMake's automatic Qt processing, - # also include implicitly generated _automoc.cpp file - list (APPEND _unityTargetSources "${_target}_automoc.cpp") - set_property (SOURCE "${_target}_automoc.cpp" PROPERTY GENERATED TRUE) - endif() - # prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created - set (CMAKE_AUTOMOC OFF) - set (CMAKE_AUTOUIC OFF) - set (CMAKE_AUTORCC OFF) - if (COTIRE_DEBUG) - message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}") - endif() - # generate unity target - if ("${_targetType}" STREQUAL "EXECUTABLE") - add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - else() - add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}) - endif() - if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc) - # depend on the original target's implicity generated _automoc target - add_dependencies(${_unityTargetName} ${_target}_automoc) - endif() - # copy output location properties - set (_outputDirProperties - ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_ - LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_ - RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_) - if (COTIRE_UNITY_OUTPUT_DIRECTORY) - set (_setDefaultOutputDir TRUE) - if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}") - else() - # append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties}) - cotire_resolve_config_properites("${_configurations}" _properties ${_outputDirProperties}) - foreach (_property ${_properties}) - get_property(_outputDir TARGET ${_target} PROPERTY ${_property}) - if (_outputDir) - get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}") - set (_setDefaultOutputDir FALSE) - endif() - endforeach() - if (_setDefaultOutputDir) - get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE) - endif() - endif() - if (_setDefaultOutputDir) - set_target_properties(${_unityTargetName} PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}" - LIBRARY_OUTPUT_DIRECTORY "${_outputDir}" - RUNTIME_OUTPUT_DIRECTORY "${_outputDir}") - endif() - else() - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - ${_outputDirProperties}) - endif() - # copy output name - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_ - LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_ - OUTPUT_NAME OUTPUT_NAME_ - RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_ - PREFIX _POSTFIX SUFFIX - IMPORT_PREFIX IMPORT_SUFFIX) - # copy compile stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPILE_DEFINITIONS COMPILE_DEFINITIONS_ - COMPILE_FLAGS COMPILE_OPTIONS - Fortran_FORMAT Fortran_MODULE_DIRECTORY - INCLUDE_DIRECTORIES - INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_ - POSITION_INDEPENDENT_CODE - C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER - C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE - C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN) - # copy compile features - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED - CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED - COMPILE_FEATURES) - # copy interface stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN - COMPATIBLE_INTERFACE_STRING - INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS - INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES - INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES - INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED) - # copy link stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUILD_WITH_INSTALL_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH - LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED - LINK_FLAGS LINK_FLAGS_ - LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_ - LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_ - LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC - STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_ - NO_SONAME SOVERSION VERSION) - # copy cmake stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK) - # copy Apple platform specific stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR - MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH - OSX_ARCHITECTURES OSX_ARCHITECTURES_ PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST) - # copy Windows platform specific stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - GNUtoMS - COMPILE_PDB_NAME COMPILE_PDB_NAME_ - COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_ - PDB_NAME PDB_NAME_ PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_ - VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION - VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE - VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK - VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION - VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER - VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION - VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES - WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS) - # copy Android platform specific stuff - cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} - ANDROID_API ANDROID_API_MIN ANDROID_GUI - ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES - ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR - ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES - ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH - ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE) - # use output name from original target - get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME) - if (NOT _targetOutputName) - set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}") - endif() - # use export symbol from original target - cotire_get_target_export_symbol("${_target}" _defineSymbol) - if (_defineSymbol) - set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}") - if ("${_targetType}" STREQUAL "EXECUTABLE") - set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE) - endif() - endif() - cotire_init_target(${_unityTargetName}) - cotire_add_to_unity_all_target(${_unityTargetName}) - set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}") -endfunction(cotire_setup_unity_build_target) - -function (cotire_target _target) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - if (NOT _option_LANGUAGES) - get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) - endif() - if (NOT _option_CONFIGURATIONS) - cotire_get_configuration_types(_option_CONFIGURATIONS) - endif() - # trivial checks - get_target_property(_imported ${_target} IMPORTED) - if (_imported) - message (WARNING "cotire: imported target ${_target} cannot be cotired.") - return() - endif() - # resolve alias - get_target_property(_aliasName ${_target} ALIASED_TARGET) - if (_aliasName) - if (COTIRE_DEBUG) - message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.") - endif() - set (_target ${_aliasName}) - endif() - # check if target needs to be cotired for build type - # when using configuration types, the test is performed at build time - cotire_init_cotire_target_properties(${_target}) - if (NOT CMAKE_CONFIGURATION_TYPES) - if (CMAKE_BUILD_TYPE) - list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index) - else() - list (FIND _option_CONFIGURATIONS "None" _index) - endif() - if (_index EQUAL -1) - if (COTIRE_DEBUG) - message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})") - endif() - return() - endif() - endif() - # when not using configuration types, immediately create cotire intermediate dir - if (NOT CMAKE_CONFIGURATION_TYPES) - cotire_get_intermediate_dir(_baseDir) - file (MAKE_DIRECTORY "${_baseDir}") - endif() - # choose languages that apply to the target - cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES}) - if (NOT _targetLanguages) - return() - endif() - set (_cmds "") - foreach (_language ${_targetLanguages}) - cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd) - if (_cmd) - list (APPEND _cmds ${_cmd}) - endif() - endforeach() - get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD) - if (_targetAddSCU) - cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - endif() - get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER) - if (_targetUsePCH) - cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds}) - cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target}) - if (_targetAddSCU) - cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target}) - endif() - endif() - get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN) - if (_targetAddCleanTarget) - cotire_setup_clean_target(${_target}) - endif() -endfunction(cotire_target) - -function (cotire_map_libraries _strategy _mappedLibrariesVar) - set (_mappedLibraries "") - foreach (_library ${ARGN}) - if (TARGET "${_library}" AND "${_strategy}" MATCHES "COPY_UNITY") - # use target's corresponding unity target, if available - get_target_property(_libraryUnityTargetName ${_library} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_libraryUnityTargetName}") - list (APPEND _mappedLibraries "${_libraryUnityTargetName}") - else() - list (APPEND _mappedLibraries "${_library}") - endif() - else() - list (APPEND _mappedLibraries "${_library}") - endif() - endforeach() - list (REMOVE_DUPLICATES _mappedLibraries) - set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE) -endfunction() - -function (cotire_target_link_libraries _target) - get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME) - if (TARGET "${_unityTargetName}") - get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}") - endif() - if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$") - set (_unityLinkLibraries "") - get_target_property(_linkLibraries ${_target} LINK_LIBRARIES) - if (_linkLibraries) - list (APPEND _unityLinkLibraries ${_linkLibraries}) - endif() - get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES) - if (_interfaceLinkLibraries) - list (APPEND _unityLinkLibraries ${_interfaceLinkLibraries}) - endif() - cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_unityLinkLibraries}) - if (COTIRE_DEBUG) - message (STATUS "unity target ${_unityTargetName} libraries: ${_unityLinkLibraries}") - endif() - if (_unityLinkLibraries) - target_link_libraries(${_unityTargetName} ${_unityLinkLibraries}) - endif() - endif() - endif() -endfunction(cotire_target_link_libraries) - -function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName) - if (_targetName) - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*") - else() - file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*") - endif() - # filter files in intermediate directory - set (_filesToRemove "") - foreach (_file ${_cotireFiles}) - get_filename_component(_dir "${_file}" DIRECTORY) - get_filename_component(_dirName "${_dir}" NAME) - if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}") - list (APPEND _filesToRemove "${_file}") - endif() - endforeach() - if (_filesToRemove) - if (COTIRE_VERBOSE) - message (STATUS "cleaning up ${_filesToRemove}") - endif() - file (REMOVE ${_filesToRemove}) - endif() -endfunction() - -function (cotire_init_target _targetName) - if (COTIRE_TARGETS_FOLDER) - set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}") - endif() - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE) - if (MSVC_IDE) - set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE) - endif() -endfunction() - -function (cotire_add_to_pch_all_target _pchTargetName) - set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_pchTargetName}) -endfunction() - -function (cotire_add_to_unity_all_target _unityTargetName) - set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - add_custom_target("${_targetName}" - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - VERBATIM) - cotire_init_target("${_targetName}") - endif() - cotire_setup_clean_all_target() - add_dependencies(${_targetName} ${_unityTargetName}) -endfunction() - -function (cotire_setup_clean_all_target) - set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}") - if (NOT TARGET "${_targetName}") - cotire_set_cmd_to_prologue(_cmds) - list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}") - add_custom_target(${_targetName} - COMMAND ${_cmds} - WORKING_DIRECTORY "${CMAKE_BINARY_DIR}" - COMMENT "Cleaning up all cotire generated files" - VERBATIM) - cotire_init_target("${_targetName}") - endif() -endfunction() - -function (cotire) - set(_options "") - set(_oneValueArgs "") - set(_multiValueArgs LANGUAGES CONFIGURATIONS) - cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN}) - set (_targets ${_option_UNPARSED_ARGUMENTS}) - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS}) - else() - message (WARNING "cotire: ${_target} is not a target.") - endif() - endforeach() - foreach (_target ${_targets}) - if (TARGET ${_target}) - cotire_target_link_libraries(${_target}) - endif() - endforeach() -endfunction() - -if (CMAKE_SCRIPT_MODE_FILE) - - # cotire is being run in script mode - # locate -P on command args - set (COTIRE_ARGC -1) - foreach (_index RANGE ${CMAKE_ARGC}) - if (COTIRE_ARGC GREATER -1) - set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}") - math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1") - elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P") - set (COTIRE_ARGC 0) - endif() - endforeach() - - # include target script if available - if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$") - # the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES) - include("${COTIRE_ARGV2}") - endif() - - if (COTIRE_DEBUG) - message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}") - endif() - - if (NOT COTIRE_BUILD_TYPE) - set (COTIRE_BUILD_TYPE "None") - endif() - string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig) - set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}}) - set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}}) - set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}}) - # check if target has been cotired for actual build type COTIRE_BUILD_TYPE - list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index) - if (_index GREATER -1) - set (_sources ${COTIRE_TARGET_SOURCES}) - set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}}) - else() - if (COTIRE_DEBUG) - message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})") - endif() - set (_sources "") - set (_sourcesDefinitions "") - endif() - set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS}) - set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS}) - set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS}) - set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS}) - - if ("${COTIRE_ARGV1}" STREQUAL "unity") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on target script - set (_dependsOption DEPENDS "${COTIRE_ARGV2}") - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources}) - - cotire_generate_unity_source( - "${COTIRE_ARGV3}" ${_sources} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions} - PRE_UNDEFS ${_targetPreUndefs} - POST_UNDEFS ${_targetPostUndefs} - SOURCES_PRE_UNDEFS ${_sourcesPreUndefs} - SOURCES_POST_UNDEFS ${_sourcesPostUndefs} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "prefix") - - if (XCODE) - # executing pre-build action under Xcode, check dependency on unity file and prefix dependencies - set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - set (_files "") - foreach (_index RANGE 4 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_generate_prefix_header( - "${COTIRE_ARGV3}" ${_files} - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}" - INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH} - IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}" - INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH} - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags} - ${_dependsOption}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "precompile") - - set (_files "") - foreach (_index RANGE 5 ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - cotire_precompile_prefix_header( - "${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}" - COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}" - COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1} - COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}" - COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}" - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - INCLUDE_DIRECTORIES ${_includeDirs} - SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs} - COMPILE_DEFINITIONS ${_compileDefinitions} - COMPILE_FLAGS ${_compileFlags}) - - elseif ("${COTIRE_ARGV1}" STREQUAL "combine") - - if (COTIRE_TARGET_LANGUAGE) - set (_combinedFile "${COTIRE_ARGV3}") - set (_startIndex 4) - else() - set (_combinedFile "${COTIRE_ARGV2}") - set (_startIndex 3) - endif() - set (_files "") - foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC}) - if (COTIRE_ARGV${_index}) - list (APPEND _files "${COTIRE_ARGV${_index}}") - endif() - endforeach() - - if (XCODE) - # executing pre-build action under Xcode, check dependency on files to be combined - set (_dependsOption DEPENDS ${_files}) - else() - # executing custom command, no need to re-check for dependencies - set (_dependsOption "") - endif() - - if (COTIRE_TARGET_LANGUAGE) - cotire_generate_unity_source( - "${_combinedFile}" ${_files} - LANGUAGE "${COTIRE_TARGET_LANGUAGE}" - ${_dependsOption}) - else() - cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption}) - endif() - - elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup") - - cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}") - - else() - message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".") - endif() - -else() - - # cotire is being run in include mode - # set up all variable and property definitions - - if (NOT DEFINED COTIRE_DEBUG_INIT) - if (DEFINED COTIRE_DEBUG) - set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG}) - else() - set (COTIRE_DEBUG_INIT FALSE) - endif() - endif() - option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT}) - - if (NOT DEFINED COTIRE_VERBOSE_INIT) - if (DEFINED COTIRE_VERBOSE) - set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE}) - else() - set (COTIRE_VERBOSE_INIT FALSE) - endif() - endif() - option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT}) - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING - "Ignore headers with the listed file extensions from the generated prefix header.") - - set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING - "Ignore headers from these directories when generating the prefix header.") - - set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING - "Ignore sources with the listed file extensions from the generated unity source.") - - set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "3" CACHE STRING - "Minimum number of sources in target required to enable use of precompiled header.") - - if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT) - if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES) - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}) - elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio") - # enable parallelization for generators that run multiple jobs by default - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j") - else() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0") - endif() - endif() - set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING - "Maximum number of source files to include in a single unity source file.") - - if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX) - set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix") - endif() - if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX) - set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity") - endif() - if (NOT COTIRE_INTDIR) - set (COTIRE_INTDIR "cotire") - endif() - if (NOT COTIRE_PCH_ALL_TARGET_NAME) - set (COTIRE_PCH_ALL_TARGET_NAME "all_pch") - endif() - if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME) - set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity") - endif() - if (NOT COTIRE_CLEAN_ALL_TARGET_NAME) - set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire") - endif() - if (NOT COTIRE_CLEAN_TARGET_SUFFIX) - set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire") - endif() - if (NOT COTIRE_PCH_TARGET_SUFFIX) - set (COTIRE_PCH_TARGET_SUFFIX "_pch") - endif() - if (MSVC) - # MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code - # use a bigger default factor of 170 percent (128 MB) - if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR) - set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170") - endif() - endif() - if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX) - set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity") - endif() - if (NOT DEFINED COTIRE_TARGETS_FOLDER) - set (COTIRE_TARGETS_FOLDER "cotire") - endif() - if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY) - if ("${CMAKE_GENERATOR}" MATCHES "Ninja") - # generated Ninja build files do not work if the unity target produces the same output file as the cotired target - set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity") - else() - set (COTIRE_UNITY_OUTPUT_DIRECTORY "") - endif() - endif() - - # define cotire cache variables - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of include directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "If not defined, defaults to empty list." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS" - BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a header file extension matches one in the list, it will be excluded from the generated prefix header." - "Includes with an extension in CMAKE__SOURCE_FILE_EXTENSIONS are always ignored." - "If not defined, defaults to inc;inl;ipp." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS" - BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source." - FULL_DOCS - "The variable can be set to a semicolon separated list of file extensions." - "If a source file extension matches one in the list, it will be excluded from the generated unity source file." - "Source files with an extension in CMAKE__IGNORE_EXTENSIONS are always excluded." - "If not defined, defaults to m;mm." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES" - BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header." - FULL_DOCS - "The variable can be set to an integer > 0." - "If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target." - "If not defined, defaults to 3." - ) - - define_property( - CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer >= 0." - "If 0, cotire will only create a single unity source file." - "If a target contains more than that number of source files, cotire will create multiple unity source files for it." - "Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores." - "Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs." - "Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - "Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise." - ) - - # define cotire directory properties - - define_property( - DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" - BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header." - FULL_DOCS - "See target property COTIRE_ENABLE_PRECOMPILED_HEADER." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD" - BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_UNITY_BUILD." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_ADD_CLEAN" - BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory." - FULL_DOCS - "See target property COTIRE_ADD_CLEAN." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_IGNORE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" - BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header." - FULL_DOCS - "See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_POST_UNDEFS." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES." - ) - - define_property( - DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" - BRIEF_DOCS "Define strategy for setting up the unity target's link libraries." - FULL_DOCS - "See target property COTIRE_UNITY_LINK_LIBRARIES_INIT." - ) - - # define cotire target properties - - define_property( - TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED - BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header." - FULL_DOCS - "If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header." - "Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target." - "For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header." - "The target name will be set to this target's name with the suffix _pch appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED - BRIEF_DOCS "Add a new target that performs a unity build for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources." - "Most of the relevant target properties will be copied from this target to the new unity build target." - "Target dependencies and linked libraries have to be manually set up for the new unity build target." - "The unity target name will be set to this target's name with the suffix _unity appended." - "Inherited from directory." - "Defaults to TRUE." - ) - - define_property( - TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED - BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target." - FULL_DOCS - "If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)." - "The clean target name will be set to this target's name with the suffix _clean_cotire appended." - "Inherited from directory." - "Defaults to FALSE." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED - BRIEF_DOCS "Ignore headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header." - "Inherited from directory." - "If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED - BRIEF_DOCS "Honor headers from these directories when generating the prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header." - "If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH," - "the option which yields the closer relative path match wins." - "Inherited from directory." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED - BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header." - FULL_DOCS - "The property can be set to a list of directories." - "Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header." - "Header files are sorted according to the order of the directories in the property." - "If not set, this property is initialized to the empty list." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after each target source file." - "Inherited from directory." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED - BRIEF_DOCS "Maximum number of source files to include in a single unity source file." - FULL_DOCS - "This may be set to an integer > 0." - "If a target contains more than that number of source files, cotire will create multiple unity build files for it." - "If not set, cotire will only create a single unity source file." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE_INIT" - BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will only add the given file(s) to the generated unity source file." - "If not set, cotire will add all the target source files to the generated unity source file." - "The property can be set to a user provided unity source file." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER_INIT" - BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one." - FULL_DOCS - "If set, cotire will add the given header file(s) to the generated prefix header file." - "If not set, cotire will generate a prefix header by tracking the header files included by the unity source file." - "The property can be set to a user provided prefix header file (e.g., stdafx.h)." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED - BRIEF_DOCS "Define strategy for setting up unity target's link libraries." - FULL_DOCS - "If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually." - "If this property is set to COPY, the unity target's link libraries will be copied from this target." - "If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets." - "Inherited from directory." - "Defaults to empty." - ) - - define_property( - TARGET PROPERTY "COTIRE__UNITY_SOURCE" - BRIEF_DOCS "Read-only property. The generated unity source file(s)." - FULL_DOCS - "cotire sets this property to the path of the generated single computation unit source file for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PREFIX_HEADER" - BRIEF_DOCS "Read-only property. The generated prefix header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language prefix header for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE__PRECOMPILED_HEADER" - BRIEF_DOCS "Read-only property. The generated precompiled header file." - FULL_DOCS - "cotire sets this property to the full path of the generated language precompiled header binary for the target." - "Defaults to empty string." - ) - - define_property( - TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME" - BRIEF_DOCS "The name of the generated unity build target corresponding to this target." - FULL_DOCS - "This property can be set to the desired name of the unity target that will be created by cotire." - "If not set, the unity target name will be set to this target's name with the suffix _unity appended." - "After this target has been processed by cotire, the property is set to the actual name of the generated unity target." - "Defaults to empty string." - ) - - # define cotire source properties - - define_property( - SOURCE PROPERTY "COTIRE_EXCLUDED" - BRIEF_DOCS "Do not modify source file's build command." - FULL_DOCS - "If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header." - "The source file will also be excluded from the generated unity source file." - "Source files that have their COMPILE_FLAGS property set will be excluded by default." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_DEPENDENCY" - BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file." - FULL_DOCS - "If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file." - "If the file is modified, cotire will re-generate the prefix header source upon build." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file before this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" - BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file." - FULL_DOCS - "This may be set to a semicolon-separated list of preprocessor symbols." - "cotire will add corresponding #undef directives to the generated unit source file after this file is included." - "Defaults to empty string." - ) - - define_property( - SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE" - BRIEF_DOCS "Start a new unity source file which includes this source file as the first one." - FULL_DOCS - "If this property is set to TRUE, cotire will complete the current unity file and start a new one." - "The new unity source file will include this source file as the first one." - "This property essentially works as a separator for unity source files." - "Defaults to FALSE." - ) - - define_property( - SOURCE PROPERTY "COTIRE_TARGET" - BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target." - FULL_DOCS - "cotire sets this property to the name of target, that the source file's build command has been altered for." - "Defaults to empty string." - ) - - message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.") - -endif() diff --git a/path_10_8/config.lua b/path_10_8/config.lua deleted file mode 100644 index 293e0dfd1..000000000 --- a/path_10_8/config.lua +++ /dev/null @@ -1,112 +0,0 @@ --- The OTX Server Config - - -- Combat settings - -- NOTE: valid values for worldType are: "pvp", "no-pvp" and "pvp-enforced" - worldType = "pvp" - hotkeyAimbotEnabled = true - protectionLevel = 1 - killsToRedSkull = 3 - killsToBlackSkull = 6 - pzLocked = 1 * 60 * 1000 - removeChargesFromRunes = true - timeToDecreaseFrags = 24 * 60 * 60 * 1000 - whiteSkullTime = 15 * 60 * 1000 - stairJumpExhaustion = 2 * 1000 - experienceByKillingPlayers = false - expFromPlayersLevelRange = 75 - - -- Connection Config - -- NOTE: maxPlayers set to 0 means no limit - ip = "127.0.0.1" - bindOnlyGlobalAddress = false - loginProtocolPort = 7171 - gameProtocolPort = 7172 - statusProtocolPort = 7171 - maxPlayers = 0 - motd = "Welcome to The OTX Server!" - onePlayerOnlinePerAccount = true - allowClones = false - allowWalkthrough = true - serverName = "OTXSERVER" - statusTimeout = 1 * 1000 - replaceKickOnLogin = true - maxPacketsPerSecond = 25 - - -- Deaths - -- NOTE: Leave deathLosePercent as -1 if you want to use the default - -- death penalty formula. For the old formula, set it to 10. For - -- no skill/experience loss, set it to 0. - deathLosePercent = -1 - - -- Houses - -- NOTE: set housePriceEachSQM to -1 to disable the ingame buy house functionality - housePriceEachSQM = 1000 - houseRentPeriod = "never" - - -- Item Usage - timeBetweenActions = 200 - timeBetweenExActions = 1000 - - -- Map - -- NOTE: set mapName WITHOUT .otbm at the end - mapName = "forgotten" - mapAuthor = "Komic" - - -- Market - marketOfferDuration = 30 * 24 * 60 * 60 - premiumToCreateMarketOffer = true - checkExpiredMarketOffersEachMinutes = 60 - maxMarketOffersAtATimePerPlayer = 100 - - -- MySQL - mysqlHost = "127.0.0.1" - mysqlUser = "root" - mysqlPass = "master" - mysqlDatabase = "darkkonia" - mysqlPort = 3306 - mysqlSock = "" - - -- Misc. - allowChangeOutfit = true - freePremium = false - kickIdlePlayerAfterMinutes = 15 - maxMessageBuffer = 4 - emoteSpells = true - classicEquipmentSlots = false - - -- Rates - -- NOTE: rateExp is not used if you have enabled stages in data/XML/stages.xml - rateExp = 1 - rateSkill = 3 - rateLoot = 2 - rateMagic = 3 - rateSpawn = 1 - - -- Critical hits - -- NOTE: criticalChance and extraPercent are percentages, not absolute values. - -- extraPercent is the extra percentage of the damage to be added. - criticalChance = 1 - criticalExtra = 100 - - -- Monsters - deSpawnRange = 2 - deSpawnRadius = 50 - - -- Stamina - staminaSystem = true - - -- Scripts - warnUnsafeScripts = true - convertUnsafeScripts = true - - -- Startup - -- NOTE: defaultPriority only works on Windows and sets process - -- priority, valid values are: "normal", "above-normal", "high" - defaultPriority = "high" - startupDatabaseOptimization = true - - -- Status server information - ownerName = "Mattyx14" - ownerEmail = "darkylive@live.com.mx" - url = "https://github.com/mattyx14/" - location = "Mexico" diff --git a/path_10_8/data/XML/commands.xml b/path_10_8/data/XML/commands.xml deleted file mode 100644 index 9b1630aaa..000000000 --- a/path_10_8/data/XML/commands.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/path_10_8/data/XML/groups.xml b/path_10_8/data/XML/groups.xml deleted file mode 100644 index c9c6c7f80..000000000 --- a/path_10_8/data/XML/groups.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_10_8/data/XML/mounts.xml b/path_10_8/data/XML/mounts.xml deleted file mode 100644 index 52612eb3c..000000000 --- a/path_10_8/data/XML/mounts.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/XML/outfits.xml b/path_10_8/data/XML/outfits.xml deleted file mode 100644 index f6f2cfe0b..000000000 --- a/path_10_8/data/XML/outfits.xml +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/XML/quests.xml b/path_10_8/data/XML/quests.xml deleted file mode 100644 index 4633d44f7..000000000 --- a/path_10_8/data/XML/quests.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/path_10_8/data/XML/stages.xml b/path_10_8/data/XML/stages.xml deleted file mode 100644 index 06b639c0e..000000000 --- a/path_10_8/data/XML/stages.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_10_8/data/XML/vocations.xml b/path_10_8/data/XML/vocations.xml deleted file mode 100644 index 6ddebd0c9..000000000 --- a/path_10_8/data/XML/vocations.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/actions/actions.xml b/path_10_8/data/actions/actions.xml deleted file mode 100644 index c39a360bc..000000000 --- a/path_10_8/data/actions/actions.xml +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/actions/lib/actions.lua b/path_10_8/data/actions/lib/actions.lua deleted file mode 100644 index e6092fd66..000000000 --- a/path_10_8/data/actions/lib/actions.lua +++ /dev/null @@ -1,41 +0,0 @@ -function destroyItem(player, target, toPosition) - if target == nil or not target:isItem() then - return false - end - - if target:hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) or target:hasAttribute(ITEM_ATTRIBUTE_ACTIONID) then - return false - end - - if toPosition.x == CONTAINER_POSITION then - player:sendCancelMessage(Game.getReturnMessage(RETURNVALUE_NOTPOSSIBLE)) - return true - end - - local destroyId = ItemType(target.itemid):getDestroyId() - if destroyId == 0 then - return false - end - - if math.random(7) == 1 then - local item = Game.createItem(destroyId, 1, toPosition) - if item ~= nil then - item:decay() - end - - -- Move items outside the container - if target:isContainer() then - for i = target:getSize() - 1, 0, -1 do - local containerItem = target:getItem(i) - if containerItem then - containerItem:moveTo(toPosition) - end - end - end - - target:remove(1) - end - - toPosition:sendMagicEffect(CONST_ME_POFF) - return true -end diff --git a/path_10_8/data/actions/scripts/other/bed_modification_kits.lua b/path_10_8/data/actions/scripts/other/bed_modification_kits.lua deleted file mode 100644 index 4189df457..000000000 --- a/path_10_8/data/actions/scripts/other/bed_modification_kits.lua +++ /dev/null @@ -1,50 +0,0 @@ -local beds = { - [7904] = {{7811, 7812}, {7813, 7814}}, -- green kit - [7905] = {{7819, 7820}, {7821, 7822}}, -- yellow kit - [7906] = {{7815, 7816}, {7817, 7818}}, -- red kit - [7907] = {{1754, 1755}, {1760, 1761}}, -- removal kit - [20252] = {{20197, 20198}, {20199, 20200}} -- canopy kit -} - -local function internalBedTransform(item, targetItem, toPosition, itemArray) - targetItem:transform(itemArray[1]) - targetItem:getPosition():sendMagicEffect(CONST_ME_POFF) - - Tile(toPosition):getItemByType(ITEM_TYPE_BED):transform(itemArray[2]) - toPosition:sendMagicEffect(CONST_ME_POFF) - - item:remove() -end - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local newBed = beds[item:getId()] - if not newBed or target == nil or not target:isItem() then - return false - end - - local tile = Tile(toPosition) - if not tile or not tile:getHouse() then - return false - end - - local targetItemId = target:getId() - if targetItemId == newBed[1][1] or targetItemId == newBed[2][1] then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "You already have this bed modification.") - return true - end - - for _, bed in pairs(beds) do - if bed[1][1] == targetItemId or isInArray({1758, 5502, 18027}, targetItemId) then - toPosition:sendMagicEffect(CONST_ME_POFF) - toPosition.y = toPosition.y + 1 - internalBedTransform(item, target, toPosition, newBed[1]) - break - elseif bed[2][1] == targetItemId or isInArray({1756, 5500, 18029}, targetItemId) then - toPosition:sendMagicEffect(CONST_ME_POFF) - toPosition.x = toPosition.x + 1 - internalBedTransform(item, target, toPosition, newBed[2]) - break - end - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/blueberrybush.lua b/path_10_8/data/actions/scripts/other/blueberrybush.lua deleted file mode 100644 index a471e0c2f..000000000 --- a/path_10_8/data/actions/scripts/other/blueberrybush.lua +++ /dev/null @@ -1,6 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(2786) - item:decay() - Game.createItem(2677, 3, fromPosition) - return true -end diff --git a/path_10_8/data/actions/scripts/other/changegold.lua b/path_10_8/data/actions/scripts/other/changegold.lua deleted file mode 100644 index 6af63855a..000000000 --- a/path_10_8/data/actions/scripts/other/changegold.lua +++ /dev/null @@ -1,19 +0,0 @@ -local config = { - [ITEM_GOLD_COIN] = {changeTo = ITEM_PLATINUM_COIN}, - [ITEM_PLATINUM_COIN] = {changeBack = ITEM_GOLD_COIN, changeTo = ITEM_CRYSTAL_COIN}, - [ITEM_CRYSTAL_COIN] = {changeBack = ITEM_PLATINUM_COIN} -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local coin = config[item:getId()] - if coin.changeTo and item.type == 100 then - item:remove() - player:addItem(coin.changeTo, 1) - elseif coin.changeBack then - item:remove(1) - player:addItem(coin.changeBack, 100) - else - return false - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/constructionkits.lua b/path_10_8/data/actions/scripts/other/constructionkits.lua deleted file mode 100644 index 1e12d5687..000000000 --- a/path_10_8/data/actions/scripts/other/constructionkits.lua +++ /dev/null @@ -1,31 +0,0 @@ -local constructionKits = { - [3901] = 1666, [3902] = 1670, [3903] = 1652, [3904] = 1674, [3905] = 1658, - [3906] = 3813, [3907] = 3817, [3908] = 1619, [3909] = 12799, [3910] = 2105, - [3911] = 1614, [3912] = 3806, [3913] = 3807, [3914] = 3809, [3915] = 1716, - [3916] = 1724, [3917] = 1732, [3918] = 1775, [3919] = 1774, [3920] = 1750, - [3921] = 3832, [3922] = 2095, [3923] = 2098, [3924] = 2064, [3925] = 2582, - [3926] = 2117, [3927] = 1728, [3928] = 1442, [3929] = 1446, [3930] = 1447, - [3931] = 2034, [3932] = 2604, [3933] = 2080, [3934] = 2084, [3935] = 3821, - [3936] = 3811, [3937] = 2101, [3938] = 3812, [5086] = 5046, [5087] = 5055, - [5088] = 5056, [6114] = 6111, [6115] = 6109, [6372] = 6356, [6373] = 6371, - [8692] = 8688, [9974] = 9975, [11126] = 11127, [11133] = 11129, [11124] = 11125, - [11205] = 11203, [14328] = 1616, [14329] = 1615, [16075] = 16020, [16099] = 16098, - [20254] = 20295, [20255] = 20297, [20257] = 20299 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local kit = constructionKits[item.itemid] - if not kit then - return false - end - - if fromPosition.x == CONTAINER_POSITION then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "Put the construction kit on the floor first.") - elseif not Tile(fromPosition):getHouse() then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "You may construct this only inside a house.") - else - item:transform(kit) - fromPosition:sendMagicEffect(CONST_ME_POFF) - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/createbread.lua b/path_10_8/data/actions/scripts/other/createbread.lua deleted file mode 100644 index f58eb1a0b..000000000 --- a/path_10_8/data/actions/scripts/other/createbread.lua +++ /dev/null @@ -1,19 +0,0 @@ -local liquidContainers = {1775, 2005, 2006, 2007, 2008, 2009, 2011, 2012, 2013, 2014, 2015, 2023, 2031, 2032, 2033} -local millstones = {1381, 1382, 1383, 1384} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local itemId = item:getId() - if itemId == 2692 then - if target.type == 1 and isInArray(liquidContainers, target.itemid) then - item:remove(1) - player:addItem(2693, 1) - target:transform(target.itemid, 0) - return true - end - elseif isInArray(millstones, target.itemid) then - item:remove(1) - player:addItem(2692, 1) - return true - end - return false -end diff --git a/path_10_8/data/actions/scripts/other/decayto.lua b/path_10_8/data/actions/scripts/other/decayto.lua deleted file mode 100644 index ee8543e86..000000000 --- a/path_10_8/data/actions/scripts/other/decayto.lua +++ /dev/null @@ -1,16 +0,0 @@ -local decayItems = { - [2041] = 2042, [2042] = 2041, [2044] = 2045, [2045] = 2044, [2047] = 2048, - [2048] = 2047, [2050] = 2051, [2051] = 2050, [2052] = 2053, [2053] = 2052, - [2054] = 2055, [2055] = 2054 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local decayItemId = decayItems[item:getId()] - if not decayItemId then - return false - end - - item:transform(decayItemId) - item:decay() - return true -end diff --git a/path_10_8/data/actions/scripts/other/destroy.lua b/path_10_8/data/actions/scripts/other/destroy.lua deleted file mode 100644 index 0499f62cc..000000000 --- a/path_10_8/data/actions/scripts/other/destroy.lua +++ /dev/null @@ -1,3 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - return destroyItem(player, target, toPosition) -end diff --git a/path_10_8/data/actions/scripts/other/dice.lua b/path_10_8/data/actions/scripts/other/dice.lua deleted file mode 100644 index 86505a5dc..000000000 --- a/path_10_8/data/actions/scripts/other/dice.lua +++ /dev/null @@ -1,15 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local position = item:getPosition() - local value = math.random(1, 6) - local isInGhostMode = player:isInGhostMode() - - position:sendMagicEffect(CONST_ME_CRAPS, isInGhostMode and player) - - local spectators = Game.getSpectators(position, false, true, 3, 3) - for _, spectator in ipairs(spectators) do - player:say(player:getName() .. " rolled a " .. value .. ".", TALKTYPE_MONSTER_SAY, isInGhostMode, spectator, position) - end - - item:transform(5791 + value) - return true -end diff --git a/path_10_8/data/actions/scripts/other/doors.lua b/path_10_8/data/actions/scripts/other/doors.lua deleted file mode 100644 index d1fdbe1d6..000000000 --- a/path_10_8/data/actions/scripts/other/doors.lua +++ /dev/null @@ -1,65 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local itemId = item:getId() - if isInArray(questDoors, itemId) then - if player:getStorageValue(item.actionid) ~= -1 then - item:transform(itemId + 1) - player:teleportTo(toPosition, true) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "The door seems to be sealed against unwanted intruders.") - end - return true - elseif isInArray(levelDoors, itemId) then - if item.actionid > 0 and player:getLevel() >= item.actionid - 1000 then - item:transform(itemId + 1) - player:teleportTo(toPosition, true) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "Only the worthy may pass.") - end - return true - elseif isInArray(keys, itemId) then - if target.actionid > 0 then - if item.actionid == target.actionid and doors[target.itemid] then - target:transform(doors[target.itemid]) - return true - end - player:sendTextMessage(MESSAGE_STATUS_SMALL, "The key does not match.") - return true - end - return false - end - - if isInArray(horizontalOpenDoors, itemId) or isInArray(verticalOpenDoors, itemId) then - local doorCreature = Tile(toPosition):getTopCreature() - if doorCreature ~= nil then - toPosition.x = toPosition.x + 1 - local query = Tile(toPosition):queryAdd(doorCreature, bit.bor(FLAG_IGNOREBLOCKCREATURE, FLAG_PATHFINDING)) - if query ~= RETURNVALUE_NOERROR then - toPosition.x = toPosition.x - 1 - toPosition.y = toPosition.y + 1 - query = Tile(toPosition):queryAdd(doorCreature, bit.bor(FLAG_IGNOREBLOCKCREATURE, FLAG_PATHFINDING)) - end - - if query ~= RETURNVALUE_NOERROR then - player:sendTextMessage(MESSAGE_STATUS_SMALL, query) - return true - end - - doorCreature:teleportTo(toPosition, true) - end - - if not isInArray(openSpecialDoors, itemId) then - item:transform(itemId - 1) - end - return true - end - - if doors[itemId] then - if item.actionid == 0 then - item:transform(doors[itemId]) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "It is locked.") - end - return true - end - return false -end diff --git a/path_10_8/data/actions/scripts/other/fireworksrocket.lua b/path_10_8/data/actions/scripts/other/fireworksrocket.lua deleted file mode 100644 index 57ce7989d..000000000 --- a/path_10_8/data/actions/scripts/other/fireworksrocket.lua +++ /dev/null @@ -1,14 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if fromPosition.x ~= CONTAINER_POSITION then - fromPosition:sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE)) - else - local position = player:getPosition() - position:sendMagicEffect(CONST_ME_HITBYFIRE) - position:sendMagicEffect(CONST_ME_EXPLOSIONAREA) - player:say("Ouch! Rather place it on the ground next time.", TALKTYPE_MONSTER_SAY) - player:addHealth(-10) - end - - item:remove() - return true -end diff --git a/path_10_8/data/actions/scripts/other/fluids.lua b/path_10_8/data/actions/scripts/other/fluids.lua deleted file mode 100644 index c01f40334..000000000 --- a/path_10_8/data/actions/scripts/other/fluids.lua +++ /dev/null @@ -1,71 +0,0 @@ -local drunk = Condition(CONDITION_DRUNK) -drunk:setParameter(CONDITION_PARAM_TICKS, 60000) - -local poison = Condition(CONDITION_POISON) -poison:setParameter(CONDITION_PARAM_DELAYED, true) -poison:setParameter(CONDITION_PARAM_MINVALUE, -50) -poison:setParameter(CONDITION_PARAM_MAXVALUE, -120) -poison:setParameter(CONDITION_PARAM_STARTVALUE, -5) -poison:setParameter(CONDITION_PARAM_TICKINTERVAL, 4000) -poison:setParameter(CONDITION_PARAM_FORCEUPDATE, true) - -local fluidType = {3, 4, 5, 7, 10, 11, 13, 15, 19} -local fluidMessage = {"Aah...", "Urgh!", "Mmmh.", "Aaaah...", "Aaaah...", "Urgh!", "Urgh!", "Aah...", "Urgh!"} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local targetItemType = ItemType(target.itemid) - if targetItemType and targetItemType:isFluidContainer() then - if target.type == 0 and item.type ~= 0 then - target:transform(target:getId(), item.type) - item:transform(item:getId(), 0) - return true - elseif target.type ~= 0 and item.type == 0 then - target:transform(target:getId(), 0) - item:transform(item:getId(), target.type) - return true - end - end - - if target:isCreature() then - if item.type == 0 then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "It is empty.") - elseif target == player then - item:transform(item:getId(), 0) - if item.type == 3 or item.type == 15 then - player:addCondition(drunk) - elseif item.type == 4 then - player:addCondition(poison) - elseif item.type == 7 then - player:addMana(math.random(50, 150)) - fromPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE) - elseif item.type == 10 then - player:addHealth(60) - fromPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE) - end - for i = 0, #fluidType do - if item.type == fluidType[i] then - player:say(fluidMessage[i], TALKTYPE_MONSTER_SAY) - return true - end - end - player:say("Gulp.", TALKTYPE_MONSTER_SAY) - else - Game.createItem(2016, item.type, toPosition):decay() - item:transform(item:getId(), 0) - end - else - local fluidSource = targetItemType and targetItemType:getFluidSource() or 0 - if fluidSource ~= 0 then - item:transform(item:getId(), fluidSource) - elseif item.type == 0 then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "It is empty.") - else - if toPosition.x == CONTAINER_POSITION then - toPosition = player:getPosition() - end - Game.createItem(2016, item.type, toPosition):decay() - item:transform(item:getId(), 0) - end - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/food.lua b/path_10_8/data/actions/scripts/other/food.lua deleted file mode 100644 index cfe48a0de..000000000 --- a/path_10_8/data/actions/scripts/other/food.lua +++ /dev/null @@ -1,116 +0,0 @@ -local foods = { - [2362] = {5, "Crunch."}, -- carrot - [2666] = {15, "Munch."}, -- meat - [2667] = {12, "Munch."}, -- fish - [2668] = {10, "Mmmm."}, -- salmon - [2669] = {17, "Munch."}, -- northern pike - [2670] = {4, "Gulp."}, -- shrimp - [2671] = {30, "Chomp."}, -- ham - [2672] = {60, "Chomp."}, -- dragon ham - [2673] = {5, "Yum."}, -- pear - [2674] = {6, "Yum."}, -- red apple - [2675] = {13, "Yum."}, -- orange - [2676] = {8, "Yum."}, -- banana - [2677] = {1, "Yum."}, -- blueberry - [2678] = {18, "Slurp."}, -- coconut - [2679] = {1, "Yum."}, -- cherry - [2680] = {2, "Yum."}, -- strawberry - [2681] = {9, "Yum."}, -- grapes - [2682] = {20, "Yum."}, -- melon - [2683] = {17, "Munch."}, -- pumpkin - [2684] = {5, "Crunch."}, -- carrot - [2685] = {6, "Munch."}, -- tomato - [2686] = {9, "Crunch."}, -- corncob - [2687] = {2, "Crunch."}, -- cookie - [2688] = {2, "Munch."}, -- candy cane - [2689] = {10, "Crunch."}, -- bread - [2690] = {3, "Crunch."}, -- roll - [2691] = {8, "Crunch."}, -- brown bread - [2695] = {6, "Gulp."}, -- egg - [2696] = {9, "Smack."}, -- cheese - [2787] = {9, "Munch."}, -- white mushroom - [2788] = {4, "Munch."}, -- red mushroom - [2789] = {22, "Munch."}, -- brown mushroom - [2790] = {30, "Munch."}, -- orange mushroom - [2791] = {9, "Munch."}, -- wood mushroom - [2792] = {6, "Munch."}, -- dark mushroom - [2793] = {12, "Munch."}, -- some mushrooms - [2794] = {3, "Munch."}, -- some mushrooms - [2795] = {36, "Munch."}, -- fire mushroom - [2796] = {5, "Munch."}, -- green mushroom - [5097] = {4, "Yum."}, -- mango - [6125] = {8, "Gulp."}, -- tortoise egg - [6278] = {10, "Mmmm."}, -- cake - [6279] = {15, "Mmmm."}, -- decorated cake - [6393] = {12, "Mmmm."}, -- valentine's cake - [6394] = {15, "Mmmm."}, -- cream cake - [6501] = {20, "Mmmm."}, -- gingerbread man - [6541] = {6, "Gulp."}, -- coloured egg (yellow) - [6542] = {6, "Gulp."}, -- coloured egg (red) - [6543] = {6, "Gulp."}, -- coloured egg (blue) - [6544] = {6, "Gulp."}, -- coloured egg (green) - [6545] = {6, "Gulp."}, -- coloured egg (purple) - [6569] = {1, "Mmmm."}, -- candy - [6574] = {5, "Mmmm."}, -- bar of chocolate - [7158] = {15, "Munch."}, -- rainbow trout - [7159] = {13, "Munch."}, -- green perch - [7372] = {2, "Yum."}, -- ice cream cone (crispy chocolate chips) - [7373] = {2, "Yum."}, -- ice cream cone (velvet vanilla) - [7374] = {2, "Yum."}, -- ice cream cone (sweet strawberry) - [7375] = {2, "Yum."}, -- ice cream cone (chilly cherry) - [7376] = {2, "Yum."}, -- ice cream cone (mellow melon) - [7377] = {2, "Yum."}, -- ice cream cone (blue-barian) - [7909] = {4, "Crunch."}, -- walnut - [7910] = {4, "Crunch."}, -- peanut - [7963] = {60, "Munch."}, -- marlin - [8112] = {9, "Urgh."}, -- scarab cheese - [8838] = {10, "Gulp."}, -- potato - [8839] = {5, "Yum."}, -- plum - [8840] = {1, "Yum."}, -- raspberry - [8841] = {1, "Urgh."}, -- lemon - [8842] = {7, "Munch."}, -- cucumber - [8843] = {5, "Crunch."}, -- onion - [8844] = {1, "Gulp."}, -- jalapeño pepper - [8845] = {5, "Munch."}, -- beetroot - [8847] = {11, "Yum."}, -- chocolate cake - [9005] = {7, "Slurp."}, -- yummy gummy worm - [9114] = {5, "Crunch."}, -- bulb of garlic - [9996] = {0, "Slurp."}, -- banana chocolate shake - [10454] = {0, "Your head begins to feel better."}, -- headache pill - [11246] = {15, "Yum."}, -- rice ball - [11370] = {3, "Urgh."}, -- terramite eggs - [11429] = {10, "Mmmm."}, -- crocodile steak - [12415] = {20, "Yum."}, -- pineapple - [12416] = {10, "Munch."}, -- aubergine - [12417] = {8, "Crunch."}, -- broccoli - [12418] = {9, "Crunch."}, -- cauliflower - [12637] = {55, "Gulp."}, -- ectoplasmic sushi - [12638] = {18, "Yum."}, -- dragonfruit - [12639] = {2, "Munch."}, -- peas - [13297] = {20, "Crunch."}, -- haunch of boar - [15405] = {55, "Munch."}, -- sandfish - [15487] = {14, "Urgh."}, -- larvae - [15488] = {15, "Munch."}, -- deepling filet - [16014] = {60, "Mmmm."}, -- anniversary cake - [18397] = {33, "Munch."}, -- mushroom pie - [19737] = {10, "Urgh."}, -- insectoid eggs - [20100] = {15, "Smack."}, -- soft cheese - [20101] = {12, "Smack."} -- rat cheese -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local food = foods[item.itemid] - if food == nil then - return false - end - - local condition = player:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT) - if condition and math.floor(condition:getTicks() / 1000 + food[1]) >= 1200 then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "You are full.") - else - player:feed(food[1] * 12) - player:say(food[2], TALKTYPE_MONSTER_SAY) - item:remove(1) - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/music.lua b/path_10_8/data/actions/scripts/other/music.lua deleted file mode 100644 index a6bdb61ab..000000000 --- a/path_10_8/data/actions/scripts/other/music.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - -- TODO: Different music effect for different instruments. - item:getPosition():sendMagicEffect(CONST_ME_SOUND_BLUE) - return true -end diff --git a/path_10_8/data/actions/scripts/other/partyhat.lua b/path_10_8/data/actions/scripts/other/partyhat.lua deleted file mode 100644 index 6e41b5871..000000000 --- a/path_10_8/data/actions/scripts/other/partyhat.lua +++ /dev/null @@ -1,9 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local headSlotItem = player:getSlotItem(CONST_SLOT_HEAD) - if headSlotItem == nil or item.uid ~= headSlotItem:getUniqueId() then - return false - end - - player:getPosition():sendMagicEffect(CONST_ME_GIFT_WRAPS) - return true -end diff --git a/path_10_8/data/actions/scripts/other/partytrumpet.lua b/path_10_8/data/actions/scripts/other/partytrumpet.lua deleted file mode 100644 index 136d2974a..000000000 --- a/path_10_8/data/actions/scripts/other/partytrumpet.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(13578) - item:decay() - player:say("TOOOOOOT!", TALKTYPE_MONSTER_SAY) - fromPosition:sendMagicEffect(CONST_ME_SOUND_BLUE) - return true -end diff --git a/path_10_8/data/actions/scripts/other/piggybank.lua b/path_10_8/data/actions/scripts/other/piggybank.lua deleted file mode 100644 index 07f5d93ad..000000000 --- a/path_10_8/data/actions/scripts/other/piggybank.lua +++ /dev/null @@ -1,11 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if math.random(6) == 1 then - item:getPosition():sendMagicEffect(CONST_ME_POFF) - player:addItem(ITEM_GOLD_COIN, 1) - item:transform(2115) - else - item:getPosition():sendMagicEffect(CONST_ME_SOUND_YELLOW) - player:addItem(ITEM_PLATINUM_COIN, 1) - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/potions.lua b/path_10_8/data/actions/scripts/other/potions.lua deleted file mode 100644 index 9a59245b7..000000000 --- a/path_10_8/data/actions/scripts/other/potions.lua +++ /dev/null @@ -1,158 +0,0 @@ -local ultimateHealthPot = 8473 -local greatHealthPot = 7591 -local greatManaPot = 7590 -local greatSpiritPot = 8472 -local strongHealthPot = 7588 -local strongManaPot = 7589 -local healthPot = 7618 -local manaPot = 7620 -local smallHealthPot = 8704 -local antidotePot = 8474 -local greatEmptyPot = 7635 -local strongEmptyPot = 7634 -local emptyPot = 7636 - -local antidote = Combat() -antidote:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -antidote:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -antidote:setParameter(COMBAT_PARAM_TARGETCASTERORTOPMOST, true) -antidote:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -antidote:setParameter(COMBAT_PARAM_DISPEL, CONDITION_POISON) - -local exhaust = Condition(CONDITION_EXHAUST_HEAL) -exhaust:setParameter(CONDITION_PARAM_TICKS, (configManager.getNumber(configKeys.EX_ACTIONS_DELAY_INTERVAL) - 100)) --- 1000 - 100 due to exact condition timing. -100 doesn't hurt us, and players don't have reminding ~50ms exhaustion. - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if target == nil or not target:isPlayer() then - return true - end - - if player:getCondition(CONDITION_EXHAUST_HEAL) then - player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUAREEXHAUSTED)) - return true - end - - local itemId = item:getId() - if itemId == antidotePot then - if not antidote:execute(target, numberToVariant(target:getId())) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(emptyPot, 1) - elseif itemId == smallHealthPot then - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 60, 90, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(emptyPot, 1) - elseif itemId == healthPot then - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 125, 175, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(emptyPot, 1) - elseif itemId == manaPot then - if not doTargetCombatMana(0, target, 75, 125, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(emptyPot, 1) - elseif itemId == strongHealthPot then - if (not isInArray({3, 4, 7, 8}, target:getVocation():getId()) or target:getLevel() < 50) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by paladins and knights of level 50 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 250, 350, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(strongEmptyPot, 1) - elseif itemId == strongManaPot then - if (not isInArray({1, 2, 3, 5, 6, 7}, target:getVocation():getId()) or target:getLevel() < 50) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by sorcerers, druids and paladins of level 50 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatMana(0, target, 115, 185, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(strongEmptyPot, 1) - elseif itemId == greatSpiritPot then - if (not isInArray({3, 7}, target:getVocation():getId()) or target:getLevel() < 80) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by paladins of level 80 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 250, 350, CONST_ME_MAGIC_BLUE) or not doTargetCombatMana(0, target, 100, 200, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(greatEmptyPot, 1) - elseif itemId == greatHealthPot then - if (not isInArray({4, 8}, target:getVocation():getId()) or target:getLevel() < 80) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by knights of level 80 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 425, 575, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(greatEmptyPot, 1) - elseif itemId == greatManaPot then - if (not isInArray({1,2,5,6}, target:getVocation():getId()) or target:getLevel() < 80) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by sorcerers and druids of level 80 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatMana(0, target, 150, 250, CONST_ME_MAGIC_BLUE) then - return false - end - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(greatEmptyPot, 1) - elseif itemId == ultimateHealthPot then - if (not isInArray({4, 8}, target:getVocation():getId()) or target:getLevel() < 130) and not getPlayerFlagValue(player, PlayerFlag_IgnoreSpellCheck) then - player:say("This potion can only be consumed by knights of level 130 or higher.", TALKTYPE_MONSTER_SAY) - return true - end - - if not doTargetCombatHealth(0, target, COMBAT_HEALING, 650, 850, CONST_ME_MAGIC_BLUE) then - return false - end - - player:addCondition(exhaust) - target:say("Aaaah...", TALKTYPE_MONSTER_SAY) - item:remove(1) - player:addItem(greatEmptyPot, 1) - end - return true -end diff --git a/path_10_8/data/actions/scripts/other/skilltrainer.lua b/path_10_8/data/actions/scripts/other/skilltrainer.lua deleted file mode 100644 index 8ff872bca..000000000 --- a/path_10_8/data/actions/scripts/other/skilltrainer.lua +++ /dev/null @@ -1,23 +0,0 @@ -local statues = { - [18488] = SKILL_SWORD, - [18489] = SKILL_AXE, - [18490] = SKILL_CLUB, - [18491] = SKILL_DISTANCE, - [18492] = SKILL_MAGLEVEL -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local skill = statues[item:getId()] - if not player:isPremium() then - player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_YOUNEEDPREMIUMACCOUNT)) - return true - end - - if player:isPzLocked() then - return false - end - - player:setOfflineTrainingSkill(skill) - player:remove() - return true -end diff --git a/path_10_8/data/actions/scripts/other/spellbook.lua b/path_10_8/data/actions/scripts/other/spellbook.lua deleted file mode 100644 index 5c7da6c00..000000000 --- a/path_10_8/data/actions/scripts/other/spellbook.lua +++ /dev/null @@ -1,32 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local count = getPlayerInstantSpellCount(player) - local text = "" - local spells = {} - for i = 0, count - 1 do - local spell = getPlayerInstantSpellInfo(player, i) - if spell.level ~= 0 then - if spell.manapercent > 0 then - spell.mana = spell.manapercent .. "%" - end - spells[#spells + 1] = spell - end - end - - table.sort(spells, function(a, b) return a.level < b.level end) - - local prevLevel = -1 - for i, spell in ipairs(spells) do - local line = "" - if prevLevel ~= spell.level then - if i ~= 1 then - line = "\n" - end - line = line .. "Spells for Level " .. spell.level .. "\n" - prevLevel = spell.level - end - text = text .. line .. " " .. spell.words .. " - " .. spell.name .. " : " .. spell.mana .. "\n" - end - - player:showTextDialog(item:getId(), text) - return true -end diff --git a/path_10_8/data/actions/scripts/other/surprisebag.lua b/path_10_8/data/actions/scripts/other/surprisebag.lua deleted file mode 100644 index 4727e0537..000000000 --- a/path_10_8/data/actions/scripts/other/surprisebag.lua +++ /dev/null @@ -1,27 +0,0 @@ -local presents = { - [6570] = { -- blue present - {2687, 10}, {6394, 3}, 6280, 6574, 6578, 6575, 6577, 6569, 6576, 6572, 2114 - }, - [6571] = { -- red present - {2152, 10}, {2152, 10}, {2152, 10}, 2153, 5944, 2112, 6568, 6566, 2492, 2520, 2195, 2114, 2114, 2114, 6394, 6394, 6576, 6576, 6578, 6578, 6574, 6574 - } -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local count = 1 - local targetItem = presents[item.itemid] - if not targetItem then - return true - end - - local gift = targetItem[math.random(#targetItem)] - if type(gift) == "table" then - gift = gift[1] - count = gift[2] - end - - player:addItem(gift, count) - item:remove(1) - fromPosition:sendMagicEffect(CONST_ME_GIFT_WRAPS) - return true -end diff --git a/path_10_8/data/actions/scripts/other/teleport.lua b/path_10_8/data/actions/scripts/other/teleport.lua deleted file mode 100644 index 8cb599463..000000000 --- a/path_10_8/data/actions/scripts/other/teleport.lua +++ /dev/null @@ -1,10 +0,0 @@ -local upFloorIds = {1386, 3678, 5543} -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if isInArray(upFloorIds, item.itemid) then - fromPosition:moveUpstairs() - else - fromPosition.z = fromPosition.z + 1 - end - player:teleportTo(fromPosition, false) - return true -end diff --git a/path_10_8/data/actions/scripts/other/trap.lua b/path_10_8/data/actions/scripts/other/trap.lua deleted file mode 100644 index 9d4554707..000000000 --- a/path_10_8/data/actions/scripts/other/trap.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(item:getId() - 1) - fromPosition:sendMagicEffect(CONST_ME_POFF) - return true -end diff --git a/path_10_8/data/actions/scripts/other/watch.lua b/path_10_8/data/actions/scripts/other/watch.lua deleted file mode 100644 index 88b7df4ea..000000000 --- a/path_10_8/data/actions/scripts/other/watch.lua +++ /dev/null @@ -1,4 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - player:sendTextMessage(MESSAGE_INFO_DESCR, "The time is " .. getFormattedWorldTime() .. ".") - return true -end diff --git a/path_10_8/data/actions/scripts/other/windows.lua b/path_10_8/data/actions/scripts/other/windows.lua deleted file mode 100644 index baa8b6172..000000000 --- a/path_10_8/data/actions/scripts/other/windows.lua +++ /dev/null @@ -1,50 +0,0 @@ -local windows = { - [5303] = 6448, [5304] = 6449, [6438] = 6436, [6436] = 6438, - [6439] = 6437, [6437] = 6439, [6442] = 6440, [6440] = 6442, - [6443] = 6441, [6441] = 6443, [6446] = 6444, [6444] = 6446, - [6447] = 6445, [6445] = 6447, [6448] = 5303, [6449] = 5304, - [6452] = 6450, [6450] = 6452, [6453] = 6451, [6451] = 6453, - [6456] = 6454, [6454] = 6456, [6457] = 6455, [6455] = 6457, - [6460] = 6458, [6458] = 6460, [6461] = 6459, [6459] = 6461, - [6464] = 6462, [6462] = 6464, [6465] = 6463, [6463] = 6465, - [6468] = 6466, [6466] = 6468, [6469] = 6467, [6467] = 6469, - [6472] = 6470, [6470] = 6472, [6473] = 6471, [6471] = 6473, - [6790] = 6788, [6788] = 6790, [6791] = 6789, [6789] = 6791, - [7027] = 7025, [7025] = 7027, [7028] = 7026, [7026] = 7028, - [7031] = 7029, [7029] = 7031, [7032] = 7030, [7030] = 7032, - [10264] = 10266, [10266] = 10264, [10265] = 10267, [10267] = 10265, - [10488] = 10490, [10490] = 10488, [10489] = 10491, [10491] = 10489, - [19427] = 19447, [19428] = 19448, [19441] = 19450, [19440] = 19449, - [19443] = 20180, [19444] = 20181, [19445] = 20183, [19446] = 20184, - [19447] = 19427, [19448] = 19428, [19449] = 19440, [19450] = 19441, - [19974] = 20182, [19975] = 20185, [20180] = 19443, [20181] = 19444, - [20182] = 19974, [20183] = 19445, [20184] = 19446, [20185] = 19975 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local window = windows[item:getId()] - if window == nil then - return false - end - - local tile = Tile(fromPosition) - local house = tile and tile:getHouse() - if not house then - fromPosition.y = fromPosition.y - 1 - tile = Tile(fromPosition) - house = tile and tile:getHouse() - if not house then - fromPosition.y = fromPosition.y + 1 - fromPosition.x = fromPosition.x - 1 - tile = Tile(fromPosition) - house = tile and tile:getHouse() - end - end - - if house and player:getTile():getHouse() ~= house and player:getAccountType() < ACCOUNT_TYPE_GAMEMASTER then - return false - end - - item:transform(window) - return true -end diff --git a/path_10_8/data/actions/scripts/quests/annihilator.lua b/path_10_8/data/actions/scripts/quests/annihilator.lua deleted file mode 100644 index 70066e1dd..000000000 --- a/path_10_8/data/actions/scripts/quests/annihilator.lua +++ /dev/null @@ -1,36 +0,0 @@ -local playerPosition = { - {x = 247, y = 659, z = 13}, - {x = 247, y = 660, z = 13}, - {x = 247, y = 661, z = 13}, - {x = 247, y = 662, z = 13} -} -local newPosition = { - {x = 189, y = 650, z = 13}, - {x = 189, y = 651, z = 13}, - {x = 189, y = 652, z = 13}, - {x = 189, y = 653, z = 13} -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item.itemid == 1945 then - local players = {} - for _, position in ipairs(playerPosition) do - local topPlayer = Tile(position):getTopCreature() - if topPlayer == nil or not topPlayer:isPlayer() or topPlayer:getLevel() < 100 or topPlayer:getStorageValue(30015) ~= -1 then - player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_NOTPOSSIBLE)) - return false - end - players[#players + 1] = topPlayer - end - - for i, targetPlayer in ipairs(players) do - Position(playerPosition[i]):sendMagicEffect(CONST_ME_POFF) - targetPlayer:teleportTo(newPosition[i], false) - targetPlayer:getPosition():sendMagicEffect(CONST_ME_ENERGYAREA) - end - item:transform(1946) - elseif item.itemid == 1946 then - player:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_NOTPOSSIBLE)) - end - return true -end diff --git a/path_10_8/data/actions/scripts/quests/quests.lua b/path_10_8/data/actions/scripts/quests/quests.lua deleted file mode 100644 index 60f294b36..000000000 --- a/path_10_8/data/actions/scripts/quests/quests.lua +++ /dev/null @@ -1,38 +0,0 @@ -local annihilatorReward = {1990, 2400, 2431, 2494} -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item.uid <= 1000 or item.uid > 22700 then - return false - end - - local itemType = ItemType(item.itemid) - local itemWeight = itemType:getWeight() - local playerCap = player:getFreeCapacity() - if isInArray(annihilatorReward, item.uid) then - if player:getStorageValue(30015) == -1 then - if playerCap >= itemWeight then - if item.uid == 1990 then - player:addItem(1990, 1):addItem(2326, 1) - else - player:addItem(item.uid, 1) - end - player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.') - player:setStorageValue(30015, 1) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' .. itemWeight .. ' oz it\'s too heavy.') - end - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.") - end - elseif player:getStorageValue(item.uid) == -1 then - if playerCap >= itemWeight then - player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. '.') - player:addItem(item.uid, 1) - player:setStorageValue(item.uid, 1) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have found a ' .. itemType:getName() .. ' weighing ' .. itemWeight .. ' oz it\'s too heavy.') - end - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "It is empty.") - end - return true -end diff --git a/path_10_8/data/actions/scripts/tools/fishing.lua b/path_10_8/data/actions/scripts/tools/fishing.lua deleted file mode 100644 index d50d11631..000000000 --- a/path_10_8/data/actions/scripts/tools/fishing.lua +++ /dev/null @@ -1,78 +0,0 @@ -local waterIds = {493, 4608, 4609, 4610, 4611, 4612, 4613, 4614, 4615, 4616, 4617, 4618, 4619, 4620, 4621, 4622, 4623, 4624, 4625, 7236, 10499, 15401, 15402} -local lootTrash = {2234, 2238, 2376, 2509, 2667} -local lootCommon = {2152, 2167, 2168, 2669, 7588, 7589} -local lootRare = {2143, 2146, 2149, 7158, 7159} -local lootVeryRare = {7632, 7633, 10220} -local useWorms = true - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local targetId = target.itemid - if not isInArray(waterIds, target.itemid) then - return false - end - - if targetId == 10499 then - local owner = target:getAttribute(ITEM_ATTRIBUTE_CORPSEOWNER) - if owner ~= 0 and owner ~= player:getId() then - player:sendTextMessage(MESSAGE_STATUS_SMALL, "You are not the owner.") - return true - end - - toPosition:sendMagicEffect(CONST_ME_WATERSPLASH) - target:remove() - - local rareChance = math.random(1, 100) - if rareChance == 1 then - player:addItem(lootVeryRare[math.random(#lootVeryRare)], 1) - elseif rareChance <= 3 then - player:addItem(lootRare[math.random(#lootRare)], 1) - elseif rareChance <= 10 then - player:addItem(lootCommon[math.random(#lootCommon)], 1) - else - player:addItem(lootTrash[math.random(#lootTrash)], 1) - end - return true - end - - if targetId ~= 7236 then - toPosition:sendMagicEffect(CONST_ME_LOSEENERGY) - end - - if targetId == 493 or targetId == 15402 then - return true - end - - player:addSkillTries(SKILL_FISHING, 1) - if math.random(1, 100) <= math.min(math.max(10 + (player:getEffectiveSkillLevel(SKILL_FISHING) - 10) * 0.597, 10), 50) then - if useWorms and not player:removeItem("worm", 1) then - return true - end - - if targetId == 15401 then - target:transform(targetId + 1) - target:decay() - - if math.random(1, 100) >= 97 then - player:addItem(15405, 1) - return true - end - elseif targetId == 7236 then - target:transform(targetId + 1) - target:decay() - - local rareChance = math.random(1, 100) - if rareChance == 1 then - player:addItem(7158, 1) - return true - elseif rareChance <= 4 then - player:addItem(2669, 1) - return true - elseif rareChance <= 10 then - player:addItem(7159, 1) - return true - end - end - player:addItem("fish", 1) - end - return true -end diff --git a/path_10_8/data/actions/scripts/tools/machete.lua b/path_10_8/data/actions/scripts/tools/machete.lua deleted file mode 100644 index daf0ed3da..000000000 --- a/path_10_8/data/actions/scripts/tools/machete.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if target.itemid == 2782 then - target:transform(2781) - target:decay() - return true - end - return destroyItem(player, target, toPosition) -end diff --git a/path_10_8/data/actions/scripts/tools/pick.lua b/path_10_8/data/actions/scripts/tools/pick.lua deleted file mode 100644 index 7ef688b5f..000000000 --- a/path_10_8/data/actions/scripts/tools/pick.lua +++ /dev/null @@ -1,9 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if (target.uid <= 65535 or target.actionid > 0) and (target.itemid == 354 or target.itemid == 355) then - target:transform(392) - target:decay() - toPosition:sendMagicEffect(CONST_ME_POFF) - return true - end - return false -end diff --git a/path_10_8/data/actions/scripts/tools/rope.lua b/path_10_8/data/actions/scripts/tools/rope.lua deleted file mode 100644 index 09177e895..000000000 --- a/path_10_8/data/actions/scripts/tools/rope.lua +++ /dev/null @@ -1,26 +0,0 @@ -local holeId = { - 294, 369, 370, 383, 392, 408, 409, 410, 427, 428, 430, 462, 469, 470, 482, - 484, 485, 489, 924, 3135, 3136, 7933, 7938, 8170, 8286, 8285, 8284, 8281, - 8280, 8279, 8277, 8276, 8323, 8567, 8585, 8596, 8595, 8249, 8250, 8251, - 8252, 8253, 8254, 8255, 8256, 8972, 9606, 9625, 13190, 14461, 19519, 21536 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local tile = Tile(toPosition) - if isInArray(ropeSpots, tile:getGround():getId()) or tile:getItemById(14435) then - player:teleportTo(toPosition:moveUpstairs(), false) - return true - elseif isInArray(holeId, target.itemid) then - toPosition.z = toPosition.z + 1 - tile = Tile(toPosition) - if tile then - local thing = tile:getTopVisibleThing() - if thing:isItem() and thing:getType():isMovable() then - return thing:moveTo(toPosition:moveUpstairs()) - end - end - player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - return true - end - return false -end diff --git a/path_10_8/data/actions/scripts/tools/scythe.lua b/path_10_8/data/actions/scripts/tools/scythe.lua deleted file mode 100644 index 3d2f7c18f..000000000 --- a/path_10_8/data/actions/scripts/tools/scythe.lua +++ /dev/null @@ -1,9 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if target.itemid == 2739 then - target:transform(2737) - target:decay() - Game.createItem(2694, 1, toPosition) - return true - end - return destroyItem(player, target, toPosition) -end diff --git a/path_10_8/data/actions/scripts/tools/shovel.lua b/path_10_8/data/actions/scripts/tools/shovel.lua deleted file mode 100644 index 3bacc66d8..000000000 --- a/path_10_8/data/actions/scripts/tools/shovel.lua +++ /dev/null @@ -1,37 +0,0 @@ -local holes = {468, 481, 483} -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if toPosition.x == CONTAINER_POSITION then - return false - end - - local tile = Tile(toPosition) - if not tile then - return false - end - - local ground = tile:getGround() - if not ground then - return false - end - - local groundId = ground:getId() - if isInArray(holes, groundId) then - ground:transform(groundId + 1) - ground:decay() - - toPosition.z = toPosition.z + 1 - tile:relocateTo(toPosition) - elseif groundId == 231 then - local randomValue = math.random(1, 100) - if randomValue == 1 then - Game.createItem(2159, 1, toPosition) - elseif randomValue > 95 then - Game.createMonster("Scarab", toPosition) - end - toPosition:sendMagicEffect(CONST_ME_POFF) - else - return false - end - - return true -end diff --git a/path_10_8/data/chatchannels/chatchannels.xml b/path_10_8/data/chatchannels/chatchannels.xml deleted file mode 100644 index dc7922473..000000000 --- a/path_10_8/data/chatchannels/chatchannels.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_10_8/data/chatchannels/scripts/advertising-rook.lua b/path_10_8/data/chatchannels/scripts/advertising-rook.lua deleted file mode 100644 index 6c92b4ef8..000000000 --- a/path_10_8/data/chatchannels/scripts/advertising-rook.lua +++ /dev/null @@ -1,40 +0,0 @@ -function canJoin(player) - return player:getVocation():getId() == VOCATION_NONE or player:getAccountType() >= ACCOUNT_TYPE_SENIORTUTOR -end - -local CHANNEL_ADVERTISING_ROOK = 6 - -local muted = Condition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT) -muted:setParameter(CONDITION_PARAM_SUBID, CHANNEL_ADVERTISING_ROOK) -muted:setParameter(CONDITION_PARAM_TICKS, 120000) - -function onSpeak(player, type, message) - if player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then - if type == TALKTYPE_CHANNEL_Y then - return TALKTYPE_CHANNEL_O - end - return true - end - - if player:getLevel() == 1 then - player:sendCancelMessage("You may not speak into channels as long as you are on level 1.") - return false - end - - if player:getCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_ADVERTISING_ROOK) then - player:sendCancelMessage("You may only place one offer in two minutes.") - return false - end - player:addCondition(muted) - - if type == TALKTYPE_CHANNEL_O then - if player:getAccountType() < ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/advertising.lua b/path_10_8/data/chatchannels/scripts/advertising.lua deleted file mode 100644 index 0f90e3340..000000000 --- a/path_10_8/data/chatchannels/scripts/advertising.lua +++ /dev/null @@ -1,40 +0,0 @@ -function canJoin(player) - return player:getVocation():getId() ~= VOCATION_NONE or player:getAccountType() >= ACCOUNT_TYPE_SENIORTUTOR -end - -local CHANNEL_ADVERTISING = 5 - -local muted = Condition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT) -muted:setParameter(CONDITION_PARAM_SUBID, CHANNEL_ADVERTISING) -muted:setParameter(CONDITION_PARAM_TICKS, 120000) - -function onSpeak(player, type, message) - if player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER then - if type == TALKTYPE_CHANNEL_Y then - return TALKTYPE_CHANNEL_O - end - return true - end - - if player:getLevel() == 1 then - player:sendCancelMessage("You may not speak into channels as long as you are on level 1.") - return false - end - - if player:getCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_ADVERTISING) then - player:sendCancelMessage("You may only place one offer in two minutes.") - return false - end - player:addCondition(muted) - - if type == TALKTYPE_CHANNEL_O then - if player:getAccountType() < ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/englishchat.lua b/path_10_8/data/chatchannels/scripts/englishchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_10_8/data/chatchannels/scripts/englishchat.lua +++ /dev/null @@ -1,22 +0,0 @@ -function onSpeak(player, type, message) - local playerAccountType = player:getAccountType() - if player:getLevel() == 1 and playerAccountType < ACCOUNT_TYPE_GAMEMASTER then - player:sendCancelMessage("You may not speak into channels as long as you are on level 1.") - return false - end - - if type == TALKTYPE_CHANNEL_Y then - if playerAccountType >= ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_O - end - elseif type == TALKTYPE_CHANNEL_O then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER and not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/gamemaster.lua b/path_10_8/data/chatchannels/scripts/gamemaster.lua deleted file mode 100644 index b3050cc53..000000000 --- a/path_10_8/data/chatchannels/scripts/gamemaster.lua +++ /dev/null @@ -1,21 +0,0 @@ -function canJoin(player) - return player:getAccountType() >= ACCOUNT_TYPE_GAMEMASTER -end - -function onSpeak(player, type, message) - local playerAccountType = player:getAccountType() - if type == TALKTYPE_CHANNEL_Y then - if playerAccountType == ACCOUNT_TYPE_GOD then - type = TALKTYPE_CHANNEL_O - end - elseif type == TALKTYPE_CHANNEL_O then - if playerAccountType ~= ACCOUNT_TYPE_GOD then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if playerAccountType ~= ACCOUNT_TYPE_GOD and not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/help.lua b/path_10_8/data/chatchannels/scripts/help.lua deleted file mode 100644 index 54e7de61e..000000000 --- a/path_10_8/data/chatchannels/scripts/help.lua +++ /dev/null @@ -1,77 +0,0 @@ -local CHANNEL_HELP = 7 - -local muted = Condition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT) -muted:setParameter(CONDITION_PARAM_SUBID, CHANNEL_HELP) -muted:setParameter(CONDITION_PARAM_TICKS, 3600000) - -function onSpeak(player, type, message) - local playerAccountType = player:getAccountType() - if player:getLevel() == 1 and playerAccountType == ACCOUNT_TYPE_NORMAL then - player:sendCancelMessage("You may not speak into channels as long as you are on level 1.") - return false - end - - if player:getCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_HELP) then - player:sendCancelMessage("You are muted from the Help channel for using it inappropriately.") - return false - end - - if playerAccountType >= ACCOUNT_TYPE_TUTOR then - if string.sub(message, 1, 6) == "!mute " then - local targetName = string.sub(message, 7) - local target = Player(targetName) - if target ~= nil then - if playerAccountType > target:getAccountType() then - if not target:getCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_HELP) then - target:addCondition(muted) - sendChannelMessage(CHANNEL_HELP, TALKTYPE_CHANNEL_R1, target:getName() .. " has been muted by " .. player:getName() .. " for using Help Channel inappropriately.") - else - player:sendCancelMessage("That player is already muted.") - end - else - player:sendCancelMessage("You are not authorized to mute that player.") - end - else - player:sendCancelMessage(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE) - end - return false - elseif string.sub(message, 1, 8) == "!unmute " then - local targetName = string.sub(message, 9) - local target = Player(targetName) - if target ~= nil then - if playerAccountType > target:getAccountType() then - if target:getCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_HELP) then - target:removeCondition(CONDITION_CHANNELMUTEDTICKS, CONDITIONID_DEFAULT, CHANNEL_HELP) - sendChannelMessage(CHANNEL_HELP, TALKTYPE_CHANNEL_R1, target:getName() .. " has been unmuted by " .. player:getName() .. ".") - else - player:sendCancelMessage("That player is not muted.") - end - else - player:sendCancelMessage("You are not authorized to unmute that player.") - end - else - player:sendCancelMessage(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE) - end - return false - end - end - - if type == TALKTYPE_CHANNEL_Y then - if playerAccountType >= ACCOUNT_TYPE_TUTOR or getPlayerFlagValue(player, PlayerFlag_TalkOrangeHelpChannel) then - type = TALKTYPE_CHANNEL_O - end - elseif type == TALKTYPE_CHANNEL_O then - if playerAccountType < ACCOUNT_TYPE_TUTOR and not getPlayerFlagValue(player, PlayerFlag_TalkOrangeHelpChannel) then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER and not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - if playerAccountType >= ACCOUNT_TYPE_TUTOR or getPlayerFlagValue(player, PlayerFlag_TalkOrangeHelpChannel) then - type = TALKTYPE_CHANNEL_O - else - type = TALKTYPE_CHANNEL_Y - end - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/tutor.lua b/path_10_8/data/chatchannels/scripts/tutor.lua deleted file mode 100644 index 8db26a8ba..000000000 --- a/path_10_8/data/chatchannels/scripts/tutor.lua +++ /dev/null @@ -1,21 +0,0 @@ -function canJoin(player) - return player:getAccountType() >= ACCOUNT_TYPE_TUTOR -end - -function onSpeak(player, type, message) - local playerAccountType = player:getAccountType() - if type == TALKTYPE_CHANNEL_Y then - if playerAccountType >= ACCOUNT_TYPE_SENIORTUTOR then - type = TALKTYPE_CHANNEL_O - end - elseif type == TALKTYPE_CHANNEL_O then - if playerAccountType < ACCOUNT_TYPE_SENIORTUTOR then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER and not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/chatchannels/scripts/worldchat.lua b/path_10_8/data/chatchannels/scripts/worldchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_10_8/data/chatchannels/scripts/worldchat.lua +++ /dev/null @@ -1,22 +0,0 @@ -function onSpeak(player, type, message) - local playerAccountType = player:getAccountType() - if player:getLevel() == 1 and playerAccountType < ACCOUNT_TYPE_GAMEMASTER then - player:sendCancelMessage("You may not speak into channels as long as you are on level 1.") - return false - end - - if type == TALKTYPE_CHANNEL_Y then - if playerAccountType >= ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_O - end - elseif type == TALKTYPE_CHANNEL_O then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER then - type = TALKTYPE_CHANNEL_Y - end - elseif type == TALKTYPE_CHANNEL_R1 then - if playerAccountType < ACCOUNT_TYPE_GAMEMASTER and not getPlayerFlagValue(player, PlayerFlag_CanTalkRedChannel) then - type = TALKTYPE_CHANNEL_Y - end - end - return type -end diff --git a/path_10_8/data/creaturescripts/creaturescripts.xml b/path_10_8/data/creaturescripts/creaturescripts.xml deleted file mode 100644 index 86e2c8c3a..000000000 --- a/path_10_8/data/creaturescripts/creaturescripts.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/path_10_8/data/creaturescripts/lib/creaturescripts.lua b/path_10_8/data/creaturescripts/lib/creaturescripts.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_10_8/data/creaturescripts/lib/creaturescripts.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_10_8/data/creaturescripts/scripts/droploot.lua b/path_10_8/data/creaturescripts/scripts/droploot.lua deleted file mode 100644 index 0ed33e259..000000000 --- a/path_10_8/data/creaturescripts/scripts/droploot.lua +++ /dev/null @@ -1,40 +0,0 @@ -function onDeath(player, corpse, killer, mostDamage, unjustified, mostDamage_unjustified) - if getPlayerFlagValue(player, PlayerFlag_NotGenerateLoot) or player:getVocation():getId() == VOCATION_NONE then - return true - end - - local amulet = player:getSlotItem(CONST_SLOT_NECKLACE) - if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not isInArray({SKULL_RED, SKULL_BLACK}, player:getSkull()) then - local isPlayer = false - if killer then - if killer:isPlayer() then - isPlayer = true - else - local master = killer:getMaster() - if master and master:isPlayer() then - isPlayer = true - end - end - end - - if not isPlayer or not player:hasBlessing(6) then - player:removeItem(ITEM_AMULETOFLOSS, 1, -1, false) - end - else - for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do - local item = player:getSlotItem(i) - if item then - if isInArray({SKULL_RED, SKULL_BLACK}, player:getSkull()) or math.random(item:isContainer() and 100 or 1000) <= player:getLossPercent() then - if not item:moveTo(corpse) then - item:remove() - end - end - end - end - end - - if not player:getSlotItem(CONST_SLOT_BACKPACK) then - player:addItem(ITEM_BAG, 1, false, CONST_SLOT_BACKPACK) - end - return true -end diff --git a/path_10_8/data/creaturescripts/scripts/extendedopcode.lua b/path_10_8/data/creaturescripts/scripts/extendedopcode.lua deleted file mode 100644 index 7fa2d42e6..000000000 --- a/path_10_8/data/creaturescripts/scripts/extendedopcode.lua +++ /dev/null @@ -1,13 +0,0 @@ -local OPCODE_LANGUAGE = 1 - -function onExtendedOpcode(player, opcode, buffer) - if opcode == OPCODE_LANGUAGE then - -- otclient language - if buffer == 'en' or buffer == 'pt' then - -- example, setting player language, because otclient is multi-language... - -- player:setStorageValue(SOME_STORAGE_ID, SOME_VALUE) - end - else - -- other opcodes can be ignored, and the server will just work fine... - end -end diff --git a/path_10_8/data/creaturescripts/scripts/firstitems.lua b/path_10_8/data/creaturescripts/scripts/firstitems.lua deleted file mode 100644 index 9530f4657..000000000 --- a/path_10_8/data/creaturescripts/scripts/firstitems.lua +++ /dev/null @@ -1,12 +0,0 @@ -local firstItems = {2050, 2382} - -function onLogin(player) - if player:getLastLoginSaved() == 0 then - for i = 1, #firstItems do - player:addItem(firstItems[i], 1) - end - player:addItem(player:getSex() == 0 and 2651 or 2650, 1) - player:addItem(1987, 1):addItem(2674, 1) - end - return true -end diff --git a/path_10_8/data/creaturescripts/scripts/login.lua b/path_10_8/data/creaturescripts/scripts/login.lua deleted file mode 100644 index 6c414c1bb..000000000 --- a/path_10_8/data/creaturescripts/scripts/login.lua +++ /dev/null @@ -1,36 +0,0 @@ -function onLogin(player) - local loginStr = "Welcome to " .. configManager.getString(configKeys.SERVER_NAME) .. "!" - if player:getLastLoginSaved() <= 0 then - loginStr = loginStr .. " Please choose your outfit." - player:sendOutfitWindow() - else - if loginStr ~= "" then - player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr) - end - - loginStr = string.format("Your last visit was on %s.", os.date("%a %b %d %X %Y", player:getLastLoginSaved())) - end - player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr) - - -- Stamina - nextUseStaminaTime[player.uid] = 0 - - -- Promotion - local vocation = player:getVocation() - local promotion = vocation:getPromotion() - if player:isPremium() then - local value = player:getStorageValue(STORAGEVALUE_PROMOTION) - if not promotion and value ~= 1 then - player:setStorageValue(STORAGEVALUE_PROMOTION, 1) - elseif value == 1 then - player:setVocation(promotion) - end - elseif not promotion then - player:setVocation(vocation:getDemotion()) - end - - -- Events - player:registerEvent("PlayerDeath") - player:registerEvent("DropLoot") - return true -end diff --git a/path_10_8/data/creaturescripts/scripts/logout.lua b/path_10_8/data/creaturescripts/scripts/logout.lua deleted file mode 100644 index 5a5bfe4eb..000000000 --- a/path_10_8/data/creaturescripts/scripts/logout.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onLogout(player) - local playerId = player:getId() - if nextUseStaminaTime[playerId] ~= nil then - nextUseStaminaTime[playerId] = nil - end - return true -end diff --git a/path_10_8/data/creaturescripts/scripts/offlinetraining.lua b/path_10_8/data/creaturescripts/scripts/offlinetraining.lua deleted file mode 100644 index 98e37aeae..000000000 --- a/path_10_8/data/creaturescripts/scripts/offlinetraining.lua +++ /dev/null @@ -1,75 +0,0 @@ -function onLogin(player) - local lastLogout = player:getLastLogout() - local offlineTime = lastLogout ~= 0 and math.min(os.time() - lastLogout, 86400 * 21) or 0 - local offlineTrainingSkill = player:getOfflineTrainingSkill() - if offlineTrainingSkill == -1 then - player:addOfflineTrainingTime(offlineTime * 1000) - return true - end - - player:setOfflineTrainingSkill(-1) - - if offlineTime < 600 then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You must be logged out for more than 10 minutes to start offline training.") - return true - end - - local trainingTime = math.max(0, math.min(offlineTime, math.min(43200, player:getOfflineTrainingTime() / 1000))) - player:removeOfflineTrainingTime(trainingTime * 1000) - - local remainder = offlineTime - trainingTime - if remainder > 0 then - player:addOfflineTrainingTime(remainder * 1000) - end - - if trainingTime < 60 then - return true - end - - local text = "During your absence you trained for" - local hours = math.floor(trainingTime / 3600) - if hours > 1 then - text = string.format("%s %d hours", text, hours) - elseif hours == 1 then - text = string.format("%s 1 hour", text) - end - - local minutes = math.floor((trainingTime % 3600) / 60) - if minutes ~= 0 then - if hours ~= 0 then - text = string.format("%s and", text) - end - - if minutes > 1 then - text = string.format("%s %d minutes", text, minutes) - else - text = string.format("%s 1 minute", text) - end - end - - text = string.format("%s.", text) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, text) - - local vocation = player:getVocation() - local promotion = vocation:getPromotion() - local topVocation = not promotion and vocation or promotion - - local updateSkills = false - if isInArray({SKILL_CLUB, SKILL_SWORD, SKILL_AXE, SKILL_DISTANCE}, offlineTrainingSkill) then - local modifier = topVocation:getAttackSpeed() / 1000 - updateSkills = player:addOfflineTrainingTries(offlineTrainingSkill, (trainingTime / modifier) / (offlineTrainingSkill == SKILL_DISTANCE and 4 or 2)) - elseif offlineTrainingSkill == SKILL_MAGLEVEL then - local gainTicks = topVocation:getManaGainTicks() * 2 - if gainTicks == 0 then - gainTicks = 1 - end - - updateSkills = player:addOfflineTrainingTries(SKILL_MAGLEVEL, trainingTime * (vocation:getManaGainAmount() / gainTicks)) - end - - if updateSkills then - player:addOfflineTrainingTries(SKILL_SHIELD, trainingTime / 4) - end - - return true -end diff --git a/path_10_8/data/creaturescripts/scripts/playerdeath.lua b/path_10_8/data/creaturescripts/scripts/playerdeath.lua deleted file mode 100644 index 159dbc720..000000000 --- a/path_10_8/data/creaturescripts/scripts/playerdeath.lua +++ /dev/null @@ -1,89 +0,0 @@ -local deathListEnabled = true -local maxDeathRecords = 5 - -function onDeath(player, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified) - local playerId = player:getId() - if nextUseStaminaTime[playerId] ~= nil then - nextUseStaminaTime[playerId] = nil - end - - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You are dead.") - if not deathListEnabled then - return - end - - local byPlayer = 0 - local killerName - if killer ~= nil then - if killer:isPlayer() then - byPlayer = 1 - else - local master = killer:getMaster() - if master and master ~= killer and master:isPlayer() then - killer = master - byPlayer = 1 - end - end - killerName = killer:getName() - else - killerName = "field item" - end - - local byPlayerMostDamage = 0 - local mostDamageKillerName - if mostDamageKiller ~= nil then - if mostDamageKiller:isPlayer() then - byPlayerMostDamage = 1 - else - local master = mostDamageKiller:getMaster() - if master and master ~= mostDamageKiller and master:isPlayer() then - mostDamageKiller = master - byPlayerMostDamage = 1 - end - end - mostDamageName = mostDamageKiller:getName() - else - mostDamageName = "field item" - end - - local playerGuid = player:getGuid() - db.query("INSERT INTO `player_deaths` (`player_id`, `time`, `level`, `killed_by`, `is_player`, `mostdamage_by`, `mostdamage_is_player`, `unjustified`, `mostdamage_unjustified`) VALUES (" .. playerGuid .. ", " .. os.time() .. ", " .. player:getLevel() .. ", " .. db.escapeString(killerName) .. ", " .. byPlayer .. ", " .. db.escapeString(mostDamageName) .. ", " .. byPlayerMostDamage .. ", " .. (unjustified and 1 or 0) .. ", " .. (mostDamageUnjustified and 1 or 0) .. ")") - local resultId = db.storeQuery("SELECT `player_id` FROM `player_deaths` WHERE `player_id` = " .. playerGuid) - - local deathRecords = 0 - local tmpResultId = resultId - while tmpResultId ~= false do - tmpResultId = result.next(resultId) - deathRecords = deathRecords + 1 - end - - if resultId ~= false then - result.free(resultId) - end - - local limit = deathRecords - maxDeathRecords - if limit > 0 then - db.asyncQuery("DELETE FROM `player_deaths` WHERE `player_id` = " .. playerGuid .. " ORDER BY `time` LIMIT " .. limit) - end - - if byPlayer == 1 then - local targetGuild = player:getGuild() - targetGuild = targetGuild and targetGuild:getId() or 0 - if targetGuild ~= 0 then - local killerGuild = killer:getGuild() - killerGuild = killerGuild and killerGuild:getId() or 0 - if killerGuild ~= 0 and targetGuild ~= killerGuild and isInWar(playerId, killer:getId()) then - local warId = false - resultId = db.storeQuery("SELECT `id` FROM `guild_wars` WHERE `status` = 1 AND ((`guild1` = " .. killerGuild .. " AND `guild2` = " .. targetGuild .. ") OR (`guild1` = " .. targetGuild .. " AND `guild2` = " .. killerGuild .. "))") - if resultId ~= false then - warId = result.getDataInt(resultId, "id") - result.free(resultId) - end - - if warId ~= false then - db.asyncQuery("INSERT INTO `guildwar_kills` (`killer`, `target`, `killerguild`, `targetguild`, `time`, `warid`) VALUES (" .. db.escapeString(killerName) .. ", " .. db.escapeString(player:getName()) .. ", " .. killerGuild .. ", " .. targetGuild .. ", " .. os.time() .. ", " .. warId .. ")") - end - end - end - end -end diff --git a/path_10_8/data/creaturescripts/scripts/regeneratestamina.lua b/path_10_8/data/creaturescripts/scripts/regeneratestamina.lua deleted file mode 100644 index 04409058b..000000000 --- a/path_10_8/data/creaturescripts/scripts/regeneratestamina.lua +++ /dev/null @@ -1,27 +0,0 @@ -function onLogin(player) - if not configManager.getBoolean(configKeys.STAMINA_SYSTEM) then - return true - end - - local lastLogout = player:getLastLogout() - local offlineTime = lastLogout ~= 0 and math.min(os.time() - lastLogout, 86400 * 21) or 0 - offlineTime = offlineTime - 600 - - if offlineTime < 180 then - return true - end - - local staminaMinutes = player:getStamina() - local maxNormalStaminaRegen = 2400 - math.min(2400, staminaMinutes) - - local regainStaminaMinutes = offlineTime / 180 - if regainStaminaMinutes > maxNormalStaminaRegen then - local happyHourStaminaRegen = (offlineTime - (maxNormalStaminaRegen * 180)) / 600 - staminaMinutes = math.min(2520, math.max(2400, staminaMinutes) + happyHourStaminaRegen) - else - staminaMinutes = staminaMinutes + regainStaminaMinutes - end - - player:setStamina(staminaMinutes) - return true -end diff --git a/path_10_8/data/events/events.xml b/path_10_8/data/events/events.xml deleted file mode 100644 index 66dbfcc2d..000000000 --- a/path_10_8/data/events/events.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/events/scripts/creature.lua b/path_10_8/data/events/scripts/creature.lua deleted file mode 100644 index 17116ec37..000000000 --- a/path_10_8/data/events/scripts/creature.lua +++ /dev/null @@ -1,11 +0,0 @@ -function Creature:onChangeOutfit(outfit) - return true -end - -function Creature:onAreaCombat(tile, isAggressive) - return true -end - -function Creature:onTargetCombat(target) - return true -end diff --git a/path_10_8/data/events/scripts/monster.lua b/path_10_8/data/events/scripts/monster.lua deleted file mode 100644 index 5afd8d131..000000000 --- a/path_10_8/data/events/scripts/monster.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Monster:onSpawn(position, isStartup) - return true -end diff --git a/path_10_8/data/events/scripts/party.lua b/path_10_8/data/events/scripts/party.lua deleted file mode 100644 index bbb4cfa29..000000000 --- a/path_10_8/data/events/scripts/party.lua +++ /dev/null @@ -1,11 +0,0 @@ -function Party:onJoin(player) - return true -end - -function Party:onLeave(player) - return true -end - -function Party:onDisband() - return true -end diff --git a/path_10_8/data/events/scripts/player.lua b/path_10_8/data/events/scripts/player.lua deleted file mode 100644 index a2cf445e2..000000000 --- a/path_10_8/data/events/scripts/player.lua +++ /dev/null @@ -1,186 +0,0 @@ -function Player:onBrowseField(position) - return true -end - -function Player:onLook(thing, position, distance) - local description = "You see " .. thing:getDescription(distance) - if self:getGroup():getAccess() then - if thing:isItem() then - description = string.format("%s\nItem ID: %d", description, thing:getId()) - - local actionId = thing:getActionId() - if actionId ~= 0 then - description = string.format("%s, Action ID: %d", description, actionId) - end - - local uniqueId = thing:getAttribute(ITEM_ATTRIBUTE_UNIQUEID) - if uniqueId > 0 and uniqueId < 65536 then - description = string.format("%s, Unique ID: %d", description, uniqueId) - end - - local itemType = thing:getType() - - local transformEquipId = itemType:getTransformEquipId() - local transformDeEquipId = itemType:getTransformDeEquipId() - if transformEquipId ~= 0 then - description = string.format("%s\nTransforms to: %d (onEquip)", description, transformEquipId) - elseif transformDeEquipId ~= 0 then - description = string.format("%s\nTransforms to: %d (onDeEquip)", description, transformDeEquipId) - end - - local decayId = itemType:getDecayId() - if decayId ~= -1 then - description = string.format("%s\nDecays to: %d", description, decayId) - end - elseif thing:isCreature() then - local str = "%s\nHealth: %d / %d" - if thing:getMaxMana() > 0 then - str = string.format("%s, Mana: %d / %d", str, thing:getMana(), thing:getMaxMana()) - end - description = string.format(str, description, thing:getHealth(), thing:getMaxHealth()) .. "." - end - - local position = thing:getPosition() - description = string.format( - "%s\nPosition: %d, %d, %d", - description, position.x, position.y, position.z - ) - - if thing:isCreature() then - if thing:isPlayer() then - description = string.format("%s\nIP: %s.", description, Game.convertIpToString(thing:getIp())) - end - end - end - self:sendTextMessage(MESSAGE_INFO_DESCR, description) -end - -function Player:onLookInBattleList(creature, distance) - local description = "You see " .. creature:getDescription(distance) - if self:getGroup():getAccess() then - local str = "%s\nHealth: %d / %d" - if creature:getMaxMana() > 0 then - str = string.format("%s, Mana: %d / %d", str, creature:getMana(), creature:getMaxMana()) - end - description = string.format(str, description, creature:getHealth(), creature:getMaxHealth()) .. "." - - local position = creature:getPosition() - description = string.format( - "%s\nPosition: %d, %d, %d", - description, position.x, position.y, position.z - ) - - if creature:isPlayer() then - description = string.format("%s\nIP: %s", description, Game.convertIpToString(creature:getIp())) - end - end - self:sendTextMessage(MESSAGE_INFO_DESCR, description) -end - -function Player:onLookInTrade(partner, item, distance) - self:sendTextMessage(MESSAGE_INFO_DESCR, "You see " .. item:getDescription(distance)) -end - -function Player:onLookInShop(itemType, count) - return true -end - -function Player:onMoveItem(item, count, fromPosition, toPosition) - return true -end - -function Player:onMoveCreature(creature, fromPosition, toPosition) - return true -end - -function Player:onTurn(direction) - return true -end - -function Player:onTradeRequest(target, item) - return true -end - -function Player:onTradeAccept(target, item, targetItem) - return true -end - -local soulCondition = Condition(CONDITION_SOUL, CONDITIONID_DEFAULT) -soulCondition:setTicks(4 * 60 * 1000) -soulCondition:setParameter(CONDITION_PARAM_SOULGAIN, 1) - -local function useStamina(player) - local staminaMinutes = player:getStamina() - if staminaMinutes == 0 then - return - end - - local playerId = player:getId() - local currentTime = os.time() - local timePassed = currentTime - nextUseStaminaTime[playerId] - if timePassed <= 0 then - return - end - - if timePassed > 60 then - if staminaMinutes > 2 then - staminaMinutes = staminaMinutes - 2 - else - staminaMinutes = 0 - end - nextUseStaminaTime[playerId] = currentTime + 120 - else - staminaMinutes = staminaMinutes - 1 - nextUseStaminaTime[playerId] = currentTime + 60 - end - player:setStamina(staminaMinutes) -end - -function Player:onGainExperience(source, exp, rawExp) - if not source or source:isPlayer() then - return exp - end - - -- Soul regeneration - local vocation = self:getVocation() - if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then - soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000) - self:addCondition(soulCondition) - end - - -- Apply experience stage multiplier - exp = exp * Game.getExperienceStage(self:getLevel()) - - -- Stamina modifier - if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then - useStamina(self) - - local staminaMinutes = self:getStamina() - if staminaMinutes > 2400 and self:isPremium() then - exp = exp * 1.5 - elseif staminaMinutes <= 840 then - exp = exp * 0.5 - end - end - - return exp -end - -function Player:onLoseExperience(exp) - return exp -end - -function Player:onGainSkillTries(skill, tries) - if APPLY_SKILL_MULTIPLIER == false then - return tries - end - - if skill == SKILL_MAGLEVEL then - return tries * configManager.getNumber(configKeys.RATE_MAGIC) - end - return tries * configManager.getNumber(configKeys.RATE_SKILL) -end - -function Player:onSave(GUID) - return true -end diff --git a/path_10_8/data/global.lua b/path_10_8/data/global.lua deleted file mode 100644 index 5ec76e514..000000000 --- a/path_10_8/data/global.lua +++ /dev/null @@ -1,54 +0,0 @@ -dofile('data/lib/lib.lua') - -ddos = {}; -ddos.enabled = false; -ddos.broadcasted = false - -STORAGEVALUE_PROMOTION = 30018 - -ropeSpots = {384, 418, 8278, 8592, 13189, 14435, 14436, 15635, 19518} - -doors = {[1209] = 1211, [1210] = 1211, [1212] = 1214, [1213] = 1214, [1219] = 1220, [1221] = 1222, [1231] = 1233, [1232] = 1233, [1234] = 1236, [1235] = 1236, [1237] = 1238, [1239] = 1240, [1249] = 1251, [1250] = 1251, [1252] = 1254, [1253] = 1254, [1539] = 1540, [1541] = 1542, [3535] = 3537, [3536] = 3537, [3538] = 3539, [3544] = 3546, [3545] = 3546, [3547] = 3548, [4913] = 4915, [4914] = 4915, [4916] = 4918, [4917] = 4918, [5082] = 5083, [5084] = 5085, [5098] = 5100, [5099] = 5100, [5101] = 5102, [5107] = 5109, [5108] = 5109, [5110] = 5111, [5116] = 5118, [5117] = 5118, [5119] = 5120, [5125] = 5127, [5126] = 5127, [5128] = 5129, [5134] = 5136, [5135] = 5136, [5137] = 5139, [5138] = 5139, [5140] = 5142, [5141] = 5142, [5143] = 5145, [5144] = 5145, [5278] = 5280, [5279] = 5280, [5281] = 5283, [5282] = 5283, [5284] = 5285, [5286] = 5287, [5515] = 5516, [5517] = 5518, [5732] = 5734, [5733] = 5734, [5735] = 5737, [5736] = 5737, [6192] = 6194, [6193] = 6194, [6195] = 6197, [6196] = 6197, [6198] = 6199, [6200] = 6201, [6249] = 6251, [6250] = 6251, [6252] = 6254, [6253] = 6254, [6255] = 6256, [6257] = 6258, [6795] = 6796, [6797] = 6798, [6799] = 6800, [6801] = 6802, [6891] = 6893, [6892] = 6893, [6894] = 6895, [6900] = 6902, [6901] = 6902, [6903] = 6904, [7033] = 7035, [7034] = 7035, [7036] = 7037, [7042] = 7044, [7043] = 7044, [7045] = 7046, [7054] = 7055, [7056] = 7057, [8541] = 8543, [8542] = 8543, [8544] = 8546, [8545] = 8546, [8547] = 8548, [8549] = 8550, [9165] = 9167, [9166] = 9167, [9168] = 9170, [9169] = 9170, [9171] = 9172, [9173] = 9174, [9267] = 9269, [9268] = 9269, [9270] = 9272, [9271] = 9272, [9273] = 9274, [9275] = 9276, [10276] = 10277, [10274] = 10275, [10268] = 10270, [10269] = 10270, [10271] = 10273, [10272] = 10273, [10471] = 10472, [10480] = 10481, [10477] = 10479, [10478] = 10479, [10468] = 10470, [10469] = 10470, [10775] = 10777, [10776] = 10777, [12092] = 12094, [12093] = 12094, [12188] = 12190, [12189] = 12190, [19840] = 19842, [19841] = 19842, [19843] = 19844, [19980] = 19982, [19981] = 19982, [19983] = 19984, [20273] = 20275, [20274] = 20275, [20276] = 20277, [17235] = 17236, [18208] = 18209, [13022] = 13023, [10784] = 10786, [10785] = 10786, [12099] = 12101, [12100] = 12101, [12197] = 12199, [12198] = 12199, [19849] = 19851, [19850] = 19851, [19852] = 19853, [19989] = 19991, [19990] = 19991, [19992] = 19993, [20282] = 20284, [20283] = 20284, [20285] = 20286, [17237] = 17238, [13020] = 13021, [10780] = 10781, [12095] = 12096, [12195] = 12196, [19845] = 19846, [19985] = 19986, [20278] = 20279, [10789] = 10790, [12102] = 12103, [12204] = 12205, [19854] = 19855, [19994] = 19995, [20287] = 20288, [10782] = 10783, [12097] = 12098, [12193] = 12194, [19847] = 19848, [19987] = 19988, [20280] = 20281, [10791] = 10792, [12104] = 12105, [12202] = 12203, [19856] = 19857, [19996] = 19997, [20289] = 20290} -verticalOpenDoors = {1211, 1220, 1224, 1228, 1233, 1238, 1242, 1246, 1251, 1256, 1260, 1540, 3546, 3548, 3550, 3552, 4915, 5083, 5109, 5111, 5113, 5115, 5127, 5129, 5131, 5133, 5142, 5145, 5283, 5285, 5289, 5293, 5516, 5737, 5749, 6194, 6199, 6203, 6207, 6251, 6256, 6260, 6264, 6798, 6802, 6902, 6904, 6906, 6908, 7044, 7046, 7048, 7050, 7055, 8543, 8548, 8552, 8556, 9167, 9172, 9269, 9274, 9274, 9269, 9278, 9282, 10270, 10275, 10279, 10283, 10479, 10481, 10485, 10483, 10786, 12101, 12199, 19851, 19853, 19991, 19993, 20284, 20286, 17238, 13021, 10790, 12103, 12205, 19855, 19995, 20288, 10792, 12105, 12203, 19857, 19997, 20290} -horizontalOpenDoors = {1214, 1222, 1226, 1230, 1236, 1240, 1244, 1248, 1254, 1258, 1262, 1542, 3537, 3539, 3541, 3543, 4918, 5085, 5100, 5102, 5104, 5106, 5118, 5120, 5122, 5124, 5136, 5139, 5280, 5287, 5291, 5295, 5518, 5734, 5746, 6197, 6201, 6205, 6209, 6254, 6258, 6262, 6266, 6796, 6800, 6893, 6895, 6897, 6899, 7035, 7037, 7039, 7041, 7057, 8546, 8550, 8554, 8558, 9170, 9174, 9272, 9276, 9280, 9284, 10273, 10277, 10281, 10285, 10470, 10472, 10476, 10474, 10777, 12094, 12190, 19842, 19844, 19982, 19984, 20275, 20277, 17236, 18209, 13023, 10781, 12096, 12196, 19846, 19986, 20279, 10783, 12098, 12194, 19848, 19988, 20281} -openSpecialDoors = {1224, 1226, 1228, 1230, 1242, 1244, 1246, 1248, 1256, 1258, 1260, 1262, 3541, 3543, 3550, 3552, 5104, 5106, 5113, 5115, 5122, 5124, 5131, 5133, 5289, 5291, 5293, 5295, 6203, 6205, 6207, 6209, 6260, 6262, 6264, 6266, 6897, 6899, 6906, 6908, 7039, 7041, 7048, 7050, 8552, 8554, 8556, 8558, 9176, 9178, 9180, 9182, 9278, 9280, 9282, 9284, 10279, 10281, 10283, 10285, 10474, 10476, 10483, 10485, 10781, 12096, 12196, 19846, 19986, 20279, 10783, 12098, 12194, 19848, 19988, 20281, 10790, 12103, 12205, 19855, 19995, 20288, 10792, 12105, 12203, 19857, 19997, 20290} -questDoors = {1223, 1225, 1241, 1243, 1255, 1257, 3542, 3551, 5105, 5114, 5123, 5132, 5288, 5290, 5745, 5748, 6202, 6204, 6259, 6261, 6898, 6907, 7040, 7049, 8551, 8553, 9175, 9177, 9277, 9279, 10278, 10280, 10475, 10484, 10782, 12097, 12193, 19847, 19987, 20280, 10791, 12104, 12202, 19856, 19996, 20289} -levelDoors = {1227, 1229, 1245, 1247, 1259, 1261, 3540, 3549, 5103, 5112, 5121, 5130, 5292, 5294, 6206, 6208, 6263, 6265, 6896, 6905, 7038, 7047, 8555, 8557, 9179, 9181, 9281, 9283, 10282, 10284, 10473, 10482, 10780, 10789, 10780, 12095, 12195, 19845, 19985, 20278, 10789, 12102, 12204, 19854, 19994, 20287} -keys = {2086, 2087, 2088, 2089, 2090, 2091, 2092, 10032} - -function getDistanceBetween(firstPosition, secondPosition) - local xDif = math.abs(firstPosition.x - secondPosition.x) - local yDif = math.abs(firstPosition.y - secondPosition.y) - local posDif = math.max(xDif, yDif) - if firstPosition.z ~= secondPosition.z then - posDif = posDif + 15 - end - return posDif -end - -function getFormattedWorldTime() - local worldTime = getWorldTime() - local hours = math.floor(worldTime / 60) - - local minutes = worldTime % 60 - if minutes < 10 then - minutes = '0' .. minutes - end - return hours .. ':' .. minutes -end - -string.split = function(str, sep) - local res = {} - for v in str:gmatch("([^" .. sep .. "]+)") do - res[#res + 1] = v - end - return res -end - -string.trim = function(str) - return str:match'^()%s*$' and '' or str:match'^%s*(.*%S)' -end - -if nextUseStaminaTime == nil then - nextUseStaminaTime = {} -end diff --git a/path_10_8/data/globalevents/globalevents.xml b/path_10_8/data/globalevents/globalevents.xml deleted file mode 100644 index e136115ce..000000000 --- a/path_10_8/data/globalevents/globalevents.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/path_10_8/data/globalevents/lib/globalevents.lua b/path_10_8/data/globalevents/lib/globalevents.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_10_8/data/globalevents/lib/globalevents.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_10_8/data/globalevents/scripts/ddos.lua b/path_10_8/data/globalevents/scripts/ddos.lua deleted file mode 100644 index c629eaffd..000000000 --- a/path_10_8/data/globalevents/scripts/ddos.lua +++ /dev/null @@ -1,27 +0,0 @@ -function onThink(interval) -local counter = 0 -local players = getOnlinePlayers() - if players[1] ~= nil then - local l = (#players > 50 and 50 or #players) - for i = 1, l do - local tmpPlayer = Player(players[i]) - if tmpPlayer then - if tmpPlayer:getIp() == 0 then - counter = counter + 1 - end - end - end - if counter >= (l / 2) and l > 4 then - ddos.enabled = true - if not ddos.broadcasted then - broadcastMessage("Server is under attack, monsters have been disabled.", MESSAGE_STATUS_WARNING) - end - else - if ddos.enabled then - ddos.enabled = false - ddos.broadcasted = false - end - end - end - return true -end diff --git a/path_10_8/data/globalevents/scripts/record.lua b/path_10_8/data/globalevents/scripts/record.lua deleted file mode 100644 index 47d6b79ef..000000000 --- a/path_10_8/data/globalevents/scripts/record.lua +++ /dev/null @@ -1,4 +0,0 @@ -function onRecord(current, old) - addEvent(broadcastMessage, 150, "New record: " .. current .. " players are logged in.", MESSAGE_STATUS_DEFAULT) - return true -end diff --git a/path_10_8/data/globalevents/scripts/serversave.lua b/path_10_8/data/globalevents/scripts/serversave.lua deleted file mode 100644 index 3a6c2f59e..000000000 --- a/path_10_8/data/globalevents/scripts/serversave.lua +++ /dev/null @@ -1,33 +0,0 @@ -local shutdownAtServerSave = false -local cleanMapAtServerSave = false - -local function serverSave() - if shutdownAtServerSave then - Game.setGameState(GAME_STATE_SHUTDOWN) - else - Game.setGameState(GAME_STATE_CLOSED) - - if cleanMapAtServerSave then - cleanMap() - end - - Game.setGameState(GAME_STATE_NORMAL) - end -end - -local function secondServerSaveWarning() - broadcastMessage("Server is saving game in one minute. Please logout.", MESSAGE_STATUS_WARNING) - addEvent(serverSave, 60000) -end - -local function firstServerSaveWarning() - broadcastMessage("Server is saving game in 3 minutes. Please logout.", MESSAGE_STATUS_WARNING) - addEvent(secondServerSaveWarning, 120000) -end - -function onTime(interval) - broadcastMessage("Server is saving game in 5 minutes. Please logout.", MESSAGE_STATUS_WARNING) - Game.setGameState(GAME_STATE_STARTUP) - addEvent(firstServerSaveWarning, 120000) - return not shutdownAtServerSave -end diff --git a/path_10_8/data/globalevents/scripts/startup.lua b/path_10_8/data/globalevents/scripts/startup.lua deleted file mode 100644 index 0ec476897..000000000 --- a/path_10_8/data/globalevents/scripts/startup.lua +++ /dev/null @@ -1,39 +0,0 @@ -function onStartup() - math.randomseed(os.mtime()) - - db.query("TRUNCATE TABLE `players_online`") - db.asyncQuery("DELETE FROM `guild_wars` WHERE `status` = 0") - db.asyncQuery("DELETE FROM `players` WHERE `deletion` != 0 AND `deletion` < " .. os.time()) - db.asyncQuery("DELETE FROM `ip_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time()) - db.asyncQuery("DELETE FROM `market_history` WHERE `inserted` <= " .. (os.time() - configManager.getNumber(configKeys.MARKET_OFFER_DURATION))) - - -- Move expired bans to ban history - local resultId = db.storeQuery("SELECT * FROM `account_bans` WHERE `expires_at` != 0 AND `expires_at` <= " .. os.time()) - if resultId ~= false then - repeat - local accountId = result.getDataInt(resultId, "account_id") - db.asyncQuery("INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" .. accountId .. ", " .. db.escapeString(result.getDataString(resultId, "reason")) .. ", " .. result.getDataLong(resultId, "banned_at") .. ", " .. result.getDataLong(resultId, "expires_at") .. ", " .. result.getDataInt(resultId, "banned_by") .. ")") - db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. accountId) - until not result.next(resultId) - result.free(resultId) - end - - -- Check house auctions - local resultId = db.storeQuery("SELECT `id`, `highest_bidder`, `last_bid`, (SELECT `balance` FROM `players` WHERE `players`.`id` = `highest_bidder`) AS `balance` FROM `houses` WHERE `owner` = 0 AND `bid_end` != 0 AND `bid_end` < " .. os.time()) - if resultId ~= false then - repeat - local house = House(result.getDataInt(resultId, "id")) - if house ~= nil then - local highestBidder = result.getDataInt(resultId, "highest_bidder") - local balance = result.getDataLong(resultId, "balance") - local lastBid = result.getDataInt(resultId, "last_bid") - if balance >= lastBid then - db.query("UPDATE `players` SET `balance` = " .. (balance - lastBid) .. " WHERE `id` = " .. highestBidder) - house:setOwnerGuid(highestBidder) - end - db.asyncQuery("UPDATE `houses` SET `last_bid` = 0, `bid_end` = 0, `highest_bidder` = 0, `bid` = 0 WHERE `id` = " .. house:getId()) - end - until not result.next(resultId) - result.free(resultId) - end -end diff --git a/path_10_8/data/items/items.otb b/path_10_8/data/items/items.otb deleted file mode 100644 index b372c1099..000000000 Binary files a/path_10_8/data/items/items.otb and /dev/null differ diff --git a/path_10_8/data/items/items.xml b/path_10_8/data/items/items.xml deleted file mode 100644 index facd820ae..000000000 --- a/path_10_8/data/items/items.xml +++ /dev/null @@ -1,30264 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/lib/compat/compat.lua b/path_10_8/data/lib/compat/compat.lua deleted file mode 100644 index b97eded21..000000000 --- a/path_10_8/data/lib/compat/compat.lua +++ /dev/null @@ -1,1007 +0,0 @@ -TRUE = true -FALSE = false - -result.getDataInt = result.getNumber -result.getDataLong = result.getNumber -result.getDataString = result.getString -result.getDataStream = result.getStream - -LUA_ERROR = false -LUA_NO_ERROR = true - -STACKPOS_GROUND = 0 -STACKPOS_FIRST_ITEM_ABOVE_GROUNDTILE = 1 -STACKPOS_SECOND_ITEM_ABOVE_GROUNDTILE = 2 -STACKPOS_THIRD_ITEM_ABOVE_GROUNDTILE = 3 -STACKPOS_FOURTH_ITEM_ABOVE_GROUNDTILE = 4 -STACKPOS_FIFTH_ITEM_ABOVE_GROUNDTILE = 5 -STACKPOS_TOP_CREATURE = 253 -STACKPOS_TOP_FIELD = 254 -STACKPOS_TOP_MOVEABLE_ITEM_OR_CREATURE = 255 - -THING_TYPE_PLAYER = CREATURETYPE_PLAYER + 1 -THING_TYPE_MONSTER = CREATURETYPE_MONSTER + 1 -THING_TYPE_NPC = CREATURETYPE_NPC + 1 - -COMBAT_POISONDAMAGE = COMBAT_EARTHDAMAGE -CONDITION_EXHAUST = CONDITION_EXHAUST_WEAPON -TALKTYPE_ORANGE_1 = TALKTYPE_MONSTER_SAY -TALKTYPE_ORANGE_2 = TALKTYPE_MONSTER_YELL - -NORTH = DIRECTION_NORTH -EAST = DIRECTION_EAST -SOUTH = DIRECTION_SOUTH -WEST = DIRECTION_WEST -SOUTHWEST = DIRECTION_SOUTHWEST -SOUTHEAST = DIRECTION_SOUTHEAST -NORTHWEST = DIRECTION_NORTHWEST -NORTHEAST = DIRECTION_NORTHEAST - -do - local function CreatureIndex(self, key) - local methods = getmetatable(self) - if key == "uid" then - return methods.getId(self) - elseif key == "type" then - local creatureType = 0 - if methods.isPlayer(self) then - creatureType = THING_TYPE_PLAYER - elseif methods.isMonster(self) then - creatureType = THING_TYPE_MONSTER - elseif methods.isNpc(self) then - creatureType = THING_TYPE_NPC - end - return creatureType - elseif key == "itemid" then - return 1 - elseif key == "actionid" then - return 0 - end - return methods[key] - end - rawgetmetatable("Player").__index = CreatureIndex - rawgetmetatable("Monster").__index = CreatureIndex - rawgetmetatable("Npc").__index = CreatureIndex -end - -do - local function ItemIndex(self, key) - local methods = getmetatable(self) - if key == "itemid" then - return methods.getId(self) - elseif key == "actionid" then - return methods.getActionId(self) - elseif key == "uid" then - return methods.getUniqueId(self) - elseif key == "type" then - return methods.getSubType(self) - end - return methods[key] - end - rawgetmetatable("Item").__index = ItemIndex - rawgetmetatable("Container").__index = ItemIndex - rawgetmetatable("Teleport").__index = ItemIndex -end - -function pushThing(thing) - local t = {uid = 0, itemid = 0, type = 0, actionid = 0} - if thing ~= nil then - if thing:isItem() then - t.uid = thing:getUniqueId() - t.itemid = thing:getId() - if ItemType(t.itemid):hasSubType() then - t.type = thing:getSubType() - end - t.actionid = thing:getActionId() - elseif thing:isCreature() then - t.uid = thing:getId() - t.itemid = 1 - if thing:isPlayer() then - t.type = THING_TYPE_PLAYER - elseif thing:isMonster() then - t.type = THING_TYPE_MONSTER - else - t.type = THING_TYPE_NPC - end - end - end - return t -end - -createCombatObject = Combat -setCombatArea = Combat.setArea -setCombatCallback = Combat.setCallback -setCombatCondition = Combat.setCondition -setCombatFormula = Combat.setFormula -setCombatParam = Combat.setParameter - -createConditionObject = Condition -setConditionParam = Condition.setParameter -setConditionFormula = Condition.setFormula -addDamageCondition = Condition.addDamage -addOutfitCondition = Condition.setOutfit - -function doCombat(cid, combat, var) return combat:execute(cid, var) end - -function isCreature(cid) return Creature(cid) ~= nil end -function isPlayer(cid) return Player(cid) ~= nil end -function isMonster(cid) return Monster(cid) ~= nil end -function isSummon(cid) return Creature(cid):getMaster() ~= nil end -function isNpc(cid) return Npc(cid) ~= nil end -function isItem(uid) return Item(uid) ~= nil end -function isContainer(uid) return Container(uid) ~= nil end - -function getCreatureName(cid) local c = Creature(cid) return c ~= nil and c:getName() or false end -function getCreatureHealth(cid) local c = Creature(cid) return c ~= nil and c:getHealth() or false end -function getCreatureMaxHealth(cid) local c = Creature(cid) return c ~= nil and c:getMaxHealth() or false end -function getCreaturePosition(cid) local c = Creature(cid) return c ~= nil and c:getPosition() or false end -function getCreatureOutfit(cid) local c = Creature(cid) return c ~= nil and c:getOutfit() or false end -function getCreatureSpeed(cid) local c = Creature(cid) return c ~= nil and c:getSpeed() or false end -function getCreatureBaseSpeed(cid) local c = Creature(cid) return c ~= nil and c:getBaseSpeed() or false end - -function getCreatureTarget(cid) - local c = Creature(cid) - if c ~= nil then - local target = c:getTarget() - return target ~= nil and target:getId() or 0 - end - return false -end - -function getCreatureMaster(cid) - local c = Creature(cid) - if c ~= nil then - local master = c:getMaster() - return master ~= nil and master:getId() or c:getId() - end - return false -end - -function getCreatureSummons(cid) - local c = Creature(cid) - if c == nil then - return false - end - - local result = {} - for _, summon in ipairs(c:getSummons()) do - result[#result + 1] = summon:getId() - end - return result -end - -getCreaturePos = getCreaturePosition - -function doCreatureAddHealth(cid, health) local c = Creature(cid) return c ~= nil and c:addHealth(health) or false end -function doRemoveCreature(cid) local c = Creature(cid) return c ~= nil and c:remove() or false end -function doCreatureSetLookDir(cid, direction) local c = Creature(cid) return c ~= nil and c:setDirection(direction) or false end -function doCreatureSay(cid, text, type, ...) local c = Creature(cid) return c ~= nil and c:say(text, type, ...) or false end -function doCreatureChangeOutfit(cid, outfit) local c = Creature(cid) return c ~= nil and c:setOutfit(outfit) or false end -function doSetCreatureDropLoot(cid, doDrop) local c = Creature(cid) return c ~= nil and c:setDropLoot(doDrop) or false end -function doChangeSpeed(cid, delta) local c = Creature(cid) return c ~= nil and c:changeSpeed(delta) or false end -function doAddCondition(cid, conditionId) local c = Creature(cid) return c ~= nil and c:addCondition(conditionId) or false end -function doRemoveCondition(cid, conditionType, subId) local c = Creature(cid) return c ~= nil and (c:removeCondition(conditionType, CONDITIONID_COMBAT, subId) or c:removeCondition(conditionType, CONDITIONID_DEFAULT, subId) or true) end - -doSetCreatureDirection = doCreatureSetLookDir - -function registerCreatureEvent(cid, name) local c = Creature(cid) return c ~= nil and c:registerEvent(name) or false end -function unregisterCreatureEvent(cid, name) local c = Creature(cid) return c ~= nil and c:unregisterEvent(name) or false end - -function getPlayerByName(name) local p = Player(name) return p ~= nil and p:getId() or false end -function getIPByPlayerName(name) local p = Player(name) return p ~= nil and p:getIp() or false end -function getPlayerGUID(cid) local p = Player(cid) return p ~= nil and p:getGuid() or false end -function getPlayerIp(cid) local p = Player(cid) return p ~= nil and p:getIp() or false end -function getPlayerAccountType(cid) local p = Player(cid) return p ~= nil and p:getAccountType() or false end -function getPlayerLastLoginSaved(cid) local p = Player(cid) return p ~= nil and p:getLastLoginSaved() or false end -function getPlayerName(cid) local p = Player(cid) return p ~= nil and p:getName() or false end -function getPlayerFreeCap(cid) local p = Player(cid) return p ~= nil and (p:getFreeCapacity() / 100) or false end -function getPlayerPosition(cid) local p = Player(cid) return p ~= nil and p:getPosition() or false end -function getPlayerMagLevel(cid) local p = Player(cid) return p ~= nil and p:getMagicLevel() or false end -function getPlayerAccess(cid) - local player = Player(cid) - if player == nil then - return false - end - return player:getGroup():getAccess() and 1 or 0 -end -function getPlayerSkill(cid, skillId) local p = Player(cid) return p ~= nil and p:getSkillLevel(skillId) or false end -function getPlayerMana(cid) local p = Player(cid) return p ~= nil and p:getMana() or false end -function getPlayerMaxMana(cid) local p = Player(cid) return p ~= nil and p:getMaxMana() or false end -function getPlayerLevel(cid) local p = Player(cid) return p ~= nil and p:getLevel() or false end -function getPlayerTown(cid) local p = Player(cid) return p ~= nil and p:getTown():getId() or false end -function getPlayerVocation(cid) local p = Player(cid) return p ~= nil and p:getVocation():getId() or false end -function getPlayerSoul(cid) local p = Player(cid) return p ~= nil and p:getSoul() or false end -function getPlayerSex(cid) local p = Player(cid) return p ~= nil and p:getSex() or false end -function getPlayerStorageValue(cid, key) local p = Player(cid) return p ~= nil and p:getStorageValue(key) or false end -function getPlayerBalance(cid) local p = Player(cid) return p ~= nil and p:getBankBalance() or false end -function getPlayerMoney(cid) local p = Player(cid) return p ~= nil and p:getMoney() or false end -function getPlayerGroupId(cid) local p = Player(cid) return p ~= nil and p:getGroup():getId() or false end -function getPlayerLookDir(cid) local p = Player(cid) return p ~= nil and p:getDirection() or false end -function getPlayerLight(cid) local p = Player(cid) return p ~= nil and p:getLight() or false end -function getPlayerDepotItems(cid, depotId) local p = Player(cid) return p ~= nil and p:getDepotItems(depotId) or false end -function getPlayerSkullType(cid) local p = Player(cid) return p ~= nil and p:getSkull() or false end -function getPlayerLossPercent(cid) local p = Player(cid) return p ~= nil and p:getDeathPenalty() or false end -function getPlayerMount(cid, mountId) local p = Player(cid) return p ~= nil and p:hasMount(mountId) or false end -function getPlayerPremiumDays(cid) local p = Player(cid) return p ~= nil and p:getPremiumDays() or false end -function getPlayerBlessing(cid, blessing) local p = Player(cid) return p ~= nil and p:hasBlessing(blessing) or false end -function getPlayerParty(cid) - local player = Player(cid) - if player == nil then - return false - end - - local party = player:getParty() - if party == nil then - return nil - end - return party:getLeader():getId() -end -function getPlayerGuildId(cid) - local player = Player(cid) - if player == nil then - return false - end - - local guild = player:getGuild() - if guild == nil then - return false - end - return guild:getId() -end -function getPlayerGuildLevel(cid) local p = Player(cid) return p ~= nil and p:getGuildLevel() or false end -function getPlayerGuildName(cid) - local player = Player(cid) - if player == nil then - return false - end - - local guild = player:getGuild() - if guild == nil then - return false - end - return guild:getName() -end -function getPlayerGuildRank(cid) - local player = Player(cid) - if player == nil then - return false - end - - local guild = player:getGuild() - if guild == nil then - return false - end - - local rank = guild:getRankByLevel(player:getGuildLevel()) - return rank ~= nil and rank.name or false -end -function getPlayerGuildNick(cid) local p = Player(cid) return p ~= nil and p:getGuildNick() or false end -function getPlayerMasterPos(cid) local p = Player(cid) return p ~= nil and p:getTown():getTemplePosition() or false end -function getPlayerItemCount(cid, itemId, ...) local p = Player(cid) return p ~= nil and p:getItemCount(itemId, ...) or false end -function getPlayerSlotItem(cid, slot) - local player = Player(cid) - if player == nil then - return pushThing(nil) - end - return pushThing(player:getSlotItem(slot)) -end -function getPlayerItemById(cid, deepSearch, itemId, ...) - local player = Player(cid) - if player == nil then - return pushThing(nil) - end - return pushThing(player:getItemById(itemId, deepSearch, ...)) -end -function getPlayerFood(cid) - local player = Player(cid) - if player == nil then - return false - end - local c = player:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT) return c ~= nil and math.floor(c:getTicks() / 1000) or 0 -end -function canPlayerLearnInstantSpell(cid, name) local p = Player(cid) return p ~= nil and p:canLearnSpell(name) or false end -function getPlayerLearnedInstantSpell(cid, name) local p = Player(cid) return p ~= nil and p:hasLearnedSpell(name) or false end -function isPlayerGhost(cid) local p = Player(cid) return p ~= nil and p:isInGhostMode() or false end -function isPlayerPzLocked(cid) local p = Player(cid) return p ~= nil and p:isPzLocked() or false end -function isPremium(cid) local p = Player(cid) return p ~= nil and p:isPremium() or false end -function getPlayersByIPAddress(ip, mask) - if mask == nil then mask = 0xFFFFFFFF end - local masked = bit.band(ip, mask) - local result = {} - for _, player in ipairs(Game.getPlayers()) do - if bit.band(player:getIp(), mask) == masked then - result[#result + 1] = player:getId() - end - end - return result -end -function getOnlinePlayers() - local result = {} - for _, player in ipairs(Game.getPlayers()) do - result[#result + 1] = player:getName() - end - return result -end -function getPlayersByAccountNumber(accountNumber) - local result = {} - for _, player in ipairs(Game.getPlayers()) do - if player:getAccountId() == accountNumber then - result[#result + 1] = player:getId() - end - end - return result -end -function getPlayerGUIDByName(name) - local player = Player(name) - if player ~= nil then - return player:getGuid() - end - - local resultId = db.storeQuery("SELECT `id` FROM `players` WHERE `name` = " .. db.escapeString(name)) - if resultId ~= false then - local guid = result.getDataInt(resultId, "id") - result.free(resultId) - return guid - end - return 0 -end -function getAccountNumberByPlayerName(name) - local player = Player(name) - if player ~= nil then - return player:getAccountId() - end - - local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(name)) - if resultId ~= false then - local accountId = result.getDataInt(resultId, "account_id") - result.free(resultId) - return accountId - end - return 0 -end - -getPlayerAccountBalance = getPlayerBalance -getIpByName = getIPByPlayerName - -function setPlayerStorageValue(cid, key, value) local p = Player(cid) return p ~= nil and p:setStorageValue(key, value) or false end -function doPlayerSetBalance(cid, balance) local p = Player(cid) return p ~= nil and p:setBankBalance(balance) or false end -function doPlayerAddMoney(cid, money) local p = Player(cid) return p ~= nil and p:addMoney(money) or false end -function doPlayerRemoveMoney(cid, money) local p = Player(cid) return p ~= nil and p:removeMoney(money) or false end -function doPlayerAddSoul(cid, soul) local p = Player(cid) return p ~= nil and p:addSoul(soul) or false end -function doPlayerSetVocation(cid, vocation) local p = Player(cid) return p ~= nil and p:setVocation(Vocation(vocation)) or false end -function doPlayerSetTown(cid, town) local p = Player(cid) return p ~= nil and p:setTown(Town(town)) or false end -function setPlayerGroupId(cid, groupId) local p = Player(cid) return p ~= nil and p:setGroup(Group(groupId)) or false end -function doPlayerSetSex(cid, sex) local p = Player(cid) return p ~= nil and p:setSex(sex) or false end -function doPlayerSetGuildLevel(cid, level) local p = Player(cid) return p ~= nil and p:setGuildLevel(level) or false end -function doPlayerSetGuildNick(cid, nick) local p = Player(cid) return p ~= nil and p:setGuildNick(nick) or false end -function doPlayerSetOfflineTrainingSkill(cid, skillId) local p = Player(cid) return p ~= nil and p:setOfflineTrainingSkill(skillId) or false end -function doShowTextDialog(cid, itemId, text) local p = Player(cid) return p ~= nil and p:showTextDialog(itemId, text) or false end -function doPlayerAddItemEx(cid, uid, ...) local p = Player(cid) return p ~= nil and p:addItemEx(Item(uid), ...) or false end -function doPlayerRemoveItem(cid, itemid, count, ...) local p = Player(cid) return p ~= nil and p:removeItem(itemid, count, ...) or false end -function doPlayerAddPremiumDays(cid, days) local p = Player(cid) return p ~= nil and p:addPremiumDays(days) or false end -function doPlayerRemovePremiumDays(cid, days) local p = Player(cid) return p ~= nil and p:removePremiumDays(days) or false end -function doPlayerAddBlessing(cid, blessing) local p = Player(cid) return p ~= nil and p:addBlessing(blessing) or false end -function doPlayerAddOutfit(cid, lookType, addons) local p = Player(cid) return p ~= nil and p:addOutfitAddon(lookType, addons) or false end -function doPlayerRemOutfit(cid, lookType, addons) - local player = Player(cid) - if player == nil then - return false - end - if addons == 255 then - return player:removeOutfit(lookType) - else - return player:removeOutfitAddon(lookType, addons) - end -end -function canPlayerWearOutfit(cid, lookType, addons) local p = Player(cid) return p ~= nil and p:hasOutfit(lookType, addons) or false end -function doPlayerAddMount(cid, mountId) local p = Player(cid) return p ~= nil and p:addMount(mountId) or false end -function doPlayerRemoveMount(cid, mountId) local p = Player(cid) return p ~= nil and p:removeMount(mountId) or false end -function doPlayerSendCancel(cid, text) local p = Player(cid) return p ~= nil and p:sendCancelMessage(text) or false end -function doPlayerFeed(cid, food) local p = Player(cid) return p ~= nil and p:feed(food) or false end -function playerLearnInstantSpell(cid, name) local p = Player(cid) return p ~= nil and p:learnSpell(name) or false end -function doPlayerPopupFYI(cid, message) local p = Player(cid) return p ~= nil and p:popupFYI(message) or false end -function doSendTutorial(cid, tutorialId) local p = Player(cid) return p ~= nil and p:sendTutorial(tutorialId) or false end -function doAddMapMark(cid, pos, type, description) local p = Player(cid) return p ~= nil and p:addMapMark(pos, type, description or "") or false end -function doPlayerSendTextMessage(cid, type, text, ...) local p = Player(cid) return p ~= nil and p:sendTextMessage(type, text, ...) or false end -function doSendAnimatedText() debugPrint("Deprecated function.") return true end -function doPlayerAddExp(cid, exp, useMult, ...) - local player = Player(cid) - if player == nil then - return false - end - - if useMult then - exp = exp * Game.getExperienceStage(player:getLevel()) - end - return player:addExperience(exp, ...) -end -function doPlayerAddManaSpent(cid, mana) local p = Player(cid) return p ~= nil and p:addManaSpent(mana * configManager.getNumber(configKeys.RATE_MAGIC)) or false end -function doPlayerAddSkillTry(cid, skillid, n) local p = Player(cid) return p ~= nil and p:addSkillTries(skillid, n * configManager.getNumber(configKeys.RATE_SKILL)) or false end -function doPlayerAddMana(cid, mana, ...) local p = Player(cid) return p ~= nil and p:addMana(mana, ...) or false end -function doPlayerJoinParty(cid, leaderId) - local player = Player(cid) - if player == nil then - return false - end - - if player:getParty() ~= nil then - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are already in a party.") - return true - end - - local leader = Player(leaderId) - if leader == nil then - return false - end - - local party = leader:getParty() - if party == nil or party:getLeader() ~= leader then - return true - end - - for _, invitee in ipairs(party:getInvitees()) do - if player ~= invitee then - return true - end - end - - party:addMember(player) - return true -end -function getPartyMembers(cid) - local player = Player(cid) - if player == nil then - return false - end - - local party = player:getParty() - if party == nil then - return false - end - - local result = {party:getLeader():getId()} - for _, member in ipairs(party:getMembers()) do - result[#result + 1] = member:getId() - end - return result -end - -doPlayerSendDefaultCancel = doPlayerSendCancel - -function getMonsterTargetList(cid) - local monster = Monster(cid) - if monster == nil then - return false - end - - local result = {} - for _, creature in ipairs(monster:getTargetList()) do - if monster:isTarget(creature) then - result[#result + 1] = creature:getId() - end - end - return result -end -function getMonsterFriendList(cid) - local monster = Monster(cid) - if monster == nil then - return false - end - - local z = monster:getPosition().z - - local result = {} - for _, creature in ipairs(monster:getFriendList()) do - if not creature:isRemoved() and creature:getPosition().z == z then - result[#result + 1] = creature:getId() - end - end - return result -end -function doSetMonsterTarget(cid, target) - local monster = Monster(cid) - if monster == nil then - return false - end - - if monster:getMaster() ~= nil then - return true - end - - local target = Creature(cid) - if target == nil then - return false - end - - monster:selectTarget(target) - return true -end -function doMonsterChangeTarget(cid) - local monster = Monster(cid) - if monster == nil then - return false - end - - if monster:getMaster() ~= nil then - return true - end - - monster:searchTarget(1) - return true -end -function doCreateNpc(name, pos, ...) - local npc = Game.createNpc(name, pos, ...) return npc ~= nil and npc:setMasterPos(pos) or false -end -function doSummonCreature(name, pos, ...) - local m = Game.createMonster(name, pos, ...) return m ~= nil and m:getId() or false -end -function doConvinceCreature(cid, target) - local creature = Creature(cid) - if creature == nil then - return false - end - - local targetCreature = Creature(target) - if targetCreature == nil then - return false - end - - targetCreature:setMaster(creature) - return true -end - -function getTownId(townName) local t = Town(townName) return t ~= nil and t:getId() or false end -function getTownName(townId) local t = Town(townId) return t ~= nil and t:getName() or false end -function getTownTemplePosition(townId) local t = Town(townId) return t ~= nil and t:getTemplePosition() or false end - -function doSetItemActionId(uid, actionId) local i = Item(uid) return i ~= nil and i:setActionId(actionId) or false end -function doTransformItem(uid, newItemId, ...) local i = Item(uid) return i ~= nil and i:transform(newItemId, ...) or false end -function doChangeTypeItem(uid, newType) local i = Item(uid) return i ~= nil and i:transform(i:getId(), newType) or false end -function doRemoveItem(uid, ...) local i = Item(uid) return i ~= nil and i:remove(...) or false end - -function getContainerSize(uid) local c = Container(uid) return c ~= nil and c:getSize() or false end -function getContainerCap(uid) local c = Container(uid) return c ~= nil and c:getCapacity() or false end -function getContainerItem(uid, slot) - local container = Container(uid) - if container == nil then - return pushThing(nil) - end - return pushThing(container:getItem(slot)) -end - -function doAddContainerItemEx(uid, virtualId) - local container = Container(uid) - if container == nil then - return false - end - - local res = container:addItemEx(Item(virtualId)) - if res == nil then - return false - end - return res -end - -function doSendMagicEffect(pos, magicEffect, ...) return Position(pos):sendMagicEffect(magicEffect, ...) end -function doSendDistanceShoot(fromPos, toPos, distanceEffect, ...) return Position(fromPos):sendDistanceEffect(toPos, distanceEffect, ...) end -function isSightClear(fromPos, toPos, floorCheck) return Position(fromPos):isSightClear(toPos, floorCheck) end - -function getPromotedVocation(vocationId) - local vocation = Vocation(vocationId) - if vocation == nil then - return 0 - end - - local promotedVocation = vocation:getPromotion() - if promotedVocation == nil then - return 0 - end - return promotedVocation:getId() -end - -function getGuildId(guildName) - local resultId = db.storeQuery("SELECT `id` FROM `guilds` WHERE `name` = " .. db.escapeString(guildName)) - if resultId == false then - return false - end - - local guildId = result.getDataInt(resultId, "id") - result.free(resultId) - return guildId -end - -function getHouseName(houseId) local h = House(houseId) return h ~= nil and h:getName() or false end -function getHouseOwner(houseId) local h = House(houseId) return h ~= nil and h:getOwnerGuid() or false end -function getHouseEntry(houseId) local h = House(houseId) return h ~= nil and h:getExitPosition() or false end -function getHouseTown(houseId) local h = House(houseId) if h == nil then return false end local t = h:getTown() return t ~= nil and t:getId() or false end -function getHouseTilesSize(houseId) local h = House(houseId) return h ~= nil and h:getTileCount() or false end - -function isItemStackable(itemId) return ItemType(itemId):isStackable() end -function isItemRune(itemId) return ItemType(itemId):isRune() end -function isItemDoor(itemId) return ItemType(itemId):isDoor() end -function isItemContainer(itemId) return ItemType(itemId):isContainer() end -function isItemFluidContainer(itemId) return ItemType(itemId):isFluidContainer() end -function isItemMovable(itemId) return ItemType(itemId):isMovable() end -function isCorpse(uid) local i = Item(uid) return i ~= nil and ItemType(i:getId()):isCorpse() or false end - -isItemMoveable = isItemMovable -isMoveable = isMovable - -function getItemName(itemId) return ItemType(itemId):getName() end -function getItemWeight(itemId, ...) return ItemType(itemId):getWeight(...) / 100 end -function getItemDescriptions(itemId) - local itemType = ItemType(itemId) - return { - name = itemType:getName(), - plural = itemType:getPluralName(), - article = itemType:getArticle(), - description = itemType:getDescription() - } -end -function getItemIdByName(name) - local id = ItemType(name):getId() - if id == 0 then - return false - end - return id -end -function getItemWeightByUID(uid, ...) - local item = Item(uid) - if item == nil then - return false - end - - local itemType = ItemType(item:getId()) - return itemType:isStackable() and (itemType:getWeight(item:getCount(), ...) / 100) or (itemType:getWeight(1, ...) / 100) -end -function getItemRWInfo(uid) - local item = Item(uid) - if item == nil then - return false - end - - local rwFlags = 0 - local itemType = ItemType(item:getId()) - if itemType:isReadable() then - rwFlags = bit.bor(rwFlags, 1) - end - - if itemType:isWritable() then - rwFlags = bit.bor(rwFlags, 2) - end - return rwFlags -end -function getContainerCapById(itemId) return ItemType(itemId):getCapacity() end -function getFluidSourceType(itemId) local it = ItemType(itemId) return it.id ~= 0 and it:getFluidSource() or false end -function hasProperty(uid, prop) - local item = Item(uid) - if item == nil then - return false - end - - local parent = item:getParent() - if parent:isTile() and item == parent:getGround() then - return parent:hasProperty(prop) - else - return item:hasProperty(prop) - end -end - -function doSetItemText(uid, text) - local item = Item(uid) - if item == nil then - return false - end - - if text ~= "" then - item:setAttribute(ITEM_ATTRIBUTE_TEXT, text) - else - item:removeAttribute(ITEM_ATTRIBUTE_TEXT) - end - return true -end -function doSetItemSpecialDescription(uid, desc) - local item = Item(uid) - if item == nil then - return false - end - - if desc ~= "" then - item:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, desc) - else - item:removeAttribute(ITEM_ATTRIBUTE_DESCRIPTION) - end - return true -end -function doDecayItem(uid) local i = Item(uid) return i ~= nil and i:decay() or false end - -function setHouseOwner(id, guid) local h = House(id) return h ~= nil and h:setOwnerGuid(guid) or false end -function getHouseRent(id) local h = House(id) return h ~= nil and h:getRent() or nil end -function getHouseAccessList(id, listId) local h = House(id) return h ~= nil and h:getAccessList(listId) or nil end -function setHouseAccessList(id, listId, listText) local h = House(id) return h ~= nil and h:setAccessList(listId, listText) or false end - -function getHouseByPlayerGUID(playerGUID) - for _, house in ipairs(Game.getHouses()) do - if house:getOwnerGuid() == playerGUID then - return house:getId() - end - end - return nil -end - -function getTileHouseInfo(pos) - local t = Tile(pos) - if t == nil then - return false - end - local h = t:getHouse() - return h ~= nil and h:getId() or false -end - -function getTilePzInfo(position) - local t = Tile(position) - if t == nil then - return false - end - return t:hasFlag(TILESTATE_PROTECTIONZONE) -end - -function getTileInfo(position) - local t = Tile(position) - if t == nil then - return false - end - - local ret = pushThing(t:getGround()) - ret.protection = t:hasFlag(TILESTATE_PROTECTIONZONE) - ret.nopz = ret.protection - ret.nologout = t:hasFlag(TILESTATE_NOLOGOUT) - ret.refresh = t:hasFlag(TILESTATE_REFRESH) - ret.house = t:hasFlag(TILESTATE_HOUSE) - ret.bed = t:hasFlag(TILESTATE_BED) - ret.depot = t:hasFlag(TILESTATE_DEPOT) - - ret.things = t:getThingCount() - ret.creatures = t:getCreatureCount() - ret.items = t:getItemCount() - ret.topItems = t:getTopItemCount() - ret.downItems = t:getDownItemCount() - return ret -end - -function getTileItemByType(position, itemType) - local t = Tile(position) - if t == nil then - return pushThing(nil) - end - return pushThing(t:getItemByType(itemType)) -end - -function getTileItemById(position, itemId, ...) - local t = Tile(position) - if t == nil then - return pushThing(nil) - end - return pushThing(t:getItemById(itemId, ...)) -end - -function getTileThingByPos(position) - local t = Tile(position) - if t == nil then - if position.stackpos == -1 then - return -1 - end - return pushThing(nil) - end - - if position.stackpos == -1 then - return t:getThingCount() - end - return pushThing(t:getThing(position.stackpos)) -end - -function getTileThingByTopOrder(position, topOrder) - local t = Tile(position) - if t == nil then - return pushThing(nil) - end - return pushThing(t:getItemByTopOrder(topOrder)) -end - -function getTopCreature(position) - local t = Tile(position) - if t == nil then - return pushThing(nil) - end - return pushThing(t:getTopCreature()) -end - -function queryTileAddThing(thing, position, ...) local t = Tile(position) return t ~= nil and t:queryAdd(thing, ...) or false end - -function doTeleportThing(uid, dest, pushMovement) - if type(uid) == "userdata" then - if uid:isCreature() then - return uid:teleportTo(dest, pushMovement or false) - else - return uid:moveTo(dest) - end - else - if uid >= 0x10000000 then - local creature = Creature(uid) - if creature ~= nil then - return creature:teleportTo(dest, pushMovement or false) - end - else - local item = Item(uid) - if item ~= nil then - return item:moveTo(dest) - end - end - end - return false -end - -function getThingPos(uid) - local thing - if type(uid) ~= "userdata" then - if uid >= 0x10000000 then - thing = Creature(uid) - else - thing = Item(uid) - end - else - thing = uid - end - - if thing == nil then - return false - end - - local stackpos = 0 - local tile = thing:getTile() - if tile ~= nil then - stackpos = tile:getThingIndex(thing) - end - - local position = thing:getPosition() - position.stackpos = stackpos - return position -end - -function getThingfromPos(pos) - local tile = Tile(pos) - if tile == nil then - return pushThing(nil) - end - - local thing - if stackpos == STACKPOS_TOP_MOVEABLE_ITEM_OR_CREATURE then - thing = tile:getTopCreature() - if thing == nil then - local item = tile:getTopDownItem() - if item ~= nil and item:getType():isMovable() then - thing = item - end - end - elseif stackpos == STACKPOS_TOP_FIELD then - thing = tile:getFieldItem() - elseif stackpos == STACKPOS_TOP_CREATURE then - thing = tile:getTopCreature() - else - thing = tile:getThing(pos.stackpos) - end - return pushThing(thing) -end - -function doRelocate(fromPos, toPos) - if fromPos == toPos then - return false - end - - local fromTile = Tile(fromPos) - if fromTile == nil then - return false - end - - if Tile(toPos) == nil then - return false - end - - for i = fromTile:getThingCount() - 1, 0, -1 do - local thing = fromTile:getThing(i) - if thing ~= nil then - if thing:isItem() then - if ItemType(thing:getId()):isMovable() then - thing:moveTo(toPos) - end - elseif thing:isCreature() then - thing:teleportTo(toPos) - end - end - end - return true -end - -function getThing(uid) - return uid >= 0x10000000 and pushThing(Creature(uid)) or pushThing(Item(uid)) -end - -function getConfigInfo(info) - if type(info) ~= "string" then - return nil - end - dofile('config.lua') - return _G[info] -end - -function getWorldCreatures(type) - if type == 0 then - return Game.getPlayerCount() - elseif type == 1 then - return Game.getMonsterCount() - elseif type == 2 then - return Game.getNpcCount() - end - return Game.getPlayerCount() + Game.getMonsterCount() + Game.getNpcCount() -end - -saveData = saveServer - -function getGlobalStorageValue(key) - return Game.getStorageValue(key) or -1 -end - -function setGlobalStorageValue(key, value) - Game.setStorageValue(key, value) - return true -end - -getWorldType = Game.getWorldType - -numberToVariant = Variant -stringToVariant = Variant -positionToVariant = Variant - -function targetPositionToVariant(position) - local variant = Variant(position) - variant.type = VARIANT_TARGETPOSITION - return variant -end - -variantToNumber = Variant.getNumber -variantToString = Variant.getString -variantToPosition = Variant.getPosition - -function doCreateTeleport(itemId, destination, position) - local item = Game.createItem(itemId, 1, position) - if not item:isTeleport() then - item:remove() - return false - end - item:setDestination(destination) - return item:getUniqueId() -end - -function getSpectators(centerPos, rangex, rangey, multifloor, onlyPlayers) - local result = Game.getSpectators(centerPos, multifloor, onlyPlayers or false, rangex, rangex, rangey, rangey) - if #result == 0 then - return nil - end - - for index, spectator in ipairs(result) do - result[index] = spectator:getId() - end - return result -end - -function broadcastMessage(message, messageType) - Game.broadcastMessage(message, messageType) - print("> Broadcasted message: \"" .. message .. "\".") -end - -function Guild.addMember(self, player) - return player:setGuild(guild) -end -function Guild.removeMember(self, player) - return player:getGuild() == self and player:setGuild(nil) -end diff --git a/path_10_8/data/lib/core/constants.lua b/path_10_8/data/lib/core/constants.lua deleted file mode 100644 index 9d1f90bc1..000000000 --- a/path_10_8/data/lib/core/constants.lua +++ /dev/null @@ -1 +0,0 @@ -CONTAINER_POSITION = 0xFFFF diff --git a/path_10_8/data/lib/core/container.lua b/path_10_8/data/lib/core/container.lua deleted file mode 100644 index 65343eb7f..000000000 --- a/path_10_8/data/lib/core/container.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Container.isContainer(self) - return true -end diff --git a/path_10_8/data/lib/core/core.lua b/path_10_8/data/lib/core/core.lua deleted file mode 100644 index 1b78513f1..000000000 --- a/path_10_8/data/lib/core/core.lua +++ /dev/null @@ -1,10 +0,0 @@ -dofile('data/lib/core/constants.lua') -dofile('data/lib/core/container.lua') -dofile('data/lib/core/creature.lua') -dofile('data/lib/core/game.lua') -dofile('data/lib/core/item.lua') -dofile('data/lib/core/itemtype.lua') -dofile('data/lib/core/player.lua') -dofile('data/lib/core/position.lua') -dofile('data/lib/core/teleport.lua') -dofile('data/lib/core/tile.lua') diff --git a/path_10_8/data/lib/core/creature.lua b/path_10_8/data/lib/core/creature.lua deleted file mode 100644 index e0fd78578..000000000 --- a/path_10_8/data/lib/core/creature.lua +++ /dev/null @@ -1,52 +0,0 @@ -function Creature.getClosestFreePosition(self, position, extended) - local usePosition = Position(position) - local tiles = { Tile(usePosition) } - local length = extended and 2 or 1 - - local tile - for y = -length, length do - for x = -length, length do - if x ~= 0 or y ~= 0 then - usePosition.x = position.x + x - usePosition.y = position.y + y - - tile = Tile(usePosition) - if tile then - tiles[#tiles + 1] = tile - end - end - end - end - - for i = 1, #tiles do - tile = tiles[i] - if tile:getCreatureCount() == 0 and not tile:hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) then - return tile:getPosition() - end - end - return Position() -end - -function Creature.getPlayer(self) - return self:isPlayer() and self or nil -end - -function Creature.isItem(self) - return false -end - -function Creature.isMonster(self) - return false -end - -function Creature.isNpc(self) - return false -end - -function Creature.isPlayer(self) - return false -end - -function Creature.isTile(self) - return false -end diff --git a/path_10_8/data/lib/core/game.lua b/path_10_8/data/lib/core/game.lua deleted file mode 100644 index 4e0c5d8aa..000000000 --- a/path_10_8/data/lib/core/game.lua +++ /dev/null @@ -1,68 +0,0 @@ -function Game.broadcastMessage(message, messageType) - if messageType == nil then - messageType = MESSAGE_STATUS_WARNING - end - - for _, player in ipairs(Game.getPlayers()) do - player:sendTextMessage(messageType, message) - end -end - -function Game.convertIpToString(ip) - local band = bit.band - local rshift = bit.rshift - return string.format("%d.%d.%d.%d", - band(ip, 0xFF), - band(rshift(ip, 8), 0xFF), - band(rshift(ip, 16), 0xFF), - rshift(ip, 24) - ) -end - -function Game.getReverseDirection(direction) - if direction == WEST then - return EAST - elseif direction == EAST then - return WEST - elseif direction == NORTH then - return SOUTH - elseif direction == SOUTH then - return NORTH - elseif direction == NORTHWEST then - return SOUTHEAST - elseif direction == NORTHEAST then - return SOUTHWEST - elseif direction == SOUTHWEST then - return NORTHEAST - elseif direction == SOUTHEAST then - return NORTHWEST - end - return NORTH -end - -function Game.getSkillType(weaponType) - if weaponType == WEAPON_CLUB then - return SKILL_CLUB - elseif weaponType == WEAPON_SWORD then - return SKILL_SWORD - elseif weaponType == WEAPON_AXE then - return SKILL_AXE - elseif weaponType == WEAPON_DISTANCE then - return SKILL_DISTANCE - elseif weaponType == WEAPON_SHIELD then - return SKILL_SHIELD - end - return SKILL_FIST -end - -if not globalStorageTable then - globalStorageTable = {} -end - -function Game.getStorageValue(key) - return globalStorageTable[key] -end - -function Game.setStorageValue(key, value) - globalStorageTable[key] = value -end diff --git a/path_10_8/data/lib/core/item.lua b/path_10_8/data/lib/core/item.lua deleted file mode 100644 index 7980d5ae1..000000000 --- a/path_10_8/data/lib/core/item.lua +++ /dev/null @@ -1,23 +0,0 @@ -function Item.getType(self) - return ItemType(self:getId()) -end - -function Item.isContainer(self) - return false -end - -function Item.isCreature(self) - return false -end - -function Item.isPlayer(self) - return false -end - -function Item.isTeleport(self) - return false -end - -function Item.isTile(self) - return false -end diff --git a/path_10_8/data/lib/core/itemtype.lua b/path_10_8/data/lib/core/itemtype.lua deleted file mode 100644 index c94ba7f1b..000000000 --- a/path_10_8/data/lib/core/itemtype.lua +++ /dev/null @@ -1,16 +0,0 @@ -local slotBits = { - [CONST_SLOT_HEAD] = SLOTP_HEAD, - [CONST_SLOT_NECKLACE] = SLOTP_NECKLACE, - [CONST_SLOT_BACKPACK] = SLOTP_BACKPACK, - [CONST_SLOT_ARMOR] = SLOTP_ARMOR, - [CONST_SLOT_RIGHT] = SLOTP_RIGHT, - [CONST_SLOT_LEFT] = SLOTP_LEFT, - [CONST_SLOT_LEGS] = SLOTP_LEGS, - [CONST_SLOT_FEET] = SLOTP_FEET, - [CONST_SLOT_RING] = SLOTP_RING, - [CONST_SLOT_AMMO] = SLOTP_AMMO -} - -function ItemType.usesSlot(self, slot) - return bit.band(self:getSlotPosition(), slotBits[slot] or 0) ~= 0 -end diff --git a/path_10_8/data/lib/core/player.lua b/path_10_8/data/lib/core/player.lua deleted file mode 100644 index 7f5aae17e..000000000 --- a/path_10_8/data/lib/core/player.lua +++ /dev/null @@ -1,98 +0,0 @@ -local foodCondition = Condition(CONDITION_REGENERATION, CONDITIONID_DEFAULT) - -function Player.feed(self, food) - local condition = self:getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT) - if condition then - condition:setTicks(condition:getTicks() + (food * 1000)) - else - local vocation = self:getVocation() - if not vocation then - return nil - end - - foodCondition:setTicks(food * 1000) - foodCondition:setParameter(CONDITION_PARAM_HEALTHGAIN, vocation:getHealthGainAmount()) - foodCondition:setParameter(CONDITION_PARAM_HEALTHTICKS, vocation:getHealthGainTicks() * 1000) - foodCondition:setParameter(CONDITION_PARAM_MANAGAIN, vocation:getManaGainAmount()) - foodCondition:setParameter(CONDITION_PARAM_MANATICKS, vocation:getManaGainTicks() * 1000) - - self:addCondition(foodCondition) - end - return true -end - -function Player.getClosestFreePosition(self, position, extended) - if self:getAccountType() >= ACCOUNT_TYPE_GOD then - return position - end - return Creature.getClosestFreePosition(self, position, extended) -end - -function Player.getDepotItems(self, depotId) - return self:getDepotChest(depotId, true):getItemHoldingCount() -end - -function Player.getLossPercent(self) - local blessings = 0 - local lossPercent = { - [0] = 100, - [1] = 70, - [2] = 45, - [3] = 25, - [4] = 10, - [5] = 0 - } - - for i = 1, 5 do - if self:hasBlessing(i) then - blessings = blessings + 1 - end - end - return lossPercent[blessings] -end - -function Player.isPremium(self) - return self:getPremiumDays() > 0 or configManager.getBoolean(configKeys.FREE_PREMIUM) -end - -function Player.sendCancelMessage(self, message) - if type(message) == "number" then - message = Game.getReturnMessage(message) - end - return self:sendTextMessage(MESSAGE_STATUS_SMALL, message) -end - -function Player.isUsingOtClient(self) - return self:getClient().os >= CLIENTOS_OTCLIENT_LINUX -end - -function Player.sendExtendedOpcode(self, opcode, buffer) - if not self:isUsingOtClient() then - return false - end - - local networkMessage = NetworkMessage() - networkMessage:addByte(0x32) - networkMessage:addByte(opcode) - networkMessage:addString(buffer) - networkMessage:sendToPlayer(self) - networkMessage:delete() - return true -end - -APPLY_SKILL_MULTIPLIER = true -local addSkillTriesFunc = Player.addSkillTries -function Player.addSkillTries(...) - APPLY_SKILL_MULTIPLIER = false - local ret = addSkillTriesFunc(...) - APPLY_SKILL_MULTIPLIER = true - return ret -end - -local addManaSpentFunc = Player.addManaSpent -function Player.addManaSpent(...) - APPLY_SKILL_MULTIPLIER = false - local ret = addManaSpentFunc(...) - APPLY_SKILL_MULTIPLIER = true - return ret -end diff --git a/path_10_8/data/lib/core/position.lua b/path_10_8/data/lib/core/position.lua deleted file mode 100644 index 572c6a29f..000000000 --- a/path_10_8/data/lib/core/position.lua +++ /dev/null @@ -1,68 +0,0 @@ -Position.directionOffset = { - [DIRECTION_NORTH] = {x = 0, y = -1}, - [DIRECTION_EAST] = {x = 1, y = 0}, - [DIRECTION_SOUTH] = {x = 0, y = 1}, - [DIRECTION_WEST] = {x = -1, y = 0}, - [DIRECTION_SOUTHWEST] = {x = -1, y = 1}, - [DIRECTION_SOUTHEAST] = {x = 1, y = 1}, - [DIRECTION_NORTHWEST] = {x = -1, y = -1}, - [DIRECTION_NORTHEAST] = {x = 1, y = -1} -} - -function Position:getNextPosition(direction, steps) - local offset = Position.directionOffset[direction] - if offset then - steps = steps or 1 - self.x = self.x + offset.x * steps - self.y = self.y + offset.y * steps - end -end - -function Position:moveUpstairs() - local isWalkable = function (position) - local tile = Tile(position) - if not tile then - return false - end - - local ground = tile:getGround() - if not ground or ground:hasProperty(CONST_PROP_BLOCKSOLID) then - return false - end - - local items = tile:getItems() - for i = 1, tile:getItemCount() do - local item = items[i] - local itemType = item:getType() - if itemType:getType() ~= ITEM_TYPE_MAGICFIELD and not itemType:isMovable() and item:hasProperty(CONST_PROP_BLOCKSOLID) then - return false - end - end - return true - end - - local swap = function (lhs, rhs) - lhs.x, rhs.x = rhs.x, lhs.x - lhs.y, rhs.y = rhs.y, lhs.y - lhs.z, rhs.z = rhs.z, lhs.z - end - - self.z = self.z - 1 - - local defaultPosition = self + Position.directionOffset[DIRECTION_SOUTH] - if not isWalkable(defaultPosition) then - for direction = DIRECTION_NORTH, DIRECTION_NORTHEAST do - if direction == DIRECTION_SOUTH then - direction = DIRECTION_WEST - end - - local position = self + Position.directionOffset[direction] - if isWalkable(position) then - swap(self, position) - return self - end - end - end - swap(self, defaultPosition) - return self -end diff --git a/path_10_8/data/lib/core/teleport.lua b/path_10_8/data/lib/core/teleport.lua deleted file mode 100644 index 89302688e..000000000 --- a/path_10_8/data/lib/core/teleport.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Teleport.isTeleport(self) - return true -end diff --git a/path_10_8/data/lib/core/tile.lua b/path_10_8/data/lib/core/tile.lua deleted file mode 100644 index e2e26c4ba..000000000 --- a/path_10_8/data/lib/core/tile.lua +++ /dev/null @@ -1,34 +0,0 @@ -function Tile.isCreature(self) - return false -end - -function Tile.isItem(self) - return false -end - -function Tile.isTile(self) - return true -end - -function Tile.relocateTo(self, toPosition) - if self:getPosition() == toPosition or not Tile(toPosition) then - return false - end - - for i = self:getThingCount() - 1, 0, -1 do - local thing = self:getThing(i) - if thing then - if thing:isItem() then - if thing:getFluidType() ~= 0 then - thing:remove() - elseif ItemType(thing:getId()):isMovable() then - thing:moveTo(toPosition) - end - elseif thing:isCreature() then - thing:teleportTo(toPosition) - end - end - end - - return true -end diff --git a/path_10_8/data/lib/lib.lua b/path_10_8/data/lib/lib.lua deleted file mode 100644 index 5a0e2b553..000000000 --- a/path_10_8/data/lib/lib.lua +++ /dev/null @@ -1,5 +0,0 @@ --- Core API functions implemented in Lua -dofile('data/lib/core/core.lua') - --- Compatibility library for our old Lua API -dofile('data/lib/compat/compat.lua') diff --git a/path_10_8/data/logs/.gitignore b/path_10_8/data/logs/.gitignore deleted file mode 100644 index 5e7d2734c..000000000 --- a/path_10_8/data/logs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/path_10_8/data/migrations/0.lua b/path_10_8/data/migrations/0.lua deleted file mode 100644 index 0fb3ff971..000000000 --- a/path_10_8/data/migrations/0.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 1 (account names)") - db.query("ALTER TABLE `accounts` ADD `name` VARCHAR(32) NOT NULL AFTER `id`") - db.query("UPDATE `accounts` SET `name` = `id`") - db.query("ALTER TABLE `accounts` ADD UNIQUE (`name`)") - return true -end diff --git a/path_10_8/data/migrations/1.lua b/path_10_8/data/migrations/1.lua deleted file mode 100644 index c3e6f22fb..000000000 --- a/path_10_8/data/migrations/1.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 2 (market offers)") - db.query("CREATE TABLE `market_offers` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `player_id` INT NOT NULL, `sale` TINYINT(1) NOT NULL DEFAULT 0, `itemtype` INT UNSIGNED NOT NULL, `amount` SMALLINT UNSIGNED NOT NULL, `created` BIGINT UNSIGNED NOT NULL, `anonymous` TINYINT(1) NOT NULL DEFAULT 0, `price` INT UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (`id`), KEY(`sale`, `itemtype`), KEY(`created`), FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE) ENGINE = InnoDB") - return true -end diff --git a/path_10_8/data/migrations/10.lua b/path_10_8/data/migrations/10.lua deleted file mode 100644 index 9e1357e73..000000000 --- a/path_10_8/data/migrations/10.lua +++ /dev/null @@ -1,28 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 11 (improved guild and players online structure)") - db.query("CREATE TABLE IF NOT EXISTS `guild_membership` (`player_id` int(11) NOT NULL, `guild_id` int(11) NOT NULL, `rank_id` int(11) NOT NULL, `nick` varchar(15) NOT NULL DEFAULT '', PRIMARY KEY (`player_id`), KEY `guild_id` (`guild_id`), KEY `rank_id` (`rank_id`)) ENGINE=InnoDB") - db.query("ALTER TABLE `guild_membership` ADD CONSTRAINT `guild_membership_ibfk_3` FOREIGN KEY (`rank_id`) REFERENCES `guild_ranks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT `guild_membership_ibfk_1` FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT `guild_membership_ibfk_2` FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE ON UPDATE CASCADE") - db.query("ALTER TABLE `guild_invites` ADD PRIMARY KEY (`player_id`, `guild_id`)") - db.query("ALTER TABLE `player_skills` ADD PRIMARY KEY (`player_id`, `skillid`)") - db.query("ALTER TABLE `player_storage` ADD PRIMARY KEY (`player_id`, `key`)") - - local resultId = db.storeQuery("SELECT `players`.`id` AS `player_id`, `players`.`rank_id` AS `rank_id`, `players`.`guildnick` AS `guild_nick`, `guild_ranks`.`guild_id` AS `guild_id` FROM `guild_ranks` INNER JOIN `players` ON `guild_ranks`.`id` = `players`.`rank_id`") - if resultId ~= false then - local stmt = "INSERT INTO `guild_membership` (`player_id`, `guild_id`, `rank_id`, `nick`) VALUES " - repeat - stmt = stmt .. "(" .. result.getDataInt(resultId, "player_id") .. "," .. result.getDataInt(resultId, "guild_id") .. "," .. result.getDataInt(resultId, "rank_id") .. "," .. db.escapeString(result.getDataString(resultId, "guild_nick")) .. ")," - until not result.next(resultId) - result.free(resultId) - - local stmtLen = string.len(stmt) - if stmtLen > 83 then - stmt = string.sub(stmt, 1, stmtLen - 1) - db.query(stmt) - end - end - - db.query("ALTER TABLE `players` DROP `rank_id`, DROP `guildnick`, DROP `direction`, DROP `loss_experience`, DROP `loss_mana`, DROP `loss_skills`, DROP `premend`, DROP `online`") - db.query("DROP TRIGGER IF EXISTS `ondelete_guilds`") - db.query("CREATE TABLE IF NOT EXISTS `players_online` (`player_id` int(11) NOT NULL, PRIMARY KEY (`player_id`)) ENGINE=MEMORY") - return true -end diff --git a/path_10_8/data/migrations/11.lua b/path_10_8/data/migrations/11.lua deleted file mode 100644 index 69b1691cb..000000000 --- a/path_10_8/data/migrations/11.lua +++ /dev/null @@ -1,24 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 12 (storing players record and message of the day in database)") - - local motdNum = "" - local motd = "" - - local lastMotdFile = io.open("lastMotd.txt", "r") - if lastMotdFile ~= nil then - motdNum = lastMotdFile:read() - motd = lastMotdFile:read() - lastMotdFile:close() - end - - local record = 0 - - local playersRecordFile = io.open("playersRecord.txt", "r") - if playersRecordFile ~= nil then - record = playersRecordFile:read("*n") - playersRecordFile:close() - end - - db.query("INSERT INTO `server_config` (`config`, `value`) VALUES ('players_record', '" .. record .. "'), ('motd_hash', SHA1(" .. db.escapeString(motd) .. ")), ('motd_num', " .. db.escapeString(motdNum) .. ")") - return true -end diff --git a/path_10_8/data/migrations/12.lua b/path_10_8/data/migrations/12.lua deleted file mode 100644 index 6e168586b..000000000 --- a/path_10_8/data/migrations/12.lua +++ /dev/null @@ -1,9 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 13 (house bidding system and additional columns to other tables)") - - db.query("ALTER TABLE `player_deaths` ADD `mostdamage_by` varchar(100) NOT NULL, ADD `mostdamage_is_player` tinyint(1) NOT NULL DEFAULT '0', ADD `unjustified` tinyint(1) NOT NULL DEFAULT '0', ADD `mostdamage_unjustified` tinyint(1) NOT NULL DEFAULT '0', ADD KEY `killed_by` (`killed_by`), ADD KEY `mostdamage_by` (`mostdamage_by`)") - db.query("ALTER TABLE `houses` ADD `name` varchar(255) NOT NULL, ADD `rent` int(11) NOT NULL DEFAULT '0', ADD `town_id` int(11) NOT NULL DEFAULT '0', ADD `bid` int(11) NOT NULL DEFAULT '0', ADD `bid_end` int(11) NOT NULL DEFAULT '0', ADD `last_bid` int(11) NOT NULL DEFAULT '0', ADD `highest_bidder` int(11) NOT NULL DEFAULT '0', ADD `size` int(11) NOT NULL DEFAULT '0', ADD `beds` int(11) NOT NULL DEFAULT '0', ADD KEY `owner` (`owner`), ADD KEY `town_id` (`town_id`)") - db.query("ALTER TABLE `players` ADD `onlinetime` int(11) NOT NULL DEFAULT '0', ADD `deletion` bigint(15) NOT NULL DEFAULT '0'") - db.query("ALTER TABLE `accounts` ADD `points` int(11) NOT NULL DEFAULT '0', ADD `creation` int(11) NOT NULL DEFAULT '0'") - return true -end diff --git a/path_10_8/data/migrations/13.lua b/path_10_8/data/migrations/13.lua deleted file mode 100644 index 7b123b40f..000000000 --- a/path_10_8/data/migrations/13.lua +++ /dev/null @@ -1,37 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 14 (account_bans, ip_bans and player_bans)") - - db.query("CREATE TABLE IF NOT EXISTS `account_bans` (`account_id` int(11) NOT NULL, `reason` varchar(255) NOT NULL, `banned_at` bigint(20) NOT NULL, `expires_at` bigint(20) NOT NULL, `banned_by` int(11) NOT NULL, PRIMARY KEY (`account_id`), KEY `banned_by` (`banned_by`), FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB") - db.query("CREATE TABLE IF NOT EXISTS `account_ban_history` (`account_id` int(11) NOT NULL, `reason` varchar(255) NOT NULL, `banned_at` bigint(20) NOT NULL, `expired_at` bigint(20) NOT NULL, `banned_by` int(11) NOT NULL, PRIMARY KEY (`account_id`), KEY `banned_by` (`banned_by`), FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB") - db.query("CREATE TABLE IF NOT EXISTS `ip_bans` (`ip` int(10) unsigned NOT NULL, `reason` varchar(255) NOT NULL, `banned_at` bigint(20) NOT NULL, `expires_at` bigint(20) NOT NULL, `banned_by` int(11) NOT NULL, PRIMARY KEY (`ip`), KEY `banned_by` (`banned_by`), FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB") - db.query("CREATE TABLE IF NOT EXISTS `player_namelocks` (`player_id` int(11) NOT NULL, `reason` varchar(255) NOT NULL, `namelocked_at` bigint(20) NOT NULL, `namelocked_by` int(11) NOT NULL, PRIMARY KEY (`player_id`), KEY `namelocked_by` (`namelocked_by`), FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (`namelocked_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE) ENGINE=InnoDB") - - local resultId = db.storeQuery("SELECT `player`, `time` FROM `bans` WHERE `type` = 2") - if resultId ~= false then - local stmt = "INSERT INTO `player_namelocks` (`player_id`, `namelocked_at`, `namelocked_by`) VALUES " - repeat - stmt = stmt .. "(" .. result.getDataInt(resultId, "player") .. "," .. result.getDataInt(resultId, "time") .. "," .. result.getDataInt(resultId, "player") .. ")," - until not result.next(resultId) - result.free(resultId) - - local stmtLen = string.len(stmt) - if stmtLen > 86 then - stmt = string.sub(stmt, 1, stmtLen - 1) - db.query(stmt) - end - end - - db.query("DROP TRIGGER `ondelete_accounts`") - db.query("DROP TRIGGER `ondelete_players`") - db.query("ALTER TABLE `accounts` DROP `warnings`") - - db.query("DROP TABLE `bans`") - - print("Run this query in your database to create the ondelete_players trigger:") - print("DELIMITER //") - print("CREATE TRIGGER `ondelete_players` BEFORE DELETE ON `players`") - print(" FOR EACH ROW BEGIN") - print(" UPDATE `houses` SET `owner` = 0 WHERE `owner` = OLD.`id`;") - print("END //") - return true -end diff --git a/path_10_8/data/migrations/14.lua b/path_10_8/data/migrations/14.lua deleted file mode 100644 index 632bbaf09..000000000 --- a/path_10_8/data/migrations/14.lua +++ /dev/null @@ -1,30 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 15 (moving groups to data/XML/groups.xml)") - - db.query("ALTER TABLE players DROP FOREIGN KEY players_ibfk_2") - db.query("DROP INDEX group_id ON players") - - db.query("ALTER TABLE accounts DROP FOREIGN KEY accounts_ibfk_1") - db.query("DROP INDEX group_id ON accounts") - db.query("ALTER TABLE `accounts` DROP `group_id`") - - local groupsFile = io.open("data/XML/groups.xml", "w") - if groupsFile ~= nil then - groupsFile:write("\r\n") - groupsFile:write("\r\n") - - local resultId = db.storeQuery("SELECT `id`, `name`, `flags`, `access`, `maxdepotitems`, `maxviplist` FROM `groups` ORDER BY `id` ASC") - if resultId ~= false then - repeat - groupsFile:write("\t\r\n") - until not result.next(resultId) - result.free(resultId) - end - - groupsFile:write("\r\n") - groupsFile:close() - - db.query("DROP TABLE `groups`") - end - return true -end diff --git a/path_10_8/data/migrations/15.lua b/path_10_8/data/migrations/15.lua deleted file mode 100644 index f04796b66..000000000 --- a/path_10_8/data/migrations/15.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 16 (moving skills into players table)") - db.query("ALTER TABLE `players` ADD `skill_fist` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_fist_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_club` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_club_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_sword` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_sword_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_axe` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_axe_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_dist` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_dist_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_shielding` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_shielding_tries` bigint(20) unsigned NOT NULL DEFAULT 0, ADD `skill_fishing` int(10) unsigned NOT NULL DEFAULT 10, ADD `skill_fishing_tries` bigint(20) unsigned NOT NULL DEFAULT 0") - db.query("UPDATE `players` SET `skill_fist` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 0), `skill_fist_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 0), `skill_club` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 1), `skill_club_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 1), `skill_sword` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 2), `skill_sword_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 2), `skill_axe` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 3), `skill_axe_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 3), `skill_dist` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 4), `skill_dist_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 4), `skill_shielding` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 5), `skill_shielding_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 5), `skill_fishing` = (SELECT `value` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 6), `skill_fishing_tries` = (SELECT `count` FROM `player_skills` WHERE `player_id` = `id` AND `skillid` = 6)") - db.query("DROP TRIGGER `oncreate_players`") - db.query("DROP TABLE `player_skills`") - return true -end diff --git a/path_10_8/data/migrations/16.lua b/path_10_8/data/migrations/16.lua deleted file mode 100644 index 45e742227..000000000 --- a/path_10_8/data/migrations/16.lua +++ /dev/null @@ -1,9 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 17 (fixing primary key in account ban history)") - db.query("ALTER TABLE `account_ban_history` DROP FOREIGN KEY `account_ban_history_ibfk_1`") - db.query("ALTER TABLE `account_ban_history` DROP PRIMARY KEY") - db.query("ALTER TABLE `account_ban_history` ADD `id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST") - db.query("ALTER TABLE `account_ban_history` ADD INDEX (`account_id`)") - db.query("ALTER TABLE `account_ban_history` ADD FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE") - return true -end diff --git a/path_10_8/data/migrations/17.lua b/path_10_8/data/migrations/17.lua deleted file mode 100644 index e26bdd430..000000000 --- a/path_10_8/data/migrations/17.lua +++ /dev/null @@ -1,6 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 18 (optimize account password field)") - db.query("DELETE FROM `server_config` WHERE `config` = 'encryption'") - db.query("ALTER TABLE `accounts` CHANGE `password` `password` CHAR(40) NOT NULL") - return true -end diff --git a/path_10_8/data/migrations/18.lua b/path_10_8/data/migrations/18.lua deleted file mode 100644 index d0ffd9c0c..000000000 --- a/path_10_8/data/migrations/18.lua +++ /dev/null @@ -1,3 +0,0 @@ -function onUpdateDatabase() - return false -end diff --git a/path_10_8/data/migrations/2.lua b/path_10_8/data/migrations/2.lua deleted file mode 100644 index 942a1cd76..000000000 --- a/path_10_8/data/migrations/2.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 3 (bank balance)") - db.query("ALTER TABLE `players` ADD `balance` BIGINT UNSIGNED NOT NULL DEFAULT 0") - return true -end diff --git a/path_10_8/data/migrations/3.lua b/path_10_8/data/migrations/3.lua deleted file mode 100644 index c93e34d54..000000000 --- a/path_10_8/data/migrations/3.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 4 (market history)") - db.query("CREATE TABLE `market_history` (`id` INT UNSIGNED NOT NULL AUTO_INCREMENT, `player_id` INT NOT NULL, `sale` TINYINT(1) NOT NULL DEFAULT 0, `itemtype` INT UNSIGNED NOT NULL, `amount` SMALLINT UNSIGNED NOT NULL, `price` INT UNSIGNED NOT NULL DEFAULT 0, `expires_at` BIGINT UNSIGNED NOT NULL, `inserted` BIGINT UNSIGNED NOT NULL, `state` TINYINT(1) UNSIGNED NOT NULL, PRIMARY KEY(`id`), KEY(`player_id`, `sale`), FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE) ENGINE = InnoDB") - return true -end diff --git a/path_10_8/data/migrations/4.lua b/path_10_8/data/migrations/4.lua deleted file mode 100644 index 069a6432d..000000000 --- a/path_10_8/data/migrations/4.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 5 (black skull & guild wars)") - db.query("ALTER TABLE `players` CHANGE `redskull` `skull` TINYINT(1) NOT NULL DEFAULT '0', CHANGE `redskulltime` `skulltime` INT(11) NOT NULL DEFAULT '0'") - db.query("CREATE TABLE IF NOT EXISTS `guild_wars` ( `id` int(11) NOT NULL AUTO_INCREMENT, `guild1` int(11) NOT NULL DEFAULT '0', `guild2` int(11) NOT NULL DEFAULT '0', `name1` varchar(255) NOT NULL, `name2` varchar(255) NOT NULL, `status` tinyint(2) NOT NULL DEFAULT '0', `started` bigint(15) NOT NULL DEFAULT '0', `ended` bigint(15) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `guild1` (`guild1`), KEY `guild2` (`guild2`)) ENGINE=InnoDB") - db.query("CREATE TABLE IF NOT EXISTS `guildwar_kills` (`id` int(11) NOT NULL AUTO_INCREMENT, `killer` varchar(50) NOT NULL, `target` varchar(50) NOT NULL, `killerguild` int(11) NOT NULL DEFAULT '0', `targetguild` int(11) NOT NULL DEFAULT '0', `warid` int(11) NOT NULL DEFAULT '0', `time` bigint(15) NOT NULL, PRIMARY KEY (`id`), KEY `warid` (`warid`), FOREIGN KEY (`warid`) REFERENCES `guild_wars`(`id`) ON DELETE CASCADE) ENGINE=InnoDB") - return true -end diff --git a/path_10_8/data/migrations/5.lua b/path_10_8/data/migrations/5.lua deleted file mode 100644 index 82ba621a6..000000000 --- a/path_10_8/data/migrations/5.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 6 (market bug fix)") - db.query("DELETE FROM `market_offers` WHERE `amount` = 0") - return true -end diff --git a/path_10_8/data/migrations/6.lua b/path_10_8/data/migrations/6.lua deleted file mode 100644 index f98946764..000000000 --- a/path_10_8/data/migrations/6.lua +++ /dev/null @@ -1,6 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 7 (offline training)") - db.query("ALTER TABLE `players` ADD `offlinetraining_time` SMALLINT UNSIGNED NOT NULL DEFAULT 43200") - db.query("ALTER TABLE `players` ADD `offlinetraining_skill` INT NOT NULL DEFAULT -1") - return true -end diff --git a/path_10_8/data/migrations/7.lua b/path_10_8/data/migrations/7.lua deleted file mode 100644 index 1fd4a1196..000000000 --- a/path_10_8/data/migrations/7.lua +++ /dev/null @@ -1,35 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 8 (account viplist with description, icon and notify server side)") - db.query("RENAME TABLE `player_viplist` TO `account_viplist`") - db.query("ALTER TABLE `account_viplist` DROP FOREIGN KEY `account_viplist_ibfk_1`") - db.query("UPDATE `account_viplist` SET `player_id` = (SELECT `account_id` FROM `players` WHERE `id` = `player_id`)") - db.query("ALTER TABLE `account_viplist` CHANGE `player_id` `account_id` INT( 11 ) NOT NULL COMMENT 'id of account whose viplist entry it is'") - db.query("ALTER TABLE `account_viplist` DROP FOREIGN KEY `account_viplist_ibfk_2`") - db.query("ALTER TABLE `account_viplist` CHANGE `vip_id` `player_id` INT( 11 ) NOT NULL COMMENT 'id of target player of viplist entry'") - db.query("ALTER TABLE `account_viplist` DROP INDEX `player_id`, ADD INDEX `account_id` (`account_id`)") - db.query("ALTER TABLE `account_viplist` DROP INDEX `vip_id`, ADD INDEX `player_id` (`player_id`)") - db.query("ALTER TABLE `account_viplist` ADD FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE") - db.query("ALTER TABLE `account_viplist` ADD FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE") - db.query("ALTER TABLE `account_viplist` ADD `description` VARCHAR(128) NOT NULL DEFAULT '', ADD `icon` TINYINT( 2 ) UNSIGNED NOT NULL DEFAULT '0', ADD `notify` TINYINT( 1 ) NOT NULL DEFAULT '0'") - - -- Remove duplicates - local resultId = db.storeQuery("SELECT `account_id`, `player_id`, COUNT(*) AS `count` FROM `account_viplist` GROUP BY `account_id`, `player_id` HAVING COUNT(*) > 1") - if resultId ~= false then - repeat - db.query("DELETE FROM `account_viplist` WHERE `account_id` = " .. result.getDataInt(resultId, "account_id") .. " AND `player_id` = " .. result.getDataInt(resultId, "player_id") .. " LIMIT " .. (result.getDataInt(resultId, "count") - 1)) - until not result.next(resultId) - result.free(resultId) - end - - -- Remove if an account has over 200 entries - resultId = db.storeQuery("SELECT `account_id`, COUNT(*) AS `count` FROM `account_viplist` GROUP BY `account_id` HAVING COUNT(*) > 200") - if resultId ~= false then - repeat - db.query("DELETE FROM `account_viplist` WHERE `account_id` = " .. result.getDataInt(resultId, "account_id") .. " LIMIT " .. (result.getDataInt(resultId, "count") - 200)) - until not result.next(resultId) - result.free(resultId) - end - - db.query("ALTER TABLE `account_viplist` ADD UNIQUE `account_player_index` (`account_id`, `player_id`)") - return true -end diff --git a/path_10_8/data/migrations/8.lua b/path_10_8/data/migrations/8.lua deleted file mode 100644 index d2d9f1750..000000000 --- a/path_10_8/data/migrations/8.lua +++ /dev/null @@ -1,70 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 9 (global inbox)") - db.query("CREATE TABLE IF NOT EXISTS `player_inboxitems` (`player_id` int(11) NOT NULL, `sid` int(11) NOT NULL, `pid` int(11) NOT NULL DEFAULT '0', `itemtype` smallint(6) NOT NULL, `count` smallint(5) NOT NULL DEFAULT '0', `attributes` blob NOT NULL, UNIQUE KEY `player_id_2` (`player_id`,`sid`), KEY `player_id` (`player_id`), FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE) ENGINE=InnoDB DEFAULT CHARSET=latin1") - - -- Delete "market" item - db.query("DELETE FROM `player_depotitems` WHERE `itemtype` = 14405") - - -- Move up items in depot chests - local resultId = db.storeQuery("SELECT `player_id`, `pid`, (SELECT `dp2`.`sid` FROM `player_depotitems` AS `dp2` WHERE `dp2`.`player_id` = `dp1`.`player_id` AND `dp2`.`pid` = `dp1`.`sid` AND `itemtype` = 2594) AS `sid` FROM `player_depotitems` AS `dp1` WHERE `itemtype` = 2589") - if resultId ~= false then - repeat - db.query("UPDATE `player_depotitems` SET `pid` = " .. result.getDataInt(resultId, "pid") .. " WHERE `player_id` = " .. result.getDataInt(resultId, "player_id") .. " AND `pid` = " .. result.getDataInt(resultId, "sid")) - until not result.next(resultId) - result.free(resultId) - end - - -- Delete the depot lockers - db.query("DELETE FROM `player_depotitems` WHERE `itemtype` = 2589") - - -- Delete the depot chests - db.query("DELETE FROM `player_depotitems` WHERE `itemtype` = 2594") - - resultId = db.storeQuery("SELECT DISTINCT `player_id` FROM `player_depotitems` WHERE `itemtype` = 14404") - if resultId ~= false then - repeat - local playerId = result.getDataInt(resultId, "player_id") - - local runningId = 100 - - local stmt = "INSERT INTO `player_inboxitems` (`player_id`, `sid`, `pid`, `itemtype`, `count`, `attributes`) VALUES " - - local resultId2 = db.storeQuery("SELECT `sid` FROM `player_depotitems` WHERE `player_id` = " .. playerId .. " AND `itemtype` = 14404") - if resultId2 ~= false then - repeat - local sids = {} - sids[#sids + 1] = result.getDataInt(resultId2, "sid") - while #sids > 0 do - local sid = sids[#sids] - sids[#sids] = nil - - local resultId3 = db.storeQuery("SELECT * FROM `player_depotitems` WHERE `player_id` = " .. playerId .. " AND `pid` = " .. sid) - if resultId3 ~= false then - repeat - local attr, attrSize = result.getDataStream(resultId3, "attributes") - runningId = runningId + 1 - stmt = stmt .. "(" .. playerId .. "," .. runningId .. ",0," .. result.getDataInt(resultId3, "itemtype") .. "," .. result.getDataInt(resultId3, "count") .. "," .. db.escapeBlob(attr, attrSize) .. ")," - sids[#sids + 1] = result.getDataInt(resultId3, "sid") - - db.query("DELETE FROM `player_depotitems` WHERE `player_id` = " .. result.getDataInt(resultId, "player_id") .. " AND `sid` = " .. result.getDataInt(resultId3, "sid")) - until not result.next(resultId3) - result.free(resultId3) - end - end - until not result.next(resultId2) - result.free(resultId2) - end - - local stmtLen = string.len(stmt) - if stmtLen > 102 then - stmt = string.sub(stmt, 1, stmtLen - 1) - db.query(stmt) - end - until not result.next(resultId) - result.free(resultId) - end - - -- Delete the inboxes - db.query("DELETE FROM `player_depotitems` WHERE `itemtype` = 14404") - return true -end diff --git a/path_10_8/data/migrations/9.lua b/path_10_8/data/migrations/9.lua deleted file mode 100644 index 33022ee08..000000000 --- a/path_10_8/data/migrations/9.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onUpdateDatabase() - print("> Updating database to version 10 (stamina)") - db.query("ALTER TABLE `players` ADD `stamina` SMALLINT UNSIGNED NOT NULL DEFAULT 2520") - return true -end diff --git a/path_10_8/data/monster/Amazons/amazon.xml b/path_10_8/data/monster/Amazons/amazon.xml deleted file mode 100644 index 081a6f259..000000000 --- a/path_10_8/data/monster/Amazons/amazon.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Amazons/valkyrie.xml b/path_10_8/data/monster/Amazons/valkyrie.xml deleted file mode 100644 index a7cfe9d6c..000000000 --- a/path_10_8/data/monster/Amazons/valkyrie.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Annelids/carrion worm.xml b/path_10_8/data/monster/Annelids/carrion worm.xml deleted file mode 100644 index 000b0dc4e..000000000 --- a/path_10_8/data/monster/Annelids/carrion worm.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Annelids/drillworm.xml b/path_10_8/data/monster/Annelids/drillworm.xml deleted file mode 100644 index 3edcf41e8..000000000 --- a/path_10_8/data/monster/Annelids/drillworm.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Annelids/rift worm.xml b/path_10_8/data/monster/Annelids/rift worm.xml deleted file mode 100644 index af7e574b8..000000000 --- a/path_10_8/data/monster/Annelids/rift worm.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Annelids/rotworm.xml b/path_10_8/data/monster/Annelids/rotworm.xml deleted file mode 100644 index 37c3dd8e7..000000000 --- a/path_10_8/data/monster/Annelids/rotworm.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Apes/kongra.xml b/path_10_8/data/monster/Apes/kongra.xml deleted file mode 100644 index 2fc2649b4..000000000 --- a/path_10_8/data/monster/Apes/kongra.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Apes/merlkin.xml b/path_10_8/data/monster/Apes/merlkin.xml deleted file mode 100644 index 61ee98dcb..000000000 --- a/path_10_8/data/monster/Apes/merlkin.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Apes/sibang.xml b/path_10_8/data/monster/Apes/sibang.xml deleted file mode 100644 index 44f2270de..000000000 --- a/path_10_8/data/monster/Apes/sibang.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Apes/yeti.xml b/path_10_8/data/monster/Apes/yeti.xml deleted file mode 100644 index 0119958e7..000000000 --- a/path_10_8/data/monster/Apes/yeti.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/crystal spider.xml b/path_10_8/data/monster/Arachnids/crystal spider.xml deleted file mode 100644 index 32551dd4f..000000000 --- a/path_10_8/data/monster/Arachnids/crystal spider.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/giant spider wyda.xml b/path_10_8/data/monster/Arachnids/giant spider wyda.xml deleted file mode 100644 index acec3794e..000000000 --- a/path_10_8/data/monster/Arachnids/giant spider wyda.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/giant spider.xml b/path_10_8/data/monster/Arachnids/giant spider.xml deleted file mode 100644 index 98b190dcc..000000000 --- a/path_10_8/data/monster/Arachnids/giant spider.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/poison spider.xml b/path_10_8/data/monster/Arachnids/poison spider.xml deleted file mode 100644 index c348f51d6..000000000 --- a/path_10_8/data/monster/Arachnids/poison spider.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/sacred spider.xml b/path_10_8/data/monster/Arachnids/sacred spider.xml deleted file mode 100644 index 3d5901ae2..000000000 --- a/path_10_8/data/monster/Arachnids/sacred spider.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/sandstone scorpion.xml b/path_10_8/data/monster/Arachnids/sandstone scorpion.xml deleted file mode 100644 index 8872a3c4a..000000000 --- a/path_10_8/data/monster/Arachnids/sandstone scorpion.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/scorpion.xml b/path_10_8/data/monster/Arachnids/scorpion.xml deleted file mode 100644 index 2fb488840..000000000 --- a/path_10_8/data/monster/Arachnids/scorpion.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/spider.xml b/path_10_8/data/monster/Arachnids/spider.xml deleted file mode 100644 index a95c6bcdd..000000000 --- a/path_10_8/data/monster/Arachnids/spider.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/tarantula.xml b/path_10_8/data/monster/Arachnids/tarantula.xml deleted file mode 100644 index d29497c72..000000000 --- a/path_10_8/data/monster/Arachnids/tarantula.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arachnids/wailing widow.xml b/path_10_8/data/monster/Arachnids/wailing widow.xml deleted file mode 100644 index 2a1649a12..000000000 --- a/path_10_8/data/monster/Arachnids/wailing widow.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/achad.xml b/path_10_8/data/monster/Arena/greenhorn/achad.xml deleted file mode 100644 index 0db1ed333..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/achad.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/axeitus headbanger.xml b/path_10_8/data/monster/Arena/greenhorn/axeitus headbanger.xml deleted file mode 100644 index e165992d6..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/axeitus headbanger.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/bloodpaw.xml b/path_10_8/data/monster/Arena/greenhorn/bloodpaw.xml deleted file mode 100644 index 3d14ff56a..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/bloodpaw.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/bovinus.xml b/path_10_8/data/monster/Arena/greenhorn/bovinus.xml deleted file mode 100644 index e0e80b996..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/bovinus.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/colerian the barbarian.xml b/path_10_8/data/monster/Arena/greenhorn/colerian the barbarian.xml deleted file mode 100644 index cc298267a..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/colerian the barbarian.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/cursed gladiator.xml b/path_10_8/data/monster/Arena/greenhorn/cursed gladiator.xml deleted file mode 100644 index 6c9317702..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/cursed gladiator.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/frostfur.xml b/path_10_8/data/monster/Arena/greenhorn/frostfur.xml deleted file mode 100644 index 6ffa9bae0..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/frostfur.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/orcus the cruel.xml b/path_10_8/data/monster/Arena/greenhorn/orcus the cruel.xml deleted file mode 100644 index 56ecbb3a8..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/orcus the cruel.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/rocky.xml b/path_10_8/data/monster/Arena/greenhorn/rocky.xml deleted file mode 100644 index 7baca1b84..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/rocky.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/greenhorn/the hairy one.xml b/path_10_8/data/monster/Arena/greenhorn/the hairy one.xml deleted file mode 100644 index d77210a2e..000000000 --- a/path_10_8/data/monster/Arena/greenhorn/the hairy one.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/avalanche.xml b/path_10_8/data/monster/Arena/scrapper/avalanche.xml deleted file mode 100644 index 0e9f20d29..000000000 --- a/path_10_8/data/monster/Arena/scrapper/avalanche.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/drasilla.xml b/path_10_8/data/monster/Arena/scrapper/drasilla.xml deleted file mode 100644 index 7231d20d6..000000000 --- a/path_10_8/data/monster/Arena/scrapper/drasilla.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/grimgor guteater.xml b/path_10_8/data/monster/Arena/scrapper/grimgor guteater.xml deleted file mode 100644 index dad03967f..000000000 --- a/path_10_8/data/monster/Arena/scrapper/grimgor guteater.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/kreebosh the exile.xml b/path_10_8/data/monster/Arena/scrapper/kreebosh the exile.xml deleted file mode 100644 index 69848248f..000000000 --- a/path_10_8/data/monster/Arena/scrapper/kreebosh the exile.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/slim.xml b/path_10_8/data/monster/Arena/scrapper/slim.xml deleted file mode 100644 index be3afb692..000000000 --- a/path_10_8/data/monster/Arena/scrapper/slim.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/spirit of earth.xml b/path_10_8/data/monster/Arena/scrapper/spirit of earth.xml deleted file mode 100644 index 043ccf757..000000000 --- a/path_10_8/data/monster/Arena/scrapper/spirit of earth.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/spirit of fire.xml b/path_10_8/data/monster/Arena/scrapper/spirit of fire.xml deleted file mode 100644 index d092c93a2..000000000 --- a/path_10_8/data/monster/Arena/scrapper/spirit of fire.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/spirit of water.xml b/path_10_8/data/monster/Arena/scrapper/spirit of water.xml deleted file mode 100644 index 515ea1d70..000000000 --- a/path_10_8/data/monster/Arena/scrapper/spirit of water.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/the dark dancer.xml b/path_10_8/data/monster/Arena/scrapper/the dark dancer.xml deleted file mode 100644 index 2a8c3b05f..000000000 --- a/path_10_8/data/monster/Arena/scrapper/the dark dancer.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/scrapper/the hag.xml b/path_10_8/data/monster/Arena/scrapper/the hag.xml deleted file mode 100644 index 83326d47a..000000000 --- a/path_10_8/data/monster/Arena/scrapper/the hag.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/darakan the executioner.xml b/path_10_8/data/monster/Arena/warlord/darakan the executioner.xml deleted file mode 100644 index cc762e819..000000000 --- a/path_10_8/data/monster/Arena/warlord/darakan the executioner.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/deathbringer.xml b/path_10_8/data/monster/Arena/warlord/deathbringer.xml deleted file mode 100644 index ddf733af6..000000000 --- a/path_10_8/data/monster/Arena/warlord/deathbringer.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml b/path_10_8/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml deleted file mode 100644 index 9c58644b5..000000000 --- a/path_10_8/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/gnorre chyllson.xml b/path_10_8/data/monster/Arena/warlord/gnorre chyllson.xml deleted file mode 100644 index 3cd285d86..000000000 --- a/path_10_8/data/monster/Arena/warlord/gnorre chyllson.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/norgle glacierbeard.xml b/path_10_8/data/monster/Arena/warlord/norgle glacierbeard.xml deleted file mode 100644 index 8bb212f08..000000000 --- a/path_10_8/data/monster/Arena/warlord/norgle glacierbeard.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/svoren the mad.xml b/path_10_8/data/monster/Arena/warlord/svoren the mad.xml deleted file mode 100644 index a64bac1e1..000000000 --- a/path_10_8/data/monster/Arena/warlord/svoren the mad.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/the masked marauder.xml b/path_10_8/data/monster/Arena/warlord/the masked marauder.xml deleted file mode 100644 index 25d32ae1d..000000000 --- a/path_10_8/data/monster/Arena/warlord/the masked marauder.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/the obliverator.xml b/path_10_8/data/monster/Arena/warlord/the obliverator.xml deleted file mode 100644 index 46b2f9d7b..000000000 --- a/path_10_8/data/monster/Arena/warlord/the obliverator.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/the pit lord.xml b/path_10_8/data/monster/Arena/warlord/the pit lord.xml deleted file mode 100644 index 9a2d5935c..000000000 --- a/path_10_8/data/monster/Arena/warlord/the pit lord.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Arena/warlord/webster.xml b/path_10_8/data/monster/Arena/warlord/webster.xml deleted file mode 100644 index 73316b8de..000000000 --- a/path_10_8/data/monster/Arena/warlord/webster.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Barbarians/barbarian bloodwalker.xml b/path_10_8/data/monster/Barbarians/barbarian bloodwalker.xml deleted file mode 100644 index feb0c822e..000000000 --- a/path_10_8/data/monster/Barbarians/barbarian bloodwalker.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Barbarians/barbarian brutetamer.xml b/path_10_8/data/monster/Barbarians/barbarian brutetamer.xml deleted file mode 100644 index e88d3c3f2..000000000 --- a/path_10_8/data/monster/Barbarians/barbarian brutetamer.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Barbarians/barbarian headsplitter.xml b/path_10_8/data/monster/Barbarians/barbarian headsplitter.xml deleted file mode 100644 index 021f7e92e..000000000 --- a/path_10_8/data/monster/Barbarians/barbarian headsplitter.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Barbarians/barbarian skullhunter.xml b/path_10_8/data/monster/Barbarians/barbarian skullhunter.xml deleted file mode 100644 index 96e35ce8f..000000000 --- a/path_10_8/data/monster/Barbarians/barbarian skullhunter.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bears/bear.xml b/path_10_8/data/monster/Bears/bear.xml deleted file mode 100644 index aadc6484a..000000000 --- a/path_10_8/data/monster/Bears/bear.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bears/panda.xml b/path_10_8/data/monster/Bears/panda.xml deleted file mode 100644 index f28c2cc42..000000000 --- a/path_10_8/data/monster/Bears/panda.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bears/polar bear.xml b/path_10_8/data/monster/Bears/polar bear.xml deleted file mode 100644 index 10dbfe2a1..000000000 --- a/path_10_8/data/monster/Bears/polar bear.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bears/undead cavebear.xml b/path_10_8/data/monster/Bears/undead cavebear.xml deleted file mode 100644 index 9ac6941b7..000000000 --- a/path_10_8/data/monster/Bears/undead cavebear.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/bane bringer.xml b/path_10_8/data/monster/Bio-Elementals/bane bringer.xml deleted file mode 100644 index 617b747ad..000000000 --- a/path_10_8/data/monster/Bio-Elementals/bane bringer.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/bog raider.xml b/path_10_8/data/monster/Bio-Elementals/bog raider.xml deleted file mode 100644 index 1bdb9fae9..000000000 --- a/path_10_8/data/monster/Bio-Elementals/bog raider.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/carniphila.xml b/path_10_8/data/monster/Bio-Elementals/carniphila.xml deleted file mode 100644 index 3566ec5bc..000000000 --- a/path_10_8/data/monster/Bio-Elementals/carniphila.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/defiler.xml b/path_10_8/data/monster/Bio-Elementals/defiler.xml deleted file mode 100644 index bcd8b22e0..000000000 --- a/path_10_8/data/monster/Bio-Elementals/defiler.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/diseased bill.xml b/path_10_8/data/monster/Bio-Elementals/diseased bill.xml deleted file mode 100644 index 238c188cc..000000000 --- a/path_10_8/data/monster/Bio-Elementals/diseased bill.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/diseased dan.xml b/path_10_8/data/monster/Bio-Elementals/diseased dan.xml deleted file mode 100644 index 7c29f3206..000000000 --- a/path_10_8/data/monster/Bio-Elementals/diseased dan.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/diseased fred.xml b/path_10_8/data/monster/Bio-Elementals/diseased fred.xml deleted file mode 100644 index 08c29dcb9..000000000 --- a/path_10_8/data/monster/Bio-Elementals/diseased fred.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/haunted treeling.xml b/path_10_8/data/monster/Bio-Elementals/haunted treeling.xml deleted file mode 100644 index 2126941c3..000000000 --- a/path_10_8/data/monster/Bio-Elementals/haunted treeling.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/hideous fungus.xml b/path_10_8/data/monster/Bio-Elementals/hideous fungus.xml deleted file mode 100644 index 214301131..000000000 --- a/path_10_8/data/monster/Bio-Elementals/hideous fungus.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/humongous fungus.xml b/path_10_8/data/monster/Bio-Elementals/humongous fungus.xml deleted file mode 100644 index 36e0cd578..000000000 --- a/path_10_8/data/monster/Bio-Elementals/humongous fungus.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/humorless fungus.xml b/path_10_8/data/monster/Bio-Elementals/humorless fungus.xml deleted file mode 100644 index 3ffa98b8f..000000000 --- a/path_10_8/data/monster/Bio-Elementals/humorless fungus.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/leaf golem.xml b/path_10_8/data/monster/Bio-Elementals/leaf golem.xml deleted file mode 100644 index cc382afed..000000000 --- a/path_10_8/data/monster/Bio-Elementals/leaf golem.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/mechanical fighter.xml b/path_10_8/data/monster/Bio-Elementals/mechanical fighter.xml deleted file mode 100644 index 5a0eb4ef9..000000000 --- a/path_10_8/data/monster/Bio-Elementals/mechanical fighter.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/slime.xml b/path_10_8/data/monster/Bio-Elementals/slime.xml deleted file mode 100644 index b5ce4125a..000000000 --- a/path_10_8/data/monster/Bio-Elementals/slime.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/son of verminor.xml b/path_10_8/data/monster/Bio-Elementals/son of verminor.xml deleted file mode 100644 index e5efdf806..000000000 --- a/path_10_8/data/monster/Bio-Elementals/son of verminor.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/spit nettle.xml b/path_10_8/data/monster/Bio-Elementals/spit nettle.xml deleted file mode 100644 index 5ceebd9a8..000000000 --- a/path_10_8/data/monster/Bio-Elementals/spit nettle.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/strange slime.xml b/path_10_8/data/monster/Bio-Elementals/strange slime.xml deleted file mode 100644 index 2f246ac8a..000000000 --- a/path_10_8/data/monster/Bio-Elementals/strange slime.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/swampling.xml b/path_10_8/data/monster/Bio-Elementals/swampling.xml deleted file mode 100644 index 4a3d35fbf..000000000 --- a/path_10_8/data/monster/Bio-Elementals/swampling.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bio-Elementals/wilting leaf golem.xml b/path_10_8/data/monster/Bio-Elementals/wilting leaf golem.xml deleted file mode 100644 index d7acf87b1..000000000 --- a/path_10_8/data/monster/Bio-Elementals/wilting leaf golem.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/berserker chicken.xml b/path_10_8/data/monster/Birds/berserker chicken.xml deleted file mode 100644 index 65075f5e3..000000000 --- a/path_10_8/data/monster/Birds/berserker chicken.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/chicken.xml b/path_10_8/data/monster/Birds/chicken.xml deleted file mode 100644 index 88ea45900..000000000 --- a/path_10_8/data/monster/Birds/chicken.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/demon parrot.xml b/path_10_8/data/monster/Birds/demon parrot.xml deleted file mode 100644 index ad85ba90e..000000000 --- a/path_10_8/data/monster/Birds/demon parrot.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/dire penguin.xml b/path_10_8/data/monster/Birds/dire penguin.xml deleted file mode 100644 index 8c12ef4d1..000000000 --- a/path_10_8/data/monster/Birds/dire penguin.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/flamingo.xml b/path_10_8/data/monster/Birds/flamingo.xml deleted file mode 100644 index 3c136ef9e..000000000 --- a/path_10_8/data/monster/Birds/flamingo.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/marsh stalker.xml b/path_10_8/data/monster/Birds/marsh stalker.xml deleted file mode 100644 index bd6cef70e..000000000 --- a/path_10_8/data/monster/Birds/marsh stalker.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/parrot.xml b/path_10_8/data/monster/Birds/parrot.xml deleted file mode 100644 index 446d6b47d..000000000 --- a/path_10_8/data/monster/Birds/parrot.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/penguin.xml b/path_10_8/data/monster/Birds/penguin.xml deleted file mode 100644 index aaed616e8..000000000 --- a/path_10_8/data/monster/Birds/penguin.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/pigeon.xml b/path_10_8/data/monster/Birds/pigeon.xml deleted file mode 100644 index 89f850ed8..000000000 --- a/path_10_8/data/monster/Birds/pigeon.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/seagull.xml b/path_10_8/data/monster/Birds/seagull.xml deleted file mode 100644 index ee1c8ee4f..000000000 --- a/path_10_8/data/monster/Birds/seagull.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Birds/terror bird.xml b/path_10_8/data/monster/Birds/terror bird.xml deleted file mode 100644 index ad5368f70..000000000 --- a/path_10_8/data/monster/Birds/terror bird.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/acid blob.xml b/path_10_8/data/monster/Blobs/acid blob.xml deleted file mode 100644 index f9ba1dfb3..000000000 --- a/path_10_8/data/monster/Blobs/acid blob.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/death blob.xml b/path_10_8/data/monster/Blobs/death blob.xml deleted file mode 100644 index b6dacaadd..000000000 --- a/path_10_8/data/monster/Blobs/death blob.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/essence of darkness.xml b/path_10_8/data/monster/Blobs/essence of darkness.xml deleted file mode 100644 index 36da96f2e..000000000 --- a/path_10_8/data/monster/Blobs/essence of darkness.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/floor blob.xml b/path_10_8/data/monster/Blobs/floor blob.xml deleted file mode 100644 index 612157b78..000000000 --- a/path_10_8/data/monster/Blobs/floor blob.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/mercury blob.xml b/path_10_8/data/monster/Blobs/mercury blob.xml deleted file mode 100644 index 5b702d50f..000000000 --- a/path_10_8/data/monster/Blobs/mercury blob.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Blobs/midnight spawn.xml b/path_10_8/data/monster/Blobs/midnight spawn.xml deleted file mode 100644 index 3ad0ec88e..000000000 --- a/path_10_8/data/monster/Blobs/midnight spawn.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bonelords/bonelord.xml b/path_10_8/data/monster/Bonelords/bonelord.xml deleted file mode 100644 index d2fe74624..000000000 --- a/path_10_8/data/monster/Bonelords/bonelord.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bonelords/braindeath.xml b/path_10_8/data/monster/Bonelords/braindeath.xml deleted file mode 100644 index e4d6b093b..000000000 --- a/path_10_8/data/monster/Bonelords/braindeath.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bonelords/elder bonelord.xml b/path_10_8/data/monster/Bonelords/elder bonelord.xml deleted file mode 100644 index e055f8ce4..000000000 --- a/path_10_8/data/monster/Bonelords/elder bonelord.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bonelords/eye of the seven.xml b/path_10_8/data/monster/Bonelords/eye of the seven.xml deleted file mode 100644 index bbe77e28c..000000000 --- a/path_10_8/data/monster/Bonelords/eye of the seven.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bonelords/gazer.xml b/path_10_8/data/monster/Bonelords/gazer.xml deleted file mode 100644 index 68100fb24..000000000 --- a/path_10_8/data/monster/Bonelords/gazer.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Apocalypse.xml b/path_10_8/data/monster/Bosses/Apocalypse.xml deleted file mode 100644 index 27f6f6462..000000000 --- a/path_10_8/data/monster/Bosses/Apocalypse.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Arachir the ancient one.xml b/path_10_8/data/monster/Bosses/Arachir the ancient one.xml deleted file mode 100644 index a76eda1d1..000000000 --- a/path_10_8/data/monster/Bosses/Arachir the ancient one.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Bazir.xml b/path_10_8/data/monster/Bosses/Bazir.xml deleted file mode 100644 index d20912797..000000000 --- a/path_10_8/data/monster/Bosses/Bazir.xml +++ /dev/null @@ -1,157 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Coldheart.xml b/path_10_8/data/monster/Bosses/Coldheart.xml deleted file mode 100644 index 798cdab38..000000000 --- a/path_10_8/data/monster/Bosses/Coldheart.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Diblis The Fair.xml b/path_10_8/data/monster/Bosses/Diblis The Fair.xml deleted file mode 100644 index a9403ef9f..000000000 --- a/path_10_8/data/monster/Bosses/Diblis The Fair.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Doomhowl.xml b/path_10_8/data/monster/Bosses/Doomhowl.xml deleted file mode 100644 index 8c8a01467..000000000 --- a/path_10_8/data/monster/Bosses/Doomhowl.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Freegoiz.xml b/path_10_8/data/monster/Bosses/Freegoiz.xml deleted file mode 100644 index 5ead241ce..000000000 --- a/path_10_8/data/monster/Bosses/Freegoiz.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Infernatil.xml b/path_10_8/data/monster/Bosses/Infernatil.xml deleted file mode 100644 index e95d89072..000000000 --- a/path_10_8/data/monster/Bosses/Infernatil.xml +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Kraknaknork Demon.xml b/path_10_8/data/monster/Bosses/Kraknaknork Demon.xml deleted file mode 100644 index eed05d3ab..000000000 --- a/path_10_8/data/monster/Bosses/Kraknaknork Demon.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Obujos.xml b/path_10_8/data/monster/Bosses/Obujos.xml deleted file mode 100644 index 1d9c84e80..000000000 --- a/path_10_8/data/monster/Bosses/Obujos.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Rottie the Rotworm.xml b/path_10_8/data/monster/Bosses/Rottie the Rotworm.xml deleted file mode 100644 index 5a79613cc..000000000 --- a/path_10_8/data/monster/Bosses/Rottie the Rotworm.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Sir Valorcrest.xml b/path_10_8/data/monster/Bosses/Sir Valorcrest.xml deleted file mode 100644 index e0697fcfe..000000000 --- a/path_10_8/data/monster/Bosses/Sir Valorcrest.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Tanjis.xml b/path_10_8/data/monster/Bosses/Tanjis.xml deleted file mode 100644 index 51e00d2f5..000000000 --- a/path_10_8/data/monster/Bosses/Tanjis.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Verminor.xml b/path_10_8/data/monster/Bosses/Verminor.xml deleted file mode 100644 index 110e9d732..000000000 --- a/path_10_8/data/monster/Bosses/Verminor.xml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Yaga The Crone.xml b/path_10_8/data/monster/Bosses/Yaga The Crone.xml deleted file mode 100644 index 52f4af3d3..000000000 --- a/path_10_8/data/monster/Bosses/Yaga The Crone.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Zevelon Duskbringer.xml b/path_10_8/data/monster/Bosses/Zevelon Duskbringer.xml deleted file mode 100644 index 3f22837c5..000000000 --- a/path_10_8/data/monster/Bosses/Zevelon Duskbringer.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/Zoralurk.xml b/path_10_8/data/monster/Bosses/Zoralurk.xml deleted file mode 100644 index 92cfdf057..000000000 --- a/path_10_8/data/monster/Bosses/Zoralurk.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/abyssador.xml b/path_10_8/data/monster/Bosses/abyssador.xml deleted file mode 100644 index 71df174b2..000000000 --- a/path_10_8/data/monster/Bosses/abyssador.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/annihilon.xml b/path_10_8/data/monster/Bosses/annihilon.xml deleted file mode 100644 index 8392ed6c3..000000000 --- a/path_10_8/data/monster/Bosses/annihilon.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/apprentice sheng.xml b/path_10_8/data/monster/Bosses/apprentice sheng.xml deleted file mode 100644 index c9e18a14b..000000000 --- a/path_10_8/data/monster/Bosses/apprentice sheng.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/barbaria.xml b/path_10_8/data/monster/Bosses/barbaria.xml deleted file mode 100644 index a01fe1c81..000000000 --- a/path_10_8/data/monster/Bosses/barbaria.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/baron brute.xml b/path_10_8/data/monster/Bosses/baron brute.xml deleted file mode 100644 index 45df975c0..000000000 --- a/path_10_8/data/monster/Bosses/baron brute.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/big boss trolliver.xml b/path_10_8/data/monster/Bosses/big boss trolliver.xml deleted file mode 100644 index b6c91f90a..000000000 --- a/path_10_8/data/monster/Bosses/big boss trolliver.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/bones.xml b/path_10_8/data/monster/Bosses/bones.xml deleted file mode 100644 index f385a0e52..000000000 --- a/path_10_8/data/monster/Bosses/bones.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/boogey.xml b/path_10_8/data/monster/Bosses/boogey.xml deleted file mode 100644 index c3ea08201..000000000 --- a/path_10_8/data/monster/Bosses/boogey.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/brutus bloodbeard.xml b/path_10_8/data/monster/Bosses/brutus bloodbeard.xml deleted file mode 100644 index 4be5f9b57..000000000 --- a/path_10_8/data/monster/Bosses/brutus bloodbeard.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/chizzoron the distorter.xml b/path_10_8/data/monster/Bosses/chizzoron the distorter.xml deleted file mode 100644 index 5bcd35b33..000000000 --- a/path_10_8/data/monster/Bosses/chizzoron the distorter.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/countess sorrow.xml b/path_10_8/data/monster/Bosses/countess sorrow.xml deleted file mode 100644 index e45febdb0..000000000 --- a/path_10_8/data/monster/Bosses/countess sorrow.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/deadeye devious.xml b/path_10_8/data/monster/Bosses/deadeye devious.xml deleted file mode 100644 index 73a05a4e9..000000000 --- a/path_10_8/data/monster/Bosses/deadeye devious.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/deathbine.xml b/path_10_8/data/monster/Bosses/deathbine.xml deleted file mode 100644 index a908d69dd..000000000 --- a/path_10_8/data/monster/Bosses/deathbine.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/demodras.xml b/path_10_8/data/monster/Bosses/demodras.xml deleted file mode 100644 index 54c1e1c90..000000000 --- a/path_10_8/data/monster/Bosses/demodras.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/dharalion.xml b/path_10_8/data/monster/Bosses/dharalion.xml deleted file mode 100644 index 89caa1d53..000000000 --- a/path_10_8/data/monster/Bosses/dharalion.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/dirtbeard.xml b/path_10_8/data/monster/Bosses/dirtbeard.xml deleted file mode 100644 index 43d35baf4..000000000 --- a/path_10_8/data/monster/Bosses/dirtbeard.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/dracola.xml b/path_10_8/data/monster/Bosses/dracola.xml deleted file mode 100644 index ccdd255cd..000000000 --- a/path_10_8/data/monster/Bosses/dracola.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/dreadwing.xml b/path_10_8/data/monster/Bosses/dreadwing.xml deleted file mode 100644 index c371aea73..000000000 --- a/path_10_8/data/monster/Bosses/dreadwing.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/esmeralda.xml b/path_10_8/data/monster/Bosses/esmeralda.xml deleted file mode 100644 index f78384346..000000000 --- a/path_10_8/data/monster/Bosses/esmeralda.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/evil mastermind.xml b/path_10_8/data/monster/Bosses/evil mastermind.xml deleted file mode 100644 index 602055252..000000000 --- a/path_10_8/data/monster/Bosses/evil mastermind.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/fatality.xml b/path_10_8/data/monster/Bosses/fatality.xml deleted file mode 100644 index d1298223b..000000000 --- a/path_10_8/data/monster/Bosses/fatality.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/fernfang.xml b/path_10_8/data/monster/Bosses/fernfang.xml deleted file mode 100644 index b52032e4e..000000000 --- a/path_10_8/data/monster/Bosses/fernfang.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/ferumbras.xml b/path_10_8/data/monster/Bosses/ferumbras.xml deleted file mode 100644 index 9db7be7be..000000000 --- a/path_10_8/data/monster/Bosses/ferumbras.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/fluffy.xml b/path_10_8/data/monster/Bosses/fluffy.xml deleted file mode 100644 index d5303b3b7..000000000 --- a/path_10_8/data/monster/Bosses/fluffy.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/foreman kneebiter.xml b/path_10_8/data/monster/Bosses/foreman kneebiter.xml deleted file mode 100644 index c1a98b53a..000000000 --- a/path_10_8/data/monster/Bosses/foreman kneebiter.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/fury of the emperor.xml b/path_10_8/data/monster/Bosses/fury of the emperor.xml deleted file mode 100644 index 6c2a9791b..000000000 --- a/path_10_8/data/monster/Bosses/fury of the emperor.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/gaz'haragoth.xml b/path_10_8/data/monster/Bosses/gaz'haragoth.xml deleted file mode 100644 index 941c7efff..000000000 --- a/path_10_8/data/monster/Bosses/gaz'haragoth.xml +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/general murius.xml b/path_10_8/data/monster/Bosses/general murius.xml deleted file mode 100644 index b70687c80..000000000 --- a/path_10_8/data/monster/Bosses/general murius.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/glitterscale.xml b/path_10_8/data/monster/Bosses/glitterscale.xml deleted file mode 100644 index 328529f5c..000000000 --- a/path_10_8/data/monster/Bosses/glitterscale.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/gnomevil.xml b/path_10_8/data/monster/Bosses/gnomevil.xml deleted file mode 100644 index 0068aa653..000000000 --- a/path_10_8/data/monster/Bosses/gnomevil.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/golgordan.xml b/path_10_8/data/monster/Bosses/golgordan.xml deleted file mode 100644 index 824ce7919..000000000 --- a/path_10_8/data/monster/Bosses/golgordan.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/grand mother foulscale.xml b/path_10_8/data/monster/Bosses/grand mother foulscale.xml deleted file mode 100644 index 4efc511b7..000000000 --- a/path_10_8/data/monster/Bosses/grand mother foulscale.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/groam.xml b/path_10_8/data/monster/Bosses/groam.xml deleted file mode 100644 index 7ea994bd9..000000000 --- a/path_10_8/data/monster/Bosses/groam.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/grorlam.xml b/path_10_8/data/monster/Bosses/grorlam.xml deleted file mode 100644 index 22ef85b6f..000000000 --- a/path_10_8/data/monster/Bosses/grorlam.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/hairman the huge.xml b/path_10_8/data/monster/Bosses/hairman the huge.xml deleted file mode 100644 index 21a1f5b6b..000000000 --- a/path_10_8/data/monster/Bosses/hairman the huge.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/handmaiden.xml b/path_10_8/data/monster/Bosses/handmaiden.xml deleted file mode 100644 index 4bb54db11..000000000 --- a/path_10_8/data/monster/Bosses/handmaiden.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/haunter.xml b/path_10_8/data/monster/Bosses/haunter.xml deleted file mode 100644 index f85cd716a..000000000 --- a/path_10_8/data/monster/Bosses/haunter.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/hellgorak.xml b/path_10_8/data/monster/Bosses/hellgorak.xml deleted file mode 100644 index 084206556..000000000 --- a/path_10_8/data/monster/Bosses/hellgorak.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/heoni.xml b/path_10_8/data/monster/Bosses/heoni.xml deleted file mode 100644 index 36be2e99f..000000000 --- a/path_10_8/data/monster/Bosses/heoni.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/hide.xml b/path_10_8/data/monster/Bosses/hide.xml deleted file mode 100644 index ebd4b35db..000000000 --- a/path_10_8/data/monster/Bosses/hide.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/incineron.xml b/path_10_8/data/monster/Bosses/incineron.xml deleted file mode 100644 index fe3fc533e..000000000 --- a/path_10_8/data/monster/Bosses/incineron.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/inky.xml b/path_10_8/data/monster/Bosses/inky.xml deleted file mode 100644 index 70fb698fa..000000000 --- a/path_10_8/data/monster/Bosses/inky.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/jaul.xml b/path_10_8/data/monster/Bosses/jaul.xml deleted file mode 100644 index 4e4dea7ce..000000000 --- a/path_10_8/data/monster/Bosses/jaul.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/koshei the deathless.xml b/path_10_8/data/monster/Bosses/koshei the deathless.xml deleted file mode 100644 index 8f2b5aa02..000000000 --- a/path_10_8/data/monster/Bosses/koshei the deathless.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/kraknaknork.xml b/path_10_8/data/monster/Bosses/kraknaknork.xml deleted file mode 100644 index 52cbb39e4..000000000 --- a/path_10_8/data/monster/Bosses/kraknaknork.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/latrivan.xml b/path_10_8/data/monster/Bosses/latrivan.xml deleted file mode 100644 index 75203e7d5..000000000 --- a/path_10_8/data/monster/Bosses/latrivan.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/lethal lissy.xml b/path_10_8/data/monster/Bosses/lethal lissy.xml deleted file mode 100644 index bbc2df0b8..000000000 --- a/path_10_8/data/monster/Bosses/lethal lissy.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/leviathan.xml b/path_10_8/data/monster/Bosses/leviathan.xml deleted file mode 100644 index 47ddf46a3..000000000 --- a/path_10_8/data/monster/Bosses/leviathan.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/mad mage.xml b/path_10_8/data/monster/Bosses/mad mage.xml deleted file mode 100644 index 91553b35e..000000000 --- a/path_10_8/data/monster/Bosses/mad mage.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/mad technomancer.xml b/path_10_8/data/monster/Bosses/mad technomancer.xml deleted file mode 100644 index 5821937ad..000000000 --- a/path_10_8/data/monster/Bosses/mad technomancer.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/madareth.xml b/path_10_8/data/monster/Bosses/madareth.xml deleted file mode 100644 index 571187caa..000000000 --- a/path_10_8/data/monster/Bosses/madareth.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/man in the cave.xml b/path_10_8/data/monster/Bosses/man in the cave.xml deleted file mode 100644 index 95390f088..000000000 --- a/path_10_8/data/monster/Bosses/man in the cave.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/massacre.xml b/path_10_8/data/monster/Bosses/massacre.xml deleted file mode 100644 index ca19022e8..000000000 --- a/path_10_8/data/monster/Bosses/massacre.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/mawhawk.xml b/path_10_8/data/monster/Bosses/mawhawk.xml deleted file mode 100644 index 117849ed4..000000000 --- a/path_10_8/data/monster/Bosses/mawhawk.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/menace.xml b/path_10_8/data/monster/Bosses/menace.xml deleted file mode 100644 index 217e1ef12..000000000 --- a/path_10_8/data/monster/Bosses/menace.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/mephiles.xml b/path_10_8/data/monster/Bosses/mephiles.xml deleted file mode 100644 index 81a6e62b9..000000000 --- a/path_10_8/data/monster/Bosses/mephiles.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/minishabaal.xml b/path_10_8/data/monster/Bosses/minishabaal.xml deleted file mode 100644 index 710d9f86a..000000000 --- a/path_10_8/data/monster/Bosses/minishabaal.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/monstor.xml b/path_10_8/data/monster/Bosses/monstor.xml deleted file mode 100644 index 28c16c138..000000000 --- a/path_10_8/data/monster/Bosses/monstor.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/mr. punish.xml b/path_10_8/data/monster/Bosses/mr. punish.xml deleted file mode 100644 index 173c3f629..000000000 --- a/path_10_8/data/monster/Bosses/mr. punish.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/munster.xml b/path_10_8/data/monster/Bosses/munster.xml deleted file mode 100644 index 625dded01..000000000 --- a/path_10_8/data/monster/Bosses/munster.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/necropharus.xml b/path_10_8/data/monster/Bosses/necropharus.xml deleted file mode 100644 index 50bf98f38..000000000 --- a/path_10_8/data/monster/Bosses/necropharus.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/pythius the rotten.xml b/path_10_8/data/monster/Bosses/pythius the rotten.xml deleted file mode 100644 index 60bf96f3d..000000000 --- a/path_10_8/data/monster/Bosses/pythius the rotten.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/rocko.xml b/path_10_8/data/monster/Bosses/rocko.xml deleted file mode 100644 index e8449a41f..000000000 --- a/path_10_8/data/monster/Bosses/rocko.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/ron the ripper.xml b/path_10_8/data/monster/Bosses/ron the ripper.xml deleted file mode 100644 index ee098800f..000000000 --- a/path_10_8/data/monster/Bosses/ron the ripper.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/rotworm queen.xml b/path_10_8/data/monster/Bosses/rotworm queen.xml deleted file mode 100644 index 503c56687..000000000 --- a/path_10_8/data/monster/Bosses/rotworm queen.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/scorn of the emperor.xml b/path_10_8/data/monster/Bosses/scorn of the emperor.xml deleted file mode 100644 index 474da5922..000000000 --- a/path_10_8/data/monster/Bosses/scorn of the emperor.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/shardhead.xml b/path_10_8/data/monster/Bosses/shardhead.xml deleted file mode 100644 index 17aa1bf1b..000000000 --- a/path_10_8/data/monster/Bosses/shardhead.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/sharptooth.xml b/path_10_8/data/monster/Bosses/sharptooth.xml deleted file mode 100644 index 93c7d92b5..000000000 --- a/path_10_8/data/monster/Bosses/sharptooth.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/snake god essence.xml b/path_10_8/data/monster/Bosses/snake god essence.xml deleted file mode 100644 index 57c05aa4d..000000000 --- a/path_10_8/data/monster/Bosses/snake god essence.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/snake thing.xml b/path_10_8/data/monster/Bosses/snake thing.xml deleted file mode 100644 index 80abbdb0e..000000000 --- a/path_10_8/data/monster/Bosses/snake thing.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/spider queen.xml b/path_10_8/data/monster/Bosses/spider queen.xml deleted file mode 100644 index 606df76da..000000000 --- a/path_10_8/data/monster/Bosses/spider queen.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/spite of the emperor.xml b/path_10_8/data/monster/Bosses/spite of the emperor.xml deleted file mode 100644 index 54c1e1039..000000000 --- a/path_10_8/data/monster/Bosses/spite of the emperor.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/splasher.xml b/path_10_8/data/monster/Bosses/splasher.xml deleted file mode 100644 index 8e025f368..000000000 --- a/path_10_8/data/monster/Bosses/splasher.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/stonecracker.xml b/path_10_8/data/monster/Bosses/stonecracker.xml deleted file mode 100644 index 6ca19258c..000000000 --- a/path_10_8/data/monster/Bosses/stonecracker.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/terofar.xml b/path_10_8/data/monster/Bosses/terofar.xml deleted file mode 100644 index c96bf647a..000000000 --- a/path_10_8/data/monster/Bosses/terofar.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the abomination.xml b/path_10_8/data/monster/Bosses/the abomination.xml deleted file mode 100644 index fc1ffad1b..000000000 --- a/path_10_8/data/monster/Bosses/the abomination.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the axeorcist.xml b/path_10_8/data/monster/Bosses/the axeorcist.xml deleted file mode 100644 index e19e9ef02..000000000 --- a/path_10_8/data/monster/Bosses/the axeorcist.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the blightfather.xml b/path_10_8/data/monster/Bosses/the blightfather.xml deleted file mode 100644 index db7682f9d..000000000 --- a/path_10_8/data/monster/Bosses/the blightfather.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the bloodtusk.xml b/path_10_8/data/monster/Bosses/the bloodtusk.xml deleted file mode 100644 index 6c918812a..000000000 --- a/path_10_8/data/monster/Bosses/the bloodtusk.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the bloodweb.xml b/path_10_8/data/monster/Bosses/the bloodweb.xml deleted file mode 100644 index 4ade9ec4c..000000000 --- a/path_10_8/data/monster/Bosses/the bloodweb.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the count.xml b/path_10_8/data/monster/Bosses/the count.xml deleted file mode 100644 index 7c7cf1ddd..000000000 --- a/path_10_8/data/monster/Bosses/the count.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the dreadorian.xml b/path_10_8/data/monster/Bosses/the dreadorian.xml deleted file mode 100644 index 5cb278aa5..000000000 --- a/path_10_8/data/monster/Bosses/the dreadorian.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the evil eye.xml b/path_10_8/data/monster/Bosses/the evil eye.xml deleted file mode 100644 index c96ada487..000000000 --- a/path_10_8/data/monster/Bosses/the evil eye.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the frog prince.xml b/path_10_8/data/monster/Bosses/the frog prince.xml deleted file mode 100644 index bd68c2144..000000000 --- a/path_10_8/data/monster/Bosses/the frog prince.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the handmaiden.xml b/path_10_8/data/monster/Bosses/the handmaiden.xml deleted file mode 100644 index 34412f754..000000000 --- a/path_10_8/data/monster/Bosses/the handmaiden.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the horned fox.xml b/path_10_8/data/monster/Bosses/the horned fox.xml deleted file mode 100644 index 78bf98205..000000000 --- a/path_10_8/data/monster/Bosses/the horned fox.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the imperor.xml b/path_10_8/data/monster/Bosses/the imperor.xml deleted file mode 100644 index fa0159626..000000000 --- a/path_10_8/data/monster/Bosses/the imperor.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the many.xml b/path_10_8/data/monster/Bosses/the many.xml deleted file mode 100644 index f43a898c6..000000000 --- a/path_10_8/data/monster/Bosses/the many.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the noxious spawn.xml b/path_10_8/data/monster/Bosses/the noxious spawn.xml deleted file mode 100644 index 7d59d333b..000000000 --- a/path_10_8/data/monster/Bosses/the noxious spawn.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the old widow.xml b/path_10_8/data/monster/Bosses/the old widow.xml deleted file mode 100644 index 7f80a6256..000000000 --- a/path_10_8/data/monster/Bosses/the old widow.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the plasmother.xml b/path_10_8/data/monster/Bosses/the plasmother.xml deleted file mode 100644 index d603a3be2..000000000 --- a/path_10_8/data/monster/Bosses/the plasmother.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/the snapper.xml b/path_10_8/data/monster/Bosses/the snapper.xml deleted file mode 100644 index f73ccada0..000000000 --- a/path_10_8/data/monster/Bosses/the snapper.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/thul.xml b/path_10_8/data/monster/Bosses/thul.xml deleted file mode 100644 index c3c171db4..000000000 --- a/path_10_8/data/monster/Bosses/thul.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/tiquandas revenge.xml b/path_10_8/data/monster/Bosses/tiquandas revenge.xml deleted file mode 100644 index 66bf30f63..000000000 --- a/path_10_8/data/monster/Bosses/tiquandas revenge.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/tirecz.xml b/path_10_8/data/monster/Bosses/tirecz.xml deleted file mode 100644 index 6d0cf2490..000000000 --- a/path_10_8/data/monster/Bosses/tirecz.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/tremorak.xml b/path_10_8/data/monster/Bosses/tremorak.xml deleted file mode 100644 index 48e23a9ab..000000000 --- a/path_10_8/data/monster/Bosses/tremorak.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/ungreez.xml b/path_10_8/data/monster/Bosses/ungreez.xml deleted file mode 100644 index 0b437bcdd..000000000 --- a/path_10_8/data/monster/Bosses/ungreez.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/ushuriel.xml b/path_10_8/data/monster/Bosses/ushuriel.xml deleted file mode 100644 index 03bb978b9..000000000 --- a/path_10_8/data/monster/Bosses/ushuriel.xml +++ /dev/null @@ -1,106 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/versperoth.xml b/path_10_8/data/monster/Bosses/versperoth.xml deleted file mode 100644 index 89f22e399..000000000 --- a/path_10_8/data/monster/Bosses/versperoth.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/warlord ruzad.xml b/path_10_8/data/monster/Bosses/warlord ruzad.xml deleted file mode 100644 index 9c95ba93f..000000000 --- a/path_10_8/data/monster/Bosses/warlord ruzad.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/wrath of the emperor.xml b/path_10_8/data/monster/Bosses/wrath of the emperor.xml deleted file mode 100644 index 1c6ceab57..000000000 --- a/path_10_8/data/monster/Bosses/wrath of the emperor.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/xenia.xml b/path_10_8/data/monster/Bosses/xenia.xml deleted file mode 100644 index aa03ef9e9..000000000 --- a/path_10_8/data/monster/Bosses/xenia.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/yakchal.xml b/path_10_8/data/monster/Bosses/yakchal.xml deleted file mode 100644 index 3c05fd4ac..000000000 --- a/path_10_8/data/monster/Bosses/yakchal.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/zomba.xml b/path_10_8/data/monster/Bosses/zomba.xml deleted file mode 100644 index c2fcf6082..000000000 --- a/path_10_8/data/monster/Bosses/zomba.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/zugurosh.xml b/path_10_8/data/monster/Bosses/zugurosh.xml deleted file mode 100644 index af39ca880..000000000 --- a/path_10_8/data/monster/Bosses/zugurosh.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Bosses/zulazza the corruptor.xml b/path_10_8/data/monster/Bosses/zulazza the corruptor.xml deleted file mode 100644 index b0d6a3afe..000000000 --- a/path_10_8/data/monster/Bosses/zulazza the corruptor.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/crystal wolf.xml b/path_10_8/data/monster/Canines/crystal wolf.xml deleted file mode 100644 index 9cdb024de..000000000 --- a/path_10_8/data/monster/Canines/crystal wolf.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/dog.xml b/path_10_8/data/monster/Canines/dog.xml deleted file mode 100644 index 01aeee631..000000000 --- a/path_10_8/data/monster/Canines/dog.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/gnarlhound.xml b/path_10_8/data/monster/Canines/gnarlhound.xml deleted file mode 100644 index cd60f98b2..000000000 --- a/path_10_8/data/monster/Canines/gnarlhound.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/hellhound.xml b/path_10_8/data/monster/Canines/hellhound.xml deleted file mode 100644 index 029c3223f..000000000 --- a/path_10_8/data/monster/Canines/hellhound.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/hot dog.xml b/path_10_8/data/monster/Canines/hot dog.xml deleted file mode 100644 index 4e412ea7a..000000000 --- a/path_10_8/data/monster/Canines/hot dog.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/husky.xml b/path_10_8/data/monster/Canines/husky.xml deleted file mode 100644 index 6cd6ce778..000000000 --- a/path_10_8/data/monster/Canines/husky.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/poodle.xml b/path_10_8/data/monster/Canines/poodle.xml deleted file mode 100644 index 530d6f4b0..000000000 --- a/path_10_8/data/monster/Canines/poodle.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/starving wolf.xml b/path_10_8/data/monster/Canines/starving wolf.xml deleted file mode 100644 index 868bae688..000000000 --- a/path_10_8/data/monster/Canines/starving wolf.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/thornfire wolf.xml b/path_10_8/data/monster/Canines/thornfire wolf.xml deleted file mode 100644 index 8d3f3796d..000000000 --- a/path_10_8/data/monster/Canines/thornfire wolf.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/war wolf.xml b/path_10_8/data/monster/Canines/war wolf.xml deleted file mode 100644 index 370dceb2e..000000000 --- a/path_10_8/data/monster/Canines/war wolf.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/werewolf.xml b/path_10_8/data/monster/Canines/werewolf.xml deleted file mode 100644 index edddd7df7..000000000 --- a/path_10_8/data/monster/Canines/werewolf.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/wild dog.xml b/path_10_8/data/monster/Canines/wild dog.xml deleted file mode 100644 index dbcf826fb..000000000 --- a/path_10_8/data/monster/Canines/wild dog.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/winter wolf.xml b/path_10_8/data/monster/Canines/winter wolf.xml deleted file mode 100644 index 10a1b81cd..000000000 --- a/path_10_8/data/monster/Canines/winter wolf.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Canines/wolf.xml b/path_10_8/data/monster/Canines/wolf.xml deleted file mode 100644 index aae6a9dec..000000000 --- a/path_10_8/data/monster/Canines/wolf.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Chakoyas/chakoya toolshaper.xml b/path_10_8/data/monster/Chakoyas/chakoya toolshaper.xml deleted file mode 100644 index 2511233a5..000000000 --- a/path_10_8/data/monster/Chakoyas/chakoya toolshaper.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Chakoyas/chakoya tribewarden.xml b/path_10_8/data/monster/Chakoyas/chakoya tribewarden.xml deleted file mode 100644 index 9380ca6f8..000000000 --- a/path_10_8/data/monster/Chakoyas/chakoya tribewarden.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Chakoyas/chakoya windcaller.xml b/path_10_8/data/monster/Chakoyas/chakoya windcaller.xml deleted file mode 100644 index 26bfde6a9..000000000 --- a/path_10_8/data/monster/Chakoyas/chakoya windcaller.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Cnidarians/jellyfish.xml b/path_10_8/data/monster/Cnidarians/jellyfish.xml deleted file mode 100644 index 8308b4de3..000000000 --- a/path_10_8/data/monster/Cnidarians/jellyfish.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Corym/corym charlatan.xml b/path_10_8/data/monster/Corym/corym charlatan.xml deleted file mode 100644 index a358f0c26..000000000 --- a/path_10_8/data/monster/Corym/corym charlatan.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Corym/corym skirmisher.xml b/path_10_8/data/monster/Corym/corym skirmisher.xml deleted file mode 100644 index 6961ebe95..000000000 --- a/path_10_8/data/monster/Corym/corym skirmisher.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Corym/corym vanguard.xml b/path_10_8/data/monster/Corym/corym vanguard.xml deleted file mode 100644 index b80ec1829..000000000 --- a/path_10_8/data/monster/Corym/corym vanguard.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Corym/little corym charlatan.xml b/path_10_8/data/monster/Corym/little corym charlatan.xml deleted file mode 100644 index 42aced103..000000000 --- a/path_10_8/data/monster/Corym/little corym charlatan.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Crustaceans/blood crab underwater.xml b/path_10_8/data/monster/Crustaceans/blood crab underwater.xml deleted file mode 100644 index 4062df0ba..000000000 --- a/path_10_8/data/monster/Crustaceans/blood crab underwater.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Crustaceans/blood crab.xml b/path_10_8/data/monster/Crustaceans/blood crab.xml deleted file mode 100644 index 32d9f00ed..000000000 --- a/path_10_8/data/monster/Crustaceans/blood crab.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Crustaceans/crab.xml b/path_10_8/data/monster/Crustaceans/crab.xml deleted file mode 100644 index 4d8437583..000000000 --- a/path_10_8/data/monster/Crustaceans/crab.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Crustaceans/crustacea gigantica.xml b/path_10_8/data/monster/Crustaceans/crustacea gigantica.xml deleted file mode 100644 index a9b1e5370..000000000 --- a/path_10_8/data/monster/Crustaceans/crustacea gigantica.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Cryo-Elementals/ice golem.xml b/path_10_8/data/monster/Cryo-Elementals/ice golem.xml deleted file mode 100644 index 10ec031cd..000000000 --- a/path_10_8/data/monster/Cryo-Elementals/ice golem.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Cryo-Elementals/the collector.xml b/path_10_8/data/monster/Cryo-Elementals/the collector.xml deleted file mode 100644 index 07022cc4a..000000000 --- a/path_10_8/data/monster/Cryo-Elementals/the collector.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/Deepling Guard.xml b/path_10_8/data/monster/Deeplings/Deepling Guard.xml deleted file mode 100644 index 13b230a25..000000000 --- a/path_10_8/data/monster/Deeplings/Deepling Guard.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/Deepling Master Librarian.xml b/path_10_8/data/monster/Deeplings/Deepling Master Librarian.xml deleted file mode 100644 index c93c13466..000000000 --- a/path_10_8/data/monster/Deeplings/Deepling Master Librarian.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/Deepling Spellsinger.xml b/path_10_8/data/monster/Deeplings/Deepling Spellsinger.xml deleted file mode 100644 index d11e18fcf..000000000 --- a/path_10_8/data/monster/Deeplings/Deepling Spellsinger.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/Deepling Tyrant.xml b/path_10_8/data/monster/Deeplings/Deepling Tyrant.xml deleted file mode 100644 index ca71c604b..000000000 --- a/path_10_8/data/monster/Deeplings/Deepling Tyrant.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/Deepling Worker.xml b/path_10_8/data/monster/Deeplings/Deepling Worker.xml deleted file mode 100644 index 6a675933a..000000000 --- a/path_10_8/data/monster/Deeplings/Deepling Worker.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/deepling brawler.xml b/path_10_8/data/monster/Deeplings/deepling brawler.xml deleted file mode 100644 index 4a9c73238..000000000 --- a/path_10_8/data/monster/Deeplings/deepling brawler.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/deepling elite.xml b/path_10_8/data/monster/Deeplings/deepling elite.xml deleted file mode 100644 index a1747d032..000000000 --- a/path_10_8/data/monster/Deeplings/deepling elite.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/deepling scout.xml b/path_10_8/data/monster/Deeplings/deepling scout.xml deleted file mode 100644 index bcb72e331..000000000 --- a/path_10_8/data/monster/Deeplings/deepling scout.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Deeplings/deepling warrior.xml b/path_10_8/data/monster/Deeplings/deepling warrior.xml deleted file mode 100644 index fc2efa225..000000000 --- a/path_10_8/data/monster/Deeplings/deepling warrior.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demonlord/orshabaal.xml b/path_10_8/data/monster/Demonlord/orshabaal.xml deleted file mode 100644 index 0a021d1aa..000000000 --- a/path_10_8/data/monster/Demonlord/orshabaal.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/askarak demon.xml b/path_10_8/data/monster/Demons/askarak demon.xml deleted file mode 100644 index ab8fff440..000000000 --- a/path_10_8/data/monster/Demons/askarak demon.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/askarak lord.xml b/path_10_8/data/monster/Demons/askarak lord.xml deleted file mode 100644 index 23d3a8744..000000000 --- a/path_10_8/data/monster/Demons/askarak lord.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/askarak prince.xml b/path_10_8/data/monster/Demons/askarak prince.xml deleted file mode 100644 index 9329f7728..000000000 --- a/path_10_8/data/monster/Demons/askarak prince.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/dark torturer.xml b/path_10_8/data/monster/Demons/dark torturer.xml deleted file mode 100644 index c27d6481a..000000000 --- a/path_10_8/data/monster/Demons/dark torturer.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/demon.xml b/path_10_8/data/monster/Demons/demon.xml deleted file mode 100644 index e5275ee73..000000000 --- a/path_10_8/data/monster/Demons/demon.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/destroyer.xml b/path_10_8/data/monster/Demons/destroyer.xml deleted file mode 100644 index 1f3fa3a96..000000000 --- a/path_10_8/data/monster/Demons/destroyer.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/diabolic imp.xml b/path_10_8/data/monster/Demons/diabolic imp.xml deleted file mode 100644 index b28f815d1..000000000 --- a/path_10_8/data/monster/Demons/diabolic imp.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/fire devil.xml b/path_10_8/data/monster/Demons/fire devil.xml deleted file mode 100644 index 98faac4b4..000000000 --- a/path_10_8/data/monster/Demons/fire devil.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/gozzler.xml b/path_10_8/data/monster/Demons/gozzler.xml deleted file mode 100644 index a1f618779..000000000 --- a/path_10_8/data/monster/Demons/gozzler.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/grave guard.xml b/path_10_8/data/monster/Demons/grave guard.xml deleted file mode 100644 index 776956f7c..000000000 --- a/path_10_8/data/monster/Demons/grave guard.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/gravedigger.xml b/path_10_8/data/monster/Demons/gravedigger.xml deleted file mode 100644 index 35b30848c..000000000 --- a/path_10_8/data/monster/Demons/gravedigger.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/hand of cursed fate.xml b/path_10_8/data/monster/Demons/hand of cursed fate.xml deleted file mode 100644 index 601407e5c..000000000 --- a/path_10_8/data/monster/Demons/hand of cursed fate.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/hellhound.xml b/path_10_8/data/monster/Demons/hellhound.xml deleted file mode 100644 index 029c3223f..000000000 --- a/path_10_8/data/monster/Demons/hellhound.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/hellspawn.xml b/path_10_8/data/monster/Demons/hellspawn.xml deleted file mode 100644 index 57d604b8f..000000000 --- a/path_10_8/data/monster/Demons/hellspawn.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/herald of gloom.xml b/path_10_8/data/monster/Demons/herald of gloom.xml deleted file mode 100644 index d17019bc1..000000000 --- a/path_10_8/data/monster/Demons/herald of gloom.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/juggernaut.xml b/path_10_8/data/monster/Demons/juggernaut.xml deleted file mode 100644 index bc3c860b7..000000000 --- a/path_10_8/data/monster/Demons/juggernaut.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/kraknaknork's demon.xml b/path_10_8/data/monster/Demons/kraknaknork's demon.xml deleted file mode 100644 index 7570bffae..000000000 --- a/path_10_8/data/monster/Demons/kraknaknork's demon.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/nightmare scion.xml b/path_10_8/data/monster/Demons/nightmare scion.xml deleted file mode 100644 index 460466a07..000000000 --- a/path_10_8/data/monster/Demons/nightmare scion.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/nightmare.xml b/path_10_8/data/monster/Demons/nightmare.xml deleted file mode 100644 index f5a1e349e..000000000 --- a/path_10_8/data/monster/Demons/nightmare.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/nightstalker.xml b/path_10_8/data/monster/Demons/nightstalker.xml deleted file mode 100644 index 1372ebef7..000000000 --- a/path_10_8/data/monster/Demons/nightstalker.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/plaguesmith.xml b/path_10_8/data/monster/Demons/plaguesmith.xml deleted file mode 100644 index b4b260de3..000000000 --- a/path_10_8/data/monster/Demons/plaguesmith.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/rift brood.xml b/path_10_8/data/monster/Demons/rift brood.xml deleted file mode 100644 index a17d8aafc..000000000 --- a/path_10_8/data/monster/Demons/rift brood.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/rift scythe.xml b/path_10_8/data/monster/Demons/rift scythe.xml deleted file mode 100644 index a38b4576b..000000000 --- a/path_10_8/data/monster/Demons/rift scythe.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/shaburak demon.xml b/path_10_8/data/monster/Demons/shaburak demon.xml deleted file mode 100644 index 327e0fa73..000000000 --- a/path_10_8/data/monster/Demons/shaburak demon.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/shaburak lord.xml b/path_10_8/data/monster/Demons/shaburak lord.xml deleted file mode 100644 index 8d5a4ccb9..000000000 --- a/path_10_8/data/monster/Demons/shaburak lord.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/shaburak prince.xml b/path_10_8/data/monster/Demons/shaburak prince.xml deleted file mode 100644 index d6e40e3ca..000000000 --- a/path_10_8/data/monster/Demons/shaburak prince.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/shadow hound.xml b/path_10_8/data/monster/Demons/shadow hound.xml deleted file mode 100644 index e9b0a9909..000000000 --- a/path_10_8/data/monster/Demons/shadow hound.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/yielothax.xml b/path_10_8/data/monster/Demons/yielothax.xml deleted file mode 100644 index 98007817d..000000000 --- a/path_10_8/data/monster/Demons/yielothax.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Demons/zavarash.xml b/path_10_8/data/monster/Demons/zavarash.xml deleted file mode 100644 index 68b9b778a..000000000 --- a/path_10_8/data/monster/Demons/zavarash.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Djinn/blue djinn.xml b/path_10_8/data/monster/Djinn/blue djinn.xml deleted file mode 100644 index df2e6dcf1..000000000 --- a/path_10_8/data/monster/Djinn/blue djinn.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Djinn/efreet.xml b/path_10_8/data/monster/Djinn/efreet.xml deleted file mode 100644 index e7e926333..000000000 --- a/path_10_8/data/monster/Djinn/efreet.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Djinn/green djinn.xml b/path_10_8/data/monster/Djinn/green djinn.xml deleted file mode 100644 index 89b616fb5..000000000 --- a/path_10_8/data/monster/Djinn/green djinn.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Djinn/marid.xml b/path_10_8/data/monster/Djinn/marid.xml deleted file mode 100644 index 27c3608d2..000000000 --- a/path_10_8/data/monster/Djinn/marid.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/Dragonling.xml b/path_10_8/data/monster/Dragons/Dragonling.xml deleted file mode 100644 index ac90d3c27..000000000 --- a/path_10_8/data/monster/Dragons/Dragonling.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/dragon hatchling.xml b/path_10_8/data/monster/Dragons/dragon hatchling.xml deleted file mode 100644 index 0b001f18a..000000000 --- a/path_10_8/data/monster/Dragons/dragon hatchling.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/dragon lord hatchling.xml b/path_10_8/data/monster/Dragons/dragon lord hatchling.xml deleted file mode 100644 index 7ff0300b0..000000000 --- a/path_10_8/data/monster/Dragons/dragon lord hatchling.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/dragon lord.xml b/path_10_8/data/monster/Dragons/dragon lord.xml deleted file mode 100644 index c79d7c239..000000000 --- a/path_10_8/data/monster/Dragons/dragon lord.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/dragon.xml b/path_10_8/data/monster/Dragons/dragon.xml deleted file mode 100644 index c23dc5c5b..000000000 --- a/path_10_8/data/monster/Dragons/dragon.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/draptor.xml b/path_10_8/data/monster/Dragons/draptor.xml deleted file mode 100644 index 9efcf80e4..000000000 --- a/path_10_8/data/monster/Dragons/draptor.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/elder wyrm.xml b/path_10_8/data/monster/Dragons/elder wyrm.xml deleted file mode 100644 index 0b0936858..000000000 --- a/path_10_8/data/monster/Dragons/elder wyrm.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/frost dragon hatchling.xml b/path_10_8/data/monster/Dragons/frost dragon hatchling.xml deleted file mode 100644 index 35ee8a12d..000000000 --- a/path_10_8/data/monster/Dragons/frost dragon hatchling.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/frost dragon.xml b/path_10_8/data/monster/Dragons/frost dragon.xml deleted file mode 100644 index 78e261d86..000000000 --- a/path_10_8/data/monster/Dragons/frost dragon.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/ghastly dragon.xml b/path_10_8/data/monster/Dragons/ghastly dragon.xml deleted file mode 100644 index d452a210a..000000000 --- a/path_10_8/data/monster/Dragons/ghastly dragon.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/undead dragon.xml b/path_10_8/data/monster/Dragons/undead dragon.xml deleted file mode 100644 index 545ae121b..000000000 --- a/path_10_8/data/monster/Dragons/undead dragon.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dragons/wyrm.xml b/path_10_8/data/monster/Dragons/wyrm.xml deleted file mode 100644 index b6f5b6f5d..000000000 --- a/path_10_8/data/monster/Dragons/wyrm.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/bad dream.xml b/path_10_8/data/monster/Dreamhaunters/bad dream.xml deleted file mode 100644 index 05ff23bac..000000000 --- a/path_10_8/data/monster/Dreamhaunters/bad dream.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/choking fear.xml b/path_10_8/data/monster/Dreamhaunters/choking fear.xml deleted file mode 100644 index 547bd425a..000000000 --- a/path_10_8/data/monster/Dreamhaunters/choking fear.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/demon outcast.xml b/path_10_8/data/monster/Dreamhaunters/demon outcast.xml deleted file mode 100644 index cf61072fc..000000000 --- a/path_10_8/data/monster/Dreamhaunters/demon outcast.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/feversleep.xml b/path_10_8/data/monster/Dreamhaunters/feversleep.xml deleted file mode 100644 index 902edff87..000000000 --- a/path_10_8/data/monster/Dreamhaunters/feversleep.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/frazzlemaw.xml b/path_10_8/data/monster/Dreamhaunters/frazzlemaw.xml deleted file mode 100644 index 89a47a7b7..000000000 --- a/path_10_8/data/monster/Dreamhaunters/frazzlemaw.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/gaz'haragoth.xml b/path_10_8/data/monster/Dreamhaunters/gaz'haragoth.xml deleted file mode 100644 index 18dd9eec6..000000000 --- a/path_10_8/data/monster/Dreamhaunters/gaz'haragoth.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/guzzlemaw.xml b/path_10_8/data/monster/Dreamhaunters/guzzlemaw.xml deleted file mode 100644 index 93aed4f91..000000000 --- a/path_10_8/data/monster/Dreamhaunters/guzzlemaw.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/mawhawk.xml b/path_10_8/data/monster/Dreamhaunters/mawhawk.xml deleted file mode 100644 index 09e4eb572..000000000 --- a/path_10_8/data/monster/Dreamhaunters/mawhawk.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/minion of gaz'haragoth.xml b/path_10_8/data/monster/Dreamhaunters/minion of gaz'haragoth.xml deleted file mode 100644 index 787f55363..000000000 --- a/path_10_8/data/monster/Dreamhaunters/minion of gaz'haragoth.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/nightmare of gaz'haragoth.xml b/path_10_8/data/monster/Dreamhaunters/nightmare of gaz'haragoth.xml deleted file mode 100644 index 2649787de..000000000 --- a/path_10_8/data/monster/Dreamhaunters/nightmare of gaz'haragoth.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/retching horror.xml b/path_10_8/data/monster/Dreamhaunters/retching horror.xml deleted file mode 100644 index 0d94c2d09..000000000 --- a/path_10_8/data/monster/Dreamhaunters/retching horror.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/shiversleep.xml b/path_10_8/data/monster/Dreamhaunters/shiversleep.xml deleted file mode 100644 index 4623ec20b..000000000 --- a/path_10_8/data/monster/Dreamhaunters/shiversleep.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/shock head.xml b/path_10_8/data/monster/Dreamhaunters/shock head.xml deleted file mode 100644 index a5fc7b5fc..000000000 --- a/path_10_8/data/monster/Dreamhaunters/shock head.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/sight of surrender.xml b/path_10_8/data/monster/Dreamhaunters/sight of surrender.xml deleted file mode 100644 index 857abce2e..000000000 --- a/path_10_8/data/monster/Dreamhaunters/sight of surrender.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/silencer.xml b/path_10_8/data/monster/Dreamhaunters/silencer.xml deleted file mode 100644 index eb4d1f6cd..000000000 --- a/path_10_8/data/monster/Dreamhaunters/silencer.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dreamhaunters/terrorsleep.xml b/path_10_8/data/monster/Dreamhaunters/terrorsleep.xml deleted file mode 100644 index e7cb02ce8..000000000 --- a/path_10_8/data/monster/Dreamhaunters/terrorsleep.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/dwarf geomancer.xml b/path_10_8/data/monster/Dwarves/dwarf geomancer.xml deleted file mode 100644 index 2e0f8dbfb..000000000 --- a/path_10_8/data/monster/Dwarves/dwarf geomancer.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/dwarf guard.xml b/path_10_8/data/monster/Dwarves/dwarf guard.xml deleted file mode 100644 index a0c3cce90..000000000 --- a/path_10_8/data/monster/Dwarves/dwarf guard.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/dwarf miner.xml b/path_10_8/data/monster/Dwarves/dwarf miner.xml deleted file mode 100644 index 921e0faff..000000000 --- a/path_10_8/data/monster/Dwarves/dwarf miner.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/dwarf soldier.xml b/path_10_8/data/monster/Dwarves/dwarf soldier.xml deleted file mode 100644 index 67069e17a..000000000 --- a/path_10_8/data/monster/Dwarves/dwarf soldier.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/dwarf.xml b/path_10_8/data/monster/Dwarves/dwarf.xml deleted file mode 100644 index aba67d612..000000000 --- a/path_10_8/data/monster/Dwarves/dwarf.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/enslaved dwarf.xml b/path_10_8/data/monster/Dwarves/enslaved dwarf.xml deleted file mode 100644 index 9d99b9148..000000000 --- a/path_10_8/data/monster/Dwarves/enslaved dwarf.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/lost basher.xml b/path_10_8/data/monster/Dwarves/lost basher.xml deleted file mode 100644 index 9ebf9f33d..000000000 --- a/path_10_8/data/monster/Dwarves/lost basher.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/lost berserker.xml b/path_10_8/data/monster/Dwarves/lost berserker.xml deleted file mode 100644 index 97772b59f..000000000 --- a/path_10_8/data/monster/Dwarves/lost berserker.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/lost husher.xml b/path_10_8/data/monster/Dwarves/lost husher.xml deleted file mode 100644 index 687b79321..000000000 --- a/path_10_8/data/monster/Dwarves/lost husher.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dwarves/lost thrower.xml b/path_10_8/data/monster/Dwarves/lost thrower.xml deleted file mode 100644 index 8adfa1aec..000000000 --- a/path_10_8/data/monster/Dwarves/lost thrower.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dworcs/dworc fleshhunter.xml b/path_10_8/data/monster/Dworcs/dworc fleshhunter.xml deleted file mode 100644 index f15c98b2a..000000000 --- a/path_10_8/data/monster/Dworcs/dworc fleshhunter.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dworcs/dworc venomsniper.xml b/path_10_8/data/monster/Dworcs/dworc venomsniper.xml deleted file mode 100644 index 0c997e141..000000000 --- a/path_10_8/data/monster/Dworcs/dworc venomsniper.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Dworcs/dworc voodoomaster.xml b/path_10_8/data/monster/Dworcs/dworc voodoomaster.xml deleted file mode 100644 index 041f96be6..000000000 --- a/path_10_8/data/monster/Dworcs/dworc voodoomaster.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Electro-Elementals/charged energy elemental.xml b/path_10_8/data/monster/Electro-Elementals/charged energy elemental.xml deleted file mode 100644 index 4590ac5ee..000000000 --- a/path_10_8/data/monster/Electro-Elementals/charged energy elemental.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Electro-Elementals/energy elemental.xml b/path_10_8/data/monster/Electro-Elementals/energy elemental.xml deleted file mode 100644 index 625256476..000000000 --- a/path_10_8/data/monster/Electro-Elementals/energy elemental.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Electro-Elementals/massive energy elemental.xml b/path_10_8/data/monster/Electro-Elementals/massive energy elemental.xml deleted file mode 100644 index 98f370e76..000000000 --- a/path_10_8/data/monster/Electro-Elementals/massive energy elemental.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Electro-Elementals/overcharged energy elemental.xml b/path_10_8/data/monster/Electro-Elementals/overcharged energy elemental.xml deleted file mode 100644 index 2b5887c5c..000000000 --- a/path_10_8/data/monster/Electro-Elementals/overcharged energy elemental.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elemental Lords/earth overlord.xml b/path_10_8/data/monster/Elemental Lords/earth overlord.xml deleted file mode 100644 index 8000d04e9..000000000 --- a/path_10_8/data/monster/Elemental Lords/earth overlord.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elemental Lords/energy overlord.xml b/path_10_8/data/monster/Elemental Lords/energy overlord.xml deleted file mode 100644 index f32df151a..000000000 --- a/path_10_8/data/monster/Elemental Lords/energy overlord.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elemental Lords/fire overlord.xml b/path_10_8/data/monster/Elemental Lords/fire overlord.xml deleted file mode 100644 index 302605ebb..000000000 --- a/path_10_8/data/monster/Elemental Lords/fire overlord.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elemental Lords/ice overlord.xml b/path_10_8/data/monster/Elemental Lords/ice overlord.xml deleted file mode 100644 index 81d46d9e6..000000000 --- a/path_10_8/data/monster/Elemental Lords/ice overlord.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elemental Lords/lord of the elements.xml b/path_10_8/data/monster/Elemental Lords/lord of the elements.xml deleted file mode 100644 index 2ad43c56b..000000000 --- a/path_10_8/data/monster/Elemental Lords/lord of the elements.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elves/elf arcanist.xml b/path_10_8/data/monster/Elves/elf arcanist.xml deleted file mode 100644 index c49abdd4e..000000000 --- a/path_10_8/data/monster/Elves/elf arcanist.xml +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elves/elf scout.xml b/path_10_8/data/monster/Elves/elf scout.xml deleted file mode 100644 index 88e782a3f..000000000 --- a/path_10_8/data/monster/Elves/elf scout.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elves/elf.xml b/path_10_8/data/monster/Elves/elf.xml deleted file mode 100644 index 3e652d27d..000000000 --- a/path_10_8/data/monster/Elves/elf.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Elves/firestarter.xml b/path_10_8/data/monster/Elves/firestarter.xml deleted file mode 100644 index 6e044ce70..000000000 --- a/path_10_8/data/monster/Elves/firestarter.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Event Creatures/hacker.xml b/path_10_8/data/monster/Event Creatures/hacker.xml deleted file mode 100644 index 6caaca3f3..000000000 --- a/path_10_8/data/monster/Event Creatures/hacker.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Event Creatures/spectral scum.xml b/path_10_8/data/monster/Event Creatures/spectral scum.xml deleted file mode 100644 index b862a54b1..000000000 --- a/path_10_8/data/monster/Event Creatures/spectral scum.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Felines/cat.xml b/path_10_8/data/monster/Felines/cat.xml deleted file mode 100644 index abdaf10fe..000000000 --- a/path_10_8/data/monster/Felines/cat.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Felines/lion.xml b/path_10_8/data/monster/Felines/lion.xml deleted file mode 100644 index 70275f00a..000000000 --- a/path_10_8/data/monster/Felines/lion.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Felines/midnight panther.xml b/path_10_8/data/monster/Felines/midnight panther.xml deleted file mode 100644 index 277ea851a..000000000 --- a/path_10_8/data/monster/Felines/midnight panther.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Felines/tiger.xml b/path_10_8/data/monster/Felines/tiger.xml deleted file mode 100644 index 9f4b4bc19..000000000 --- a/path_10_8/data/monster/Felines/tiger.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Fish/fish.xml b/path_10_8/data/monster/Fish/fish.xml deleted file mode 100644 index 3d54ea437..000000000 --- a/path_10_8/data/monster/Fish/fish.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Fish/manta ray.xml b/path_10_8/data/monster/Fish/manta ray.xml deleted file mode 100644 index 9fd6caa98..000000000 --- a/path_10_8/data/monster/Fish/manta ray.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Fish/northern pike.xml b/path_10_8/data/monster/Fish/northern pike.xml deleted file mode 100644 index 4acafe2e6..000000000 --- a/path_10_8/data/monster/Fish/northern pike.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Fish/shark.xml b/path_10_8/data/monster/Fish/shark.xml deleted file mode 100644 index d25f7f7e1..000000000 --- a/path_10_8/data/monster/Fish/shark.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/azure frog.xml b/path_10_8/data/monster/Frogs/azure frog.xml deleted file mode 100644 index 908fa4c49..000000000 --- a/path_10_8/data/monster/Frogs/azure frog.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/bog frog.xml b/path_10_8/data/monster/Frogs/bog frog.xml deleted file mode 100644 index 3bd21569e..000000000 --- a/path_10_8/data/monster/Frogs/bog frog.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/coral frog.xml b/path_10_8/data/monster/Frogs/coral frog.xml deleted file mode 100644 index 819cf316c..000000000 --- a/path_10_8/data/monster/Frogs/coral frog.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/crimson frog.xml b/path_10_8/data/monster/Frogs/crimson frog.xml deleted file mode 100644 index 24d03a0d7..000000000 --- a/path_10_8/data/monster/Frogs/crimson frog.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/deathspawn.xml b/path_10_8/data/monster/Frogs/deathspawn.xml deleted file mode 100644 index 95a32eb37..000000000 --- a/path_10_8/data/monster/Frogs/deathspawn.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/filth toad.xml b/path_10_8/data/monster/Frogs/filth toad.xml deleted file mode 100644 index 054e96071..000000000 --- a/path_10_8/data/monster/Frogs/filth toad.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/green frog.xml b/path_10_8/data/monster/Frogs/green frog.xml deleted file mode 100644 index d73285982..000000000 --- a/path_10_8/data/monster/Frogs/green frog.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/infernal frog.xml b/path_10_8/data/monster/Frogs/infernal frog.xml deleted file mode 100644 index 81f72bc53..000000000 --- a/path_10_8/data/monster/Frogs/infernal frog.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/orchid frog.xml b/path_10_8/data/monster/Frogs/orchid frog.xml deleted file mode 100644 index 4826281c4..000000000 --- a/path_10_8/data/monster/Frogs/orchid frog.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Frogs/toad.xml b/path_10_8/data/monster/Frogs/toad.xml deleted file mode 100644 index 1cd6a01e7..000000000 --- a/path_10_8/data/monster/Frogs/toad.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/armadile.xml b/path_10_8/data/monster/Geo-Elementals/armadile.xml deleted file mode 100644 index 86eb04d38..000000000 --- a/path_10_8/data/monster/Geo-Elementals/armadile.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/clay guardian.xml b/path_10_8/data/monster/Geo-Elementals/clay guardian.xml deleted file mode 100644 index 6a7c7e415..000000000 --- a/path_10_8/data/monster/Geo-Elementals/clay guardian.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/cliff strider.xml b/path_10_8/data/monster/Geo-Elementals/cliff strider.xml deleted file mode 100644 index 480957c3e..000000000 --- a/path_10_8/data/monster/Geo-Elementals/cliff strider.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/crystalcrusher.xml b/path_10_8/data/monster/Geo-Elementals/crystalcrusher.xml deleted file mode 100644 index e8bd41f13..000000000 --- a/path_10_8/data/monster/Geo-Elementals/crystalcrusher.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/damaged crystal golem.xml b/path_10_8/data/monster/Geo-Elementals/damaged crystal golem.xml deleted file mode 100644 index 608a844eb..000000000 --- a/path_10_8/data/monster/Geo-Elementals/damaged crystal golem.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/damaged worker golem.xml b/path_10_8/data/monster/Geo-Elementals/damaged worker golem.xml deleted file mode 100644 index aa6cc1053..000000000 --- a/path_10_8/data/monster/Geo-Elementals/damaged worker golem.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/deathstrike.xml b/path_10_8/data/monster/Geo-Elementals/deathstrike.xml deleted file mode 100644 index 46da3005a..000000000 --- a/path_10_8/data/monster/Geo-Elementals/deathstrike.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/diamond servant.xml b/path_10_8/data/monster/Geo-Elementals/diamond servant.xml deleted file mode 100644 index 3a41c51ea..000000000 --- a/path_10_8/data/monster/Geo-Elementals/diamond servant.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/earth elemental.xml b/path_10_8/data/monster/Geo-Elementals/earth elemental.xml deleted file mode 100644 index 6b31db842..000000000 --- a/path_10_8/data/monster/Geo-Elementals/earth elemental.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/enraged crystal golem.xml b/path_10_8/data/monster/Geo-Elementals/enraged crystal golem.xml deleted file mode 100644 index 0038a65bd..000000000 --- a/path_10_8/data/monster/Geo-Elementals/enraged crystal golem.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/eternal guardian.xml b/path_10_8/data/monster/Geo-Elementals/eternal guardian.xml deleted file mode 100644 index d6725e35b..000000000 --- a/path_10_8/data/monster/Geo-Elementals/eternal guardian.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/forest fury.xml b/path_10_8/data/monster/Geo-Elementals/forest fury.xml deleted file mode 100644 index 52a4332fe..000000000 --- a/path_10_8/data/monster/Geo-Elementals/forest fury.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/gargoyle.xml b/path_10_8/data/monster/Geo-Elementals/gargoyle.xml deleted file mode 100644 index 411d25493..000000000 --- a/path_10_8/data/monster/Geo-Elementals/gargoyle.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/golden servant.xml b/path_10_8/data/monster/Geo-Elementals/golden servant.xml deleted file mode 100644 index f389826b1..000000000 --- a/path_10_8/data/monster/Geo-Elementals/golden servant.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/iron servant.xml b/path_10_8/data/monster/Geo-Elementals/iron servant.xml deleted file mode 100644 index a56e2672b..000000000 --- a/path_10_8/data/monster/Geo-Elementals/iron servant.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/ironblight.xml b/path_10_8/data/monster/Geo-Elementals/ironblight.xml deleted file mode 100644 index 9c194221d..000000000 --- a/path_10_8/data/monster/Geo-Elementals/ironblight.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/jagged earth elemental.xml b/path_10_8/data/monster/Geo-Elementals/jagged earth elemental.xml deleted file mode 100644 index 41dd3e6bd..000000000 --- a/path_10_8/data/monster/Geo-Elementals/jagged earth elemental.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/massive earth elemental.xml b/path_10_8/data/monster/Geo-Elementals/massive earth elemental.xml deleted file mode 100644 index e088eb6dc..000000000 --- a/path_10_8/data/monster/Geo-Elementals/massive earth elemental.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/medusa.xml b/path_10_8/data/monster/Geo-Elementals/medusa.xml deleted file mode 100644 index 877ef39cb..000000000 --- a/path_10_8/data/monster/Geo-Elementals/medusa.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/muddy earth elemental.xml b/path_10_8/data/monster/Geo-Elementals/muddy earth elemental.xml deleted file mode 100644 index e26bc57a4..000000000 --- a/path_10_8/data/monster/Geo-Elementals/muddy earth elemental.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/stone devourer.xml b/path_10_8/data/monster/Geo-Elementals/stone devourer.xml deleted file mode 100644 index 1c95d15df..000000000 --- a/path_10_8/data/monster/Geo-Elementals/stone devourer.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/stone golem.xml b/path_10_8/data/monster/Geo-Elementals/stone golem.xml deleted file mode 100644 index 0336cf9cc..000000000 --- a/path_10_8/data/monster/Geo-Elementals/stone golem.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/vulcongra.xml b/path_10_8/data/monster/Geo-Elementals/vulcongra.xml deleted file mode 100644 index 7df2b3f81..000000000 --- a/path_10_8/data/monster/Geo-Elementals/vulcongra.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/war golem.xml b/path_10_8/data/monster/Geo-Elementals/war golem.xml deleted file mode 100644 index 7df5f4b18..000000000 --- a/path_10_8/data/monster/Geo-Elementals/war golem.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Geo-Elementals/worker golem.xml b/path_10_8/data/monster/Geo-Elementals/worker golem.xml deleted file mode 100644 index b73c02f69..000000000 --- a/path_10_8/data/monster/Geo-Elementals/worker golem.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/ghost.xml b/path_10_8/data/monster/Ghosts/ghost.xml deleted file mode 100644 index db73e068c..000000000 --- a/path_10_8/data/monster/Ghosts/ghost.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/phantasm summon.xml b/path_10_8/data/monster/Ghosts/phantasm summon.xml deleted file mode 100644 index 673c7ddb7..000000000 --- a/path_10_8/data/monster/Ghosts/phantasm summon.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/phantasm.xml b/path_10_8/data/monster/Ghosts/phantasm.xml deleted file mode 100644 index 155de8465..000000000 --- a/path_10_8/data/monster/Ghosts/phantasm.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/souleater.xml b/path_10_8/data/monster/Ghosts/souleater.xml deleted file mode 100644 index 319795c7b..000000000 --- a/path_10_8/data/monster/Ghosts/souleater.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/spectre.xml b/path_10_8/data/monster/Ghosts/spectre.xml deleted file mode 100644 index fdafece6f..000000000 --- a/path_10_8/data/monster/Ghosts/spectre.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/tarnished spirit.xml b/path_10_8/data/monster/Ghosts/tarnished spirit.xml deleted file mode 100644 index b2d24d5f9..000000000 --- a/path_10_8/data/monster/Ghosts/tarnished spirit.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/tormented ghost.xml b/path_10_8/data/monster/Ghosts/tormented ghost.xml deleted file mode 100644 index d4635604c..000000000 --- a/path_10_8/data/monster/Ghosts/tormented ghost.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/white shade.xml b/path_10_8/data/monster/Ghosts/white shade.xml deleted file mode 100644 index 9b3a1d75f..000000000 --- a/path_10_8/data/monster/Ghosts/white shade.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ghosts/wisp.xml b/path_10_8/data/monster/Ghosts/wisp.xml deleted file mode 100644 index 22331abad..000000000 --- a/path_10_8/data/monster/Ghosts/wisp.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/behemoth.xml b/path_10_8/data/monster/Giants/behemoth.xml deleted file mode 100644 index 8026a6b71..000000000 --- a/path_10_8/data/monster/Giants/behemoth.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/cyclops drone.xml b/path_10_8/data/monster/Giants/cyclops drone.xml deleted file mode 100644 index aafa4961e..000000000 --- a/path_10_8/data/monster/Giants/cyclops drone.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/cyclops smith.xml b/path_10_8/data/monster/Giants/cyclops smith.xml deleted file mode 100644 index f6accea9b..000000000 --- a/path_10_8/data/monster/Giants/cyclops smith.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/cyclops.xml b/path_10_8/data/monster/Giants/cyclops.xml deleted file mode 100644 index 32d00c28b..000000000 --- a/path_10_8/data/monster/Giants/cyclops.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/frost giant.xml b/path_10_8/data/monster/Giants/frost giant.xml deleted file mode 100644 index eb5720325..000000000 --- a/path_10_8/data/monster/Giants/frost giant.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Giants/frost giantess.xml b/path_10_8/data/monster/Giants/frost giantess.xml deleted file mode 100644 index f8e2a2e97..000000000 --- a/path_10_8/data/monster/Giants/frost giantess.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/cave rat.xml b/path_10_8/data/monster/Glires/cave rat.xml deleted file mode 100644 index 8c70a1110..000000000 --- a/path_10_8/data/monster/Glires/cave rat.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/halloweenhare.xml b/path_10_8/data/monster/Glires/halloweenhare.xml deleted file mode 100644 index 07876aa71..000000000 --- a/path_10_8/data/monster/Glires/halloweenhare.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/killer rabbit.xml b/path_10_8/data/monster/Glires/killer rabbit.xml deleted file mode 100644 index a4b88e095..000000000 --- a/path_10_8/data/monster/Glires/killer rabbit.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/rabbit.xml b/path_10_8/data/monster/Glires/rabbit.xml deleted file mode 100644 index 24d7a66ba..000000000 --- a/path_10_8/data/monster/Glires/rabbit.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/rat.xml b/path_10_8/data/monster/Glires/rat.xml deleted file mode 100644 index 5c21e7206..000000000 --- a/path_10_8/data/monster/Glires/rat.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/silver rabbit.xml b/path_10_8/data/monster/Glires/silver rabbit.xml deleted file mode 100644 index 446fe4bb9..000000000 --- a/path_10_8/data/monster/Glires/silver rabbit.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Glires/squirrel.xml b/path_10_8/data/monster/Glires/squirrel.xml deleted file mode 100644 index 241e6ef6e..000000000 --- a/path_10_8/data/monster/Glires/squirrel.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/demon (goblin).xml b/path_10_8/data/monster/Goblins/demon (goblin).xml deleted file mode 100644 index c07fbd284..000000000 --- a/path_10_8/data/monster/Goblins/demon (goblin).xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/goblin assassin.xml b/path_10_8/data/monster/Goblins/goblin assassin.xml deleted file mode 100644 index d0018671c..000000000 --- a/path_10_8/data/monster/Goblins/goblin assassin.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/goblin leader.xml b/path_10_8/data/monster/Goblins/goblin leader.xml deleted file mode 100644 index 30e09bcc9..000000000 --- a/path_10_8/data/monster/Goblins/goblin leader.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/goblin scavenger.xml b/path_10_8/data/monster/Goblins/goblin scavenger.xml deleted file mode 100644 index e9a6f289a..000000000 --- a/path_10_8/data/monster/Goblins/goblin scavenger.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/goblin.xml b/path_10_8/data/monster/Goblins/goblin.xml deleted file mode 100644 index baa13f0f4..000000000 --- a/path_10_8/data/monster/Goblins/goblin.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Goblins/grynch clan goblin.xml b/path_10_8/data/monster/Goblins/grynch clan goblin.xml deleted file mode 100644 index f6124c46b..000000000 --- a/path_10_8/data/monster/Goblins/grynch clan goblin.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Hydro-Elementals/massive water elemental.xml b/path_10_8/data/monster/Hydro-Elementals/massive water elemental.xml deleted file mode 100644 index 763d7dd67..000000000 --- a/path_10_8/data/monster/Hydro-Elementals/massive water elemental.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Hydro-Elementals/roaring water elemental.xml b/path_10_8/data/monster/Hydro-Elementals/roaring water elemental.xml deleted file mode 100644 index 4840c8626..000000000 --- a/path_10_8/data/monster/Hydro-Elementals/roaring water elemental.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Hydro-Elementals/slick water elemental.xml b/path_10_8/data/monster/Hydro-Elementals/slick water elemental.xml deleted file mode 100644 index 007ffc7b5..000000000 --- a/path_10_8/data/monster/Hydro-Elementals/slick water elemental.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Hydro-Elementals/water elemental.xml b/path_10_8/data/monster/Hydro-Elementals/water elemental.xml deleted file mode 100644 index ede748336..000000000 --- a/path_10_8/data/monster/Hydro-Elementals/water elemental.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/ancient scarab.xml b/path_10_8/data/monster/Insects/ancient scarab.xml deleted file mode 100644 index 3ba261c5e..000000000 --- a/path_10_8/data/monster/Insects/ancient scarab.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/blue butterfly.xml b/path_10_8/data/monster/Insects/blue butterfly.xml deleted file mode 100644 index 5c4e0205d..000000000 --- a/path_10_8/data/monster/Insects/blue butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/brimstone bug.xml b/path_10_8/data/monster/Insects/brimstone bug.xml deleted file mode 100644 index bc03a1b52..000000000 --- a/path_10_8/data/monster/Insects/brimstone bug.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/bug.xml b/path_10_8/data/monster/Insects/bug.xml deleted file mode 100644 index 87b95e8df..000000000 --- a/path_10_8/data/monster/Insects/bug.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/butterfly.xml b/path_10_8/data/monster/Insects/butterfly.xml deleted file mode 100644 index 26582b97b..000000000 --- a/path_10_8/data/monster/Insects/butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/cockroach.xml b/path_10_8/data/monster/Insects/cockroach.xml deleted file mode 100644 index ac86f3609..000000000 --- a/path_10_8/data/monster/Insects/cockroach.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/emerald damselfly.xml b/path_10_8/data/monster/Insects/emerald damselfly.xml deleted file mode 100644 index 80f917222..000000000 --- a/path_10_8/data/monster/Insects/emerald damselfly.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/fleshslicer.xml b/path_10_8/data/monster/Insects/fleshslicer.xml deleted file mode 100644 index 6d6e41f7f..000000000 --- a/path_10_8/data/monster/Insects/fleshslicer.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/hive overseer.xml b/path_10_8/data/monster/Insects/hive overseer.xml deleted file mode 100644 index d1e7033d6..000000000 --- a/path_10_8/data/monster/Insects/hive overseer.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/insect swarm.xml b/path_10_8/data/monster/Insects/insect swarm.xml deleted file mode 100644 index 375c42550..000000000 --- a/path_10_8/data/monster/Insects/insect swarm.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/insectoid scout.xml b/path_10_8/data/monster/Insects/insectoid scout.xml deleted file mode 100644 index 7504911c7..000000000 --- a/path_10_8/data/monster/Insects/insectoid scout.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/insectoid worker.xml b/path_10_8/data/monster/Insects/insectoid worker.xml deleted file mode 100644 index de18112cc..000000000 --- a/path_10_8/data/monster/Insects/insectoid worker.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/kollos.xml b/path_10_8/data/monster/Insects/kollos.xml deleted file mode 100644 index a9203c239..000000000 --- a/path_10_8/data/monster/Insects/kollos.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/lady bug.xml b/path_10_8/data/monster/Insects/lady bug.xml deleted file mode 100644 index 52caf0e18..000000000 --- a/path_10_8/data/monster/Insects/lady bug.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/lancer beetle.xml b/path_10_8/data/monster/Insects/lancer beetle.xml deleted file mode 100644 index 720387f4f..000000000 --- a/path_10_8/data/monster/Insects/lancer beetle.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/larva.xml b/path_10_8/data/monster/Insects/larva.xml deleted file mode 100644 index f955b9fbb..000000000 --- a/path_10_8/data/monster/Insects/larva.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/lesser swarmer.xml b/path_10_8/data/monster/Insects/lesser swarmer.xml deleted file mode 100644 index 94817b26d..000000000 --- a/path_10_8/data/monster/Insects/lesser swarmer.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/parasite.xml b/path_10_8/data/monster/Insects/parasite.xml deleted file mode 100644 index e7bfbb898..000000000 --- a/path_10_8/data/monster/Insects/parasite.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/pink butterfly.xml b/path_10_8/data/monster/Insects/pink butterfly.xml deleted file mode 100644 index 4dc00c20a..000000000 --- a/path_10_8/data/monster/Insects/pink butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/purple butterfly.xml b/path_10_8/data/monster/Insects/purple butterfly.xml deleted file mode 100644 index e3c81b3bf..000000000 --- a/path_10_8/data/monster/Insects/purple butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/red butterfly.xml b/path_10_8/data/monster/Insects/red butterfly.xml deleted file mode 100644 index 0ff74de94..000000000 --- a/path_10_8/data/monster/Insects/red butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/sandcrawler.xml b/path_10_8/data/monster/Insects/sandcrawler.xml deleted file mode 100644 index c947f8116..000000000 --- a/path_10_8/data/monster/Insects/sandcrawler.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/scarab.xml b/path_10_8/data/monster/Insects/scarab.xml deleted file mode 100644 index c6d215ed6..000000000 --- a/path_10_8/data/monster/Insects/scarab.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/spidris elite.xml b/path_10_8/data/monster/Insects/spidris elite.xml deleted file mode 100644 index a91bec0dc..000000000 --- a/path_10_8/data/monster/Insects/spidris elite.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/spidris.xml b/path_10_8/data/monster/Insects/spidris.xml deleted file mode 100644 index 71d061018..000000000 --- a/path_10_8/data/monster/Insects/spidris.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/spitter.xml b/path_10_8/data/monster/Insects/spitter.xml deleted file mode 100644 index a26bd0adf..000000000 --- a/path_10_8/data/monster/Insects/spitter.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/swarmer hatchling.xml b/path_10_8/data/monster/Insects/swarmer hatchling.xml deleted file mode 100644 index c13567221..000000000 --- a/path_10_8/data/monster/Insects/swarmer hatchling.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/swarmer.xml b/path_10_8/data/monster/Insects/swarmer.xml deleted file mode 100644 index bd36f7dfd..000000000 --- a/path_10_8/data/monster/Insects/swarmer.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/terramite.xml b/path_10_8/data/monster/Insects/terramite.xml deleted file mode 100644 index 19452cdc6..000000000 --- a/path_10_8/data/monster/Insects/terramite.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/wasp.xml b/path_10_8/data/monster/Insects/wasp.xml deleted file mode 100644 index 64a455ac1..000000000 --- a/path_10_8/data/monster/Insects/wasp.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/waspoid.xml b/path_10_8/data/monster/Insects/waspoid.xml deleted file mode 100644 index df1f9d21c..000000000 --- a/path_10_8/data/monster/Insects/waspoid.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Insects/yellow butterfly.xml b/path_10_8/data/monster/Insects/yellow butterfly.xml deleted file mode 100644 index 1b38da032..000000000 --- a/path_10_8/data/monster/Insects/yellow butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/battlemaster zunzu.xml b/path_10_8/data/monster/Lizards/battlemaster zunzu.xml deleted file mode 100644 index c2f7f20b4..000000000 --- a/path_10_8/data/monster/Lizards/battlemaster zunzu.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/draken abomination.xml b/path_10_8/data/monster/Lizards/draken abomination.xml deleted file mode 100644 index 59436732f..000000000 --- a/path_10_8/data/monster/Lizards/draken abomination.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/draken elite.xml b/path_10_8/data/monster/Lizards/draken elite.xml deleted file mode 100644 index d386f375c..000000000 --- a/path_10_8/data/monster/Lizards/draken elite.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/draken spellweaver.xml b/path_10_8/data/monster/Lizards/draken spellweaver.xml deleted file mode 100644 index ae07c5047..000000000 --- a/path_10_8/data/monster/Lizards/draken spellweaver.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/draken warmaster.xml b/path_10_8/data/monster/Lizards/draken warmaster.xml deleted file mode 100644 index 6c1c96475..000000000 --- a/path_10_8/data/monster/Lizards/draken warmaster.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard abomination.xml b/path_10_8/data/monster/Lizards/lizard abomination.xml deleted file mode 100644 index cff95da47..000000000 --- a/path_10_8/data/monster/Lizards/lizard abomination.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard chosen.xml b/path_10_8/data/monster/Lizards/lizard chosen.xml deleted file mode 100644 index 4f2957356..000000000 --- a/path_10_8/data/monster/Lizards/lizard chosen.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard dragon priest.xml b/path_10_8/data/monster/Lizards/lizard dragon priest.xml deleted file mode 100644 index 16b553bcb..000000000 --- a/path_10_8/data/monster/Lizards/lizard dragon priest.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard high guard.xml b/path_10_8/data/monster/Lizards/lizard high guard.xml deleted file mode 100644 index d2d7c75b3..000000000 --- a/path_10_8/data/monster/Lizards/lizard high guard.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard legionnaire.xml b/path_10_8/data/monster/Lizards/lizard legionnaire.xml deleted file mode 100644 index 373ef2a14..000000000 --- a/path_10_8/data/monster/Lizards/lizard legionnaire.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard magistratus.xml b/path_10_8/data/monster/Lizards/lizard magistratus.xml deleted file mode 100644 index 3c680fd88..000000000 --- a/path_10_8/data/monster/Lizards/lizard magistratus.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard noble.xml b/path_10_8/data/monster/Lizards/lizard noble.xml deleted file mode 100644 index e61414c57..000000000 --- a/path_10_8/data/monster/Lizards/lizard noble.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard sentinel.xml b/path_10_8/data/monster/Lizards/lizard sentinel.xml deleted file mode 100644 index 8900807e9..000000000 --- a/path_10_8/data/monster/Lizards/lizard sentinel.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard snakecharmer.xml b/path_10_8/data/monster/Lizards/lizard snakecharmer.xml deleted file mode 100644 index 6772b0c2a..000000000 --- a/path_10_8/data/monster/Lizards/lizard snakecharmer.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard templar.xml b/path_10_8/data/monster/Lizards/lizard templar.xml deleted file mode 100644 index fd8e086a6..000000000 --- a/path_10_8/data/monster/Lizards/lizard templar.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/lizard zaogun.xml b/path_10_8/data/monster/Lizards/lizard zaogun.xml deleted file mode 100644 index 92e0dd28e..000000000 --- a/path_10_8/data/monster/Lizards/lizard zaogun.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Lizards/wyvern.xml b/path_10_8/data/monster/Lizards/wyvern.xml deleted file mode 100644 index a9f1d6f8b..000000000 --- a/path_10_8/data/monster/Lizards/wyvern.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Minotaurs/minotaur archer.xml b/path_10_8/data/monster/Minotaurs/minotaur archer.xml deleted file mode 100644 index cea9ffece..000000000 --- a/path_10_8/data/monster/Minotaurs/minotaur archer.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Minotaurs/minotaur guard.xml b/path_10_8/data/monster/Minotaurs/minotaur guard.xml deleted file mode 100644 index 1dcddac80..000000000 --- a/path_10_8/data/monster/Minotaurs/minotaur guard.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Minotaurs/minotaur mage.xml b/path_10_8/data/monster/Minotaurs/minotaur mage.xml deleted file mode 100644 index 24eae9984..000000000 --- a/path_10_8/data/monster/Minotaurs/minotaur mage.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Minotaurs/minotaur.xml b/path_10_8/data/monster/Minotaurs/minotaur.xml deleted file mode 100644 index 9e42f0e0e..000000000 --- a/path_10_8/data/monster/Minotaurs/minotaur.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/badger.xml b/path_10_8/data/monster/Misc/Misc Mammals/badger.xml deleted file mode 100644 index 5d9f62865..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/badger.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/bat.xml b/path_10_8/data/monster/Misc/Misc Mammals/bat.xml deleted file mode 100644 index c0e6f103d..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/bat.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/ghoulish hyaena.xml b/path_10_8/data/monster/Misc/Misc Mammals/ghoulish hyaena.xml deleted file mode 100644 index 03c67f73e..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/ghoulish hyaena.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/hyaena.xml b/path_10_8/data/monster/Misc/Misc Mammals/hyaena.xml deleted file mode 100644 index 88c648205..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/hyaena.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/skunk.xml b/path_10_8/data/monster/Misc/Misc Mammals/skunk.xml deleted file mode 100644 index 3649f7f6e..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/skunk.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mammals/water buffalo.xml b/path_10_8/data/monster/Misc/Misc Mammals/water buffalo.xml deleted file mode 100644 index fda7eba99..000000000 --- a/path_10_8/data/monster/Misc/Misc Mammals/water buffalo.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mounts/Incredibly Old Witch.xml b/path_10_8/data/monster/Misc/Misc Mounts/Incredibly Old Witch.xml deleted file mode 100644 index 7c62c6e1d..000000000 --- a/path_10_8/data/monster/Misc/Misc Mounts/Incredibly Old Witch.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mounts/donkey.xml b/path_10_8/data/monster/Misc/Misc Mounts/donkey.xml deleted file mode 100644 index 49166bf7f..000000000 --- a/path_10_8/data/monster/Misc/Misc Mounts/donkey.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Mounts/modified gnarlhound.xml b/path_10_8/data/monster/Misc/Misc Mounts/modified gnarlhound.xml deleted file mode 100644 index fcd9ffb7a..000000000 --- a/path_10_8/data/monster/Misc/Misc Mounts/modified gnarlhound.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Reptiles/crocodile.xml b/path_10_8/data/monster/Misc/Misc Reptiles/crocodile.xml deleted file mode 100644 index 77de9e563..000000000 --- a/path_10_8/data/monster/Misc/Misc Reptiles/crocodile.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Reptiles/hydra.xml b/path_10_8/data/monster/Misc/Misc Reptiles/hydra.xml deleted file mode 100644 index 0617f7d28..000000000 --- a/path_10_8/data/monster/Misc/Misc Reptiles/hydra.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Reptiles/killer caiman.xml b/path_10_8/data/monster/Misc/Misc Reptiles/killer caiman.xml deleted file mode 100644 index df0983489..000000000 --- a/path_10_8/data/monster/Misc/Misc Reptiles/killer caiman.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Reptiles/thornback tortoise.xml b/path_10_8/data/monster/Misc/Misc Reptiles/thornback tortoise.xml deleted file mode 100644 index 44f4b74b6..000000000 --- a/path_10_8/data/monster/Misc/Misc Reptiles/thornback tortoise.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Misc/Misc Reptiles/tortoise.xml b/path_10_8/data/monster/Misc/Misc Reptiles/tortoise.xml deleted file mode 100644 index 6a243a1b3..000000000 --- a/path_10_8/data/monster/Misc/Misc Reptiles/tortoise.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mollusks/calamary.xml b/path_10_8/data/monster/Mollusks/calamary.xml deleted file mode 100644 index a759ca934..000000000 --- a/path_10_8/data/monster/Mollusks/calamary.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mollusks/slug.xml b/path_10_8/data/monster/Mollusks/slug.xml deleted file mode 100644 index d629b9647..000000000 --- a/path_10_8/data/monster/Mollusks/slug.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Monks/dark monk.xml b/path_10_8/data/monster/Monks/dark monk.xml deleted file mode 100644 index 7a63d5a53..000000000 --- a/path_10_8/data/monster/Monks/dark monk.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Monks/monk.xml b/path_10_8/data/monster/Monks/monk.xml deleted file mode 100644 index 9b14631c0..000000000 --- a/path_10_8/data/monster/Monks/monk.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mutated/mutated bat.xml b/path_10_8/data/monster/Mutated/mutated bat.xml deleted file mode 100644 index 5d2b5858a..000000000 --- a/path_10_8/data/monster/Mutated/mutated bat.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mutated/mutated human.xml b/path_10_8/data/monster/Mutated/mutated human.xml deleted file mode 100644 index 0d82edc9d..000000000 --- a/path_10_8/data/monster/Mutated/mutated human.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mutated/mutated rat.xml b/path_10_8/data/monster/Mutated/mutated rat.xml deleted file mode 100644 index e17c81266..000000000 --- a/path_10_8/data/monster/Mutated/mutated rat.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Mutated/mutated tiger.xml b/path_10_8/data/monster/Mutated/mutated tiger.xml deleted file mode 100644 index 10ddf02bb..000000000 --- a/path_10_8/data/monster/Mutated/mutated tiger.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Myriapods/centipede.xml b/path_10_8/data/monster/Myriapods/centipede.xml deleted file mode 100644 index 1fd3d2dbb..000000000 --- a/path_10_8/data/monster/Myriapods/centipede.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Myriapods/crawler.xml b/path_10_8/data/monster/Myriapods/crawler.xml deleted file mode 100644 index 4303d8312..000000000 --- a/path_10_8/data/monster/Myriapods/crawler.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Myriapods/wiggler.xml b/path_10_8/data/monster/Myriapods/wiggler.xml deleted file mode 100644 index 83c0b2d81..000000000 --- a/path_10_8/data/monster/Myriapods/wiggler.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/blood hand.xml b/path_10_8/data/monster/Necromancers/blood hand.xml deleted file mode 100644 index 0a0ca0a18..000000000 --- a/path_10_8/data/monster/Necromancers/blood hand.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/blood priest.xml b/path_10_8/data/monster/Necromancers/blood priest.xml deleted file mode 100644 index b1d3edde2..000000000 --- a/path_10_8/data/monster/Necromancers/blood priest.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/necromancer servant.xml b/path_10_8/data/monster/Necromancers/necromancer servant.xml deleted file mode 100644 index 6a091bc15..000000000 --- a/path_10_8/data/monster/Necromancers/necromancer servant.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/necromancer.xml b/path_10_8/data/monster/Necromancers/necromancer.xml deleted file mode 100644 index d337f0697..000000000 --- a/path_10_8/data/monster/Necromancers/necromancer.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/priestess.xml b/path_10_8/data/monster/Necromancers/priestess.xml deleted file mode 100644 index 62b44c745..000000000 --- a/path_10_8/data/monster/Necromancers/priestess.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Necromancers/shadow pupil.xml b/path_10_8/data/monster/Necromancers/shadow pupil.xml deleted file mode 100644 index 5c39f58a2..000000000 --- a/path_10_8/data/monster/Necromancers/shadow pupil.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/furious orc berserker.xml b/path_10_8/data/monster/Orcs/furious orc berserker.xml deleted file mode 100644 index 378a86303..000000000 --- a/path_10_8/data/monster/Orcs/furious orc berserker.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc berserker.xml b/path_10_8/data/monster/Orcs/orc berserker.xml deleted file mode 100644 index bdf4eda43..000000000 --- a/path_10_8/data/monster/Orcs/orc berserker.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc leader.xml b/path_10_8/data/monster/Orcs/orc leader.xml deleted file mode 100644 index 3f08ce388..000000000 --- a/path_10_8/data/monster/Orcs/orc leader.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc marauder.xml b/path_10_8/data/monster/Orcs/orc marauder.xml deleted file mode 100644 index 874b764d3..000000000 --- a/path_10_8/data/monster/Orcs/orc marauder.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc rider.xml b/path_10_8/data/monster/Orcs/orc rider.xml deleted file mode 100644 index c915a0929..000000000 --- a/path_10_8/data/monster/Orcs/orc rider.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc shaman.xml b/path_10_8/data/monster/Orcs/orc shaman.xml deleted file mode 100644 index 193e1b557..000000000 --- a/path_10_8/data/monster/Orcs/orc shaman.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc spearman.xml b/path_10_8/data/monster/Orcs/orc spearman.xml deleted file mode 100644 index 5502e6514..000000000 --- a/path_10_8/data/monster/Orcs/orc spearman.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc warlord.xml b/path_10_8/data/monster/Orcs/orc warlord.xml deleted file mode 100644 index 42cc50b18..000000000 --- a/path_10_8/data/monster/Orcs/orc warlord.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc warrior.xml b/path_10_8/data/monster/Orcs/orc warrior.xml deleted file mode 100644 index 45a46eb43..000000000 --- a/path_10_8/data/monster/Orcs/orc warrior.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/orc.xml b/path_10_8/data/monster/Orcs/orc.xml deleted file mode 100644 index 630ea8e09..000000000 --- a/path_10_8/data/monster/Orcs/orc.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Orcs/rorc.xml b/path_10_8/data/monster/Orcs/rorc.xml deleted file mode 100644 index 082c92892..000000000 --- a/path_10_8/data/monster/Orcs/rorc.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/adventurer.xml b/path_10_8/data/monster/Outlaws/adventurer.xml deleted file mode 100644 index e1f4babd3..000000000 --- a/path_10_8/data/monster/Outlaws/adventurer.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/angry adventurer.xml b/path_10_8/data/monster/Outlaws/angry adventurer.xml deleted file mode 100644 index 45985893e..000000000 --- a/path_10_8/data/monster/Outlaws/angry adventurer.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/assassin.xml b/path_10_8/data/monster/Outlaws/assassin.xml deleted file mode 100644 index 2e7543d5c..000000000 --- a/path_10_8/data/monster/Outlaws/assassin.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/bandit.xml b/path_10_8/data/monster/Outlaws/bandit.xml deleted file mode 100644 index 67ed067aa..000000000 --- a/path_10_8/data/monster/Outlaws/bandit.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/black knight.xml b/path_10_8/data/monster/Outlaws/black knight.xml deleted file mode 100644 index 958595525..000000000 --- a/path_10_8/data/monster/Outlaws/black knight.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/crazed beggar.xml b/path_10_8/data/monster/Outlaws/crazed beggar.xml deleted file mode 100644 index b0d46b2a4..000000000 --- a/path_10_8/data/monster/Outlaws/crazed beggar.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/crypt defiler.xml b/path_10_8/data/monster/Outlaws/crypt defiler.xml deleted file mode 100644 index eee126ab6..000000000 --- a/path_10_8/data/monster/Outlaws/crypt defiler.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/feverish citizen.xml b/path_10_8/data/monster/Outlaws/feverish citizen.xml deleted file mode 100644 index 6567095b5..000000000 --- a/path_10_8/data/monster/Outlaws/feverish citizen.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/gang member.xml b/path_10_8/data/monster/Outlaws/gang member.xml deleted file mode 100644 index 1b866dbb8..000000000 --- a/path_10_8/data/monster/Outlaws/gang member.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/gladiator.xml b/path_10_8/data/monster/Outlaws/gladiator.xml deleted file mode 100644 index 457eb5f82..000000000 --- a/path_10_8/data/monster/Outlaws/gladiator.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/grave robber.xml b/path_10_8/data/monster/Outlaws/grave robber.xml deleted file mode 100644 index 1ebb3edb8..000000000 --- a/path_10_8/data/monster/Outlaws/grave robber.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/hero.xml b/path_10_8/data/monster/Outlaws/hero.xml deleted file mode 100644 index e23054887..000000000 --- a/path_10_8/data/monster/Outlaws/hero.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/hunter.xml b/path_10_8/data/monster/Outlaws/hunter.xml deleted file mode 100644 index 04dc7433b..000000000 --- a/path_10_8/data/monster/Outlaws/hunter.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/morik the gladiator.xml b/path_10_8/data/monster/Outlaws/morik the gladiator.xml deleted file mode 100644 index 1e8e584c1..000000000 --- a/path_10_8/data/monster/Outlaws/morik the gladiator.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/nomad.xml b/path_10_8/data/monster/Outlaws/nomad.xml deleted file mode 100644 index 2b0872a78..000000000 --- a/path_10_8/data/monster/Outlaws/nomad.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/poacher.xml b/path_10_8/data/monster/Outlaws/poacher.xml deleted file mode 100644 index 553b0770c..000000000 --- a/path_10_8/data/monster/Outlaws/poacher.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/primitive.xml b/path_10_8/data/monster/Outlaws/primitive.xml deleted file mode 100644 index 3dff40e91..000000000 --- a/path_10_8/data/monster/Outlaws/primitive.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/smuggler.xml b/path_10_8/data/monster/Outlaws/smuggler.xml deleted file mode 100644 index cc938cab6..000000000 --- a/path_10_8/data/monster/Outlaws/smuggler.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/stalker.xml b/path_10_8/data/monster/Outlaws/stalker.xml deleted file mode 100644 index dc758a071..000000000 --- a/path_10_8/data/monster/Outlaws/stalker.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Outlaws/wild warrior.xml b/path_10_8/data/monster/Outlaws/wild warrior.xml deleted file mode 100644 index 88eca6fac..000000000 --- a/path_10_8/data/monster/Outlaws/wild warrior.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/ashmunrah.xml b/path_10_8/data/monster/Pharaohs/ashmunrah.xml deleted file mode 100644 index 59012029c..000000000 --- a/path_10_8/data/monster/Pharaohs/ashmunrah.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/dipthrah.xml b/path_10_8/data/monster/Pharaohs/dipthrah.xml deleted file mode 100644 index aed41f233..000000000 --- a/path_10_8/data/monster/Pharaohs/dipthrah.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/horestis.xml b/path_10_8/data/monster/Pharaohs/horestis.xml deleted file mode 100644 index ac6a75956..000000000 --- a/path_10_8/data/monster/Pharaohs/horestis.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/mahrdis.xml b/path_10_8/data/monster/Pharaohs/mahrdis.xml deleted file mode 100644 index b4e2c8afa..000000000 --- a/path_10_8/data/monster/Pharaohs/mahrdis.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/morguthis.xml b/path_10_8/data/monster/Pharaohs/morguthis.xml deleted file mode 100644 index 4aefdb4df..000000000 --- a/path_10_8/data/monster/Pharaohs/morguthis.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/omruc.xml b/path_10_8/data/monster/Pharaohs/omruc.xml deleted file mode 100644 index 631edb839..000000000 --- a/path_10_8/data/monster/Pharaohs/omruc.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/rahemos.xml b/path_10_8/data/monster/Pharaohs/rahemos.xml deleted file mode 100644 index 37a4b932b..000000000 --- a/path_10_8/data/monster/Pharaohs/rahemos.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/thalas.xml b/path_10_8/data/monster/Pharaohs/thalas.xml deleted file mode 100644 index a05726723..000000000 --- a/path_10_8/data/monster/Pharaohs/thalas.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pharaohs/vashresamun.xml b/path_10_8/data/monster/Pharaohs/vashresamun.xml deleted file mode 100644 index c42f631ff..000000000 --- a/path_10_8/data/monster/Pharaohs/vashresamun.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate buccaneer.xml b/path_10_8/data/monster/Pirates/pirate buccaneer.xml deleted file mode 100644 index 6caa46a10..000000000 --- a/path_10_8/data/monster/Pirates/pirate buccaneer.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate corsair.xml b/path_10_8/data/monster/Pirates/pirate corsair.xml deleted file mode 100644 index b065cb268..000000000 --- a/path_10_8/data/monster/Pirates/pirate corsair.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate cutthroat.xml b/path_10_8/data/monster/Pirates/pirate cutthroat.xml deleted file mode 100644 index 1586d2ee4..000000000 --- a/path_10_8/data/monster/Pirates/pirate cutthroat.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate ghost.xml b/path_10_8/data/monster/Pirates/pirate ghost.xml deleted file mode 100644 index 025cae0c1..000000000 --- a/path_10_8/data/monster/Pirates/pirate ghost.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate marauder.xml b/path_10_8/data/monster/Pirates/pirate marauder.xml deleted file mode 100644 index d4bc97a1c..000000000 --- a/path_10_8/data/monster/Pirates/pirate marauder.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pirates/pirate skeleton.xml b/path_10_8/data/monster/Pirates/pirate skeleton.xml deleted file mode 100644 index 9f882585b..000000000 --- a/path_10_8/data/monster/Pirates/pirate skeleton.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/Magma Crawler.xml b/path_10_8/data/monster/Pyro-Elementals/Magma Crawler.xml deleted file mode 100644 index 0a199d68f..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/Magma Crawler.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/blazing fire elemental.xml b/path_10_8/data/monster/Pyro-Elementals/blazing fire elemental.xml deleted file mode 100644 index 077269582..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/blazing fire elemental.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/blistering fire elemental.xml b/path_10_8/data/monster/Pyro-Elementals/blistering fire elemental.xml deleted file mode 100644 index 9c4ab0268..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/blistering fire elemental.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/fire elemental.xml b/path_10_8/data/monster/Pyro-Elementals/fire elemental.xml deleted file mode 100644 index e732535b1..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/fire elemental.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/hellfire fighter.xml b/path_10_8/data/monster/Pyro-Elementals/hellfire fighter.xml deleted file mode 100644 index a7752baa5..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/hellfire fighter.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/infected weeper.xml b/path_10_8/data/monster/Pyro-Elementals/infected weeper.xml deleted file mode 100644 index a34b3a66a..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/infected weeper.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/lava golem.xml b/path_10_8/data/monster/Pyro-Elementals/lava golem.xml deleted file mode 100644 index 69176be9d..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/lava golem.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/massive fire elemental.xml b/path_10_8/data/monster/Pyro-Elementals/massive fire elemental.xml deleted file mode 100644 index ae3070cc8..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/massive fire elemental.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/orewalker.xml b/path_10_8/data/monster/Pyro-Elementals/orewalker.xml deleted file mode 100644 index 766897f24..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/orewalker.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Pyro-Elementals/weeper.xml b/path_10_8/data/monster/Pyro-Elementals/weeper.xml deleted file mode 100644 index ff2d0802c..000000000 --- a/path_10_8/data/monster/Pyro-Elementals/weeper.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara constrictor scout.xml b/path_10_8/data/monster/Quaras/quara constrictor scout.xml deleted file mode 100644 index 6b47fbf98..000000000 --- a/path_10_8/data/monster/Quaras/quara constrictor scout.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara constrictor.xml b/path_10_8/data/monster/Quaras/quara constrictor.xml deleted file mode 100644 index b8897222b..000000000 --- a/path_10_8/data/monster/Quaras/quara constrictor.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara hydromancer scout.xml b/path_10_8/data/monster/Quaras/quara hydromancer scout.xml deleted file mode 100644 index c5fb4816b..000000000 --- a/path_10_8/data/monster/Quaras/quara hydromancer scout.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara hydromancer.xml b/path_10_8/data/monster/Quaras/quara hydromancer.xml deleted file mode 100644 index c240cd388..000000000 --- a/path_10_8/data/monster/Quaras/quara hydromancer.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara mantassin scout.xml b/path_10_8/data/monster/Quaras/quara mantassin scout.xml deleted file mode 100644 index c231c6cd7..000000000 --- a/path_10_8/data/monster/Quaras/quara mantassin scout.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara mantassin.xml b/path_10_8/data/monster/Quaras/quara mantassin.xml deleted file mode 100644 index fa65be39c..000000000 --- a/path_10_8/data/monster/Quaras/quara mantassin.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara pincher scout.xml b/path_10_8/data/monster/Quaras/quara pincher scout.xml deleted file mode 100644 index a012d7451..000000000 --- a/path_10_8/data/monster/Quaras/quara pincher scout.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara pincher.xml b/path_10_8/data/monster/Quaras/quara pincher.xml deleted file mode 100644 index 22e5573da..000000000 --- a/path_10_8/data/monster/Quaras/quara pincher.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara predator scout.xml b/path_10_8/data/monster/Quaras/quara predator scout.xml deleted file mode 100644 index 2d16390e8..000000000 --- a/path_10_8/data/monster/Quaras/quara predator scout.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Quaras/quara predator.xml b/path_10_8/data/monster/Quaras/quara predator.xml deleted file mode 100644 index 95cb484ab..000000000 --- a/path_10_8/data/monster/Quaras/quara predator.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Salamanders/salamander.xml b/path_10_8/data/monster/Salamanders/salamander.xml deleted file mode 100644 index e39f6dfea..000000000 --- a/path_10_8/data/monster/Salamanders/salamander.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Serpents/cobra.xml b/path_10_8/data/monster/Serpents/cobra.xml deleted file mode 100644 index e6fd5c137..000000000 --- a/path_10_8/data/monster/Serpents/cobra.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Serpents/sea serpent.xml b/path_10_8/data/monster/Serpents/sea serpent.xml deleted file mode 100644 index b70f02cbe..000000000 --- a/path_10_8/data/monster/Serpents/sea serpent.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Serpents/serpent spawn.xml b/path_10_8/data/monster/Serpents/serpent spawn.xml deleted file mode 100644 index 1cfb54361..000000000 --- a/path_10_8/data/monster/Serpents/serpent spawn.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Serpents/snake.xml b/path_10_8/data/monster/Serpents/snake.xml deleted file mode 100644 index 61215d1e6..000000000 --- a/path_10_8/data/monster/Serpents/snake.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Serpents/young sea serpent.xml b/path_10_8/data/monster/Serpents/young sea serpent.xml deleted file mode 100644 index d48becffb..000000000 --- a/path_10_8/data/monster/Serpents/young sea serpent.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Shapeshifters/mimic.xml b/path_10_8/data/monster/Shapeshifters/mimic.xml deleted file mode 100644 index 8584176b7..000000000 --- a/path_10_8/data/monster/Shapeshifters/mimic.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/betrayed wraith.xml b/path_10_8/data/monster/Skeletons/betrayed wraith.xml deleted file mode 100644 index 39e671480..000000000 --- a/path_10_8/data/monster/Skeletons/betrayed wraith.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/bonebeast.xml b/path_10_8/data/monster/Skeletons/bonebeast.xml deleted file mode 100644 index dcca7fe28..000000000 --- a/path_10_8/data/monster/Skeletons/bonebeast.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/demon skeleton.xml b/path_10_8/data/monster/Skeletons/demon skeleton.xml deleted file mode 100644 index 0c4c973e4..000000000 --- a/path_10_8/data/monster/Skeletons/demon skeleton.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/dreadbeast.xml b/path_10_8/data/monster/Skeletons/dreadbeast.xml deleted file mode 100644 index 25056d725..000000000 --- a/path_10_8/data/monster/Skeletons/dreadbeast.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/honour guard.xml b/path_10_8/data/monster/Skeletons/honour guard.xml deleted file mode 100644 index a71501c86..000000000 --- a/path_10_8/data/monster/Skeletons/honour guard.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/lost soul.xml b/path_10_8/data/monster/Skeletons/lost soul.xml deleted file mode 100644 index 8f93e2389..000000000 --- a/path_10_8/data/monster/Skeletons/lost soul.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/party skeleton.xml b/path_10_8/data/monster/Skeletons/party skeleton.xml deleted file mode 100644 index 469f8940a..000000000 --- a/path_10_8/data/monster/Skeletons/party skeleton.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/skeleton warrior.xml b/path_10_8/data/monster/Skeletons/skeleton warrior.xml deleted file mode 100644 index d46270f78..000000000 --- a/path_10_8/data/monster/Skeletons/skeleton warrior.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/skeleton.xml b/path_10_8/data/monster/Skeletons/skeleton.xml deleted file mode 100644 index d83a1e3e5..000000000 --- a/path_10_8/data/monster/Skeletons/skeleton.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/undead gladiator.xml b/path_10_8/data/monster/Skeletons/undead gladiator.xml deleted file mode 100644 index ee050424d..000000000 --- a/path_10_8/data/monster/Skeletons/undead gladiator.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/undead mine worker.xml b/path_10_8/data/monster/Skeletons/undead mine worker.xml deleted file mode 100644 index 987e65a4c..000000000 --- a/path_10_8/data/monster/Skeletons/undead mine worker.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Skeletons/undead minion.xml b/path_10_8/data/monster/Skeletons/undead minion.xml deleted file mode 100644 index 97895e365..000000000 --- a/path_10_8/data/monster/Skeletons/undead minion.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/azerus.xml b/path_10_8/data/monster/Sorcerers/azerus.xml deleted file mode 100644 index e8563cec7..000000000 --- a/path_10_8/data/monster/Sorcerers/azerus.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/dark apprentice.xml b/path_10_8/data/monster/Sorcerers/dark apprentice.xml deleted file mode 100644 index 8b3d57f6a..000000000 --- a/path_10_8/data/monster/Sorcerers/dark apprentice.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/dark magician.xml b/path_10_8/data/monster/Sorcerers/dark magician.xml deleted file mode 100644 index e013e7c71..000000000 --- a/path_10_8/data/monster/Sorcerers/dark magician.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/energized raging mage.xml b/path_10_8/data/monster/Sorcerers/energized raging mage.xml deleted file mode 100644 index 0920f6b2d..000000000 --- a/path_10_8/data/monster/Sorcerers/energized raging mage.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/fury.xml b/path_10_8/data/monster/Sorcerers/fury.xml deleted file mode 100644 index b26b05756..000000000 --- a/path_10_8/data/monster/Sorcerers/fury.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/ice witch.xml b/path_10_8/data/monster/Sorcerers/ice witch.xml deleted file mode 100644 index ec659920e..000000000 --- a/path_10_8/data/monster/Sorcerers/ice witch.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/incredibly old witch.xml b/path_10_8/data/monster/Sorcerers/incredibly old witch.xml deleted file mode 100644 index bed56fdb0..000000000 --- a/path_10_8/data/monster/Sorcerers/incredibly old witch.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/infernalist.xml b/path_10_8/data/monster/Sorcerers/infernalist.xml deleted file mode 100644 index 5ac5c65eb..000000000 --- a/path_10_8/data/monster/Sorcerers/infernalist.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/mad mage.xml b/path_10_8/data/monster/Sorcerers/mad mage.xml deleted file mode 100644 index 731b226e6..000000000 --- a/path_10_8/data/monster/Sorcerers/mad mage.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/mad scientist.xml b/path_10_8/data/monster/Sorcerers/mad scientist.xml deleted file mode 100644 index 78b1541c3..000000000 --- a/path_10_8/data/monster/Sorcerers/mad scientist.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/raging mage.xml b/path_10_8/data/monster/Sorcerers/raging mage.xml deleted file mode 100644 index 3e2b44572..000000000 --- a/path_10_8/data/monster/Sorcerers/raging mage.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/warlock.xml b/path_10_8/data/monster/Sorcerers/warlock.xml deleted file mode 100644 index abc6aeed9..000000000 --- a/path_10_8/data/monster/Sorcerers/warlock.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/witch.xml b/path_10_8/data/monster/Sorcerers/witch.xml deleted file mode 100644 index e118b5564..000000000 --- a/path_10_8/data/monster/Sorcerers/witch.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Sorcerers/yalahari.xml b/path_10_8/data/monster/Sorcerers/yalahari.xml deleted file mode 100644 index 1dc84e836..000000000 --- a/path_10_8/data/monster/Sorcerers/yalahari.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/The Triangle of Terror/ghazbaran.xml b/path_10_8/data/monster/The Triangle of Terror/ghazbaran.xml deleted file mode 100644 index f30ff5d6a..000000000 --- a/path_10_8/data/monster/The Triangle of Terror/ghazbaran.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/The Triangle of Terror/morgaroth.xml b/path_10_8/data/monster/The Triangle of Terror/morgaroth.xml deleted file mode 100644 index 61cdcb484..000000000 --- a/path_10_8/data/monster/The Triangle of Terror/morgaroth.xml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/deathslicer.xml b/path_10_8/data/monster/Traps/deathslicer.xml deleted file mode 100644 index 99f461e7f..000000000 --- a/path_10_8/data/monster/Traps/deathslicer.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/flamethrower.xml b/path_10_8/data/monster/Traps/flamethrower.xml deleted file mode 100644 index 18a056529..000000000 --- a/path_10_8/data/monster/Traps/flamethrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/hive pore.xml b/path_10_8/data/monster/Traps/hive pore.xml deleted file mode 100644 index 24973dc2e..000000000 --- a/path_10_8/data/monster/Traps/hive pore.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/lavahole.xml b/path_10_8/data/monster/Traps/lavahole.xml deleted file mode 100644 index 00d62e76b..000000000 --- a/path_10_8/data/monster/Traps/lavahole.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/magic pillar.xml b/path_10_8/data/monster/Traps/magic pillar.xml deleted file mode 100644 index 59b6f649d..000000000 --- a/path_10_8/data/monster/Traps/magic pillar.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/magicthrower.xml b/path_10_8/data/monster/Traps/magicthrower.xml deleted file mode 100644 index 4a7e10e0a..000000000 --- a/path_10_8/data/monster/Traps/magicthrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/plaguethrower.xml b/path_10_8/data/monster/Traps/plaguethrower.xml deleted file mode 100644 index 762cdfb51..000000000 --- a/path_10_8/data/monster/Traps/plaguethrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Traps/shredderthrower.xml b/path_10_8/data/monster/Traps/shredderthrower.xml deleted file mode 100644 index 70c850976..000000000 --- a/path_10_8/data/monster/Traps/shredderthrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/frost troll.xml b/path_10_8/data/monster/Trolls/frost troll.xml deleted file mode 100644 index 3ab3d8089..000000000 --- a/path_10_8/data/monster/Trolls/frost troll.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/furious troll.xml b/path_10_8/data/monster/Trolls/furious troll.xml deleted file mode 100644 index b040f75d2..000000000 --- a/path_10_8/data/monster/Trolls/furious troll.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/island troll.xml b/path_10_8/data/monster/Trolls/island troll.xml deleted file mode 100644 index f9769055c..000000000 --- a/path_10_8/data/monster/Trolls/island troll.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/swamp troll.xml b/path_10_8/data/monster/Trolls/swamp troll.xml deleted file mode 100644 index 51ccc1e39..000000000 --- a/path_10_8/data/monster/Trolls/swamp troll.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/troll champion.xml b/path_10_8/data/monster/Trolls/troll champion.xml deleted file mode 100644 index cdc559f87..000000000 --- a/path_10_8/data/monster/Trolls/troll champion.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/troll guard.xml b/path_10_8/data/monster/Trolls/troll guard.xml deleted file mode 100644 index e0ae1ea21..000000000 --- a/path_10_8/data/monster/Trolls/troll guard.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/troll legionnaire.xml b/path_10_8/data/monster/Trolls/troll legionnaire.xml deleted file mode 100644 index f06391418..000000000 --- a/path_10_8/data/monster/Trolls/troll legionnaire.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/troll.xml b/path_10_8/data/monster/Trolls/troll.xml deleted file mode 100644 index f754d4439..000000000 --- a/path_10_8/data/monster/Trolls/troll.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Trolls/young troll.xml b/path_10_8/data/monster/Trolls/young troll.xml deleted file mode 100644 index dc6ac7a7c..000000000 --- a/path_10_8/data/monster/Trolls/young troll.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/armenius.xml b/path_10_8/data/monster/Undead Humanoids/armenius.xml deleted file mode 100644 index 8ac43b529..000000000 --- a/path_10_8/data/monster/Undead Humanoids/armenius.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/banshee.xml b/path_10_8/data/monster/Undead Humanoids/banshee.xml deleted file mode 100644 index d453e4fd2..000000000 --- a/path_10_8/data/monster/Undead Humanoids/banshee.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/blightwalker.xml b/path_10_8/data/monster/Undead Humanoids/blightwalker.xml deleted file mode 100644 index de2014d48..000000000 --- a/path_10_8/data/monster/Undead Humanoids/blightwalker.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/crypt shambler.xml b/path_10_8/data/monster/Undead Humanoids/crypt shambler.xml deleted file mode 100644 index da3a1dbba..000000000 --- a/path_10_8/data/monster/Undead Humanoids/crypt shambler.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/death priest.xml b/path_10_8/data/monster/Undead Humanoids/death priest.xml deleted file mode 100644 index 0ae8d9e5b..000000000 --- a/path_10_8/data/monster/Undead Humanoids/death priest.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/elder mummy.xml b/path_10_8/data/monster/Undead Humanoids/elder mummy.xml deleted file mode 100644 index b83c16223..000000000 --- a/path_10_8/data/monster/Undead Humanoids/elder mummy.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/ghoul.xml b/path_10_8/data/monster/Undead Humanoids/ghoul.xml deleted file mode 100644 index e8ad5d105..000000000 --- a/path_10_8/data/monster/Undead Humanoids/ghoul.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/grim reaper.xml b/path_10_8/data/monster/Undead Humanoids/grim reaper.xml deleted file mode 100644 index f9f44c738..000000000 --- a/path_10_8/data/monster/Undead Humanoids/grim reaper.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/lich.xml b/path_10_8/data/monster/Undead Humanoids/lich.xml deleted file mode 100644 index da20014d7..000000000 --- a/path_10_8/data/monster/Undead Humanoids/lich.xml +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/mummy.xml b/path_10_8/data/monster/Undead Humanoids/mummy.xml deleted file mode 100644 index f9105e373..000000000 --- a/path_10_8/data/monster/Undead Humanoids/mummy.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/nightfiend.xml b/path_10_8/data/monster/Undead Humanoids/nightfiend.xml deleted file mode 100644 index d76cf954c..000000000 --- a/path_10_8/data/monster/Undead Humanoids/nightfiend.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/the pale count.xml b/path_10_8/data/monster/Undead Humanoids/the pale count.xml deleted file mode 100644 index 031e11114..000000000 --- a/path_10_8/data/monster/Undead Humanoids/the pale count.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/tomb servant.xml b/path_10_8/data/monster/Undead Humanoids/tomb servant.xml deleted file mode 100644 index a89ca5a7a..000000000 --- a/path_10_8/data/monster/Undead Humanoids/tomb servant.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/undead prospector.xml b/path_10_8/data/monster/Undead Humanoids/undead prospector.xml deleted file mode 100644 index 487929bb2..000000000 --- a/path_10_8/data/monster/Undead Humanoids/undead prospector.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/vampire bride.xml b/path_10_8/data/monster/Undead Humanoids/vampire bride.xml deleted file mode 100644 index 4f5380056..000000000 --- a/path_10_8/data/monster/Undead Humanoids/vampire bride.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/vampire viscount.xml b/path_10_8/data/monster/Undead Humanoids/vampire viscount.xml deleted file mode 100644 index 581f7d6c9..000000000 --- a/path_10_8/data/monster/Undead Humanoids/vampire viscount.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/vampire.xml b/path_10_8/data/monster/Undead Humanoids/vampire.xml deleted file mode 100644 index 76539b2c0..000000000 --- a/path_10_8/data/monster/Undead Humanoids/vampire.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/vicious manbat.xml b/path_10_8/data/monster/Undead Humanoids/vicious manbat.xml deleted file mode 100644 index f7af3a68e..000000000 --- a/path_10_8/data/monster/Undead Humanoids/vicious manbat.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Undead Humanoids/zombie.xml b/path_10_8/data/monster/Undead Humanoids/zombie.xml deleted file mode 100644 index 7118b856e..000000000 --- a/path_10_8/data/monster/Undead Humanoids/zombie.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/black sheep.xml b/path_10_8/data/monster/Ungulates/black sheep.xml deleted file mode 100644 index 07f31532b..000000000 --- a/path_10_8/data/monster/Ungulates/black sheep.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/boar.xml b/path_10_8/data/monster/Ungulates/boar.xml deleted file mode 100644 index c80f8a938..000000000 --- a/path_10_8/data/monster/Ungulates/boar.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/deer.xml b/path_10_8/data/monster/Ungulates/deer.xml deleted file mode 100644 index 98a9d0d78..000000000 --- a/path_10_8/data/monster/Ungulates/deer.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/desperate white deer.xml b/path_10_8/data/monster/Ungulates/desperate white deer.xml deleted file mode 100644 index 235440c34..000000000 --- a/path_10_8/data/monster/Ungulates/desperate white deer.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/doom deer.xml b/path_10_8/data/monster/Ungulates/doom deer.xml deleted file mode 100644 index 5bd4f25cb..000000000 --- a/path_10_8/data/monster/Ungulates/doom deer.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/dromedary.xml b/path_10_8/data/monster/Ungulates/dromedary.xml deleted file mode 100644 index 2e5a136ab..000000000 --- a/path_10_8/data/monster/Ungulates/dromedary.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/elephant.xml b/path_10_8/data/monster/Ungulates/elephant.xml deleted file mode 100644 index 7a8fcac67..000000000 --- a/path_10_8/data/monster/Ungulates/elephant.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/enraged white deer.xml b/path_10_8/data/monster/Ungulates/enraged white deer.xml deleted file mode 100644 index 6ac275330..000000000 --- a/path_10_8/data/monster/Ungulates/enraged white deer.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/evil sheep lord.xml b/path_10_8/data/monster/Ungulates/evil sheep lord.xml deleted file mode 100644 index 8026f19d9..000000000 --- a/path_10_8/data/monster/Ungulates/evil sheep lord.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/evil sheep.xml b/path_10_8/data/monster/Ungulates/evil sheep.xml deleted file mode 100644 index 0d6807ed2..000000000 --- a/path_10_8/data/monster/Ungulates/evil sheep.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/horse(brown).xml b/path_10_8/data/monster/Ungulates/horse(brown).xml deleted file mode 100644 index a5f531f10..000000000 --- a/path_10_8/data/monster/Ungulates/horse(brown).xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/horse(fire).xml b/path_10_8/data/monster/Ungulates/horse(fire).xml deleted file mode 100644 index 2c2b95d25..000000000 --- a/path_10_8/data/monster/Ungulates/horse(fire).xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/horse(grey).xml b/path_10_8/data/monster/Ungulates/horse(grey).xml deleted file mode 100644 index 12b76f873..000000000 --- a/path_10_8/data/monster/Ungulates/horse(grey).xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/horse.xml b/path_10_8/data/monster/Ungulates/horse.xml deleted file mode 100644 index e797f6f52..000000000 --- a/path_10_8/data/monster/Ungulates/horse.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/mammoth.xml b/path_10_8/data/monster/Ungulates/mammoth.xml deleted file mode 100644 index 62eec0ccb..000000000 --- a/path_10_8/data/monster/Ungulates/mammoth.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/mushroom sniffer.xml b/path_10_8/data/monster/Ungulates/mushroom sniffer.xml deleted file mode 100644 index 47ba6fec9..000000000 --- a/path_10_8/data/monster/Ungulates/mushroom sniffer.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/pig.xml b/path_10_8/data/monster/Ungulates/pig.xml deleted file mode 100644 index 1f3f6a5ca..000000000 --- a/path_10_8/data/monster/Ungulates/pig.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/sheep.xml b/path_10_8/data/monster/Ungulates/sheep.xml deleted file mode 100644 index 2f86e86db..000000000 --- a/path_10_8/data/monster/Ungulates/sheep.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/stampor.xml b/path_10_8/data/monster/Ungulates/stampor.xml deleted file mode 100644 index 33e6173a4..000000000 --- a/path_10_8/data/monster/Ungulates/stampor.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/terrified elephant.xml b/path_10_8/data/monster/Ungulates/terrified elephant.xml deleted file mode 100644 index 8fa5a9c00..000000000 --- a/path_10_8/data/monster/Ungulates/terrified elephant.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/vampire pig.xml b/path_10_8/data/monster/Ungulates/vampire pig.xml deleted file mode 100644 index 3ab19e296..000000000 --- a/path_10_8/data/monster/Ungulates/vampire pig.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Ungulates/white deer.xml b/path_10_8/data/monster/Ungulates/white deer.xml deleted file mode 100644 index fe69a8cf4..000000000 --- a/path_10_8/data/monster/Ungulates/white deer.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Voodoo Cultists/acolyte of the cult.xml b/path_10_8/data/monster/Voodoo Cultists/acolyte of the cult.xml deleted file mode 100644 index dc7e7b555..000000000 --- a/path_10_8/data/monster/Voodoo Cultists/acolyte of the cult.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Voodoo Cultists/adept of the cult.xml b/path_10_8/data/monster/Voodoo Cultists/adept of the cult.xml deleted file mode 100644 index 116fe32e6..000000000 --- a/path_10_8/data/monster/Voodoo Cultists/adept of the cult.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Voodoo Cultists/enlightened of the cult.xml b/path_10_8/data/monster/Voodoo Cultists/enlightened of the cult.xml deleted file mode 100644 index 23775d3fb..000000000 --- a/path_10_8/data/monster/Voodoo Cultists/enlightened of the cult.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Voodoo Cultists/novice of the cult.xml b/path_10_8/data/monster/Voodoo Cultists/novice of the cult.xml deleted file mode 100644 index 080a1ff60..000000000 --- a/path_10_8/data/monster/Voodoo Cultists/novice of the cult.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Wild Magics/wild fire magic.xml b/path_10_8/data/monster/Wild Magics/wild fire magic.xml deleted file mode 100644 index db1be4f92..000000000 --- a/path_10_8/data/monster/Wild Magics/wild fire magic.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Wild Magics/wild fury magic.xml b/path_10_8/data/monster/Wild Magics/wild fury magic.xml deleted file mode 100644 index 5555b4671..000000000 --- a/path_10_8/data/monster/Wild Magics/wild fury magic.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Wild Magics/wild nature magic.xml b/path_10_8/data/monster/Wild Magics/wild nature magic.xml deleted file mode 100644 index fa6c55da5..000000000 --- a/path_10_8/data/monster/Wild Magics/wild nature magic.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/Wild Magics/wild water magic.xml b/path_10_8/data/monster/Wild Magics/wild water magic.xml deleted file mode 100644 index e4b4236b1..000000000 --- a/path_10_8/data/monster/Wild Magics/wild water magic.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/monster/monsters.xml b/path_10_8/data/monster/monsters.xml deleted file mode 100644 index 680330387..000000000 --- a/path_10_8/data/monster/monsters.xml +++ /dev/null @@ -1,823 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/movements/lib/movements.lua b/path_10_8/data/movements/lib/movements.lua deleted file mode 100644 index b081a0ffe..000000000 --- a/path_10_8/data/movements/lib/movements.lua +++ /dev/null @@ -1,2 +0,0 @@ --- Nothing -- - diff --git a/path_10_8/data/movements/movements.xml b/path_10_8/data/movements/movements.xml deleted file mode 100644 index 25569d019..000000000 --- a/path_10_8/data/movements/movements.xml +++ /dev/null @@ -1,1047 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/movements/scripts/citizen.lua b/path_10_8/data/movements/scripts/citizen.lua deleted file mode 100644 index 94e882d5e..000000000 --- a/path_10_8/data/movements/scripts/citizen.lua +++ /dev/null @@ -1,12 +0,0 @@ -function onStepIn(creature, item, position, fromPosition) - if item.actionid > 30020 and item.actionid < 30050 then - local player = creature:getPlayer() - if player == nil then - return false - end - - local town = Town(item.actionid - 30020) - player:setTown(town) - end - return true -end diff --git a/path_10_8/data/movements/scripts/closingdoor.lua b/path_10_8/data/movements/scripts/closingdoor.lua deleted file mode 100644 index 83904ae06..000000000 --- a/path_10_8/data/movements/scripts/closingdoor.lua +++ /dev/null @@ -1,31 +0,0 @@ -function onStepOut(creature, item, position, fromPosition) - local tile = Tile(position) - if tile:getCreatureCount() > 0 then - return true - end - - local newPosition = {x = position.x + 1, y = position.y, z = position.z} - local query = Tile(newPosition):queryAdd(creature) - if query ~= RETURNVALUE_NOERROR or query == RETURNVALUE_NOTENOUGHROOM then - newPosition.x = newPosition.x - 1 - newPosition.y = newPosition.y + 1 - query = Tile(newPosition):queryAdd(creature) - end - - if query == RETURNVALUE_NOERROR or query ~= RETURNVALUE_NOTENOUGHROOM then - doRelocate(position, newPosition) - end - - local i, tileItem, tileCount = 1, true, tile:getThingCount() - while tileItem and i < tileCount do - tileItem = tile:getThing(i) - if tileItem and tileItem:getUniqueId() ~= item.uid and tileItem:getType():isMovable() then - tileItem:remove() - else - i = i + 1 - end - end - - item:transform(item.itemid - 1) - return true -end diff --git a/path_10_8/data/movements/scripts/decay.lua b/path_10_8/data/movements/scripts/decay.lua deleted file mode 100644 index 9a48822b2..000000000 --- a/path_10_8/data/movements/scripts/decay.lua +++ /dev/null @@ -1,5 +0,0 @@ -function onStepIn(creature, item, position, fromPosition) - item:transform(item.itemid + 1) - item:decay() - return true -end diff --git a/path_10_8/data/movements/scripts/dough.lua b/path_10_8/data/movements/scripts/dough.lua deleted file mode 100644 index a0b371fa4..000000000 --- a/path_10_8/data/movements/scripts/dough.lua +++ /dev/null @@ -1,10 +0,0 @@ -function onAddItem(moveitem, tileitem, position) - if moveitem:getId() == 2693 then - moveitem:transform(2689) - position:sendMagicEffect(CONST_ME_HITBYFIRE) - elseif moveitem:getId() == 6277 then - moveitem:transform(2687, 12) - position:sendMagicEffect(CONST_ME_HITBYFIRE) - end - return true -end diff --git a/path_10_8/data/movements/scripts/drowning.lua b/path_10_8/data/movements/scripts/drowning.lua deleted file mode 100644 index ee5a6979d..000000000 --- a/path_10_8/data/movements/scripts/drowning.lua +++ /dev/null @@ -1,27 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_PERIODICDAMAGE, -20) -condition:setParameter(CONDITION_PARAM_TICKS, -1) -condition:setParameter(CONDITION_PARAM_TICKINTERVAL, 2000) - -function onStepIn(creature, item, position, fromPosition) - local player = creature:getPlayer() - if player == nil then - return true - end - - if math.random(1, 10) == 1 then - position:sendMagicEffect(CONST_ME_BUBBLES) - end - player:addCondition(condition) - return true -end - -function onStepOut(creature, item, position, fromPosition) - local player = creature:getPlayer() - if player == nil then - return true - end - - player:removeCondition(CONDITION_DROWN) - return true -end diff --git a/path_10_8/data/movements/scripts/snow.lua b/path_10_8/data/movements/scripts/snow.lua deleted file mode 100644 index 8a07bbfa3..000000000 --- a/path_10_8/data/movements/scripts/snow.lua +++ /dev/null @@ -1,13 +0,0 @@ -function onStepOut(creature, item, position, fromPosition) - if creature:isPlayer() and creature:isInGhostMode() then - return true - end - - if item:getId() == 670 then - item:transform(6594) - else - item:transform(item.itemid + 15) - end - item:decay() - return true -end diff --git a/path_10_8/data/movements/scripts/swimming.lua b/path_10_8/data/movements/scripts/swimming.lua deleted file mode 100644 index f11af1a6c..000000000 --- a/path_10_8/data/movements/scripts/swimming.lua +++ /dev/null @@ -1,20 +0,0 @@ -local outfit = {lookType = 267, lookHead = 0, lookBody = 0, lookLegs = 0, lookFeet = 0, lookTypeEx = 0, lookAddons = 0} - -function onStepIn(creature, item, position, fromPosition) - if not creature:isPlayer() then - return false - end - - doSetCreatureOutfit(creature, outfit, -1) - return true -end - -function onStepOut(creature, item, position, fromPosition) - local player = creature:getPlayer() - if player == nil then - return false - end - - player:removeCondition(CONDITION_OUTFIT) - return true -end diff --git a/path_10_8/data/movements/scripts/tiles.lua b/path_10_8/data/movements/scripts/tiles.lua deleted file mode 100644 index 9a47a2a34..000000000 --- a/path_10_8/data/movements/scripts/tiles.lua +++ /dev/null @@ -1,56 +0,0 @@ -local increasing = {[416] = 417, [426] = 425, [446] = 447, [3216] = 3217, [3202] = 3215, [11062] = 11063} -local decreasing = {[417] = 416, [425] = 426, [447] = 446, [3217] = 3216, [3215] = 3202, [11063] = 11062} - -function onStepIn(creature, item, position, fromPosition) - if not increasing[item.itemid] then - return true - end - - local player = creature:getPlayer() - if player == nil or player:isInGhostMode() then - return true - end - - item:transform(increasing[item.itemid]) - - if item.actionid >= 1000 then - if player:getLevel() < item.actionid - 1000 then - player:teleportTo(fromPosition, false) - position:sendMagicEffect(CONST_ME_MAGIC_BLUE) - player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.") - end - return true - end - - if Tile(position):hasFlag(TILESTATE_PROTECTIONZONE) then - local lookPosition = player:getPosition() - lookPosition:getNextPosition(player:getDirection()) - local depotItem = Tile(lookPosition):getItemByType(ITEM_TYPE_DEPOT) - if depotItem ~= nil then - local depotItems = player:getDepotChest(getDepotId(depotItem:getUniqueId()), true):getItemHoldingCount() - player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or ".")) - return true - end - end - - if item.actionid ~= 0 and player:getStorageValue(item.actionid) <= 0 then - player:teleportTo(fromPosition, false) - position:sendMagicEffect(CONST_ME_MAGIC_BLUE) - player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.") - return true - end - return true -end - -function onStepOut(creature, item, position, fromPosition) - if not decreasing[item.itemid] then - return true - end - - if creature:isPlayer() and creature:isInGhostMode() then - return true - end - - item:transform(decreasing[item.itemid]) - return true -end diff --git a/path_10_8/data/movements/scripts/trap.lua b/path_10_8/data/movements/scripts/trap.lua deleted file mode 100644 index e8a49f7a5..000000000 --- a/path_10_8/data/movements/scripts/trap.lua +++ /dev/null @@ -1,36 +0,0 @@ -local traps = { - [1510] = {transformTo = 1511, damage = {-50, -100}}, - [1513] = {damage = {-50, -100}}, - [2579] = {transformTo = 2578, damage = {-15, -30}}, - [4208] = {transformTo = 4209, damage = {-15, -30}, type = COMBAT_EARTHDAMAGE} -} - -function onStepIn(creature, item, position, fromPosition) - local trap = traps[item.itemid] - if trap == nil then - return true - end - - if creature:isMonster() then - doTargetCombatHealth(0, creature, trap.type or COMBAT_PHYSICALDAMAGE, trap.damage[1], trap.damage[2], CONST_ME_NONE) - end - - if trap.transformTo ~= nil then - item:transform(trap.transformTo) - end - return true -end - -function onStepOut(creature, item, position, fromPosition) - item:transform(item.itemid - 1) - return true -end - -function onRemoveItem(item, tile, position) - local itemPosition = item:getPosition() - if itemPosition:getDistance(position) > 0 then - item:transform(item.itemid - 1) - itemPosition:sendMagicEffect(CONST_ME_POFF) - end - return true -end diff --git a/path_10_8/data/movements/scripts/walkback.lua b/path_10_8/data/movements/scripts/walkback.lua deleted file mode 100644 index 30b00f21f..000000000 --- a/path_10_8/data/movements/scripts/walkback.lua +++ /dev/null @@ -1,6 +0,0 @@ -function onStepIn(creature, item, position, fromPosition) - if item.uid > 0 and item.uid <= 65535 then - creature:teleportTo(fromPosition, false) - end - return true -end diff --git a/path_10_8/data/npc/Alice.xml b/path_10_8/data/npc/Alice.xml deleted file mode 100644 index 755d769ea..000000000 --- a/path_10_8/data/npc/Alice.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Deruno.xml b/path_10_8/data/npc/Deruno.xml deleted file mode 100644 index 9e56d893c..000000000 --- a/path_10_8/data/npc/Deruno.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Dimral.xml b/path_10_8/data/npc/Dimral.xml deleted file mode 100644 index 287660d3f..000000000 --- a/path_10_8/data/npc/Dimral.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Donald.xml b/path_10_8/data/npc/Donald.xml deleted file mode 100644 index 91e5bd147..000000000 --- a/path_10_8/data/npc/Donald.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Eryn.xml b/path_10_8/data/npc/Eryn.xml deleted file mode 100644 index 93622cdbf..000000000 --- a/path_10_8/data/npc/Eryn.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_10_8/data/npc/Nimral.xml b/path_10_8/data/npc/Nimral.xml deleted file mode 100644 index 9eb14da8c..000000000 --- a/path_10_8/data/npc/Nimral.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Riona.xml b/path_10_8/data/npc/Riona.xml deleted file mode 100644 index ed6df9a6f..000000000 --- a/path_10_8/data/npc/Riona.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_10_8/data/npc/Soya.xml b/path_10_8/data/npc/Soya.xml deleted file mode 100644 index 3f9ad1381..000000000 --- a/path_10_8/data/npc/Soya.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/The Forgotten King.xml b/path_10_8/data/npc/The Forgotten King.xml deleted file mode 100644 index 5f34703f6..000000000 --- a/path_10_8/data/npc/The Forgotten King.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_10_8/data/npc/The Oracle.xml b/path_10_8/data/npc/The Oracle.xml deleted file mode 100644 index 8aec9e74f..000000000 --- a/path_10_8/data/npc/The Oracle.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_10_8/data/npc/Timral.xml b/path_10_8/data/npc/Timral.xml deleted file mode 100644 index 6186e61c0..000000000 --- a/path_10_8/data/npc/Timral.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/path_10_8/data/npc/Tyoric.xml b/path_10_8/data/npc/Tyoric.xml deleted file mode 100644 index 38f6114b1..000000000 --- a/path_10_8/data/npc/Tyoric.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_10_8/data/npc/lib/npc.lua b/path_10_8/data/npc/lib/npc.lua deleted file mode 100644 index 8161efeab..000000000 --- a/path_10_8/data/npc/lib/npc.lua +++ /dev/null @@ -1,130 +0,0 @@ --- Including the Advanced NPC System -dofile('data/npc/lib/npcsystem/npcsystem.lua') - -function msgcontains(message, keyword) - local message, keyword = message:lower(), keyword:lower() - if message == keyword then - return true - end - - return message:find(keyword) and not message:find('(%w+)' .. keyword) -end - -function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack) - local amount = amount or 1 - local subType = subType or 0 - local item = 0 - if isItemStackable(itemid) then - if inBackpacks then - stuff = doCreateItemEx(backpack, 1) - item = doAddContainerItem(stuff, itemid, math.min(100, amount)) - else - stuff = doCreateItemEx(itemid, math.min(100, amount)) - end - return doPlayerAddItemEx(cid, stuff, ignoreCap) ~= RETURNVALUE_NOERROR and 0 or amount, 0 - end - - local a = 0 - if inBackpacks then - local container, b = doCreateItemEx(backpack, 1), 1 - for i = 1, amount do - local item = doAddContainerItem(container, itemid, subType) - if isInArray({(getContainerCapById(backpack) * b), amount}, i) then - if doPlayerAddItemEx(cid, container, ignoreCap) ~= RETURNVALUE_NOERROR then - b = b - 1 - break - end - - a = i - if amount > i then - container = doCreateItemEx(backpack, 1) - b = b + 1 - end - end - end - return a, b - end - - for i = 1, amount do -- normal method for non-stackable items - local item = doCreateItemEx(itemid, subType) - if doPlayerAddItemEx(cid, item, ignoreCap) ~= RETURNVALUE_NOERROR then - break - end - a = i - end - return a, 0 -end - -local func = function(cid, text, type, e, pcid) - if isPlayer(pcid) then - doCreatureSay(cid, text, type, false, pcid, getCreaturePosition(cid)) - e.done = TRUE - end -end - -function doCreatureSayWithDelay(cid, text, type, delay, e, pcid) - if isPlayer(pcid) then - e.done = FALSE - e.event = addEvent(func, delay < 1 and 1000 or delay, cid, text, type, e, pcid) - end -end - -function doPlayerTakeItem(cid, itemid, count) - if getPlayerItemCount(cid,itemid) < count then - return false - end - - while count > 0 do - local tempcount = 0 - if isItemStackable(itemid) then - tempcount = math.min (100, count) - else - tempcount = 1 - end - - local ret = doPlayerRemoveItem(cid, itemid, tempcount) - if ret ~= false then - count = count - tempcount - else - return false - end - end - - if count ~= 0 then - return false - end - return true -end - -function doPlayerSellItem(cid, itemid, count, cost) - if doPlayerTakeItem(cid, itemid, count) == true then - if not doPlayerAddMoney(cid, cost) then - error('Could not add money to ' .. getPlayerName(cid) .. '(' .. cost .. 'gp)') - end - return true - end - return false -end - -function doPlayerBuyItemContainer(cid, containerid, itemid, count, cost, charges) - if not doPlayerRemoveMoney(cid, cost) then - return false - end - - for i = 1, count do - local container = doCreateItemEx(containerid, 1) - for x = 1, getContainerCapById(containerid) do - doAddContainerItem(container, itemid, charges) - end - - if doPlayerAddItemEx(cid, container, true) ~= RETURNVALUE_NOERROR then - return false - end - end - return true -end - -function getCount(string) - local b, e = string:find("%d+") - return b and e and tonumber(string:sub(b, e)) or -1 -end diff --git a/path_10_8/data/npc/lib/npcsystem/keywordhandler.lua b/path_10_8/data/npc/lib/npcsystem/keywordhandler.lua deleted file mode 100644 index ea4f5d3ad..000000000 --- a/path_10_8/data/npc/lib/npcsystem/keywordhandler.lua +++ /dev/null @@ -1,174 +0,0 @@ --- Advanced NPC System by Jiddo - -if KeywordHandler == nil then - KeywordNode = { - keywords = nil, - callback = nil, - parameters = nil, - children = nil, - parent = nil - } - - -- Created a new keywordnode with the given keywords, callback function and parameters and without any childNodes. - function KeywordNode:new(keys, func, param) - local obj = {} - obj.keywords = keys - obj.callback = func - obj.parameters = param - obj.children = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - -- Calls the underlying callback function if it is not nil. - function KeywordNode:processMessage(cid, message) - return (self.callback == nil or self.callback(cid, message, self.keywords, self.parameters, self)) - end - - -- Returns true if message contains all patterns/strings found in keywords. - function KeywordNode:checkMessage(message) - if self.keywords.callback ~= nil then - return self.keywords.callback(self.keywords, message) - end - - for _, v in ipairs(self.keywords) do - if type(v) == 'string' then - local a, b = string.find(message, v) - if a == nil or b == nil then - return false - end - end - end - return true - end - - -- Returns the parent of this node or nil if no such node exists. - function KeywordNode:getParent() - return self.parent - end - - -- Returns an array of the callback function parameters assosiated with this node. - function KeywordNode:getParameters() - return self.parameters - end - - -- Returns an array of the triggering keywords assosiated with this node. - function KeywordNode:getKeywords() - return self.keywords - end - - -- Adds a childNode to this node. Creates the childNode based on the parameters (k = keywords, c = callback, p = parameters) - function KeywordNode:addChildKeyword(keywords, callback, parameters) - local new = KeywordNode:new(keywords, callback, parameters) - return self:addChildKeywordNode(new) - end - - -- Adds a pre-created childNode to this node. Should be used for example if several nodes should have a common child. - function KeywordNode:addChildKeywordNode(childNode) - self.children[#self.children + 1] = childNode - childNode.parent = self - return childNode - end - - KeywordHandler = { - root = nil, - lastNode = nil - } - - -- Creates a new keywordhandler with an empty rootnode. - function KeywordHandler:new() - local obj = {} - obj.root = KeywordNode:new(nil, nil, nil) - obj.lastNode = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - -- Resets the lastNode field, and this resetting the current position in the node hierarchy to root. - function KeywordHandler:reset(cid) - if self.lastNode[cid] then - self.lastNode[cid] = nil - end - end - - -- Makes sure the correct childNode of lastNode gets a chance to process the message. - function KeywordHandler:processMessage(cid, message) - local node = self:getLastNode(cid) - if node == nil then - error('No root node found.') - return false - end - - local ret = self:processNodeMessage(node, cid, message) - if ret then - return true - end - - if node:getParent() then - node = node:getParent() -- Search through the parent. - local ret = self:processNodeMessage(node, cid, message) - if ret then - return true - end - end - - if node ~= self:getRoot() then - node = self:getRoot() -- Search through the root. - local ret = self:processNodeMessage(node, cid, message) - if ret then - return true - end - end - return false - end - - -- Tries to process the given message using the node parameter's children and calls the node's callback function if found. - -- Returns the childNode which processed the message or nil if no such node was found. - function KeywordHandler:processNodeMessage(node, cid, message) - local messageLower = string.lower(message) - for i, childNode in pairs(node.children) do - if childNode:checkMessage(messageLower) then - local oldLast = self.lastNode[cid] - self.lastNode[cid] = childNode - childNode.parent = node -- Make sure node is the parent of childNode (as one node can be parent to several nodes). - if childNode:processMessage(cid, message) then - return true - end - self.lastNode[cid] = oldLast - end - end - return false - end - - -- Returns the root keywordnode - function KeywordHandler:getRoot() - return self.root - end - - -- Returns the last processed keywordnode or root if no last node is found. - function KeywordHandler:getLastNode(cid) - return self.lastNode[cid] or self:getRoot() - end - - -- Adds a new keyword to the root keywordnode. Returns the new node. - function KeywordHandler:addKeyword(keys, callback, parameters) - return self:getRoot():addChildKeyword(keys, callback, parameters) - end - - -- Moves the current position in the keyword hierarchy steps upwards. Steps defalut value = 1. - function KeywordHandler:moveUp(cid, steps) - if steps == nil or type(steps) ~= "number" then - steps = 1 - end - - for i = 1, steps do - if self.lastNode[cid] == nil then - return nil - end - self.lastNode[cid] = self.lastNode[cid]:getParent() or self:getRoot() - end - return self.lastNode[cid] - end -end diff --git a/path_10_8/data/npc/lib/npcsystem/modules.lua b/path_10_8/data/npc/lib/npcsystem/modules.lua deleted file mode 100644 index c560aee15..000000000 --- a/path_10_8/data/npc/lib/npcsystem/modules.lua +++ /dev/null @@ -1,1196 +0,0 @@ --- Advanced NPC System by Jiddo - -if Modules == nil then - -- default words for greeting and ungreeting the npc. Should be a table containing all such words. - FOCUS_GREETWORDS = {"hi", "hello"} - FOCUS_FAREWELLWORDS = {"bye", "farewell"} - - -- The words for requesting trade window. - SHOP_TRADEREQUEST = {"trade"} - - -- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! Should be a table with a single string value. - SHOP_YESWORD = {"yes"} - SHOP_NOWORD = {"no"} - - -- Pattern used to get the amount of an item a player wants to buy/sell. - PATTERN_COUNT = "%d+" - - -- Constants used to separate buying from selling. - SHOPMODULE_SELL_ITEM = 1 - SHOPMODULE_BUY_ITEM = 2 - SHOPMODULE_BUY_ITEM_CONTAINER = 3 - - -- Constants used for shop mode. Notice: addBuyableItemContainer is working on all modes - SHOPMODULE_MODE_TALK = 1 -- Old system used before client version 8.2: sell/buy item name - SHOPMODULE_MODE_TRADE = 2 -- Trade window system introduced in client version 8.2 - SHOPMODULE_MODE_BOTH = 3 -- Both working at one time - - -- Used shop mode - SHOPMODULE_MODE = SHOPMODULE_MODE_BOTH - - Modules = { - parseableModules = {} - } - - StdModule = {} - - -- These callback function must be called with parameters.npcHandler = npcHandler in the parameters table or they will not work correctly. - -- Notice: The members of StdModule have not yet been tested. If you find any bugs, please report them to me. - -- Usage: - -- keywordHandler:addKeyword({"offer"}, StdModule.say, {npcHandler = npcHandler, text = "I sell many powerful melee weapons."}) - function StdModule.say(cid, message, keywords, parameters, node) - local npcHandler = parameters.npcHandler - if npcHandler == nil then - error("StdModule.say called without any npcHandler instance.") - end - local onlyFocus = (parameters.onlyFocus == nil or parameters.onlyFocus == true) - if not npcHandler:isFocused(cid) and onlyFocus then - return false - end - - local parseInfo = {[TAG_PLAYERNAME] = Player(cid):getName()} - npcHandler:say(npcHandler:parseMessage(parameters.text or parameters.message, parseInfo), cid, parameters.publicize and true) - if parameters.reset then - npcHandler:resetNpc(cid) - elseif parameters.moveup ~= nil then - npcHandler.keywordHandler:moveUp(cid, parameters.moveup) - end - - return true - end - - --Usage: - -- local node1 = keywordHandler:addKeyword({"promot"}, StdModule.say, {npcHandler = npcHandler, text = "I can promote you for 20000 gold coins. Do you want me to promote you?"}) - -- node1:addChildKeyword({"yes"}, StdModule.promotePlayer, {npcHandler = npcHandler, cost = 20000, level = 20}, text = "Congratulations! You are now promoted.") - -- node1:addChildKeyword({"no"}, StdModule.say, {npcHandler = npcHandler, text = "Allright then. Come back when you are ready."}, reset = true) - function StdModule.promotePlayer(cid, message, keywords, parameters, node) - local npcHandler = parameters.npcHandler - if npcHandler == nil then - error("StdModule.promotePlayer called without any npcHandler instance.") - end - - if not npcHandler:isFocused(cid) then - return false - end - - local player = Player(cid) - if player:isPremium() or not parameters.premium then - local promotion = player:getVocation():getPromotion() - if player:getStorageValue(STORAGEVALUE_PROMOTION) == 1 then - npcHandler:say("You are already promoted!", cid) - elseif player:getLevel() < parameters.level then - npcHandler:say("I am sorry, but I can only promote you once you have reached level " .. parameters.level .. ".", cid) - elseif not player:removeMoney(parameters.cost) then - npcHandler:say("You do not have enough money!", cid) - else - npcHandler:say(parameters.text, cid) - player:setVocation(promotion) - player:setStorageValue(STORAGEVALUE_PROMOTION, 1) - end - else - npcHandler:say("You need a premium account in order to get promoted.", cid) - end - npcHandler:resetNpc(cid) - return true - end - - function StdModule.learnSpell(cid, message, keywords, parameters, node) - local npcHandler = parameters.npcHandler - if npcHandler == nil then - error("StdModule.learnSpell called without any npcHandler instance.") - end - - if not npcHandler:isFocused(cid) then - return false - end - - local player = Player(cid) - if player:isPremium() or not parameters.premium then - if player:hasLearnedSpell(parameters.spellName) then - npcHandler:say("You already know this spell.", cid) - elseif not player:canLearnSpell(parameters.spellName) then - npcHandler:say("You cannot learn this spell.", cid) - elseif not player:removeMoney(parameters.price) then - npcHandler:say("You do not have enough money, this spell costs " .. parameters.price .. " gold.", cid) - else - npcHandler:say("You have learned " .. parameters.spellName .. ".", cid) - player:learnSpell(parameters.spellName) - end - else - npcHandler:say("You need a premium account in order to buy " .. parameters.spellName .. ".", cid) - end - npcHandler:resetNpc(cid) - return true - end - - function StdModule.bless(cid, message, keywords, parameters, node) - local npcHandler = parameters.npcHandler - if npcHandler == nil then - error("StdModule.bless called without any npcHandler instance.") - end - - if not npcHandler:isFocused(cid) or getWorldType() == WORLD_TYPE_PVP_ENFORCED then - return false - end - - local player = Player(cid) - if player:isPremium() or not parameters.premium then - if player:hasBlessing(parameters.bless) then - npcHandler:say("Gods have already blessed you with this blessing!", cid) - elseif not player:removeMoney(parameters.cost) then - npcHandler:say("You don't have enough money for blessing.", cid) - else - player:addBlessing(parameters.bless) - npcHandler:say("You have been blessed by one of the five gods!", cid) - end - else - npcHandler:say("You need a premium account in order to be blessed.", cid) - end - npcHandler:resetNpc(cid) - return true - end - - function StdModule.travel(cid, message, keywords, parameters, node) - local npcHandler = parameters.npcHandler - if npcHandler == nil then - error("StdModule.travel called without any npcHandler instance.") - end - - if not npcHandler:isFocused(cid) then - return false - end - - local player = Player(cid) - if player:isPremium() or not parameters.premium then - if player:isPzLocked() then - npcHandler:say("First get rid of those blood stains! You are not going to ruin my vehicle!", cid) - elseif parameters.level and player:getLevel() < parameters.level then - npcHandler:say("You must reach level " .. parameters.level .. " before I can let you go there.", cid) - elseif not player:removeMoney(parameters.cost) then - npcHandler:say("You don't have enough money.", cid) - else - npcHandler:say(parameters.msg or "Set the sails!", cid) - npcHandler:releaseFocus(cid) - - local destination = Position(parameters.destination) - local position = player:getPosition() - player:teleportTo(destination) - - position:sendMagicEffect(CONST_ME_TELEPORT) - destination:sendMagicEffect(CONST_ME_TELEPORT) - end - else - npcHandler:say("I'm sorry, but you need a premium account in order to travel onboard our ships.", cid) - end - npcHandler:resetNpc(cid) - return true - end - - FocusModule = { - npcHandler = nil - } - - -- Creates a new instance of FocusModule without an associated NpcHandler. - function FocusModule:new() - local obj = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - -- Inits the module and associates handler to it. - function FocusModule:init(handler) - self.npcHandler = handler - for i, word in pairs(FOCUS_GREETWORDS) do - local obj = {} - obj[#obj + 1] = word - obj.callback = FOCUS_GREETWORDS.callback or FocusModule.messageMatcher - handler.keywordHandler:addKeyword(obj, FocusModule.onGreet, {module = self}) - end - - for i, word in pairs(FOCUS_FAREWELLWORDS) do - local obj = {} - obj[#obj + 1] = word - obj.callback = FOCUS_FAREWELLWORDS.callback or FocusModule.messageMatcher - handler.keywordHandler:addKeyword(obj, FocusModule.onFarewell, {module = self}) - end - - return true - end - - -- Greeting callback function. - function FocusModule.onGreet(cid, message, keywords, parameters) - parameters.module.npcHandler:onGreet(cid) - return true - end - - -- UnGreeting callback function. - function FocusModule.onFarewell(cid, message, keywords, parameters) - if parameters.module.npcHandler:isFocused(cid) then - parameters.module.npcHandler:onFarewell(cid) - return true - else - return false - end - end - - -- Custom message matching callback function for greeting messages. - function FocusModule.messageMatcher(keywords, message) - for i, word in pairs(keywords) do - if type(word) == "string" then - if string.find(message, word) and not string.find(message, "[%w+]" .. word) and not string.find(message, word .. "[%w+]") then - return true - end - end - end - return false - end - - KeywordModule = { - npcHandler = nil - } - -- Add it to the parseable module list. - Modules.parseableModules["module_keywords"] = KeywordModule - - function KeywordModule:new() - local obj = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - function KeywordModule:init(handler) - self.npcHandler = handler - return true - end - - -- Parses all known parameters. - function KeywordModule:parseParameters() - local ret = NpcSystem.getParameter("keywords") - if ret ~= nil then - self:parseKeywords(ret) - end - end - - function KeywordModule:parseKeywords(data) - local n = 1 - for keys in string.gmatch(data, "[^;]+") do - local i = 1 - - local keywords = {} - for temp in string.gmatch(keys, "[^,]+") do - keywords[#keywords + 1] = temp - i = i + 1 - end - - if i ~= 1 then - local reply = NpcSystem.getParameter("keyword_reply" .. n) - if reply ~= nil then - self:addKeyword(keywords, reply) - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter '" .. "keyword_reply" .. n .. "' missing. Skipping...") - end - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "No keywords found for keyword set #" .. n .. ". Skipping...") - end - - n = n + 1 - end - end - - function KeywordModule:addKeyword(keywords, reply) - self.npcHandler.keywordHandler:addKeyword(keywords, StdModule.say, {npcHandler = self.npcHandler, onlyFocus = true, text = reply, reset = true}) - end - - TravelModule = { - npcHandler = nil, - destinations = nil, - yesNode = nil, - noNode = nil, - } - - -- Add it to the parseable module list. - Modules.parseableModules["module_travel"] = TravelModule - - function TravelModule:new() - local obj = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - function TravelModule:init(handler) - self.npcHandler = handler - self.yesNode = KeywordNode:new(SHOP_YESWORD, TravelModule.onConfirm, {module = self}) - self.noNode = KeywordNode:new(SHOP_NOWORD, TravelModule.onDecline, {module = self}) - self.destinations = {} - return true - end - - -- Parses all known parameters. - function TravelModule:parseParameters() - local ret = NpcSystem.getParameter("travel_destinations") - if ret ~= nil then - self:parseDestinations(ret) - - self.npcHandler.keywordHandler:addKeyword({"destination"}, TravelModule.listDestinations, {module = self}) - self.npcHandler.keywordHandler:addKeyword({"where"}, TravelModule.listDestinations, {module = self}) - self.npcHandler.keywordHandler:addKeyword({"travel"}, TravelModule.listDestinations, {module = self}) - - end - end - - function TravelModule:parseDestinations(data) - for destination in string.gmatch(data, "[^;]+") do - local i = 1 - - local name = nil - local x = nil - local y = nil - local z = nil - local cost = nil - local premium = false - - for temp in string.gmatch(destination, "[^,]+") do - if i == 1 then - name = temp - elseif i == 2 then - x = tonumber(temp) - elseif i == 3 then - y = tonumber(temp) - elseif i == 4 then - z = tonumber(temp) - elseif i == 5 then - cost = tonumber(temp) - elseif i == 6 then - premium = temp == "true" - else - print("[Warning : " .. getCreatureName(getNpcCid()) .. "] NpcSystem:", "Unknown parameter found in travel destination parameter.", temp, destination) - end - i = i + 1 - end - - if name ~= nil and x ~= nil and y ~= nil and z ~= nil and cost ~= nil then - self:addDestination(name, {x=x, y=y, z=z}, cost, premium) - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for travel destination:", name, x, y, z, cost, premium) - end - end - end - - function TravelModule:addDestination(name, position, price, premium) - self.destinations[#self.destinations + 1] = name - - local parameters = { - cost = price, - destination = position, - premium = premium, - module = self - } - local keywords = {} - keywords[#keywords + 1] = name - - local keywords2 = {} - keywords2[#keywords2 + 1] = "bring me to " .. name - local node = self.npcHandler.keywordHandler:addKeyword(keywords, TravelModule.travel, parameters) - self.npcHandler.keywordHandler:addKeyword(keywords2, TravelModule.bringMeTo, parameters) - node:addChildKeywordNode(self.yesNode) - node:addChildKeywordNode(self.noNode) - - if npcs_loaded_travel[getNpcCid()] == nil then - npcs_loaded_travel[getNpcCid()] = getNpcCid() - self.npcHandler.keywordHandler:addKeyword({'yes'}, TravelModule.onConfirm, {module = self}) - self.npcHandler.keywordHandler:addKeyword({'no'}, TravelModule.onDecline, {module = self}) - end - end - - function TravelModule.travel(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - local npcHandler = module.npcHandler - - shop_destination[cid] = parameters.destination - shop_cost[cid] = parameters.cost - shop_premium[cid] = parameters.premium - shop_npcuid[cid] = getNpcCid() - - local cost = parameters.cost - local destination = parameters.destination - local premium = parameters.premium - - module.npcHandler:say("Do you want to travel to " .. keywords[1] .. " for " .. cost .. " gold coins?", cid) - return true - end - - function TravelModule.onConfirm(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - if shop_npcuid[cid] ~= Npc().uid then - return false - end - - local npcHandler = module.npcHandler - - local cost = shop_cost[cid] - local destination = Position(shop_destination[cid]) - - local player = Player(cid) - if player:isPremium() or not shop_premium[cid] then - if not player:removeMoney(cost) then - npcHandler:say("You do not have enough money!", cid) - elseif player:isPzLocked(cid) then - npcHandler:say("Get out of there with this blood.", cid) - else - npcHandler:say("It was a pleasure doing business with you.", cid) - npcHandler:releaseFocus(cid) - - local position = player:getPosition() - player:teleportTo(destination) - - position:sendMagicEffect(CONST_ME_TELEPORT) - destination:sendMagicEffect(CONST_ME_TELEPORT) - end - else - npcHandler:say("I can only allow premium players to travel there.", cid) - end - - npcHandler:resetNpc(cid) - return true - end - - -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item. - function TravelModule.onDecline(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then - return false - end - local parentParameters = node:getParent():getParameters() - local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() } - local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_DECLINE), parseInfo) - module.npcHandler:say(msg, cid) - module.npcHandler:resetNpc(cid) - return true - end - - function TravelModule.bringMeTo(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - local cost = parameters.cost - local destination = Position(parameters.destination) - - local player = Player(cid) - if player:isPremium() or not parameters.premium then - if player:removeMoney(cost) then - local position = player:getPosition() - player:teleportTo(destination) - - position:sendMagicEffect(CONST_ME_TELEPORT) - destination:sendMagicEffect(CONST_ME_TELEPORT) - end - end - return true - end - - function TravelModule.listDestinations(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - local msg = "I can bring you to " - --local i = 1 - local maxn = #module.destinations - for i, destination in pairs(module.destinations) do - msg = msg .. destination - if i == maxn - 1 then - msg = msg .. " and " - elseif i == maxn then - msg = msg .. "." - else - msg = msg .. ", " - end - i = i + 1 - end - - module.npcHandler:say(msg, cid) - module.npcHandler:resetNpc(cid) - return true - end - - ShopModule = { - npcHandler = nil, - yesNode = nil, - noNode = nil, - noText = "", - maxCount = 100, - amount = 0 - } - - -- Add it to the parseable module list. - Modules.parseableModules["module_shop"] = ShopModule - - -- Creates a new instance of ShopModule - function ShopModule:new() - local obj = {} - setmetatable(obj, self) - self.__index = self - return obj - end - - -- Parses all known parameters. - function ShopModule:parseParameters() - local ret = NpcSystem.getParameter("shop_buyable") - if ret ~= nil then - self:parseBuyable(ret) - end - - local ret = NpcSystem.getParameter("shop_sellable") - if ret ~= nil then - self:parseSellable(ret) - end - - local ret = NpcSystem.getParameter("shop_buyable_containers") - if ret ~= nil then - self:parseBuyableContainers(ret) - end - end - - -- Parse a string contaning a set of buyable items. - function ShopModule:parseBuyable(data) - for item in string.gmatch(data, "[^;]+") do - local i = 1 - - local name = nil - local itemid = nil - local cost = nil - local subType = nil - local realName = nil - - for temp in string.gmatch(item, "[^,]+") do - if i == 1 then - name = temp - elseif i == 2 then - itemid = tonumber(temp) - elseif i == 3 then - cost = tonumber(temp) - elseif i == 4 then - subType = tonumber(temp) - elseif i == 5 then - realName = temp - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item) - end - i = i + 1 - end - - local it = ItemType(itemid) - if subType == nil and it:getCharges() ~= 0 then - subType = it:getCharges() - end - - if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then - if itemid ~= nil and cost ~= nil then - if subType == nil and it:isFluidContainer() then - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item) - else - self:addBuyableItem(nil, itemid, cost, subType, realName) - end - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost) - end - else - if name ~= nil and itemid ~= nil and cost ~= nil then - if subType == nil and it:isFluidContainer() then - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item) - else - local names = {} - names[#names + 1] = name - self:addBuyableItem(names, itemid, cost, subType, realName) - end - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost) - end - end - end - end - - -- Parse a string contaning a set of sellable items. - function ShopModule:parseSellable(data) - for item in string.gmatch(data, "[^;]+") do - local i = 1 - - local name = nil - local itemid = nil - local cost = nil - local realName = nil - local subType = nil - - for temp in string.gmatch(item, "[^,]+") do - if i == 1 then - name = temp - elseif i == 2 then - itemid = tonumber(temp) - elseif i == 3 then - cost = tonumber(temp) - elseif i == 4 then - realName = temp - elseif i == 5 then - subType = tonumber(temp) - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in sellable items parameter.", temp, item) - end - i = i + 1 - end - - if SHOPMODULE_MODE == SHOPMODULE_MODE_TRADE then - if itemid ~= nil and cost ~= nil then - self:addSellableItem(nil, itemid, cost, realName, subType) - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", itemid, cost) - end - else - if name ~= nil and itemid ~= nil and cost ~= nil then - local names = {} - names[#names + 1] = name - self:addSellableItem(names, itemid, cost, realName, subType) - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, itemid, cost) - end - end - end - end - - -- Parse a string contaning a set of buyable items. - function ShopModule:parseBuyableContainers(data) - for item in string.gmatch(data, "[^;]+") do - local i = 1 - - local name = nil - local container = nil - local itemid = nil - local cost = nil - local subType = nil - local realName = nil - - for temp in string.gmatch(item, "[^,]+") do - if i == 1 then - name = temp - elseif i == 2 then - itemid = tonumber(temp) - elseif i == 3 then - itemid = tonumber(temp) - elseif i == 4 then - cost = tonumber(temp) - elseif i == 5 then - subType = tonumber(temp) - elseif i == 6 then - realName = temp - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Unknown parameter found in buyable items parameter.", temp, item) - end - i = i + 1 - end - - if name ~= nil and container ~= nil and itemid ~= nil and cost ~= nil then - if subType == nil and ItemType(itemid):isFluidContainer() then - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "SubType missing for parameter item:", item) - else - local names = {} - names[#names + 1] = name - self:addBuyableItemContainer(names, container, itemid, cost, subType, realName) - end - else - print("[Warning : " .. Npc():getName() .. "] NpcSystem:", "Parameter(s) missing for item:", name, container, itemid, cost) - end - end - end - - -- Initializes the module and associates handler to it. - function ShopModule:init(handler) - self.npcHandler = handler - self.yesNode = KeywordNode:new(SHOP_YESWORD, ShopModule.onConfirm, {module = self}) - self.noNode = KeywordNode:new(SHOP_NOWORD, ShopModule.onDecline, {module = self}) - self.noText = handler:getMessage(MESSAGE_DECLINE) - - if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then - for i, word in pairs(SHOP_TRADEREQUEST) do - local obj = {} - obj[#obj + 1] = word - obj.callback = SHOP_TRADEREQUEST.callback or ShopModule.messageMatcher - handler.keywordHandler:addKeyword(obj, ShopModule.requestTrade, {module = self}) - end - end - - return true - end - - -- Custom message matching callback function for requesting trade messages. - function ShopModule.messageMatcher(keywords, message) - for i, word in pairs(keywords) do - if type(word) == "string" then - if string.find(message, word) and not string.find(message, "[%w+]" .. word) and not string.find(message, word .. "[%w+]") then - return true - end - end - end - - return false - end - - -- Resets the module-specific variables. - function ShopModule:reset() - self.amount = 0 - end - - -- Function used to match a number value from a string. - function ShopModule:getCount(message) - local ret = 1 - local b, e = string.find(message, PATTERN_COUNT) - if b ~= nil and e ~= nil then - ret = tonumber(string.sub(message, b, e)) - end - - if ret <= 0 then - ret = 1 - elseif ret > self.maxCount then - ret = self.maxCount - end - - return ret - end - - -- Adds a new buyable item. - -- names = A table containing one or more strings of alternative names to this item. Used only for old buy/sell system. - -- itemid = The itemid of the buyable item - -- cost = The price of one single item - -- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1. - -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getItemName will be used) - function ShopModule:addBuyableItem(names, itemid, cost, itemSubType, realName) - if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then - if itemSubType == nil then - itemSubType = 1 - end - - local shopItem = self:getShopItem(itemid, itemSubType) - if shopItem == nil then - self.npcHandler.shopItems[#self.npcHandler.shopItems + 1] = {id = itemid, buy = cost, sell = -1, subType = itemSubType, name = realName or ItemType(itemid):getName()} - else - shopItem.buy = cost - end - end - - if names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE then - for i, name in pairs(names) do - local parameters = { - itemid = itemid, - cost = cost, - eventType = SHOPMODULE_BUY_ITEM, - module = self, - realName = realName or ItemType(itemid):getName(), - subType = itemSubType or 1 - } - - keywords = {} - keywords[#keywords + 1] = "buy" - keywords[#keywords + 1] = name - local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters) - node:addChildKeywordNode(self.yesNode) - node:addChildKeywordNode(self.noNode) - end - end - - if npcs_loaded_shop[getNpcCid()] == nil then - npcs_loaded_shop[getNpcCid()] = getNpcCid() - self.npcHandler.keywordHandler:addKeyword({'yes'}, ShopModule.onConfirm, {module = self}) - self.npcHandler.keywordHandler:addKeyword({'no'}, ShopModule.onDecline, {module = self}) - end - end - - function ShopModule:getShopItem(itemId, itemSubType) - if ItemType(itemId):isFluidContainer() then - for i = 1, #self.npcHandler.shopItems do - local shopItem = self.npcHandler.shopItems[i] - if shopItem.id == itemId and shopItem.subType == itemSubType then - return shopItem - end - end - else - for i = 1, #self.npcHandler.shopItems do - local shopItem = self.npcHandler.shopItems[i] - if shopItem.id == itemId then - return shopItem - end - end - end - return nil - end - - -- Adds a new buyable container of items. - -- names = A table containing one or more strings of alternative names to this item. - -- container = Backpack, bag or any other itemid of container where bought items will be stored - -- itemid = The itemid of the buyable item - -- cost = The price of one single item - -- subType - The subType of each rune or fluidcontainer item. Can be left out if it is not a rune/fluidcontainer. Default value is 1. - -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getItemName will be used) - function ShopModule:addBuyableItemContainer(names, container, itemid, cost, subType, realName) - if names ~= nil then - for i, name in pairs(names) do - local parameters = { - container = container, - itemid = itemid, - cost = cost, - eventType = SHOPMODULE_BUY_ITEM_CONTAINER, - module = self, - realName = realName or ItemType(itemid):getName(), - subType = subType or 1 - } - - keywords = {} - keywords[#keywords + 1] = "buy" - keywords[#keywords + 1] = name - local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters) - node:addChildKeywordNode(self.yesNode) - node:addChildKeywordNode(self.noNode) - end - end - end - - -- Adds a new sellable item. - -- names = A table containing one or more strings of alternative names to this item. Used only by old buy/sell system. - -- itemid = The itemid of the sellable item - -- cost = The price of one single item - -- realName - The real, full name for the item. Will be used as ITEMNAME in MESSAGE_ONBUY and MESSAGE_ONSELL if defined. Default value is nil (getItemName will be used) - function ShopModule:addSellableItem(names, itemid, cost, realName, itemSubType) - if SHOPMODULE_MODE ~= SHOPMODULE_MODE_TALK then - if itemSubType == nil then - itemSubType = 0 - end - - local shopItem = self:getShopItem(itemid, itemSubType) - if shopItem == nil then - self.npcHandler.shopItems[#self.npcHandler.shopItems + 1] = {id = itemid, buy = -1, sell = cost, subType = itemSubType, name = realName or getItemName(itemid)} - else - shopItem.sell = cost - end - end - - if names ~= nil and SHOPMODULE_MODE ~= SHOPMODULE_MODE_TRADE then - for i, name in pairs(names) do - local parameters = { - itemid = itemid, - cost = cost, - eventType = SHOPMODULE_SELL_ITEM, - module = self, - realName = realName or getItemName(itemid) - } - - keywords = {} - keywords[#keywords + 1] = "sell" - keywords[#keywords + 1] = name - - local node = self.npcHandler.keywordHandler:addKeyword(keywords, ShopModule.tradeItem, parameters) - node:addChildKeywordNode(self.yesNode) - node:addChildKeywordNode(self.noNode) - end - end - end - - -- onModuleReset callback function. Calls ShopModule:reset() - function ShopModule:callbackOnModuleReset() - self:reset() - return true - end - - -- Callback onBuy() function. If you wish, you can change certain Npc to use your onBuy(). - function ShopModule:callbackOnBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks) - local shopItem = self:getShopItem(itemid, subType) - if shopItem == nil then - error("[ShopModule.onBuy] shopItem == nil") - return false - end - - if shopItem.buy == -1 then - error("[ShopModule.onSell] attempt to buy a non-buyable item") - return false - end - - local backpack = 1988 - local totalCost = amount * shopItem.buy - if inBackpacks then - totalCost = isItemStackable(itemid) == TRUE and totalCost + 20 or totalCost + (math.max(1, math.floor(amount / getContainerCapById(backpack))) * 20) - end - - local parseInfo = { - [TAG_PLAYERNAME] = getPlayerName(cid), - [TAG_ITEMCOUNT] = amount, - [TAG_TOTALCOST] = totalCost, - [TAG_ITEMNAME] = shopItem.name - } - - if getPlayerMoney(cid) < totalCost then - local msg = self.npcHandler:getMessage(MESSAGE_NEEDMONEY) - msg = self.npcHandler:parseMessage(msg, parseInfo) - doPlayerSendCancel(cid, msg) - return false - end - - local subType = shopItem.subType or 1 - local a, b = doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack) - if a < amount then - local msgId = MESSAGE_NEEDMORESPACE - if a == 0 then - msgId = MESSAGE_NEEDSPACE - end - - local msg = self.npcHandler:getMessage(msgId) - parseInfo[TAG_ITEMCOUNT] = a - msg = self.npcHandler:parseMessage(msg, parseInfo) - doPlayerSendCancel(cid, msg) - self.npcHandler.talkStart[cid] = os.time() - - if a > 0 then - doPlayerRemoveMoney(cid, ((a * shopItem.buy) + (b * 20))) - return true - end - - return false - else - local msg = self.npcHandler:getMessage(MESSAGE_BOUGHT) - msg = self.npcHandler:parseMessage(msg, parseInfo) - doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, msg) - doPlayerRemoveMoney(cid, totalCost) - self.npcHandler.talkStart[cid] = os.time() - return true - end - end - - -- Callback onSell() function. If you wish, you can change certain Npc to use your onSell(). - function ShopModule:callbackOnSell(cid, itemid, subType, amount, ignoreEquipped, _) - local shopItem = self:getShopItem(itemid, subType) - if shopItem == nil then - error("[ShopModule.onSell] items[itemid] == nil") - return false - end - - if shopItem.sell == -1 then - error("[ShopModule.onSell] attempt to sell a non-sellable item") - return false - end - - local parseInfo = { - [TAG_PLAYERNAME] = getPlayerName(cid), - [TAG_ITEMCOUNT] = amount, - [TAG_TOTALCOST] = amount * shopItem.sell, - [TAG_ITEMNAME] = shopItem.name - } - - if not isItemFluidContainer(itemid) then - subType = -1 - end - - if doPlayerRemoveItem(cid, itemid, amount, subType, ignoreEquipped) then - local msg = self.npcHandler:getMessage(MESSAGE_SOLD) - msg = self.npcHandler:parseMessage(msg, parseInfo) - doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, msg) - doPlayerAddMoney(cid, amount * shopItem.sell) - self.npcHandler.talkStart[cid] = os.time() - return true - else - local msg = self.npcHandler:getMessage(MESSAGE_NEEDITEM) - msg = self.npcHandler:parseMessage(msg, parseInfo) - doPlayerSendCancel(cid, msg) - self.npcHandler.talkStart[cid] = os.time() - return false - end - end - - -- Callback for requesting a trade window with the NPC. - function ShopModule.requestTrade(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - if not module.npcHandler:onTradeRequest(cid) then - return false - end - - local itemWindow = {} - for i = 1, #module.npcHandler.shopItems do - itemWindow[#itemWindow + 1] = module.npcHandler.shopItems[i] - end - - if itemWindow[1] == nil then - local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) } - local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_NOSHOP), parseInfo) - module.npcHandler:say(msg, cid) - return true - end - - local parseInfo = { [TAG_PLAYERNAME] = getPlayerName(cid) } - local msg = module.npcHandler:parseMessage(module.npcHandler:getMessage(MESSAGE_SENDTRADE), parseInfo) - openShopWindow(cid, itemWindow, - function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onBuy(cid, itemid, subType, amount, ignoreCap, inBackpacks) end, - function(cid, itemid, subType, amount, ignoreCap, inBackpacks) module.npcHandler:onSell(cid, itemid, subType, amount, ignoreCap, inBackpacks) end) - module.npcHandler:say(msg, cid) - return true - end - - -- onConfirm keyword callback function. Sells/buys the actual item. - function ShopModule.onConfirm(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then - return false - end - shop_npcuid[cid] = 0 - - local parentParameters = node:getParent():getParameters() - local parseInfo = { - [TAG_PLAYERNAME] = getPlayerName(cid), - [TAG_ITEMCOUNT] = shop_amount[cid], - [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid], - [TAG_ITEMNAME] = shop_rlname[cid] - } - - if shop_eventtype[cid] == SHOPMODULE_SELL_ITEM then - local ret = doPlayerSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid]) - if ret == true then - local msg = module.npcHandler:getMessage(MESSAGE_ONSELL) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - else - local msg = module.npcHandler:getMessage(MESSAGE_MISSINGITEM) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - end - elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM then - local cost = shop_cost[cid] * shop_amount[cid] - if getPlayerMoney(cid) < cost then - local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - return false - end - - local a, b = doNpcSellItem(cid, shop_itemid[cid], shop_amount[cid], shop_subtype[cid], false, false, 1988) - if a < shop_amount[cid] then - local msgId = MESSAGE_NEEDMORESPACE - if a == 0 then - msgId = MESSAGE_NEEDSPACE - end - - local msg = module.npcHandler:getMessage(msgId) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - if a > 0 then - doPlayerRemoveMoney(cid, a * shop_cost[cid]) - if shop_itemid[cid] == ITEM_PARCEL then - doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988) - end - return true - end - return false - else - local msg = module.npcHandler:getMessage(MESSAGE_ONBUY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - doPlayerRemoveMoney(cid, cost) - if shop_itemid[cid] == ITEM_PARCEL then - doNpcSellItem(cid, ITEM_LABEL, shop_amount[cid], shop_subtype[cid], true, false, 1988) - end - return true - end - elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER then - local ret = doPlayerBuyItemContainer(cid, shop_container[cid], shop_itemid[cid], shop_amount[cid], shop_cost[cid] * shop_amount[cid], shop_subtype[cid]) - if ret == true then - local msg = module.npcHandler:getMessage(MESSAGE_ONBUY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - else - local msg = module.npcHandler:getMessage(MESSAGE_MISSINGMONEY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - end - end - - module.npcHandler:resetNpc(cid) - return true - end - - -- onDecline keyword callback function. Generally called when the player sais "no" after wanting to buy an item. - function ShopModule.onDecline(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) or shop_npcuid[cid] ~= getNpcCid() then - return false - end - shop_npcuid[cid] = 0 - - local parentParameters = node:getParent():getParameters() - local parseInfo = { - [TAG_PLAYERNAME] = getPlayerName(cid), - [TAG_ITEMCOUNT] = shop_amount[cid], - [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid], - [TAG_ITEMNAME] = shop_rlname[cid] - } - - local msg = module.npcHandler:parseMessage(module.noText, parseInfo) - module.npcHandler:say(msg, cid) - module.npcHandler:resetNpc(cid) - return true - end - - -- tradeItem callback function. Makes the npc say the message defined by MESSAGE_BUY or MESSAGE_SELL - function ShopModule.tradeItem(cid, message, keywords, parameters, node) - local module = parameters.module - if not module.npcHandler:isFocused(cid) then - return false - end - - if not module.npcHandler:onTradeRequest(cid) then - return true - end - - local count = module:getCount(message) - module.amount = count - - shop_amount[cid] = module.amount - shop_cost[cid] = parameters.cost - shop_rlname[cid] = parameters.realName - shop_itemid[cid] = parameters.itemid - shop_container[cid] = parameters.container - shop_npcuid[cid] = getNpcCid() - shop_eventtype[cid] = parameters.eventType - shop_subtype[cid] = parameters.subType - - local parseInfo = { - [TAG_PLAYERNAME] = getPlayerName(cid), - [TAG_ITEMCOUNT] = shop_amount[cid], - [TAG_TOTALCOST] = shop_cost[cid] * shop_amount[cid], - [TAG_ITEMNAME] = shop_rlname[cid] - } - - if shop_eventtype[cid] == SHOPMODULE_SELL_ITEM then - local msg = module.npcHandler:getMessage(MESSAGE_SELL) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM then - local msg = module.npcHandler:getMessage(MESSAGE_BUY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - elseif shop_eventtype[cid] == SHOPMODULE_BUY_ITEM_CONTAINER then - local msg = module.npcHandler:getMessage(MESSAGE_BUY) - msg = module.npcHandler:parseMessage(msg, parseInfo) - module.npcHandler:say(msg, cid) - end - return true - end -end diff --git a/path_10_8/data/npc/lib/npcsystem/npchandler.lua b/path_10_8/data/npc/lib/npcsystem/npchandler.lua deleted file mode 100644 index dd82d4f34..000000000 --- a/path_10_8/data/npc/lib/npcsystem/npchandler.lua +++ /dev/null @@ -1,635 +0,0 @@ --- Advanced NPC System by Jiddo - -if NpcHandler == nil then - -- Constant talkdelay behaviors. - TALKDELAY_NONE = 0 -- No talkdelay. Npc will reply immedeatly. - TALKDELAY_ONTHINK = 1 -- Talkdelay handled through the onThink callback function. (Default) - TALKDELAY_EVENT = 2 -- Not yet implemented - - -- Currently applied talkdelay behavior. TALKDELAY_ONTHINK is default. - NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK - - -- Constant indexes for defining default messages. - MESSAGE_GREET = 1 -- When the player greets the npc. - MESSAGE_FAREWELL = 2 -- When the player unGreets the npc. - MESSAGE_BUY = 3 -- When the npc asks the player if he wants to buy something. - MESSAGE_ONBUY = 4 -- When the player successfully buys something via talk. - MESSAGE_BOUGHT = 5 -- When the player bought something through the shop window. - MESSAGE_SELL = 6 -- When the npc asks the player if he wants to sell something. - MESSAGE_ONSELL = 7 -- When the player successfully sells something via talk. - MESSAGE_SOLD = 8 -- When the player sold something through the shop window. - MESSAGE_MISSINGMONEY = 9 -- When the player does not have enough money. - MESSAGE_NEEDMONEY = 10 -- Same as above, used for shop window. - MESSAGE_MISSINGITEM = 11 -- When the player is trying to sell an item he does not have. - MESSAGE_NEEDITEM = 12 -- Same as above, used for shop window. - MESSAGE_NEEDSPACE = 13 -- When the player don't have any space to buy an item - MESSAGE_NEEDMORESPACE = 14 -- When the player has some space to buy an item, but not enough space - MESSAGE_IDLETIMEOUT = 15 -- When the player has been idle for longer then idleTime allows. - MESSAGE_WALKAWAY = 16 -- When the player walks out of the talkRadius of the npc. - MESSAGE_DECLINE = 17 -- When the player says no to something. - MESSAGE_SENDTRADE = 18 -- When the npc sends the trade window to the player - MESSAGE_NOSHOP = 19 -- When the npc's shop is requested but he doesn't have any - MESSAGE_ONCLOSESHOP = 20 -- When the player closes the npc's shop window - MESSAGE_ALREADYFOCUSED = 21 -- When the player already has the focus of this npc. - MESSAGE_WALKAWAY_MALE = 22 -- When a male player walks out of the talkRadius of the npc. - MESSAGE_WALKAWAY_FEMALE = 23 -- When a female player walks out of the talkRadius of the npc. - - -- Constant indexes for callback functions. These are also used for module callback ids. - CALLBACK_CREATURE_APPEAR = 1 - CALLBACK_CREATURE_DISAPPEAR = 2 - CALLBACK_CREATURE_SAY = 3 - CALLBACK_ONTHINK = 4 - CALLBACK_GREET = 5 - CALLBACK_FAREWELL = 6 - CALLBACK_MESSAGE_DEFAULT = 7 - CALLBACK_PLAYER_ENDTRADE = 8 - CALLBACK_PLAYER_CLOSECHANNEL = 9 - CALLBACK_ONBUY = 10 - CALLBACK_ONSELL = 11 - CALLBACK_ONADDFOCUS = 18 - CALLBACK_ONRELEASEFOCUS = 19 - CALLBACK_ONTRADEREQUEST = 20 - - -- Addidional module callback ids - CALLBACK_MODULE_INIT = 12 - CALLBACK_MODULE_RESET = 13 - - -- Constant strings defining the keywords to replace in the default messages. - TAG_PLAYERNAME = "|PLAYERNAME|" - TAG_ITEMCOUNT = "|ITEMCOUNT|" - TAG_TOTALCOST = "|TOTALCOST|" - TAG_ITEMNAME = "|ITEMNAME|" - - NpcHandler = { - keywordHandler = nil, - focuses = nil, - talkStart = nil, - idleTime = 120, - talkRadius = 3, - talkDelayTime = 1, -- Seconds to delay outgoing messages. - talkDelay = nil, - callbackFunctions = nil, - modules = nil, - shopItems = nil, -- They must be here since ShopModule uses 'static' functions - eventSay = nil, - eventDelayedSay = nil, - topic = nil, - messages = { - -- These are the default replies of all npcs. They can/should be changed individually for each npc. - [MESSAGE_GREET] = "Greetings, |PLAYERNAME|.", - [MESSAGE_FAREWELL] = "Good bye, |PLAYERNAME|.", - [MESSAGE_BUY] = "Do you want to buy |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?", - [MESSAGE_ONBUY] = "Here you are.", - [MESSAGE_BOUGHT] = "Bought |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.", - [MESSAGE_SELL] = "Do you want to sell |ITEMCOUNT| |ITEMNAME| for |TOTALCOST| gold coins?", - [MESSAGE_ONSELL] = "Here you are, |TOTALCOST| gold.", - [MESSAGE_SOLD] = "Sold |ITEMCOUNT|x |ITEMNAME| for |TOTALCOST| gold.", - [MESSAGE_MISSINGMONEY] = "You don't have enough money.", - [MESSAGE_NEEDMONEY] = "You don't have enough money.", - [MESSAGE_MISSINGITEM] = "You don't have so many.", - [MESSAGE_NEEDITEM] = "You do not have this object.", - [MESSAGE_NEEDSPACE] = "You do not have enough capacity.", - [MESSAGE_NEEDMORESPACE] = "You do not have enough capacity for all items.", - [MESSAGE_IDLETIMEOUT] = "Good bye.", - [MESSAGE_WALKAWAY] = "Good bye.", - [MESSAGE_DECLINE] = "Then not.", - [MESSAGE_SENDTRADE] = "Of course, just browse through my wares.", - [MESSAGE_NOSHOP] = "Sorry, I'm not offering anything.", - [MESSAGE_ONCLOSESHOP] = "Thank you, come back whenever you're in need of something else.", - [MESSAGE_ALREADYFOCUSED] = "|PLAYERNAME|, I am already talking to you.", - [MESSAGE_WALKAWAY_MALE] = "Good bye.", - [MESSAGE_WALKAWAY_FEMALE] = "Good bye." - } - } - - -- Creates a new NpcHandler with an empty callbackFunction stack. - function NpcHandler:new(keywordHandler) - local obj = {} - obj.callbackFunctions = {} - obj.modules = {} - obj.eventSay = {} - obj.eventDelayedSay = {} - obj.topic = {} - obj.focuses = {} - obj.talkStart = {} - obj.talkDelay = {} - obj.keywordHandler = keywordHandler - obj.messages = {} - obj.shopItems = {} - - setmetatable(obj.messages, self.messages) - self.messages.__index = self.messages - - setmetatable(obj, self) - self.__index = self - return obj - end - - -- Re-defines the maximum idle time allowed for a player when talking to this npc. - function NpcHandler:setMaxIdleTime(newTime) - self.idleTime = newTime - end - - -- Attaches a new keyword handler to this npchandler - function NpcHandler:setKeywordHandler(newHandler) - self.keywordHandler = newHandler - end - - -- Function used to change the focus of this npc. - function NpcHandler:addFocus(newFocus) - if self:isFocused(newFocus) then - return - end - - self.focuses[#self.focuses + 1] = newFocus - self.topic[newFocus] = 0 - local callback = self:getCallback(CALLBACK_ONADDFOCUS) - if callback == nil or callback(newFocus) then - self:processModuleCallback(CALLBACK_ONADDFOCUS, newFocus) - end - self:updateFocus() - end - - -- Function used to verify if npc is focused to certain player - function NpcHandler:isFocused(focus) - for k,v in pairs(self.focuses) do - if v == focus then - return true - end - end - return false - end - - -- This function should be called on each onThink and makes sure the npc faces the player it is talking to. - -- Should also be called whenever a new player is focused. - function NpcHandler:updateFocus() - for pos, focus in pairs(self.focuses) do - if focus ~= nil then - doNpcSetCreatureFocus(focus) - return - end - end - doNpcSetCreatureFocus(0) - end - - -- Used when the npc should un-focus the player. - function NpcHandler:releaseFocus(focus) - if shop_cost[focus] ~= nil then - shop_amount[focus] = nil - shop_cost[focus] = nil - shop_rlname[focus] = nil - shop_itemid[focus] = nil - shop_container[focus] = nil - shop_npcuid[focus] = nil - shop_eventtype[focus] = nil - shop_subtype[focus] = nil - shop_destination[focus] = nil - shop_premium[focus] = nil - end - - if self.eventDelayedSay[focus] then - self:cancelNPCTalk(self.eventDelayedSay[focus]) - end - - if not self:isFocused(focus) then - return - end - - local pos = nil - for k,v in pairs(self.focuses) do - if v == focus then - pos = k - end - end - self.focuses[pos] = nil - - self.eventSay[focus] = nil - self.eventDelayedSay[focus] = nil - self.talkStart[focus] = nil - self.topic[focus] = nil - - local callback = self:getCallback(CALLBACK_ONRELEASEFOCUS) - if callback == nil or callback(focus) then - self:processModuleCallback(CALLBACK_ONRELEASEFOCUS, focus) - end - - if Player(focus) ~= nil then - closeShopWindow(focus) --Even if it can not exist, we need to prevent it. - self:updateFocus() - end - end - - -- Returns the callback function with the specified id or nil if no such callback function exists. - function NpcHandler:getCallback(id) - local ret = nil - if self.callbackFunctions ~= nil then - ret = self.callbackFunctions[id] - end - return ret - end - - -- Changes the callback function for the given id to callback. - function NpcHandler:setCallback(id, callback) - if self.callbackFunctions ~= nil then - self.callbackFunctions[id] = callback - end - end - - -- Adds a module to this npchandler and inits it. - function NpcHandler:addModule(module) - if self.modules ~= nil then - self.modules[#self.modules + 1] = module - module:init(self) - end - end - - -- Calls the callback function represented by id for all modules added to this npchandler with the given arguments. - function NpcHandler:processModuleCallback(id, ...) - local ret = true - for i, module in pairs(self.modules) do - local tmpRet = true - if id == CALLBACK_CREATURE_APPEAR and module.callbackOnCreatureAppear ~= nil then - tmpRet = module:callbackOnCreatureAppear(...) - elseif id == CALLBACK_CREATURE_DISAPPEAR and module.callbackOnCreatureDisappear ~= nil then - tmpRet = module:callbackOnCreatureDisappear(...) - elseif id == CALLBACK_CREATURE_SAY and module.callbackOnCreatureSay ~= nil then - tmpRet = module:callbackOnCreatureSay(...) - elseif id == CALLBACK_PLAYER_ENDTRADE and module.callbackOnPlayerEndTrade ~= nil then - tmpRet = module:callbackOnPlayerEndTrade(...) - elseif id == CALLBACK_PLAYER_CLOSECHANNEL and module.callbackOnPlayerCloseChannel ~= nil then - tmpRet = module:callbackOnPlayerCloseChannel(...) - elseif id == CALLBACK_ONBUY and module.callbackOnBuy ~= nil then - tmpRet = module:callbackOnBuy(...) - elseif id == CALLBACK_ONSELL and module.callbackOnSell ~= nil then - tmpRet = module:callbackOnSell(...) - elseif id == CALLBACK_ONTRADEREQUEST and module.callbackOnTradeRequest ~= nil then - tmpRet = module:callbackOnTradeRequest(...) - elseif id == CALLBACK_ONADDFOCUS and module.callbackOnAddFocus ~= nil then - tmpRet = module:callbackOnAddFocus(...) - elseif id == CALLBACK_ONRELEASEFOCUS and module.callbackOnReleaseFocus ~= nil then - tmpRet = module:callbackOnReleaseFocus(...) - elseif id == CALLBACK_ONTHINK and module.callbackOnThink ~= nil then - tmpRet = module:callbackOnThink(...) - elseif id == CALLBACK_GREET and module.callbackOnGreet ~= nil then - tmpRet = module:callbackOnGreet(...) - elseif id == CALLBACK_FAREWELL and module.callbackOnFarewell ~= nil then - tmpRet = module:callbackOnFarewell(...) - elseif id == CALLBACK_MESSAGE_DEFAULT and module.callbackOnMessageDefault ~= nil then - tmpRet = module:callbackOnMessageDefault(...) - elseif id == CALLBACK_MODULE_RESET and module.callbackOnModuleReset ~= nil then - tmpRet = module:callbackOnModuleReset(...) - end - if not tmpRet then - ret = false - break - end - end - return ret - end - - -- Returns the message represented by id. - function NpcHandler:getMessage(id) - local ret = nil - if self.messages ~= nil then - ret = self.messages[id] - end - return ret - end - - -- Changes the default response message with the specified id to newMessage. - function NpcHandler:setMessage(id, newMessage) - if self.messages ~= nil then - self.messages[id] = newMessage - end - end - - -- Translates all message tags found in msg using parseInfo - function NpcHandler:parseMessage(msg, parseInfo) - local ret = msg - for search, replace in pairs(parseInfo) do - ret = string.gsub(ret, search, replace) - end - return ret - end - - -- Makes sure the npc un-focuses the currently focused player - function NpcHandler:unGreet(cid) - if not self:isFocused(cid) then - return - end - - local callback = self:getCallback(CALLBACK_FAREWELL) - if callback == nil or callback() then - if self:processModuleCallback(CALLBACK_FAREWELL) then - local msg = self:getMessage(MESSAGE_FAREWELL) - local player = Player(cid) - local playerName = player and player:getName() or -1 - local parseInfo = { [TAG_PLAYERNAME] = playerName } - self:resetNpc(cid) - msg = self:parseMessage(msg, parseInfo) - self:say(msg, cid, true) - self:releaseFocus(cid) - end - end - end - - -- Greets a new player. - function NpcHandler:greet(cid) - if cid ~= 0 then - local callback = self:getCallback(CALLBACK_GREET) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_GREET, cid) then - local msg = self:getMessage(MESSAGE_GREET) - local player = Player(cid) - local playerName = player and player:getName() or -1 - local parseInfo = { [TAG_PLAYERNAME] = playerName } - msg = self:parseMessage(msg, parseInfo) - self:say(msg, cid, true) - else - return - end - else - return - end - end - self:addFocus(cid) - end - - -- Handles onCreatureAppear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_APPEAR callback. - function NpcHandler:onCreatureAppear(creature) - local cid = creature:getId() - if cid == getNpcCid() and next(self.shopItems) ~= nil then - local npc = Npc() - local speechBubble = npc:getSpeechBubble() - if speechBubble == 3 then - npc:setSpeechBubble(4) - else - npc:setSpeechBubble(2) - end - end - - local callback = self:getCallback(CALLBACK_CREATURE_APPEAR) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_CREATURE_APPEAR, cid) then - -- - end - end - end - - -- Handles onCreatureDisappear events. If you with to handle this yourself, please use the CALLBACK_CREATURE_DISAPPEAR callback. - function NpcHandler:onCreatureDisappear(creature) - local cid = creature:getId() - if getNpcCid() == cid then - return - end - - local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then - if self:isFocused(cid) then - self:unGreet(cid) - end - end - end - end - - -- Handles onCreatureSay events. If you with to handle this yourself, please use the CALLBACK_CREATURE_SAY callback. - function NpcHandler:onCreatureSay(creature, msgtype, msg) - local cid = creature:getId() - local callback = self:getCallback(CALLBACK_CREATURE_SAY) - if callback == nil or callback(cid, msgtype, msg) then - if self:processModuleCallback(CALLBACK_CREATURE_SAY, cid, msgtype, msg) then - if not self:isInRange(cid) then - return - end - - if self.keywordHandler ~= nil then - if self:isFocused(cid) and msgtype == TALKTYPE_PRIVATE_PN or not self:isFocused(cid) then - local ret = self.keywordHandler:processMessage(cid, msg) - if not ret then - local callback = self:getCallback(CALLBACK_MESSAGE_DEFAULT) - if callback ~= nil and callback(cid, msgtype, msg) then - self.talkStart[cid] = os.time() - end - else - self.talkStart[cid] = os.time() - end - end - end - end - end - end - - -- Handles onPlayerEndTrade events. If you wish to handle this yourself, use the CALLBACK_PLAYER_ENDTRADE callback. - function NpcHandler:onPlayerEndTrade(creature) - local cid = creature:getId() - local callback = self:getCallback(CALLBACK_PLAYER_ENDTRADE) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_PLAYER_ENDTRADE, cid, msgtype, msg) then - if self:isFocused(cid) then - local player = Player(cid) - local playerName = player and player:getName() or -1 - local parseInfo = { [TAG_PLAYERNAME] = playerName } - local msg = self:parseMessage(self:getMessage(MESSAGE_ONCLOSESHOP), parseInfo) - self:say(msg, cid) - end - end - end - end - - -- Handles onPlayerCloseChannel events. If you wish to handle this yourself, use the CALLBACK_PLAYER_CLOSECHANNEL callback. - function NpcHandler:onPlayerCloseChannel(creature) - local cid = creature:getId() - local callback = self:getCallback(CALLBACK_PLAYER_CLOSECHANNEL) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_PLAYER_CLOSECHANNEL, cid, msgtype, msg) then - if self:isFocused(cid) then - self:unGreet(cid) - end - end - end - end - - -- Handles onBuy events. If you wish to handle this yourself, use the CALLBACK_ONBUY callback. - function NpcHandler:onBuy(creature, itemid, subType, amount, ignoreCap, inBackpacks) - local cid = creature:getId() - local callback = self:getCallback(CALLBACK_ONBUY) - if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then - if self:processModuleCallback(CALLBACK_ONBUY, cid, itemid, subType, amount, ignoreCap, inBackpacks) then - -- - end - end - end - - -- Handles onSell events. If you wish to handle this yourself, use the CALLBACK_ONSELL callback. - function NpcHandler:onSell(creature, itemid, subType, amount, ignoreCap, inBackpacks) - local cid = creature:getId() - local callback = self:getCallback(CALLBACK_ONSELL) - if callback == nil or callback(cid, itemid, subType, amount, ignoreCap, inBackpacks) then - if self:processModuleCallback(CALLBACK_ONSELL, cid, itemid, subType, amount, ignoreCap, inBackpacks) then - -- - end - end - end - - -- Handles onTradeRequest events. If you wish to handle this yourself, use the CALLBACK_ONTRADEREQUEST callback. - function NpcHandler:onTradeRequest(cid) - local callback = self:getCallback(CALLBACK_ONTRADEREQUEST) - if callback == nil or callback(cid) then - if self:processModuleCallback(CALLBACK_ONTRADEREQUEST, cid) then - return true - end - end - return false - end - - -- Handles onThink events. If you wish to handle this yourself, please use the CALLBACK_ONTHINK callback. - function NpcHandler:onThink() - local callback = self:getCallback(CALLBACK_ONTHINK) - if callback == nil or callback() then - if NPCHANDLER_TALKDELAY == TALKDELAY_ONTHINK then - for cid, talkDelay in pairs(self.talkDelay) do - if talkDelay.time ~= nil and talkDelay.message ~= nil and os.time() >= talkDelay.time then - selfSay(talkDelay.message, cid, talkDelay.publicize and true or false) - self.talkDelay[cid] = nil - end - end - end - - if self:processModuleCallback(CALLBACK_ONTHINK) then - for pos, focus in pairs(self.focuses) do - if focus ~= nil then - if not self:isInRange(focus) then - self:onWalkAway(focus) - elseif self.talkStart[focus] ~= nil and (os.time() - self.talkStart[focus]) > self.idleTime then - self:unGreet(focus) - else - self:updateFocus() - end - end - end - end - end - end - - -- Tries to greet the player with the given cid. - function NpcHandler:onGreet(cid) - if self:isInRange(cid) then - if not self:isFocused(cid) then - self:greet(cid) - return - end - end - end - - -- Simply calls the underlying unGreet function. - function NpcHandler:onFarewell(cid) - self:unGreet(cid) - end - - -- Should be called on this npc's focus if the distance to focus is greater then talkRadius. - function NpcHandler:onWalkAway(cid) - if self:isFocused(cid) then - local callback = self:getCallback(CALLBACK_CREATURE_DISAPPEAR) - if callback == nil or callback() then - if self:processModuleCallback(CALLBACK_CREATURE_DISAPPEAR, cid) then - local msg = self:getMessage(MESSAGE_WALKAWAY) - - local player = Player(cid) - local playerName = player and player:getName() or -1 - local playerSex = player and player:getSex() or 0 - - local parseInfo = { [TAG_PLAYERNAME] = playerName } - local message = self:parseMessage(msg, parseInfo) - - local msg_male = self:getMessage(MESSAGE_WALKAWAY_MALE) - local message_male = self:parseMessage(msg_male, parseInfo) - local msg_female = self:getMessage(MESSAGE_WALKAWAY_FEMALE) - local message_female = self:parseMessage(msg_female, parseInfo) - if message_female ~= message_male then - if playerSex == PLAYERSEX_FEMALE then - selfSay(message_female) - else - selfSay(message_male) - end - elseif message ~= "" then - selfSay(message) - end - self:resetNpc(cid) - self:releaseFocus(cid) - end - end - end - end - - -- Returns true if cid is within the talkRadius of this npc. - function NpcHandler:isInRange(cid) - local distance = Player(cid) ~= nil and getDistanceTo(cid) or -1 - if distance == -1 then - return false - end - - return distance <= self.talkRadius - end - - -- Resets the npc into its initial state (in regard of the keywordhandler). - -- All modules are also receiving a reset call through their callbackOnModuleReset function. - function NpcHandler:resetNpc(cid) - if self:processModuleCallback(CALLBACK_MODULE_RESET) then - self.keywordHandler:reset(cid) - end - end - - function NpcHandler:cancelNPCTalk(events) - for aux = 1, #events do - stopEvent(events[aux].event) - end - events = nil - end - - function NpcHandler:doNPCTalkALot(msgs, interval, pcid) - if self.eventDelayedSay[pcid] then - self:cancelNPCTalk(self.eventDelayedSay[pcid]) - end - - self.eventDelayedSay[pcid] = {} - local ret = {} - for aux = 1, #msgs do - self.eventDelayedSay[pcid][aux] = {} - doCreatureSayWithDelay(getNpcCid(), msgs[aux], TALKTYPE_PRIVATE_NP, ((aux-1) * (interval or 4000)) + 700, self.eventDelayedSay[pcid][aux], pcid) - ret[#ret + 1] = self.eventDelayedSay[pcid][aux] - end - return(ret) - end - - -- Makes the npc represented by this instance of NpcHandler say something. - -- This implements the currently set type of talkdelay. - -- shallDelay is a boolean value. If it is false, the message is not delayed. Default value is true. - function NpcHandler:say(message, focus, publicize, shallDelay, delay) - if type(message) == "table" then - return self:doNPCTalkALot(message, delay or 6000, focus) - end - - if self.eventDelayedSay[focus] then - self:cancelNPCTalk(self.eventDelayedSay[focus]) - end - - local shallDelay = not shallDelay and true or shallDelay - if NPCHANDLER_TALKDELAY == TALKDELAY_NONE or shallDelay == false then - selfSay(message, focus, publicize and true or false) - return - end - - stopEvent(self.eventSay[focus]) - self.eventSay[focus] = addEvent(function(npcId, message, focusId) - local npc = Npc(npcId) - if npc == nil then - return - end - local player = Player(focusId) - if player then - npc:say(message, TALKTYPE_PRIVATE_NP, false, player, npc:getPosition()) - end - end, self.talkDelayTime * 1000, Npc():getId(), message, focus) - end -end diff --git a/path_10_8/data/npc/lib/npcsystem/npcsystem.lua b/path_10_8/data/npc/lib/npcsystem/npcsystem.lua deleted file mode 100644 index 15d7f5fa4..000000000 --- a/path_10_8/data/npc/lib/npcsystem/npcsystem.lua +++ /dev/null @@ -1,177 +0,0 @@ --- Advanced NPC System by Jiddo - -shop_amount = {} -shop_cost = {} -shop_rlname = {} -shop_itemid = {} -shop_container = {} -shop_npcuid = {} -shop_eventtype = {} -shop_subtype = {} -shop_destination = {} -shop_premium = {} - -npcs_loaded_shop = {} -npcs_loaded_travel = {} - -if NpcSystem == nil then - -- Loads the underlying classes of the npcsystem. - dofile('data/npc/lib/npcsystem/keywordhandler.lua') - dofile('data/npc/lib/npcsystem/npchandler.lua') - dofile('data/npc/lib/npcsystem/modules.lua') - - -- Global npc constants: - - -- Greeting and unGreeting keywords. For more information look at the top of modules.lua - FOCUS_GREETWORDS = {'hi', 'hello'} - FOCUS_FAREWELLWORDS = {'bye', 'farewell'} - - -- The word for requesting trade window. For more information look at the top of modules.lua - SHOP_TRADEREQUEST = {'trade'} - - -- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! For more information look at the top of modules.lua - SHOP_YESWORD = {'yes'} - SHOP_NOWORD = {'no'} - - -- Pattern used to get the amount of an item a player wants to buy/sell. - PATTERN_COUNT = '%d+' - - -- Talkdelay behavior. For more information, look at the top of npchandler.lua. - NPCHANDLER_TALKDELAY = TALKDELAY_ONTHINK - - -- Constant strings defining the keywords to replace in the default messages. - -- For more information, look at the top of npchandler.lua... - TAG_PLAYERNAME = '|PLAYERNAME|' - TAG_ITEMCOUNT = '|ITEMCOUNT|' - TAG_TOTALCOST = '|TOTALCOST|' - TAG_ITEMNAME = '|ITEMNAME|' - - NpcSystem = {} - - -- Gets an npcparameter with the specified key. Returns nil if no such parameter is found. - function NpcSystem.getParameter(key) - local ret = getNpcParameter(tostring(key)) - if (type(ret) == 'number' and ret == 0) or ret == nil then - return nil - else - return ret - end - end - - -- Parses all known parameters for the npc. Also parses parseable modules. - function NpcSystem.parseParameters(npcHandler) - local ret = NpcSystem.getParameter('idletime') - if ret ~= nil then - npcHandler.idleTime = tonumber(ret) - end - local ret = NpcSystem.getParameter('talkradius') - if ret ~= nil then - npcHandler.talkRadius = tonumber(ret) - end - local ret = NpcSystem.getParameter('message_greet') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_GREET, ret) - end - local ret = NpcSystem.getParameter('message_farewell') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_FAREWELL, ret) - end - local ret = NpcSystem.getParameter('message_decline') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_DECLINE, ret) - end - local ret = NpcSystem.getParameter('message_needmorespace') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_NEEDMORESPACE, ret) - end - local ret = NpcSystem.getParameter('message_needspace') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_NEEDSPACE, ret) - end - local ret = NpcSystem.getParameter('message_sendtrade') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_SENDTRADE, ret) - end - local ret = NpcSystem.getParameter('message_noshop') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_NOSHOP, ret) - end - local ret = NpcSystem.getParameter('message_oncloseshop') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_ONCLOSESHOP, ret) - end - local ret = NpcSystem.getParameter('message_onbuy') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_ONBUY, ret) - end - local ret = NpcSystem.getParameter('message_onsell') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_ONSELL, ret) - end - local ret = NpcSystem.getParameter('message_missingmoney') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_MISSINGMONEY, ret) - end - local ret = NpcSystem.getParameter('message_needmoney') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_NEEDMONEY, ret) - end - local ret = NpcSystem.getParameter('message_missingitem') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_MISSINGITEM, ret) - end - local ret = NpcSystem.getParameter('message_needitem') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_NEEDITEM, ret) - end - local ret = NpcSystem.getParameter('message_idletimeout') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_IDLETIMEOUT, ret) - end - local ret = NpcSystem.getParameter('message_walkaway') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_WALKAWAY, ret) - end - local ret = NpcSystem.getParameter('message_alreadyfocused') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_ALREADYFOCUSED, ret) - end - local ret = NpcSystem.getParameter('message_buy') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_BUY, ret) - end - local ret = NpcSystem.getParameter('message_sell') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_SELL, ret) - end - local ret = NpcSystem.getParameter('message_bought') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_BOUGHT, ret) - end - local ret = NpcSystem.getParameter('message_sold') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_SOLD, ret) - end - local ret = NpcSystem.getParameter('message_walkaway_male') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_WALKAWAY_MALE, ret) - end - local ret = NpcSystem.getParameter('message_walkaway_female') - if ret ~= nil then - npcHandler:setMessage(MESSAGE_WALKAWAY_FEMALE, ret) - end - - -- Parse modules. - for parameter, module in pairs(Modules.parseableModules) do - local ret = NpcSystem.getParameter(parameter) - if ret ~= nil then - local number = tonumber(ret) - if number ~= 0 and module.parseParameters ~= nil then - local instance = module:new() - npcHandler:addModule(instance) - instance:parseParameters() - end - end - end - end -end diff --git a/path_10_8/data/npc/scripts/The Oracle.lua b/path_10_8/data/npc/scripts/The Oracle.lua deleted file mode 100644 index 6619adda1..000000000 --- a/path_10_8/data/npc/scripts/The Oracle.lua +++ /dev/null @@ -1,104 +0,0 @@ -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) -NpcSystem.parseParameters(npcHandler) - -local vocation = {} -local town = {} -local destination = {} - -function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end -function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end -function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end -function onThink() npcHandler:onThink() end - -local function greetCallback(cid) - local player = Player(cid) - local level = player:getLevel() - if level < 8 then - npcHandler:say("CHILD! COME BACK WHEN YOU HAVE GROWN UP!", cid) - return false - elseif level > 9 then - npcHandler:say(player:getName() .. ", I CAN'T LET YOU LEAVE - YOU ARE TOO STRONG ALREADY! YOU CAN ONLY LEAVE WITH LEVEL 9 OR LOWER.", cid) - return false - elseif player:getVocation():getId() > 0 then - npcHandler:say("YOU ALREADY HAVE A VOCATION!", cid) - return false - end - return true -end - -local function creatureSayCallback(cid, type, msg) - if not npcHandler:isFocused(cid) then - return false - end - - if msgcontains(msg, "yes") and npcHandler.topic[cid] == 0 then - npcHandler:say("IN WHICH TOWN DO YOU WANT TO LIVE: {RHYVES}?", cid) - npcHandler.topic[cid] = 1 - elseif npcHandler.topic[cid] == 1 then - if msgcontains(msg, "rhyves") then - town[cid] = 2 - destination[cid] = Position(159, 387, 6) - npcHandler:say("IN RHYVES! AND WHAT PROFESSION HAVE YOU CHOSEN: {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid) - npcHandler.topic[cid] = 2 - else - npcHandler:say("IN WHICH TOWN DO YOU WANT TO LIVE: {RHYVES}?", cid) - end - elseif npcHandler.topic[cid] == 2 then - if msgcontains(msg, "sorcerer") then - npcHandler:say("A SORCERER! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid) - npcHandler.topic[cid] = 3 - vocation[cid] = 1 - elseif msgcontains(msg, "druid") then - npcHandler:say("A DRUID! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid) - npcHandler.topic[cid] = 3 - vocation[cid] = 2 - elseif msgcontains(msg, "paladin") then - npcHandler:say("A PALADIN! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid) - npcHandler.topic[cid] = 3 - vocation[cid] = 3 - elseif msgcontains(msg, "knight") then - npcHandler:say("A KNIGHT! ARE YOU SURE? THIS DECISION IS IRREVERSIBLE!", cid) - npcHandler.topic[cid] = 3 - vocation[cid] = 4 - else - npcHandler:say("{KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid) - end - elseif npcHandler.topic[cid] == 3 then - if msgcontains(msg, "yes") then - local player = Player(cid) - npcHandler:say("SO BE IT!", cid) - player:setVocation(Vocation(vocation[cid])) - player:setTown(Town(town[cid])) - - local destination = destination[cid] - npcHandler:releaseFocus(cid) - player:teleportTo(destination) - player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - destination:sendMagicEffect(CONST_ME_TELEPORT) - else - npcHandler:say("THEN WHAT? {KNIGHT}, {PALADIN}, {SORCERER}, OR {DRUID}?", cid) - npcHandler.topic[cid] = 2 - end - end - return true -end - -local function onAddFocus(cid) - town[cid] = 0 - vocation[cid] = 0 - destination[cid] = 0 -end - -local function onReleaseFocus(cid) - town[cid] = nil - vocation[cid] = nil - destination[cid] = nil -end - -npcHandler:setCallback(CALLBACK_ONADDFOCUS, onAddFocus) -npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, onReleaseFocus) - -npcHandler:setCallback(CALLBACK_GREET, greetCallback) -npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) -npcHandler:addModule(FocusModule:new()) diff --git a/path_10_8/data/npc/scripts/bless.lua b/path_10_8/data/npc/scripts/bless.lua deleted file mode 100644 index eb3fc5ac3..000000000 --- a/path_10_8/data/npc/scripts/bless.lua +++ /dev/null @@ -1,30 +0,0 @@ -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) -NpcSystem.parseParameters(npcHandler) - -function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end -function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end -function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end -function onThink() npcHandler:onThink() end - -local node1 = keywordHandler:addKeyword({'first bless'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to buy the first blessing for 10000 gold?'}) - node1:addChildKeyword({'yes'}, StdModule.bless, {npcHandler = npcHandler, bless = 1, premium = true, cost = 10000}) - node1:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, reset = true, text = 'Too expensive, eh?'}) - -local node2 = keywordHandler:addKeyword({'second bless'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to buy the second blessing for 10000 gold?'}) - node2:addChildKeyword({'yes'}, StdModule.bless, {npcHandler = npcHandler, bless = 2, premium = true, cost = 10000}) - node2:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, reset = true, text = 'Too expensive, eh?'}) - -local node3 = keywordHandler:addKeyword({'third bless'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to buy the third blessing for 10000 gold?'}) - node3:addChildKeyword({'yes'}, StdModule.bless, {npcHandler = npcHandler, bless = 3, premium = true, cost = 10000}) - node3:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, reset = true, text = 'Too expensive, eh?'}) - -local node4 = keywordHandler:addKeyword({'fourth bless'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to buy the fourth blessing for 10000 gold?'}) - node4:addChildKeyword({'yes'}, StdModule.bless, {npcHandler = npcHandler, bless = 4, premium = true, cost = 10000}) - node4:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, reset = true, text = 'Too expensive, eh?'}) - -local node5 = keywordHandler:addKeyword({'fifth bless'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Do you want to buy the fifth blessing for 10000 gold?'}) - node5:addChildKeyword({'yes'}, StdModule.bless, {npcHandler = npcHandler, bless = 5, premium = true, cost = 10000}) - node5:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, reset = true, text = 'Too expensive, eh?'}) - -npcHandler:addModule(FocusModule:new()) diff --git a/path_10_8/data/npc/scripts/default.lua b/path_10_8/data/npc/scripts/default.lua deleted file mode 100644 index 36d042db2..000000000 --- a/path_10_8/data/npc/scripts/default.lua +++ /dev/null @@ -1,10 +0,0 @@ -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) -NpcSystem.parseParameters(npcHandler) - -function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end -function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end -function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end -function onThink() npcHandler:onThink() end - -npcHandler:addModule(FocusModule:new()) diff --git a/path_10_8/data/npc/scripts/promotion.lua b/path_10_8/data/npc/scripts/promotion.lua deleted file mode 100644 index e565d5703..000000000 --- a/path_10_8/data/npc/scripts/promotion.lua +++ /dev/null @@ -1,14 +0,0 @@ -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) -NpcSystem.parseParameters(npcHandler) - -function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end -function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end -function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end -function onThink() npcHandler:onThink() end - -local node1 = keywordHandler:addKeyword({'promot'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'I can promote you for 20000 gold coins. Do you want me to promote you?'}) - node1:addChildKeyword({'yes'}, StdModule.promotePlayer, {npcHandler = npcHandler, cost = 20000, level = 20, text = 'Congratulations! You are now promoted.'}) - node1:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Alright then, come back when you are ready.', reset = true}) - -npcHandler:addModule(FocusModule:new()) diff --git a/path_10_8/data/npc/scripts/runes.lua b/path_10_8/data/npc/scripts/runes.lua deleted file mode 100644 index d111ae736..000000000 --- a/path_10_8/data/npc/scripts/runes.lua +++ /dev/null @@ -1,136 +0,0 @@ -local keywordHandler = KeywordHandler:new() -local npcHandler = NpcHandler:new(keywordHandler) -NpcSystem.parseParameters(npcHandler) - -function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end -function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end -function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end -function onThink() npcHandler:onThink() end - -local shopModule = ShopModule:new() -npcHandler:addModule(shopModule) - -shopModule:addBuyableItem({'spellbook'}, 2175, 150, 'spellbook') -shopModule:addBuyableItem({'magic lightwand'}, 2163, 400, 'magic lightwand') - -shopModule:addBuyableItem({'small health'}, 8704, 20, 1, 'small health potion') -shopModule:addBuyableItem({'health potion'}, 7618, 45, 1, 'health potion') -shopModule:addBuyableItem({'mana potion'}, 7620, 50, 1, 'mana potion') -shopModule:addBuyableItem({'strong health'}, 7588, 100, 1, 'strong health potion') -shopModule:addBuyableItem({'strong mana'}, 7589, 80, 1, 'strong mana potion') -shopModule:addBuyableItem({'great health'}, 7591, 190, 1, 'great health potion') -shopModule:addBuyableItem({'great mana'}, 7590, 120, 1, 'great mana potion') -shopModule:addBuyableItem({'great spirit'}, 8472, 190, 1, 'great spirit potion') -shopModule:addBuyableItem({'ultimate health'}, 8473, 310, 1, 'ultimate health potion') -shopModule:addBuyableItem({'antidote potion'}, 8474, 50, 1, 'antidote potion') - -shopModule:addSellableItem({'normal potion flask', 'normal flask'}, 7636, 5, 'empty small potion flask') -shopModule:addSellableItem({'strong potion flask', 'strong flask'}, 7634, 10, 'empty strong potion flask') -shopModule:addSellableItem({'great potion flask', 'great flask'}, 7635, 15, 'empty great potion flask') - -shopModule:addBuyableItem({'instense healing'}, 2265, 95, 1, 'intense healing rune') -shopModule:addBuyableItem({'ultimate healing'}, 2273, 175, 1, 'ultimate healing rune') -shopModule:addBuyableItem({'magic wall'}, 2293, 350, 3, 'magic wall rune') -shopModule:addBuyableItem({'destroy field'}, 2261, 45, 3, 'destroy field rune') -shopModule:addBuyableItem({'light magic missile'}, 2287, 40, 10, 'light magic missile rune') -shopModule:addBuyableItem({'heavy magic missile'}, 2311, 120, 10, 'heavy magic missile rune') -shopModule:addBuyableItem({'great fireball'}, 2304, 180, 4, 'great fireball rune') -shopModule:addBuyableItem({'explosion'}, 2313, 250, 6, 'explosion rune') -shopModule:addBuyableItem({'sudden death'}, 2268, 350, 3, 'sudden death rune') -shopModule:addBuyableItem({'death arrow'}, 2263, 300, 3, 'death arrow rune') -shopModule:addBuyableItem({'paralyze'}, 2278, 700, 1, 'paralyze rune') -shopModule:addBuyableItem({'animate dead'}, 2316, 375, 1, 'animate dead rune') -shopModule:addBuyableItem({'convince creature'}, 2290, 80, 1, 'convince creature rune') -shopModule:addBuyableItem({'chameleon'}, 2291, 210, 1, 'chameleon rune') -shopModule:addBuyableItem({'desintegrate'}, 2310, 80, 3, 'desintegreate rune') - -shopModule:addBuyableItemContainer({'bp ap'}, 2002, 8378, 2000, 1, 'backpack of antidote potions') -shopModule:addBuyableItemContainer({'bp slhp'}, 2000, 8610, 400, 1, 'backpack of small health potions') -shopModule:addBuyableItemContainer({'bp hp'}, 2000, 7618, 900, 1, 'backpack of health potions') -shopModule:addBuyableItemContainer({'bp mp'}, 2001, 7620, 1000, 1, 'backpack of mana potions') -shopModule:addBuyableItemContainer({'bp shp'}, 2000, 7588, 2000, 1, 'backpack of strong health potions') -shopModule:addBuyableItemContainer({'bp smp'}, 2001, 7589, 1600, 1, 'backpack of strong mana potions') -shopModule:addBuyableItemContainer({'bp ghp'}, 2000, 7591, 3800, 1, 'backpack of great health potions') -shopModule:addBuyableItemContainer({'bp gmp'}, 2001, 7590, 2400, 1, 'backpack of great mana potions') -shopModule:addBuyableItemContainer({'bp gsp'}, 1999, 8376, 3800, 1, 'backpack of great spirit potions') -shopModule:addBuyableItemContainer({'bp uhp'}, 2000, 8377, 6200, 1, 'backpack of ultimate health potions') - -shopModule:addBuyableItem({'wand of vortex', 'vortex'}, 2190, 500, 'wand of vortex') -shopModule:addBuyableItem({'wand of dragonbreath', 'dragonbreath'}, 2191, 1000, 'wand of dragonbreath') -shopModule:addBuyableItem({'wand of decay', 'decay'}, 2188, 5000, 'wand of decay') -shopModule:addBuyableItem({'wand of draconia', 'draconia'}, 8921, 7500, 'wand of draconia') -shopModule:addBuyableItem({'wand of cosmic energy', 'cosmic energy'}, 2189, 10000, 'wand of cosmic energy') -shopModule:addBuyableItem({'wand of inferno', 'inferno'}, 2187, 15000, 'wand of inferno') -shopModule:addBuyableItem({'wand of starstorm', 'starstorm'}, 8920, 18000, 'wand of starstorm') -shopModule:addBuyableItem({'wand of voodoo', 'voodoo'}, 8922, 22000, 'wand of voodoo') - -shopModule:addBuyableItem({'snakebite rod', 'snakebite'}, 2182, 500, 'snakebite rod') -shopModule:addBuyableItem({'moonlight rod', 'moonlight'}, 2186, 1000, 'moonlight rod') -shopModule:addBuyableItem({'necrotic rod', 'necrotic'}, 2185, 5000, 'necrotic rod') -shopModule:addBuyableItem({'northwind rod', 'northwind'}, 8911, 7500, 'northwind rod') -shopModule:addBuyableItem({'terra rod', 'terra'}, 2181, 10000, 'terra rod') -shopModule:addBuyableItem({'hailstorm rod', 'hailstorm'}, 2183, 15000, 'hailstorm rod') -shopModule:addBuyableItem({'springsprout rod', 'springsprout'}, 8912, 18000, 'springsprout rod') -shopModule:addBuyableItem({'underworld rod', 'underworld'}, 8910, 22000, 'underworld rod') - -shopModule:addSellableItem({'wand of vortex', 'vortex'}, 2190, 100, 'wand of vortex') -shopModule:addSellableItem({'wand of dragonbreath', 'dragonbreath'}, 2191, 200, 'wand of dragonbreath') -shopModule:addSellableItem({'wand of decay', 'decay'}, 2188, 1000, 'wand of decay') -shopModule:addSellableItem({'wand of draconia', 'draconia'}, 8921, 1500, 'wand of draconia') -shopModule:addSellableItem({'wand of cosmic energy', 'cosmic energy'}, 2189, 2000, 'wand of cosmic energy') -shopModule:addSellableItem({'wand of inferno', 'inferno'}, 2187, 3000, 'wand of inferno') -shopModule:addSellableItem({'wand of starstorm', 'starstorm'}, 8920, 3600, 'wand of starstorm') -shopModule:addSellableItem({'wand of voodoo', 'voodoo'}, 8922, 4400, 'wand of voodoo') - -shopModule:addSellableItem({'snakebite rod', 'snakebite'}, 2182, 100, 'snakebite rod') -shopModule:addSellableItem({'moonlight rod', 'moonlight'}, 2186, 200, 'moonlight rod') -shopModule:addSellableItem({'necrotic rod', 'necrotic'}, 2185, 1000, 'necrotic rod') -shopModule:addSellableItem({'northwind rod', 'northwind'}, 8911, 1500, 'northwind rod') -shopModule:addSellableItem({'terra rod', 'terra'}, 2181, 2000, 'terra rod') -shopModule:addSellableItem({'hailstorm rod', 'hailstorm'}, 2183, 3000, 'hailstorm rod') -shopModule:addSellableItem({'springsprout rod', 'springsprout'}, 8912, 3600, 'springsprout rod') -shopModule:addSellableItem({'underworld rod', 'underworld'}, 8910, 4400, 'underworld rod') - - -function creatureSayCallback(cid, type, msg) - if not npcHandler:isFocused(cid) then - return false - end - - local player = Player(cid) - local items = { - [1] = 2190, - [2] = 2182, - [5] = 2190, - [6] = 2182 - } - - if msgcontains(msg, 'first rod') or msgcontains(msg, 'first wand') then - local vocationId = player:getVocation():getId() - if isInArray({1, 2, 5, 6}, vocationId) then - if player:getStorageValue(30002) == -1 then - selfSay('So you ask me for a {' .. ItemType(items[vocationId]):getName() .. '} to begin your advanture?', cid) - npcHandler.topic[cid] = 1 - else - selfSay('What? I have already gave you one {' .. ItemType(items[vocationId]):getName() .. '}!', cid) - end - else - selfSay('Sorry, you aren\'t a druid either a sorcerer.', cid) - end - elseif msgcontains(msg, 'yes') then - if npcHandler.topic[cid] == 1 then - player:addItem(items[vocationId], 1) - selfSay('Here you are young adept, take care yourself.', cid) - player:setStorageValue(30002, 1) - end - npcHandler.topic[cid] = 0 - elseif msgcontains(msg, 'no') and npcHandler.topic[cid] == 1 then - selfSay('Ok then.', cid) - npcHandler.topic[cid] = 0 - end - - return true -end - -npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) -npcHandler:addModule(FocusModule:new()) diff --git a/path_10_8/data/raids/raids.xml b/path_10_8/data/raids/raids.xml deleted file mode 100644 index e61a5a6e4..000000000 --- a/path_10_8/data/raids/raids.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/path_10_8/data/raids/testraid.xml b/path_10_8/data/raids/testraid.xml deleted file mode 100644 index ebfe9d0c9..000000000 --- a/path_10_8/data/raids/testraid.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/reports/.gitignore b/path_10_8/data/reports/.gitignore deleted file mode 100644 index eb67fe0af..000000000 --- a/path_10_8/data/reports/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Ignore user generated reports -* -!.gitignore diff --git a/path_10_8/data/spells/lib/spells.lua b/path_10_8/data/spells/lib/spells.lua deleted file mode 100644 index 2bf763d8b..000000000 --- a/path_10_8/data/spells/lib/spells.lua +++ /dev/null @@ -1,250 +0,0 @@ ---Pre-made areas - ---Waves -AREA_SHORTWAVE3 = { -{1, 1, 1}, -{1, 1, 1}, -{0, 3, 0} -} - -AREA_WAVE4 = { -{1, 1, 1, 1, 1}, -{0, 1, 1, 1, 0}, -{0, 1, 1, 1, 0}, -{0, 0, 3, 0, 0} -} - -AREA_WAVE6 = { -{0, 0, 0, 0, 0}, -{0, 1, 3, 1, 0}, -{0, 0, 0, 0, 0} -} - -AREA_SQUAREWAVE5 = { -{1, 1, 1}, -{1, 1, 1}, -{1, 1, 1}, -{0, 1, 0}, -{0, 3, 0} -} - -AREA_SQUAREWAVE6 = { -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} -} - -AREA_SQUAREWAVE7 = { -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} -} - ---Diagonal waves -AREADIAGONAL_WAVE4 = { -{0, 0, 0, 0, 1, 0}, -{0, 0, 0, 1, 1, 0}, -{0, 0, 1, 1, 1, 0}, -{0, 1, 1, 1, 1, 0}, -{1, 1, 1, 1, 1, 0}, -{0, 0, 0, 0, 0, 3} -} - -AREADIAGONAL_SQUAREWAVE5 = { -{1, 1, 1, 0, 0}, -{1, 1, 1, 0, 0}, -{1, 1, 1, 0, 0}, -{0, 0, 0, 1, 0}, -{0, 0, 0, 0, 3} -} - -AREADIAGONAL_WAVE6 = { -{0, 0, 1}, -{0, 3, 0}, -{1, 0, 0} -} - ---Beams -AREA_BEAM1 = { -{3} -} - -AREA_BEAM5 = { -{1}, -{1}, -{1}, -{1}, -{3} -} - -AREA_BEAM7 = { -{1}, -{1}, -{1}, -{1}, -{1}, -{1}, -{3} -} - -AREA_BEAM8 = { -{1}, -{1}, -{1}, -{1}, -{1}, -{1}, -{1}, -{3} -} - ---Diagonal Beams -AREADIAGONAL_BEAM5 = { -{1, 0, 0, 0, 0}, -{0, 1, 0, 0, 0}, -{0, 0, 1, 0, 0}, -{0, 0, 0, 1, 0}, -{0, 0, 0, 0, 3} -} - -AREADIAGONAL_BEAM7 = { -{1, 0, 0, 0, 0, 0, 0}, -{0, 1, 0, 0, 0, 0, 0}, -{0, 0, 1, 0, 0, 0, 0}, -{0, 0, 0, 1, 0, 0, 0}, -{0, 0, 0, 0, 1, 0, 0}, -{0, 0, 0, 0, 0, 1, 0}, -{0, 0, 0, 0, 0, 0, 3} -} - ---Circles -AREA_CIRCLE2X2 = { -{0, 1, 1, 1, 0}, -{1, 1, 1, 1, 1}, -{1, 1, 3, 1, 1}, -{1, 1, 1, 1, 1}, -{0, 1, 1, 1, 0} -} - -AREA_CIRCLE3X3 = { -{0, 0, 1, 1, 1, 0, 0}, -{0, 1, 1, 1, 1, 1, 0}, -{1, 1, 1, 1, 1, 1, 1}, -{1, 1, 1, 3, 1, 1, 1}, -{1, 1, 1, 1, 1, 1, 1}, -{0, 1, 1, 1, 1, 1, 0}, -{0, 0, 1, 1, 1, 0, 0} -} - --- Crosses -AREA_CROSS1X1 = { -{0, 1, 0}, -{1, 3, 1}, -{0, 1, 0} -} - -AREA_CROSS5X5 = { -{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0} -} - -AREA_CROSS6X6 = { -{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1}, -{0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, -{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, -{0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, -{0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, -{0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0} -} - ---Squares -AREA_SQUARE1X1 = { -{1, 1, 1}, -{1, 3, 1}, -{1, 1, 1} -} - --- Walls -AREA_WALLFIELD = { -{1, 1, 3, 1, 1} -} - -AREADIAGONAL_WALLFIELD = { -{0, 0, 0, 0, 1}, -{0, 0, 0, 1, 1}, -{0, 1, 3, 1, 0}, -{1, 1, 0, 0, 0}, -{1, 0, 0, 0, 0}, -} - --- Spells-only arrays - ---This HUGE array contains all corpses of the game, until protocol 8.0 --- It is used on animate dead rune and on undead legion spell. No unmoveable corpses are there. -CORPSES = { -2806,2807,2808,2809,2810,2811,2812,2813,2814,2815,2816,2817,2818,2819,2820,2821,2822,2823, -2824,2825,2826,2827,2828,2829,2830,2831,2832,2833,2834,2835,2836,2837,2838,2839,2840,2841, -2842,2843,2844,2845,2846,2847,2848,2849,2850,2851,2852,2853,2854,2855,2856,2857,2858,2859, -2879,2880,2881,2882,2883,2884,2885,2886,2887,2888,2889,2890,2891,2892,2893,2894,2895,2896, -2897,2898,2899,2900,2901,2902,2903,2904,2905,2906,2907,2908,2909,2910,2911,2912,2913,2914, -2915,2916,2917,2918,2919,2920,2921,2922,2923,2924,2925,2926,2927,2928,2929,2930,2931,2932, -2933,2934,2935,2936,2937,2938,2939,2940,2941,2942,2943,2944,2945,2946,2947,2948,2949,2950, -2951,2952,2953,2954,2955,2956,2957,2958,2959,2960,2961,2962,2963,2964,2965,2966,2967,2968, -2969,2970,2971,2972,2973,2974,2975,2976,2977,2978,2979,2980,2981,2982,2983,2984,2985,2986, -2987,2988,2989,2990,2991,2992,2993,2994,2995,2996,2997,2998,2999,3000,3001,3002,3003,3004, -3005,3006,3007,3008,3009,3010,3011,3012,3013,3014,3015,3016,3017,3018,3019,3020,3021,3022, -3023,3024,3025,3026,3027,3028,3029,3030,3031,3032,3033,3034,3035,3036,3037,3038,3039,3040, -3041,3042,3043,3044,3045,3046,3047,3048,3049,3050,3051,3052,3053,3054,3055,3056,3057,3058, -3059,3060,3061,3062,3063,3064,3065,3066,3067,3068,3069,3070,3071,3072,3073,3074,3075,3076, -3077,3078,3079,3080,3081,3082,3083,3084,3085,3086,3087,3088,3089,3090,3091,3092,3093,3094, -3095,3096,3097,3098,3099,3100,3101,3102,3103,3104,3105,3106,3107,3108,3109,3110,3111,3112, -3113,3114,3115,3116,3117,3118,3119,3120,3121,3128,3129,3130,3131,3132,3133,3134,4252,4253, -4254,4255,4256,4257,4258,4259,4260,4261,4262,4263,4264,4265,4266,4267,4268,4269,4270,4271, -4272,4273,4274,4275,4276,4277,4278,4279,4280,4281,4282,4283,4284,4285,4286,4287,4288,4289, -4290,4291,4292,4293,4294,4295,4296,4297,4298,4299,4300,4301,4302,4303,4304,4305,4306,4307, -4308,4309,4310,4311,4312,4313,4314,4315,4316,4317,4318,4319,4320,4321,4322,4323,4324,4325, -4326,4327,5522,5523,5524,5525,5526,5527,5528,5529,5530,5531,5532,5533,5534,5535,5536,5537, -5538,5540,5541,5542,5565,5566,5567,5568,5625,5626,5627,5628,5629,5630,5666,5667,5668,5688, -5689,5690,5727,5728,5729,5762,5765,5766,5767,5931,5932,5933,5934,5935,5936,5965,6022,6082, -6083,6084,6303,6304,6305,6307,6308,6309,6310,6313,6314,6315,6317,6318,6319,6321,6322,6323, -6325,6326,6327,6328,6329,6330,6333,6334,6335,6337,6338,6339,6341,6342,6343,6345,6346,6347, -6349,6350,6351,6355,6365,6366,6367,6520,6521,6522,6560,7092,7093,7094,7256,7257,7258,7283, -7284,7285,7317,7318,7319,7321,7322,7323,7325,7326,7328,7329,7331,7332,7333,7335,7336,7337, -7339,7340,7341,7345,7346,7347,7623,7624,7625,7626,7627,7629,7630,7631,7638,7639,7640,7741, -7742,7743,7848,7849,7908,7927,7928,7929,7931,7970,7971,8272} - --- This array contains all destroyable field items -FIELDS = {1487,1488,1489,1490,1491,1492,1493,1494,1495,1496,1500,1501,1502,1503,1504} diff --git a/path_10_8/data/spells/scripts/attack/annihilation.lua b/path_10_8/data/spells/scripts/attack/annihilation.lua deleted file mode 100644 index bcdf5bf56..000000000 --- a/path_10_8/data/spells/scripts/attack/annihilation.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_WEAPONTYPE) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.06) + 13 - local max = (player:getLevel() / 5) + (skill * attack * 0.14) + 34 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/apprentices strike.lua b/path_10_8/data/spells/scripts/attack/apprentices strike.lua deleted file mode 100644 index dc094fb17..000000000 --- a/path_10_8/data/spells/scripts/attack/apprentices strike.lua +++ /dev/null @@ -1,14 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -function onGetFormulaValues(player, level, maglevel) - return -10, -20 -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/avalanche.lua b/path_10_8/data/spells/scripts/attack/avalanche.lua deleted file mode 100644 index 60dbf78a8..000000000 --- a/path_10_8/data/spells/scripts/attack/avalanche.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ICE) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.2) + 7 - local max = (level / 5) + (maglevel * 2.85) + 16 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/berserk.lua b/path_10_8/data/spells/scripts/attack/berserk.lua deleted file mode 100644 index 9afe6025f..000000000 --- a/path_10_8/data/spells/scripts/attack/berserk.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.03) + 7 - local max = (player:getLevel() / 5) + (skill * attack * 0.05) + 11 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/brutal strike.lua b/path_10_8/data/spells/scripts/attack/brutal strike.lua deleted file mode 100644 index e7bf8be50..000000000 --- a/path_10_8/data/spells/scripts/attack/brutal strike.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_WEAPONTYPE) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.02) + 4 - local max = (player:getLevel() / 5) + (skill * attack * 0.04) + 9 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/buzz.lua b/path_10_8/data/spells/scripts/attack/buzz.lua deleted file mode 100644 index 767c6a301..000000000 --- a/path_10_8/data/spells/scripts/attack/buzz.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.4) + 2 - local max = (level / 5) + (maglevel * 0.8) + 5 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/chill out.lua b/path_10_8/data/spells/scripts/attack/chill out.lua deleted file mode 100644 index 1e682567a..000000000 --- a/path_10_8/data/spells/scripts/attack/chill out.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setArea(createCombatArea(AREA_WAVE4)) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.3) + 2 - local max = (level / 5) + (maglevel * 0.45) + 3 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/cure bleeding.lua b/path_10_8/data/spells/scripts/attack/cure bleeding.lua deleted file mode 100644 index ef1e52de7..000000000 --- a/path_10_8/data/spells/scripts/attack/cure bleeding.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = createCombatObject() -setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -setCombatParam(combat, COMBAT_PARAM_AGGRESSIVE, 0) -setCombatParam(combat, COMBAT_PARAM_DISPEL, CONDITION_PHYSICAL) - -function onCastSpell(cid, var) - return doCombat(cid, combat, var) -end diff --git a/path_10_8/data/spells/scripts/attack/curse.lua b/path_10_8/data/spells/scripts/attack/curse.lua deleted file mode 100644 index abd967267..000000000 --- a/path_10_8/data/spells/scripts/attack/curse.lua +++ /dev/null @@ -1,30 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - -local condition = Condition(CONDITION_CURSED) -condition:setParameter(CONDITION_PARAM_DELAYED, true) - -condition:addDamage(1, 4000, -45) -condition:addDamage(1, 4000, -40) -condition:addDamage(1, 4000, -35) -condition:addDamage(1, 4000, -34) -condition:addDamage(2, 4000, -33) -condition:addDamage(2, 4000, -32) -condition:addDamage(2, 4000, -31) -condition:addDamage(2, 4000, -30) -condition:addDamage(3, 4000, -29) -condition:addDamage(3, 4000, -25) -condition:addDamage(3, 4000, -24) -condition:addDamage(4, 4000, -23) -condition:addDamage(4, 4000, -20) -condition:addDamage(5, 4000, -19) -condition:addDamage(5, 4000, -15) -condition:addDamage(6, 4000, -10) -condition:addDamage(10, 4000, -5) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/death strike.lua b/path_10_8/data/spells/scripts/attack/death strike.lua deleted file mode 100644 index 53d2f1873..000000000 --- a/path_10_8/data/spells/scripts/attack/death strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 2.2) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/divine caldera.lua b/path_10_8/data/spells/scripts/attack/divine caldera.lua deleted file mode 100644 index ce15a854c..000000000 --- a/path_10_8/data/spells/scripts/attack/divine caldera.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 5) + 25 - local max = (level / 5) + (maglevel * 6.2) + 45 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/divine missile.lua b/path_10_8/data/spells/scripts/attack/divine missile.lua deleted file mode 100644 index aad549df2..000000000 --- a/path_10_8/data/spells/scripts/attack/divine missile.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLHOLY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.9) + 8 - local max = (level / 5) + (maglevel * 3) + 18 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/electrify.lua b/path_10_8/data/spells/scripts/attack/electrify.lua deleted file mode 100644 index 23eb60195..000000000 --- a/path_10_8/data/spells/scripts/attack/electrify.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(10, 10000, -25) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy beam.lua b/path_10_8/data/spells/scripts/attack/energy beam.lua deleted file mode 100644 index 47b8c177d..000000000 --- a/path_10_8/data/spells/scripts/attack/energy beam.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setArea(createCombatArea(AREA_BEAM5, AREADIAGONAL_BEAM5)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.8) + 11 - local max = (level / 5) + (maglevel * 3) + 19 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy bomb.lua b/path_10_8/data/spells/scripts/attack/energy bomb.lua deleted file mode 100644 index 78726107d..000000000 --- a/path_10_8/data/spells/scripts/attack/energy bomb.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGYBALL) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_ENERGYFIELD_PVP) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy field.lua b/path_10_8/data/spells/scripts/attack/energy field.lua deleted file mode 100644 index f026a05ed..000000000 --- a/path_10_8/data/spells/scripts/attack/energy field.lua +++ /dev/null @@ -1,9 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGYBALL) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_ENERGYFIELD_PVP) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy strike.lua b/path_10_8/data/spells/scripts/attack/energy strike.lua deleted file mode 100644 index 4c6ee5234..000000000 --- a/path_10_8/data/spells/scripts/attack/energy strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 2.2) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy wall.lua b/path_10_8/data/spells/scripts/attack/energy wall.lua deleted file mode 100644 index 9888b87d8..000000000 --- a/path_10_8/data/spells/scripts/attack/energy wall.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGYBALL) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_ENERGYFIELD_PVP) -combat:setArea(createCombatArea(AREA_WALLFIELD, AREADIAGONAL_WALLFIELD)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/energy wave.lua b/path_10_8/data/spells/scripts/attack/energy wave.lua deleted file mode 100644 index a888eca0e..000000000 --- a/path_10_8/data/spells/scripts/attack/energy wave.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) -combat:setArea(createCombatArea(AREA_SQUAREWAVE5, AREADIAGONAL_SQUAREWAVE5)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 20 - local max = (level / 5) + (maglevel * 7.6) + 48 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/envenom.lua b/path_10_8/data/spells/scripts/attack/envenom.lua deleted file mode 100644 index f5efd08ff..000000000 --- a/path_10_8/data/spells/scripts/attack/envenom.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) - -local condition = Condition(CONDITION_POISON) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(25, 4000, -45) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/eternal winter.lua b/path_10_8/data/spells/scripts/attack/eternal winter.lua deleted file mode 100644 index 29639e8cf..000000000 --- a/path_10_8/data/spells/scripts/attack/eternal winter.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICETORNADO) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 5.5) + 25 - local max = (level / 5) + (maglevel * 11) + 50 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ethereal spear.lua b/path_10_8/data/spells/scripts/attack/ethereal spear.lua deleted file mode 100644 index d97832f5a..000000000 --- a/path_10_8/data/spells/scripts/attack/ethereal spear.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ETHEREALSPEAR) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) - -function onGetFormulaValues(player, skill, attack, factor) - local distSkill = player:getEffectiveSkillLevel(SKILL_DISTANCE) - local min = (player:getLevel() / 5) + distSkill * 0.7 - local max = (player:getLevel() / 5) + distSkill + 5 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/explosion.lua b/path_10_8/data/spells/scripts/attack/explosion.lua deleted file mode 100644 index ddb1dc5a3..000000000 --- a/path_10_8/data/spells/scripts/attack/explosion.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EXPLOSION) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setArea(createCombatArea(AREA_CROSS1X1)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.6) + 9 - local max = (level / 5) + (maglevel * 3.2) + 19 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fierce berserk.lua b/path_10_8/data/spells/scripts/attack/fierce berserk.lua deleted file mode 100644 index 1f051ba06..000000000 --- a/path_10_8/data/spells/scripts/attack/fierce berserk.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.06) + 13 - local max = (player:getLevel() / 5) + (skill * attack * 0.11) + 27 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fire bomb.lua b/path_10_8/data/spells/scripts/attack/fire bomb.lua deleted file mode 100644 index eba9401f8..000000000 --- a/path_10_8/data/spells/scripts/attack/fire bomb.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_FIREFIELD_PVP_FULL) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fire field.lua b/path_10_8/data/spells/scripts/attack/fire field.lua deleted file mode 100644 index 59b2aa7e4..000000000 --- a/path_10_8/data/spells/scripts/attack/fire field.lua +++ /dev/null @@ -1,9 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_FIREFIELD_PVP_FULL) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fire wall.lua b/path_10_8/data/spells/scripts/attack/fire wall.lua deleted file mode 100644 index 8935419a6..000000000 --- a/path_10_8/data/spells/scripts/attack/fire wall.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_FIREFIELD_PVP_FULL) -combat:setArea(createCombatArea(AREA_WALLFIELD, AREADIAGONAL_WALLFIELD)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fire wave.lua b/path_10_8/data/spells/scripts/attack/fire wave.lua deleted file mode 100644 index 98b7f4bc0..000000000 --- a/path_10_8/data/spells/scripts/attack/fire wave.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setArea(createCombatArea(AREA_WAVE4, AREADIAGONAL_WAVE4)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.2) + 7 - local max = (level / 5) + (maglevel * 2) + 12 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/fireball.lua b/path_10_8/data/spells/scripts/attack/fireball.lua deleted file mode 100644 index 1a29dd5c5..000000000 --- a/path_10_8/data/spells/scripts/attack/fireball.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.8) + 12 - local max = (level / 5) + (maglevel * 3) + 17 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/flame strike.lua b/path_10_8/data/spells/scripts/attack/flame strike.lua deleted file mode 100644 index e8c5130e2..000000000 --- a/path_10_8/data/spells/scripts/attack/flame strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 2.2) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/front sweep.lua b/path_10_8/data/spells/scripts/attack/front sweep.lua deleted file mode 100644 index a57b9db02..000000000 --- a/path_10_8/data/spells/scripts/attack/front sweep.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) -combat:setArea(createCombatArea(AREA_WAVE6, AREADIAGONAL_WAVE6)) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.04) + 31 - local max = (player:getLevel() / 5) + (skill * attack * 0.08) + 45 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/great energy beam.lua b/path_10_8/data/spells/scripts/attack/great energy beam.lua deleted file mode 100644 index 33d4fd6ad..000000000 --- a/path_10_8/data/spells/scripts/attack/great energy beam.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setArea(createCombatArea(AREA_BEAM7, AREADIAGONAL_BEAM7)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 3.6) + 22 - local max = (level / 5) + (maglevel * 6) + 37 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/great fireball.lua b/path_10_8/data/spells/scripts/attack/great fireball.lua deleted file mode 100644 index 2c9291ae3..000000000 --- a/path_10_8/data/spells/scripts/attack/great fireball.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.2) + 7 - local max = (level / 5) + (maglevel * 2.85) + 16 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/groundshaker.lua b/path_10_8/data/spells/scripts/attack/groundshaker.lua deleted file mode 100644 index bb9995407..000000000 --- a/path_10_8/data/spells/scripts/attack/groundshaker.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GROUNDSHAKER) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.02) + 4 - local max = (player:getLevel() / 5) + (skill * attack * 0.03) + 6 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/heavy magic missile.lua b/path_10_8/data/spells/scripts/attack/heavy magic missile.lua deleted file mode 100644 index 6e6f6dea9..000000000 --- a/path_10_8/data/spells/scripts/attack/heavy magic missile.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 0.8) + 5 - local max = (level / 5) + (maglevel * 1.6) + 10 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/hells core.lua b/path_10_8/data/spells/scripts/attack/hells core.lua deleted file mode 100644 index 9b93527eb..000000000 --- a/path_10_8/data/spells/scripts/attack/hells core.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 8) + 50 - local max = (level / 5) + (maglevel * 12) + 75 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/holy flash.lua b/path_10_8/data/spells/scripts/attack/holy flash.lua deleted file mode 100644 index b1bff57d1..000000000 --- a/path_10_8/data/spells/scripts/attack/holy flash.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLHOLY) - -local condition = Condition(CONDITION_DAZZLED) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(50, 10000, -10) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/holy missile.lua b/path_10_8/data/spells/scripts/attack/holy missile.lua deleted file mode 100644 index b8c25ecef..000000000 --- a/path_10_8/data/spells/scripts/attack/holy missile.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_HOLY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.8) + 11 - local max = (level / 5) + (maglevel * 3.8) + 23 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ice strike.lua b/path_10_8/data/spells/scripts/attack/ice strike.lua deleted file mode 100644 index 5441a316e..000000000 --- a/path_10_8/data/spells/scripts/attack/ice strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 2.2) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ice wave.lua b/path_10_8/data/spells/scripts/attack/ice wave.lua deleted file mode 100644 index 3233c29a6..000000000 --- a/path_10_8/data/spells/scripts/attack/ice wave.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setArea(createCombatArea(AREA_WAVE4, AREADIAGONAL_WAVE4)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 0.8) + 5 - local max = (level / 5) + (maglevel * 2) + 12 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/icicle.lua b/path_10_8/data/spells/scripts/attack/icicle.lua deleted file mode 100644 index 1ec5c16b7..000000000 --- a/path_10_8/data/spells/scripts/attack/icicle.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.8) + 12 - local max = (level / 5) + (maglevel * 3) + 17 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ignite.lua b/path_10_8/data/spells/scripts/attack/ignite.lua deleted file mode 100644 index 9d69b8f69..000000000 --- a/path_10_8/data/spells/scripts/attack/ignite.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(23, 10000, -10) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/inflict wound.lua b/path_10_8/data/spells/scripts/attack/inflict wound.lua deleted file mode 100644 index 319cefc39..000000000 --- a/path_10_8/data/spells/scripts/attack/inflict wound.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_DRAWBLOOD) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_WEAPONTYPE) - -local condition = Condition(CONDITION_BLEEDING) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(25, 4000, -45) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/light magic missile.lua b/path_10_8/data/spells/scripts/attack/light magic missile.lua deleted file mode 100644 index 977d302cd..000000000 --- a/path_10_8/data/spells/scripts/attack/light magic missile.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 0.4) + 3 - local max = (level / 5) + (maglevel * 0.8) + 5 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/light stone shower.lua b/path_10_8/data/spells/scripts/attack/light stone shower.lua deleted file mode 100644 index 54f6379f8..000000000 --- a/path_10_8/data/spells/scripts/attack/light stone shower.lua +++ /dev/null @@ -1,19 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STONES) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) -combat:setArea(createCombatArea(AREA_CROSS1X1)) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.3) + 2 - local max = (level / 5) + (maglevel * 0.45) + 3 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/lightest magic missile.lua b/path_10_8/data/spells/scripts/attack/lightest magic missile.lua deleted file mode 100644 index 04ed8b505..000000000 --- a/path_10_8/data/spells/scripts/attack/lightest magic missile.lua +++ /dev/null @@ -1,14 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - return -3, -5 -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/lightest missile.lua b/path_10_8/data/spells/scripts/attack/lightest missile.lua deleted file mode 100644 index e9168459a..000000000 --- a/path_10_8/data/spells/scripts/attack/lightest missile.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.45) + 3 - local max = (level / 5) + (maglevel * 0.7) + 4 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/lightning.lua b/path_10_8/data/spells/scripts/attack/lightning.lua deleted file mode 100644 index fbfa8f44c..000000000 --- a/path_10_8/data/spells/scripts/attack/lightning.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 2.2) + 12 - local max = (level / 5) + (maglevel * 3.4) + 21 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/mud attack.lua b/path_10_8/data/spells/scripts/attack/mud attack.lua deleted file mode 100644 index 450eb0a3b..000000000 --- a/path_10_8/data/spells/scripts/attack/mud attack.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLEARTH) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.4) + 2 - local max = (level / 5) + (maglevel * 0.8) + 5 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/physical strike.lua b/path_10_8/data/spells/scripts/attack/physical strike.lua deleted file mode 100644 index 1d0caac18..000000000 --- a/path_10_8/data/spells/scripts/attack/physical strike.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EXPLOSION) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.6) + 9 - local max = (level / 5) + (maglevel * 2.4) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/poison bomb.lua b/path_10_8/data/spells/scripts/attack/poison bomb.lua deleted file mode 100644 index ec5522574..000000000 --- a/path_10_8/data/spells/scripts/attack/poison bomb.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISON) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_POISONFIELD_PVP) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/poison field.lua b/path_10_8/data/spells/scripts/attack/poison field.lua deleted file mode 100644 index f4e9e6224..000000000 --- a/path_10_8/data/spells/scripts/attack/poison field.lua +++ /dev/null @@ -1,9 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISON) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_POISONFIELD_PVP) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/poison wall.lua b/path_10_8/data/spells/scripts/attack/poison wall.lua deleted file mode 100644 index a9b8460ae..000000000 --- a/path_10_8/data/spells/scripts/attack/poison wall.lua +++ /dev/null @@ -1,10 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISON) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_POISONFIELD_PVP) -combat:setArea(createCombatArea(AREA_WALLFIELD, AREADIAGONAL_WALLFIELD)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/practise fire wave.lua b/path_10_8/data/spells/scripts/attack/practise fire wave.lua deleted file mode 100644 index 7a468fffc..000000000 --- a/path_10_8/data/spells/scripts/attack/practise fire wave.lua +++ /dev/null @@ -1,14 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setArea(createCombatArea(AREA_WAVE4, AREADIAGONAL_WAVE4)) - -function onGetFormulaValues(player, level, maglevel) - return -8, -11 -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/rage of the skies.lua b/path_10_8/data/spells/scripts/attack/rage of the skies.lua deleted file mode 100644 index 20aa89cd0..000000000 --- a/path_10_8/data/spells/scripts/attack/rage of the skies.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BIGCLOUDS) -combat:setArea(createCombatArea(AREA_CROSS6X6)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4) + 75 - local max = (level / 5) + (maglevel * 10) + 150 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/scorch.lua b/path_10_8/data/spells/scripts/attack/scorch.lua deleted file mode 100644 index 0dfbc5cf6..000000000 --- a/path_10_8/data/spells/scripts/attack/scorch.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setArea(createCombatArea(AREA_WAVE4)) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.3) + 2 - local max = (level / 5) + (maglevel * 0.45) + 3 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/soul fire.lua b/path_10_8/data/spells/scripts/attack/soul fire.lua deleted file mode 100644 index 74ee7015c..000000000 --- a/path_10_8/data/spells/scripts/attack/soul fire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(13, 10000, -10) -combat:setCondition(condition) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/stalagmite.lua b/path_10_8/data/spells/scripts/attack/stalagmite.lua deleted file mode 100644 index e2901383f..000000000 --- a/path_10_8/data/spells/scripts/attack/stalagmite.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STONES) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 0.8) + 5 - local max = (level / 5) + (maglevel * 1.6) + 10 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/stone shower.lua b/path_10_8/data/spells/scripts/attack/stone shower.lua deleted file mode 100644 index c53db830a..000000000 --- a/path_10_8/data/spells/scripts/attack/stone shower.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STONES) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + maglevel + 6 - local max = (level / 5) + (maglevel * 2.6) + 16 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong energy strike.lua b/path_10_8/data/spells/scripts/attack/strong energy strike.lua deleted file mode 100644 index ec7ea6ba5..000000000 --- a/path_10_8/data/spells/scripts/attack/strong energy strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 2.8) + 16 - local max = (level / 5) + (maglevel * 4.4) + 28 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong ethereal spear.lua b/path_10_8/data/spells/scripts/attack/strong ethereal spear.lua deleted file mode 100644 index f0d3dd627..000000000 --- a/path_10_8/data/spells/scripts/attack/strong ethereal spear.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ETHEREALSPEAR) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) - -function onGetFormulaValues(player, skill, attack, factor) - local distSkill = player:getEffectiveSkillLevel(SKILL_DISTANCE) - local min = (player:getLevel() / 5) + distSkill + 7 - local max = (player:getLevel() / 5) + (distSkill * 1.5) + 13 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong flame strike.lua b/path_10_8/data/spells/scripts/attack/strong flame strike.lua deleted file mode 100644 index 93571f092..000000000 --- a/path_10_8/data/spells/scripts/attack/strong flame strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 2.8) + 16 - local max = (level / 5) + (maglevel * 4.4) + 28 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong ice strike.lua b/path_10_8/data/spells/scripts/attack/strong ice strike.lua deleted file mode 100644 index 2a52569ca..000000000 --- a/path_10_8/data/spells/scripts/attack/strong ice strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 2.8) + 16 - local max = (level / 5) + (maglevel * 4.4) + 28 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong ice wave.lua b/path_10_8/data/spells/scripts/attack/strong ice wave.lua deleted file mode 100644 index 60819fad2..000000000 --- a/path_10_8/data/spells/scripts/attack/strong ice wave.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setArea(createCombatArea(AREA_SHORTWAVE3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 20 - local max = (level / 5) + (maglevel * 7.6) + 48 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/strong terra strike.lua b/path_10_8/data/spells/scripts/attack/strong terra strike.lua deleted file mode 100644 index e6f609af2..000000000 --- a/path_10_8/data/spells/scripts/attack/strong terra strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLEARTH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 2.8) + 16 - local max = (level / 5) + (maglevel * 4.4) + 28 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/sudden death.lua b/path_10_8/data/spells/scripts/attack/sudden death.lua deleted file mode 100644 index 4c68f3224..000000000 --- a/path_10_8/data/spells/scripts/attack/sudden death.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.3) + 32 - local max = (level / 5) + (maglevel * 7.4) + 48 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/terra strike.lua b/path_10_8/data/spells/scripts/attack/terra strike.lua deleted file mode 100644 index b6ea30bc7..000000000 --- a/path_10_8/data/spells/scripts/attack/terra strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLEARTH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 2.2) + 14 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/terra wave.lua b/path_10_8/data/spells/scripts/attack/terra wave.lua deleted file mode 100644 index 20131c908..000000000 --- a/path_10_8/data/spells/scripts/attack/terra wave.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLPLANTS) -combat:setArea(createCombatArea(AREA_SQUAREWAVE5, AREADIAGONAL_SQUAREWAVE5)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 3.25) + 5 - local max = (level / 5) + (maglevel * 6.75) + 30 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/thunderstorm.lua b/path_10_8/data/spells/scripts/attack/thunderstorm.lua deleted file mode 100644 index b7150e42d..000000000 --- a/path_10_8/data/spells/scripts/attack/thunderstorm.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGYBALL) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + maglevel + 6 - local max = (level / 5) + (maglevel * 2.6) + 16 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ultimate energy strike.lua b/path_10_8/data/spells/scripts/attack/ultimate energy strike.lua deleted file mode 100644 index c81651e1b..000000000 --- a/path_10_8/data/spells/scripts/attack/ultimate energy strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 35 - local max = (level / 5) + (maglevel * 7.3) + 55 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ultimate flame strike.lua b/path_10_8/data/spells/scripts/attack/ultimate flame strike.lua deleted file mode 100644 index 7216145e5..000000000 --- a/path_10_8/data/spells/scripts/attack/ultimate flame strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 35 - local max = (level / 5) + (maglevel * 7.3) + 55 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ultimate ice strike.lua b/path_10_8/data/spells/scripts/attack/ultimate ice strike.lua deleted file mode 100644 index d76f5125a..000000000 --- a/path_10_8/data/spells/scripts/attack/ultimate ice strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEATTACK) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLICE) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 35 - local max = (level / 5) + (maglevel * 7.3) + 55 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/ultimate terra strike.lua b/path_10_8/data/spells/scripts/attack/ultimate terra strike.lua deleted file mode 100644 index 736707195..000000000 --- a/path_10_8/data/spells/scripts/attack/ultimate terra strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_CARNIPHILA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLEARTH) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4.5) + 35 - local max = (level / 5) + (maglevel * 7.3) + 55 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/whirlwind throw.lua b/path_10_8/data/spells/scripts/attack/whirlwind throw.lua deleted file mode 100644 index 508062132..000000000 --- a/path_10_8/data/spells/scripts/attack/whirlwind throw.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_WEAPONTYPE) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setParameter(COMBAT_PARAM_USECHARGES, true) - -function onGetFormulaValues(player, skill, attack, factor) - local min = (player:getLevel() / 5) + (skill * attack * 0.01) + 1 - local max = (player:getLevel() / 5) + (skill * attack * 0.03) + 6 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_SKILLVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/attack/wrath of nature.lua b/path_10_8/data/spells/scripts/attack/wrath of nature.lua deleted file mode 100644 index 4f058ec5e..000000000 --- a/path_10_8/data/spells/scripts/attack/wrath of nature.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_PLANTATTACK) -combat:setArea(createCombatArea(AREA_CROSS6X6)) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 3) + 32 - local max = (level / 5) + (maglevel * 9) + 40 - return -min, -max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/custom/apocalypse.lua b/path_10_8/data/spells/scripts/custom/apocalypse.lua deleted file mode 100644 index 70dead24b..000000000 --- a/path_10_8/data/spells/scripts/custom/apocalypse.lua +++ /dev/null @@ -1,25 +0,0 @@ -function spellCallback(cid, position, count) - if Creature(cid) then - if count > 0 or math.random(0, 1) == 1 then - position:sendMagicEffect(CONST_ME_HITBYFIRE) - doAreaCombatHealth(cid, COMBAT_FIREDAMAGE, position, 0, -100, -100, CONST_ME_EXPLOSIONHIT) - end - - if count < 5 then - count = count + 1 - addEvent(spellCallback, math.random(1000, 4000), cid, position, count) - end - end -end - -function onTargetTile(creature, position) - spellCallback(creature:getId(), position, 0) -end - -local combat = Combat() -combat:setArea(createCombatArea(AREA_CROSS5X5)) -combat:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/custom/combustion.lua b/path_10_8/data/spells/scripts/custom/combustion.lua deleted file mode 100644 index ca9cb5aa7..000000000 --- a/path_10_8/data/spells/scripts/custom/combustion.lua +++ /dev/null @@ -1,15 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameterCONDITION_PARAM_DELAYED, 1) -condition:addDamage(5, 3000, -25) -condition:addDamage(1, 5000, -666) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) -combat:setFormula(COMBAT_FORMULA_LEVELMAGIC, -1.3, -30, -1.7, 0) -combat:setCondition(condition) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/custom/drunk.lua b/path_10_8/data/spells/scripts/custom/drunk.lua deleted file mode 100644 index 3c19aea0c..000000000 --- a/path_10_8/data/spells/scripts/custom/drunk.lua +++ /dev/null @@ -1,11 +0,0 @@ -local condition = Condition(CONDITION_DRUNK) -condition:setParameter(CONDITION_PARAM_TICKS, 20000) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) -combat:setCondition(condition) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/custom/magic prison.lua b/path_10_8/data/spells/scripts/custom/magic prison.lua deleted file mode 100644 index ee5bfba68..000000000 --- a/path_10_8/data/spells/scripts/custom/magic prison.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL) -combat:setArea(createCombatArea(AREA_CROSS1X1)) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/custom/polymorph.lua b/path_10_8/data/spells/scripts/custom/polymorph.lua deleted file mode 100644 index 27efef382..000000000 --- a/path_10_8/data/spells/scripts/custom/polymorph.lua +++ /dev/null @@ -1,29 +0,0 @@ -local condition = Condition(CONDITION_OUTFIT) -condition:setParameter(CONDITION_PARAM_TICKS, 20000) -condition:setOutfit(0, 230, 0, 0, 0, 0) -condition:setOutfit(0, 231, 0, 0, 0, 0) -condition:setOutfit(0, 232, 0, 0, 0, 0) -condition:setOutfit(0, 233, 0, 0, 0, 0) -condition:setOutfit(0, 234, 0, 0, 0, 0) -condition:setOutfit(0, 235, 0, 0, 0, 0) -condition:setOutfit(0, 236, 0, 0, 0, 0) -condition:setOutfit(0, 237, 0, 0, 0, 0) -condition:setOutfit(0, 238, 0, 0, 0, 0) -condition:setOutfit(0, 239, 0, 0, 0, 0) -condition:setOutfit(0, 240, 0, 0, 0, 0) -condition:setOutfit(0, 241, 0, 0, 0, 0) -condition:setOutfit(0, 242, 0, 0, 0, 0) -condition:setOutfit(0, 243, 0, 0, 0, 0) -condition:setOutfit(0, 244, 0, 0, 0, 0) -condition:setOutfit(0, 245, 0, 0, 0, 0) -condition:setOutfit(0, 246, 0, 0, 0, 0) -condition:setOutfit(0, 247, 0, 0, 0, 0) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/bruise bane.lua b/path_10_8/data/spells/scripts/healing/bruise bane.lua deleted file mode 100644 index 7b0c94e30..000000000 --- a/path_10_8/data/spells/scripts/healing/bruise bane.lua +++ /dev/null @@ -1,19 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 1.8) + 11 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure bleeding.lua b/path_10_8/data/spells/scripts/healing/cure bleeding.lua deleted file mode 100644 index b41638597..000000000 --- a/path_10_8/data/spells/scripts/healing/cure bleeding.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_BLEEDING) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure burning.lua b/path_10_8/data/spells/scripts/healing/cure burning.lua deleted file mode 100644 index 7813858fa..000000000 --- a/path_10_8/data/spells/scripts/healing/cure burning.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_FIRE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure curse.lua b/path_10_8/data/spells/scripts/healing/cure curse.lua deleted file mode 100644 index 1d74c77f1..000000000 --- a/path_10_8/data/spells/scripts/healing/cure curse.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_CURSED) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure electrification.lua b/path_10_8/data/spells/scripts/healing/cure electrification.lua deleted file mode 100644 index 14f88626e..000000000 --- a/path_10_8/data/spells/scripts/healing/cure electrification.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_ENERGY) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure poison rune.lua b/path_10_8/data/spells/scripts/healing/cure poison rune.lua deleted file mode 100644 index f272fb983..000000000 --- a/path_10_8/data/spells/scripts/healing/cure poison rune.lua +++ /dev/null @@ -1,9 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_POISON) -combat:setParameter(COMBAT_PARAM_TARGETCASTERORTOPMOST, true) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/cure poison.lua b/path_10_8/data/spells/scripts/healing/cure poison.lua deleted file mode 100644 index b50548e72..000000000 --- a/path_10_8/data/spells/scripts/healing/cure poison.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_POISON) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/divine healing.lua b/path_10_8/data/spells/scripts/healing/divine healing.lua deleted file mode 100644 index 237e7a434..000000000 --- a/path_10_8/data/spells/scripts/healing/divine healing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 6.9) + 40 - local max = (level / 5) + (maglevel * 13.2) + 82 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/heal friend.lua b/path_10_8/data/spells/scripts/healing/heal friend.lua deleted file mode 100644 index 621628afc..000000000 --- a/path_10_8/data/spells/scripts/healing/heal friend.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 6.3) + 45 - local max = (level / 5) + (maglevel * 14.4) + 90 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/intense healing rune.lua b/path_10_8/data/spells/scripts/healing/intense healing rune.lua deleted file mode 100644 index 53fa135aa..000000000 --- a/path_10_8/data/spells/scripts/healing/intense healing rune.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_TARGETCASTERORTOPMOST, true) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 3.2) + 20 - local max = (level / 5) + (maglevel * 5.4) + 40 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/intense healing.lua b/path_10_8/data/spells/scripts/healing/intense healing.lua deleted file mode 100644 index 2a61b871c..000000000 --- a/path_10_8/data/spells/scripts/healing/intense healing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 3.2) + 20 - local max = (level / 5) + (maglevel * 5.4) + 40 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/intense recovery.lua b/path_10_8/data/spells/scripts/healing/intense recovery.lua deleted file mode 100644 index bb13cce46..000000000 --- a/path_10_8/data/spells/scripts/healing/intense recovery.lua +++ /dev/null @@ -1,15 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_REGENERATION) -condition:setParameter(CONDITION_PARAM_SUBID, 1) -condition:setParameter(CONDITION_PARAM_TICKS, 1 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_HEALTHGAIN, 40) -condition:setParameter(CONDITION_PARAM_HEALTHTICKS, 3000) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/intense wound cleansing.lua b/path_10_8/data/spells/scripts/healing/intense wound cleansing.lua deleted file mode 100644 index e64028348..000000000 --- a/path_10_8/data/spells/scripts/healing/intense wound cleansing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 70) + 438 - local max = (level / 5) + (maglevel * 92) + 544 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/light healing.lua b/path_10_8/data/spells/scripts/healing/light healing.lua deleted file mode 100644 index bd3a0908d..000000000 --- a/path_10_8/data/spells/scripts/healing/light healing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 1.4) + 8 - local max = (level / 5) + (maglevel * 1.8) + 11 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/magic patch.lua b/path_10_8/data/spells/scripts/healing/magic patch.lua deleted file mode 100644 index 36347b377..000000000 --- a/path_10_8/data/spells/scripts/healing/magic patch.lua +++ /dev/null @@ -1,19 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - level = math.min(level, 20) - maglevel = math.min(maglevel, 20) - local min = (level / 5) + (maglevel * 0.6) + 3 - local max = (level / 5) + maglevel + 6 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/mass healing.lua b/path_10_8/data/spells/scripts/healing/mass healing.lua deleted file mode 100644 index eb921babf..000000000 --- a/path_10_8/data/spells/scripts/healing/mass healing.lua +++ /dev/null @@ -1,29 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -local healMonsters = false - -function onTargetCreature(creature, target) - local player = creature:getPlayer() - local min = ((player:getLevel() / 5) + (player:getMagicLevel() * 4.6) + 100) - local max = ((player:getLevel() / 5) + (player:getMagicLevel() * 9.6) + 125) - - local master = target:getMaster() - if not healMonsters then - if target:isMonster() and not master or master and master:isMonster() then - return true - end - end - - doTargetCombatHealth(0, target, COMBAT_HEALING, min, max, CONST_ME_NONE) - return true -end - -combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/practise healing.lua b/path_10_8/data/spells/scripts/healing/practise healing.lua deleted file mode 100644 index c336213b2..000000000 --- a/path_10_8/data/spells/scripts/healing/practise healing.lua +++ /dev/null @@ -1,15 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - return 4, 7 -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/recovery.lua b/path_10_8/data/spells/scripts/healing/recovery.lua deleted file mode 100644 index de878399a..000000000 --- a/path_10_8/data/spells/scripts/healing/recovery.lua +++ /dev/null @@ -1,15 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_REGENERATION) -condition:setParameter(CONDITION_PARAM_SUBID, 1) -condition:setParameter(CONDITION_PARAM_TICKS, 1 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_HEALTHGAIN, 20) -condition:setParameter(CONDITION_PARAM_HEALTHTICKS, 3000) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/salvation.lua b/path_10_8/data/spells/scripts/healing/salvation.lua deleted file mode 100644 index fe047c8e5..000000000 --- a/path_10_8/data/spells/scripts/healing/salvation.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 12) + 75 - local max = (level / 5) + (maglevel * 20) + 125 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/ultimate healing rune.lua b/path_10_8/data/spells/scripts/healing/ultimate healing rune.lua deleted file mode 100644 index 5aac4c00f..000000000 --- a/path_10_8/data/spells/scripts/healing/ultimate healing rune.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_TARGETCASTERORTOPMOST, true) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 7.3) + 42 - local max = (level / 5) + (maglevel * 12.4) + 90 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/ultimate healing.lua b/path_10_8/data/spells/scripts/healing/ultimate healing.lua deleted file mode 100644 index ec18d9ed9..000000000 --- a/path_10_8/data/spells/scripts/healing/ultimate healing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 6.8) + 42 - local max = (level / 5) + (maglevel * 12.9) + 90 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/healing/wound cleansing.lua b/path_10_8/data/spells/scripts/healing/wound cleansing.lua deleted file mode 100644 index 61c050d01..000000000 --- a/path_10_8/data/spells/scripts/healing/wound cleansing.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_PARALYZE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -function onGetFormulaValues(player, level, maglevel) - local min = (level / 5) + (maglevel * 4) + 25 - local max = (level / 5) + (maglevel * 8) + 50 - return min, max -end - -combat:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua b/path_10_8/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua deleted file mode 100644 index 8d7ff3758..000000000 --- a/path_10_8/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua +++ /dev/null @@ -1,19 +0,0 @@ -local combat = {} - -for i = CONDITION_PARAM_SKILL_FIST, CONDITION_PARAM_SKILL_SHIELD do - for j = 1, 6 do - local index = ((i - 20) * 6) + j - combat[index] = Combat() - combat[index]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SNOWBALL) - combat[index]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_POFF) - - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 5000) - condition:setParameter(i, -j) - combat[index]:setCondition(condition) - end -end - -function onCastSpell(creature, variant) - return combat[math.random(#combat)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/betrayed wraith skill reducer.lua b/path_10_8/data/spells/scripts/monster/betrayed wraith skill reducer.lua deleted file mode 100644 index a6d972a52..000000000 --- a/path_10_8/data/spells/scripts/monster/betrayed wraith skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 80) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_YELLOW_RINGS) -combat:setArea(createCombatArea(AREA_SQUAREWAVE5)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/blightwalker curse.lua b/path_10_8/data/spells/scripts/monster/blightwalker curse.lua deleted file mode 100644 index d025f07c7..000000000 --- a/path_10_8/data/spells/scripts/monster/blightwalker curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 10, 30 do - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 9 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i]:setArea(createCombatArea(AREA_CROSS6X6)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(10, 30)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/choking fear drown.lua b/path_10_8/data/spells/scripts/monster/choking fear drown.lua deleted file mode 100644 index 42b7ad8eb..000000000 --- a/path_10_8/data/spells/scripts/monster/choking fear drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(50, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BUBBLES) -combat:setArea(createCombatArea(AREA_CROSS6X6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/cliff strider electrify.lua b/path_10_8/data/spells/scripts/monster/cliff strider electrify.lua deleted file mode 100644 index 7231acef3..000000000 --- a/path_10_8/data/spells/scripts/monster/cliff strider electrify.lua +++ /dev/null @@ -1,12 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) - -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 10000, -25) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/dark torturer skill reducer.lua b/path_10_8/data/spells/scripts/monster/dark torturer skill reducer.lua deleted file mode 100644 index 559cec088..000000000 --- a/path_10_8/data/spells/scripts/monster/dark torturer skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 8000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 85) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SOUND_PURPLE) -combat:setArea(createCombatArea(AREA_SQUAREWAVE6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/death blob curse.lua b/path_10_8/data/spells/scripts/monster/death blob curse.lua deleted file mode 100644 index 915f9adb1..000000000 --- a/path_10_8/data/spells/scripts/monster/death blob curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 5, 10 do - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 7 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(5, 10)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/deepling spellsinger skill reducer.lua b/path_10_8/data/spells/scripts/monster/deepling spellsinger skill reducer.lua deleted file mode 100644 index cb0d443d2..000000000 --- a/path_10_8/data/spells/scripts/monster/deepling spellsinger skill reducer.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = {} - -for i = 45, 65 do - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 8000) - condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, i) - condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, i) - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STUN) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EXPLOSION) - combat[i]:setArea(createCombatArea(AREA_BEAM1)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(45, 65)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/demon outcast skill reducer.lua b/path_10_8/data/spells/scripts/monster/demon outcast skill reducer.lua deleted file mode 100644 index e36bbc78a..000000000 --- a/path_10_8/data/spells/scripts/monster/demon outcast skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 6000) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 25) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FLASHARROW) -combat:setArea(createCombatArea(AREA_BEAM1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/djinn cancel invisibility.lua b/path_10_8/data/spells/scripts/monster/djinn cancel invisibility.lua deleted file mode 100644 index 61128bc97..000000000 --- a/path_10_8/data/spells/scripts/monster/djinn cancel invisibility.lua +++ /dev/null @@ -1,7 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_INVISIBLE) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/djinn electrify.lua b/path_10_8/data/spells/scripts/monster/djinn electrify.lua deleted file mode 100644 index 83eb0c4eb..000000000 --- a/path_10_8/data/spells/scripts/monster/djinn electrify.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(3, 10000, -25) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/draken abomination curse.lua b/path_10_8/data/spells/scripts/monster/draken abomination curse.lua deleted file mode 100644 index 9304f0412..000000000 --- a/path_10_8/data/spells/scripts/monster/draken abomination curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 15, 30 do - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 8 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(15, 30)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/energy elemental electrify.lua b/path_10_8/data/spells/scripts/monster/energy elemental electrify.lua deleted file mode 100644 index 0d479c47a..000000000 --- a/path_10_8/data/spells/scripts/monster/energy elemental electrify.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(7, 10000, -25) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BLOCKHIT) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua b/path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua deleted file mode 100644 index 3790028db..000000000 --- a/path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = {} - -for i = 13, 50 do - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 6000) - condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, i) - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) - combat[i]:setArea(createCombatArea(AREA_CIRCLE2X2)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(13, 50)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/feversleep skill reducer.lua b/path_10_8/data/spells/scripts/monster/feversleep skill reducer.lua deleted file mode 100644 index f4b62f910..000000000 --- a/path_10_8/data/spells/scripts/monster/feversleep skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 50) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STUN) -combat:setArea(createCombatArea(AREA_CROSS6X6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/fury skill reducer.lua b/path_10_8/data/spells/scripts/monster/fury skill reducer.lua deleted file mode 100644 index 2f0534660..000000000 --- a/path_10_8/data/spells/scripts/monster/fury skill reducer.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 60) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 70) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SOUND_YELLOW) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/ghastly dragon curse.lua b/path_10_8/data/spells/scripts/monster/ghastly dragon curse.lua deleted file mode 100644 index c12c9fcdc..000000000 --- a/path_10_8/data/spells/scripts/monster/ghastly dragon curse.lua +++ /dev/null @@ -1,33 +0,0 @@ -local combat = {} - -for i = 40, 170 do - for j = 1, 3 do - local index = ((i - 40) * 3) + j - combat[index] = Combat() - combat[index]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[index]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[index]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for k = 1, 4 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - if j > 1 then - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - if j > 2 then - condition:addDamage(1, 4000, -(damage * 1.2)) - end - end - combat[index]:setCondition(condition) - end -end - -function onCastSpell(creature, variant) - return combat[math.random(#combat)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/hellfire fighter soulfire.lua b/path_10_8/data/spells/scripts/monster/hellfire fighter soulfire.lua deleted file mode 100644 index 8ae590fdd..000000000 --- a/path_10_8/data/spells/scripts/monster/hellfire fighter soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 9000, -10) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_FIREATTACK) -combat:setArea(createCombatArea(AREA_CROSS6X6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/hellspawn soulfire.lua b/path_10_8/data/spells/scripts/monster/hellspawn soulfire.lua deleted file mode 100644 index 1c7f144e2..000000000 --- a/path_10_8/data/spells/scripts/monster/hellspawn soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_FIRE) - -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(26, 9000, -10) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/ice golem skill reducer.lua b/path_10_8/data/spells/scripts/monster/ice golem skill reducer.lua deleted file mode 100644 index d7bc670f0..000000000 --- a/path_10_8/data/spells/scripts/monster/ice golem skill reducer.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 85) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 85) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/lancer beetle curse.lua b/path_10_8/data/spells/scripts/monster/lancer beetle curse.lua deleted file mode 100644 index abffaacaa..000000000 --- a/path_10_8/data/spells/scripts/monster/lancer beetle curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 5, 11 do - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 7 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(5, 11)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/lava golem soulfire.lua b/path_10_8/data/spells/scripts/monster/lava golem soulfire.lua deleted file mode 100644 index 69aacb1e3..000000000 --- a/path_10_8/data/spells/scripts/monster/lava golem soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(40, 9000, -10) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONHIT) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/magma crawler soulfire.lua b/path_10_8/data/spells/scripts/monster/magma crawler soulfire.lua deleted file mode 100644 index 68135f908..000000000 --- a/path_10_8/data/spells/scripts/monster/magma crawler soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 9000, -10) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONHIT) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/massive energy elemental electrify.lua b/path_10_8/data/spells/scripts/monster/massive energy elemental electrify.lua deleted file mode 100644 index 1bbd62614..000000000 --- a/path_10_8/data/spells/scripts/monster/massive energy elemental electrify.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(10, 10000, -25) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BLOCKHIT) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/massive fire elemental soulfire.lua b/path_10_8/data/spells/scripts/monster/massive fire elemental soulfire.lua deleted file mode 100644 index 1c759518a..000000000 --- a/path_10_8/data/spells/scripts/monster/massive fire elemental soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 9000, -10) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) -combat:setArea(createCombatArea(AREA_CROSS6X6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/mutated bat curse.lua b/path_10_8/data/spells/scripts/monster/mutated bat curse.lua deleted file mode 100644 index a724e6cfc..000000000 --- a/path_10_8/data/spells/scripts/monster/mutated bat curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 2, 4 do - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 9 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - combat[i]:setArea(createCombatArea(AREA_SQUAREWAVE7)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(2, 4)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/phantasm drown.lua b/path_10_8/data/spells/scripts/monster/phantasm drown.lua deleted file mode 100644 index bc13da129..000000000 --- a/path_10_8/data/spells/scripts/monster/phantasm drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setArea(createCombatArea(AREA_SQUAREWAVE7)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/pirate corsair skill reducer.lua b/path_10_8/data/spells/scripts/monster/pirate corsair skill reducer.lua deleted file mode 100644 index 7435ff606..000000000 --- a/path_10_8/data/spells/scripts/monster/pirate corsair skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 25) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SOUND_PURPLE) -combat:setArea(createCombatArea(AREA_BEAM1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/quara constrictor freeze.lua b/path_10_8/data/spells/scripts/monster/quara constrictor freeze.lua deleted file mode 100644 index 96e483d7c..000000000 --- a/path_10_8/data/spells/scripts/monster/quara constrictor freeze.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FREEZING) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(10, 8000, -8) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/sea serpent drown.lua b/path_10_8/data/spells/scripts/monster/sea serpent drown.lua deleted file mode 100644 index c0af07d2a..000000000 --- a/path_10_8/data/spells/scripts/monster/sea serpent drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(12, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_WATERSPLASH) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/shock head skill reducer 1.lua b/path_10_8/data/spells/scripts/monster/shock head skill reducer 1.lua deleted file mode 100644 index a7733c502..000000000 --- a/path_10_8/data/spells/scripts/monster/shock head skill reducer 1.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 6000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 65) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GROUNDSHAKER) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EXPLOSION) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/shock head skill reducer 2.lua b/path_10_8/data/spells/scripts/monster/shock head skill reducer 2.lua deleted file mode 100644 index f70279d7f..000000000 --- a/path_10_8/data/spells/scripts/monster/shock head skill reducer 2.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT, 70) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STUN) -combat:setArea(createCombatArea(AREA_CROSS6X6)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/silencer skill reducer.lua b/path_10_8/data/spells/scripts/monster/silencer skill reducer.lua deleted file mode 100644 index 5e2cc3d9d..000000000 --- a/path_10_8/data/spells/scripts/monster/silencer skill reducer.lua +++ /dev/null @@ -1,17 +0,0 @@ -local combat = {} - -for i = 20, 70 do - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 6000) - condition:setParameter(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT, i) - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - combat[i]:setArea(createCombatArea(AREA_CIRCLE2X2)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(20, 70)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/souleater drown.lua b/path_10_8/data/spells/scripts/monster/souleater drown.lua deleted file mode 100644 index aa1c8c820..000000000 --- a/path_10_8/data/spells/scripts/monster/souleater drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(10, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/spectre drown.lua b/path_10_8/data/spells/scripts/monster/spectre drown.lua deleted file mode 100644 index d1eda5fa3..000000000 --- a/path_10_8/data/spells/scripts/monster/spectre drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/stampor skill reducer.lua b/path_10_8/data/spells/scripts/monster/stampor skill reducer.lua deleted file mode 100644 index 5e2594633..000000000 --- a/path_10_8/data/spells/scripts/monster/stampor skill reducer.lua +++ /dev/null @@ -1,18 +0,0 @@ -local combat = {} - -for i = 60, 85 do - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 4000) - condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, i) - condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, i) - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLPLANTS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SMALLEARTH) - combat[i]:setArea(createCombatArea(AREA_BEAM1)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(60, 85)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/undead dragon curse.lua b/path_10_8/data/spells/scripts/monster/undead dragon curse.lua deleted file mode 100644 index 20e848a5d..000000000 --- a/path_10_8/data/spells/scripts/monster/undead dragon curse.lua +++ /dev/null @@ -1,24 +0,0 @@ -local combat = {} - -for i = 30, 50 do - local condition = Condition(CONDITION_CURSED) - condition:setParameter(CONDITION_PARAM_DELAYED, true) - - local damage = i - condition:addDamage(1, 4000, -damage) - for j = 1, 9 do - damage = damage * 1.2 - condition:addDamage(1, 4000, -damage) - end - - combat[i] = Combat() - combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) - combat[i]:setArea(createCombatArea(AREA_SQUAREWAVE7)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(30, 50)]:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/vulcongra soulfire.lua b/path_10_8/data/spells/scripts/monster/vulcongra soulfire.lua deleted file mode 100644 index d56c65ec5..000000000 --- a/path_10_8/data/spells/scripts/monster/vulcongra soulfire.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_FIRE) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(20, 9000, -10) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITBYFIRE) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/war golem electrify.lua b/path_10_8/data/spells/scripts/monster/war golem electrify.lua deleted file mode 100644 index 630922952..000000000 --- a/path_10_8/data/spells/scripts/monster/war golem electrify.lua +++ /dev/null @@ -1,12 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) - -local condition = Condition(CONDITION_ENERGY) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(8, 10000, -25) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/war golem skill reducer.lua b/path_10_8/data/spells/scripts/monster/war golem skill reducer.lua deleted file mode 100644 index af28828b6..000000000 --- a/path_10_8/data/spells/scripts/monster/war golem skill reducer.lua +++ /dev/null @@ -1,12 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 3000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 70) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STUN) -combat:setArea(createCombatArea(AREA_BEAM8)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/werewolf skill reducer.lua b/path_10_8/data/spells/scripts/monster/werewolf skill reducer.lua deleted file mode 100644 index ceaa58e67..000000000 --- a/path_10_8/data/spells/scripts/monster/werewolf skill reducer.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 65) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 65) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_DRAWBLOOD) -combat:setArea(createCombatArea(AREA_BEAM1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/monster/young sea serpent drown.lua b/path_10_8/data/spells/scripts/monster/young sea serpent drown.lua deleted file mode 100644 index 93d9fb5b5..000000000 --- a/path_10_8/data/spells/scripts/monster/young sea serpent drown.lua +++ /dev/null @@ -1,13 +0,0 @@ -local condition = Condition(CONDITION_DROWN) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(6, 5000, -20) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_WATERSPLASH) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/party/enchant.lua b/path_10_8/data/spells/scripts/party/enchant.lua deleted file mode 100644 index b58e636cf..000000000 --- a/path_10_8/data/spells/scripts/party/enchant.lua +++ /dev/null @@ -1,66 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_SUBID, 3) -condition:setParameter(CONDITION_PARAM_TICKS, 2 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_STAT_MAGICPOINTS, 1) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) - -local baseMana = 120 -function onCastSpell(creature, variant, isHotkey) - local position = creature:getPosition() - - local party = creature:getParty() - if not party then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local membersList = party:getMembers() - membersList[#membersList + 1] = party:getLeader() - if membersList == nil or type(membersList) ~= 'table' or #membersList <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local affectedList = {} - for _, targetPlayer in ipairs(membersList) do - if targetPlayer:getPosition():getDistance(position) <= 36 then - affectedList[#affectedList + 1] = targetPlayer - end - end - - local tmp = #affectedList - if tmp <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp) - if creature:getMana() < mana then - creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - if not combat:execute(creature, variant) then - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - creature:addMana(-(mana - baseMana), FALSE) - creature:addManaSpent((mana - baseMana)) - - for _, targetPlayer in ipairs(affectedList) do - targetPlayer:addCondition(condition) - end - - return true -end diff --git a/path_10_8/data/spells/scripts/party/heal.lua b/path_10_8/data/spells/scripts/party/heal.lua deleted file mode 100644 index 16a7d97b2..000000000 --- a/path_10_8/data/spells/scripts/party/heal.lua +++ /dev/null @@ -1,67 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -local condition = Condition(CONDITION_REGENERATION) -condition:setParameter(CONDITION_PARAM_SUBID, 1) -condition:setParameter(CONDITION_PARAM_TICKS, 2 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_HEALTHGAIN, 20) -condition:setParameter(CONDITION_PARAM_HEALTHTICKS, 2000) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) - -local baseMana = 120 -function onCastSpell(creature, variant, isHotkey) - local position = creature:getPosition() - - local party = creature:getParty() - if not party then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local membersList = party:getMembers() - membersList[#membersList + 1] = party:getLeader() - if membersList == nil or type(membersList) ~= 'table' or #membersList <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local affectedList = {} - for _, targetPlayer in ipairs(membersList) do - if targetPlayer:getPosition():getDistance(position) <= 36 then - affectedList[#affectedList + 1] = targetPlayer - end - end - - local tmp = #affectedList - if tmp <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp) - if creature:getMana() < mana then - creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - if not combat:execute(creature, variant) then - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - creature:addMana(-(mana - baseMana), false) - creature:addManaSpent((mana - baseMana)) - - for _, targetPlayer in ipairs(affectedList) do - targetPlayer:addCondition(condition) - end - - return true -end diff --git a/path_10_8/data/spells/scripts/party/protect.lua b/path_10_8/data/spells/scripts/party/protect.lua deleted file mode 100644 index 5943fe0af..000000000 --- a/path_10_8/data/spells/scripts/party/protect.lua +++ /dev/null @@ -1,66 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_SUBID, 2) -condition:setParameter(CONDITION_PARAM_TICKS, 2 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELD, 2) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) - -local baseMana = 90 -function onCastSpell(creature, variant, isHotkey) - local position = creature:getPosition() - - local party = creature:getParty() - if not party then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local membersList = party:getMembers() - membersList[#membersList + 1] = party:getLeader() - if membersList == nil or type(membersList) ~= 'table' or #membersList <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local affectedList = {} - for _, targetPlayer in ipairs(membersList) do - if targetPlayer:getPosition():getDistance(position) <= 36 then - affectedList[#affectedList + 1] = targetPlayer - end - end - - local tmp = #affectedList - if tmp <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp) - if creature:getMana() < mana then - creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - if not combat:execute(creature, variant) then - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - creature:addMana(-(mana - baseMana), false) - creature:addManaSpent((mana - baseMana)) - - for _, targetPlayer in ipairs(affectedList) do - targetPlayer:addCondition(condition) - end - - return true -end diff --git a/path_10_8/data/spells/scripts/party/train.lua b/path_10_8/data/spells/scripts/party/train.lua deleted file mode 100644 index 836ca2449..000000000 --- a/path_10_8/data/spells/scripts/party/train.lua +++ /dev/null @@ -1,67 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) -combat:setArea(createCombatArea(AREA_CROSS5X5)) - -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_SUBID, 1) -condition:setParameter(CONDITION_PARAM_TICKS, 2 * 60 * 1000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEE, 3) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCE, 3) -condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) - -local baseMana = 60 -function onCastSpell(creature, variant, isHotkey) - local position = creature:getPosition() - - local party = creature:getParty() - if not party then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local membersList = party:getMembers() - membersList[#membersList + 1] = party:getLeader() - if membersList == nil or type(membersList) ~= 'table' or #membersList <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local affectedList = {} - for _, targetPlayer in ipairs(membersList) do - if targetPlayer:getPosition():getDistance(position) <= 36 then - affectedList[#affectedList + 1] = targetPlayer - end - end - - local tmp = #affectedList - if tmp <= 1 then - creature:sendCancelMessage("No party members in range.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - local mana = math.ceil((0.9 ^ (tmp - 1) * baseMana) * tmp) - if creature:getMana() < mana then - creature:sendCancelMessage(RETURNVALUE_NOTENOUGHMANA) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - if not combat:execute(creature, variant) then - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - creature:addMana(-(mana - baseMana), FALSE) - creature:addManaSpent((mana - baseMana)) - - for _, targetPlayer in ipairs(affectedList) do - targetPlayer:addCondition(condition) - end - - return true -end diff --git a/path_10_8/data/spells/scripts/support/animate dead rune.lua b/path_10_8/data/spells/scripts/support/animate dead rune.lua deleted file mode 100644 index daa1dca62..000000000 --- a/path_10_8/data/spells/scripts/support/animate dead rune.lua +++ /dev/null @@ -1,23 +0,0 @@ -function onCastSpell(creature, variant, isHotkey) - local position = Variant.getPosition(variant) - local tile = Tile(position) - if tile and creature:getSkull() ~= SKULL_BLACK then - local corpse = tile:getTopDownItem() - if corpse then - local itemType = corpse:getType() - if itemType:isCorpse() and itemType:isMovable() then - local monster = Game.createMonster("Skeleton", position) - if monster then - corpse:remove() - monster:setMaster(creature) - position:sendMagicEffect(CONST_ME_MAGIC_BLUE) - return true - end - end - end - end - - creature:getPosition():sendMagicEffect(CONST_ME_POFF) - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - return false -end diff --git a/path_10_8/data/spells/scripts/support/cancel invisibility.lua b/path_10_8/data/spells/scripts/support/cancel invisibility.lua deleted file mode 100644 index 1137dce45..000000000 --- a/path_10_8/data/spells/scripts/support/cancel invisibility.lua +++ /dev/null @@ -1,8 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISPEL, CONDITION_INVISIBLE) -combat:setArea(createCombatArea(AREA_CIRCLE3X3)) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/challenge.lua b/path_10_8/data/spells/scripts/support/challenge.lua deleted file mode 100644 index 348a3a7ad..000000000 --- a/path_10_8/data/spells/scripts/support/challenge.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setArea(createCombatArea(AREA_SQUARE1X1)) - -function onTargetCreature(creature, target) - return doChallengeCreature(creature, target) -end - -combat:setCallback(CALLBACK_PARAM_TARGETCREATURE, "onTargetCreature") - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/charge.lua b/path_10_8/data/spells/scripts/support/charge.lua deleted file mode 100644 index 63a183ee5..000000000 --- a/path_10_8/data/spells/scripts/support/charge.lua +++ /dev/null @@ -1,12 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_HASTE) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setFormula(0.9, -72, 0.9, -72) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/desintegrate rune.lua b/path_10_8/data/spells/scripts/support/desintegrate rune.lua deleted file mode 100644 index 21d538b25..000000000 --- a/path_10_8/data/spells/scripts/support/desintegrate rune.lua +++ /dev/null @@ -1,30 +0,0 @@ -local dead_human = {3058, 3059, 3060, 3061, 3064, 3065, 3066} - -function onCastSpell(creature, variant, isHotkey) - local position = Variant.getPosition(variant) - local tile = Tile(position) - local targetItem = tile and tile:getTopVisibleThing() - - if targetItem and not targetItem:isCreature() then - local desintegrate = false - while not desintegrate - and not isInArray(dead_human, targetItem:getId()) - and targetItem:getType():isMovable() - and targetItem:getUniqueId() > 65535 - and targetItem:getActionId() == 0 - do - targetItem:remove() - desintegrate = true - targetItem = tile:getTopVisibleThing() - end - - if desintegrate then - position:sendMagicEffect(CONST_ME_BLOCKHIT) - return true - end - end - - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - creature:getPosition():sendMagicEffect(CONST_ME_POFF) - return false -end diff --git a/path_10_8/data/spells/scripts/support/destroy field rune.lua b/path_10_8/data/spells/scripts/support/destroy field rune.lua deleted file mode 100644 index d6ccc1162..000000000 --- a/path_10_8/data/spells/scripts/support/destroy field rune.lua +++ /dev/null @@ -1,15 +0,0 @@ -function onCastSpell(creature, variant, isHotkey) - local position = Variant.getPosition(variant) - local tile = Tile(position) - local field = tile and tile:getItemByType(ITEM_TYPE_MAGICFIELD) - - if field and isInArray(FIELDS, field:getId()) then - field:remove() - position:sendMagicEffect(CONST_ME_POFF) - return true - end - - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - creature:getPosition():sendMagicEffect(CONST_ME_POFF) - return false -end diff --git a/path_10_8/data/spells/scripts/support/food.lua b/path_10_8/data/spells/scripts/support/food.lua deleted file mode 100644 index 4b7a37081..000000000 --- a/path_10_8/data/spells/scripts/support/food.lua +++ /dev/null @@ -1,19 +0,0 @@ -local food = { - 2666, -- meat - 2671, -- ham - 2681, -- grape - 2674, -- apple - 2689, -- bread - 2690, -- roll - 2696 -- cheese -} - -function onCastSpell(creature, variant) - creature:addItem(food[math.random(#food)]) - if math.random(1, 100) > 50 then - creature:addItem(food[math.random(#food)]) - end - - creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) - return true -end diff --git a/path_10_8/data/spells/scripts/support/great light.lua b/path_10_8/data/spells/scripts/support/great light.lua deleted file mode 100644 index 8eea28af1..000000000 --- a/path_10_8/data/spells/scripts/support/great light.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_LIGHT) -condition:setParameter(CONDITION_PARAM_LIGHT_LEVEL, 8) -condition:setParameter(CONDITION_PARAM_LIGHT_COLOR, 215) -condition:setParameter(CONDITION_PARAM_TICKS, (11 * 60 + 35) * 1000) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/haste.lua b/path_10_8/data/spells/scripts/support/haste.lua deleted file mode 100644 index 51aca5baa..000000000 --- a/path_10_8/data/spells/scripts/support/haste.lua +++ /dev/null @@ -1,12 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_HASTE) -condition:setParameter(CONDITION_PARAM_TICKS, 33000) -condition:setFormula(0.3, -24, 0.3, -24) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/invisible.lua b/path_10_8/data/spells/scripts/support/invisible.lua deleted file mode 100644 index c5d1eec86..000000000 --- a/path_10_8/data/spells/scripts/support/invisible.lua +++ /dev/null @@ -1,11 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_INVISIBLE) -condition:setParameter(CONDITION_PARAM_TICKS, 200000) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/light.lua b/path_10_8/data/spells/scripts/support/light.lua deleted file mode 100644 index 591bf912b..000000000 --- a/path_10_8/data/spells/scripts/support/light.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_LIGHT) -condition:setParameter(CONDITION_PARAM_LIGHT_LEVEL, 6) -condition:setParameter(CONDITION_PARAM_LIGHT_COLOR, 215) -condition:setParameter(CONDITION_PARAM_TICKS, (6 * 60 + 10) * 1000) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/magic rope.lua b/path_10_8/data/spells/scripts/support/magic rope.lua deleted file mode 100644 index 012311df6..000000000 --- a/path_10_8/data/spells/scripts/support/magic rope.lua +++ /dev/null @@ -1,18 +0,0 @@ -function onCastSpell(creature, variant) - local position = creature:getPosition() - position:sendMagicEffect(CONST_ME_POFF) - - local tile = Tile(position) - if isInArray(ropeSpots, tile:getGround():getId()) or tile:getItemById(14435) then - tile = Tile(position:moveUpstairs()) - if tile then - creature:teleportTo(position, false) - position:sendMagicEffect(CONST_ME_TELEPORT) - else - creature:sendCancelMessage(RETURNVALUE_NOTENOUGHROOM) - end - else - creature:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE) - end - return true -end diff --git a/path_10_8/data/spells/scripts/support/magic shield.lua b/path_10_8/data/spells/scripts/support/magic shield.lua deleted file mode 100644 index adf714704..000000000 --- a/path_10_8/data/spells/scripts/support/magic shield.lua +++ /dev/null @@ -1,11 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_MANASHIELD) -condition:setParameter(CONDITION_PARAM_TICKS, 200000) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/magic wall rune.lua b/path_10_8/data/spells/scripts/support/magic wall rune.lua deleted file mode 100644 index 79c26ee0c..000000000 --- a/path_10_8/data/spells/scripts/support/magic wall rune.lua +++ /dev/null @@ -1,7 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_MAGICWALL) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/paralyze rune.lua b/path_10_8/data/spells/scripts/support/paralyze rune.lua deleted file mode 100644 index 4e76c6b35..000000000 --- a/path_10_8/data/spells/scripts/support/paralyze rune.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) - -local condition = Condition(CONDITION_PARALYZE) -condition:setParameter(CONDITION_PARAM_TICKS, 20000) -condition:setFormula(-0.9, 0, -0.9, 0) -combat:setCondition(condition) - -function onCastSpell(creature, variant, isHotkey) - if not combat:execute(creature, variant) then - return false - end - - creature:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) - return true -end diff --git a/path_10_8/data/spells/scripts/support/protector.lua b/path_10_8/data/spells/scripts/support/protector.lua deleted file mode 100644 index 3d9ddc91f..000000000 --- a/path_10_8/data/spells/scripts/support/protector.lua +++ /dev/null @@ -1,22 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local skill = Condition(CONDITION_ATTRIBUTES) -skill:setParameter(CONDITION_PARAM_TICKS, 13000) -skill:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 220) -skill:setParameter(CONDITION_PARAM_BUFF_SPELL, true) -combat:setCondition(skill) - -local cooldownAttackGroup = Condition(CONDITION_SPELLGROUPCOOLDOWN) -cooldownAttackGroup:setParameter(CONDITION_PARAM_SUBID, 1) -cooldownAttackGroup:setParameter(CONDITION_PARAM_TICKS, 10000) -combat:setCondition(cooldownAttackGroup) - -local pacified = Condition(CONDITION_PACIFIED) -pacified:setParameter(CONDITION_PARAM_TICKS, 10000) -combat:setCondition(pacified) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/sharpshooter.lua b/path_10_8/data/spells/scripts/support/sharpshooter.lua deleted file mode 100644 index e1168cbb7..000000000 --- a/path_10_8/data/spells/scripts/support/sharpshooter.lua +++ /dev/null @@ -1,29 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local skill = Condition(CONDITION_ATTRIBUTES) -skill:setParameter(CONDITION_PARAM_TICKS, 10000) -skill:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 150) -skill:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, -100) -skill:setParameter(CONDITION_PARAM_BUFF_SPELL, true) -combat:setCondition(skill) - -local speed = Condition(CONDITION_HASTE) -speed:setParameter(CONDITION_PARAM_TICKS, 10000) -speed:setFormula(-0.7, 56, -0.7, 56) -combat:setCondition(speed) - -local cooldownHealingGroup = Condition(CONDITION_SPELLGROUPCOOLDOWN) -cooldownHealingGroup:setParameter(CONDITION_PARAM_TICKS, 10000) -cooldownHealingGroup:setParameter(CONDITION_PARAM_SUBID, 2) -combat:setCondition(cooldownHealingGroup) - -local cooldownSupportGroup = Condition(CONDITION_SPELLGROUPCOOLDOWN) -cooldownSupportGroup:setParameter(CONDITION_PARAM_TICKS, 10000) -cooldownSupportGroup:setParameter(CONDITION_PARAM_SUBID, 3) -combat:setCondition(cooldownSupportGroup) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/strong haste.lua b/path_10_8/data/spells/scripts/support/strong haste.lua deleted file mode 100644 index 3a02eadc6..000000000 --- a/path_10_8/data/spells/scripts/support/strong haste.lua +++ /dev/null @@ -1,12 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_HASTE) -condition:setParameter(CONDITION_PARAM_TICKS, 22000) -condition:setFormula(0.7, -56, 0.7, -56) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/swift foot.lua b/path_10_8/data/spells/scripts/support/swift foot.lua deleted file mode 100644 index d710bc7d4..000000000 --- a/path_10_8/data/spells/scripts/support/swift foot.lua +++ /dev/null @@ -1,21 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local speed = Condition(CONDITION_HASTE) -speed:setParameter(CONDITION_PARAM_TICKS, 10000) -speed:setFormula(0.8, -72, 0.8, -72) -combat:setCondition(speed) - -local cooldownAttackGroup = Condition(CONDITION_SPELLGROUPCOOLDOWN) -cooldownAttackGroup:setParameter(CONDITION_PARAM_SUBID, 1) -cooldownAttackGroup:setParameter(CONDITION_PARAM_TICKS, 10000) -combat:setCondition(cooldownAttackGroup) - -local pacified = Condition(CONDITION_PACIFIED) -pacified:setParameter(CONDITION_PARAM_TICKS, 10000) -combat:setCondition(pacified) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/ultimate light.lua b/path_10_8/data/spells/scripts/support/ultimate light.lua deleted file mode 100644 index cea27680f..000000000 --- a/path_10_8/data/spells/scripts/support/ultimate light.lua +++ /dev/null @@ -1,13 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) - -local condition = Condition(CONDITION_LIGHT) -condition:setParameter(CONDITION_PARAM_LIGHT_LEVEL, 8) -condition:setParameter(CONDITION_PARAM_LIGHT_COLOR, 215) -condition:setParameter(CONDITION_PARAM_TICKS, (60 * 33 + 10) * 1000) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/scripts/support/wild growth rune.lua b/path_10_8/data/spells/scripts/support/wild growth rune.lua deleted file mode 100644 index c22683de1..000000000 --- a/path_10_8/data/spells/scripts/support/wild growth rune.lua +++ /dev/null @@ -1,7 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) -combat:setParameter(COMBAT_PARAM_CREATEITEM, ITEM_WILDGROWTH) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_10_8/data/spells/spells.xml b/path_10_8/data/spells/spells.xml deleted file mode 100644 index 513eca9d3..000000000 --- a/path_10_8/data/spells/spells.xml +++ /dev/null @@ -1,795 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/talkactions/lib/talkactions.lua b/path_10_8/data/talkactions/lib/talkactions.lua deleted file mode 100644 index 585eb19d6..000000000 --- a/path_10_8/data/talkactions/lib/talkactions.lua +++ /dev/null @@ -1 +0,0 @@ --- Nothing -- diff --git a/path_10_8/data/talkactions/scripts/add_skill.lua b/path_10_8/data/talkactions/scripts/add_skill.lua deleted file mode 100644 index 613ed0e5d..000000000 --- a/path_10_8/data/talkactions/scripts/add_skill.lua +++ /dev/null @@ -1,65 +0,0 @@ -local function getSkillId(skillName) - if skillName == "club" then - return SKILL_CLUB - elseif skillName == "sword" then - return SKILL_SWORD - elseif skillName == "axe" then - return SKILL_AXE - elseif skillName:sub(1, 4) == "dist" then - return SKILL_DISTANCE - elseif skillName:sub(1, 6) == "shield" then - return SKILL_SHIELD - elseif skillName:sub(1, 4) == "fish" then - return SKILL_FISHING - else - return SKILL_FIST - end -end - -local function getExpForLevel(level) - level = level - 1 - return ((50 * level * level * level) - (150 * level * level) + (400 * level)) / 3 -end - -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local split = param:split(",") - if split[2] == nil then - player:sendCancelMessage("Insufficient parameters.") - return false - end - - local target = Player(split[1]) - if target == nil then - player:sendCancelMessage("A player with that name is not online.") - return false - end - - -- Trim left - split[2] = split[2]:gsub("^%s*(.-)$", "%1") - - local count = 1 - if split[3] ~= nil then - count = tonumber(split[3]) - end - - local ch = split[2]:sub(1, 1) - for i = 1, count do - if ch == "l" or ch == "e" then - target:addExperience(getExpForLevel(target:getLevel() + 1) - target:getExperience(), false) - elseif ch == "m" then - target:addManaSpent(target:getVocation():getRequiredManaSpent(target:getBaseMagicLevel() + 1) - target:getManaSpent()) - else - local skillId = getSkillId(split[2]) - target:addSkillTries(skillId, target:getVocation():getRequiredSkillTries(skillId, target:getSkillLevel(skillId) + 1) - target:getSkillTries(skillId)) - end - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/add_tutor.lua b/path_10_8/data/talkactions/scripts/add_tutor.lua deleted file mode 100644 index 621b6e8df..000000000 --- a/path_10_8/data/talkactions/scripts/add_tutor.lua +++ /dev/null @@ -1,21 +0,0 @@ -function onSay(player, words, param) - if player:getAccountType() <= ACCOUNT_TYPE_TUTOR then - return true - end - - local target = Player(param) - if target == nil then - player:sendCancelMessage("A player with that name is not online.") - return false - end - - if target:getAccountType() ~= ACCOUNT_TYPE_NORMAL then - player:sendCancelMessage("You can only promote a normal player to a tutor.") - return false - end - - target:setAccountType(ACCOUNT_TYPE_TUTOR) - target:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have been promoted to a tutor by " .. player:getName() .. ".") - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have promoted " .. target:getName() .. " to a tutor.") - return false -end diff --git a/path_10_8/data/talkactions/scripts/animationeffect.lua b/path_10_8/data/talkactions/scripts/animationeffect.lua deleted file mode 100644 index ba55558ce..000000000 --- a/path_10_8/data/talkactions/scripts/animationeffect.lua +++ /dev/null @@ -1,29 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local effect = tonumber(param) - local position = player:getPosition() - local toPositionLow = {z = position.z} - local toPositionHigh = {z = position.z} - - toPositionLow.x = position.x - 7 - toPositionHigh.x = position.x + 7 - for i = -5, 5 do - toPositionLow.y = position.y + i - toPositionHigh.y = toPositionLow.y - position:sendDistanceEffect(toPositionLow, effect) - position:sendDistanceEffect(toPositionHigh, effect) - end - - toPositionLow.y = position.y - 5 - toPositionHigh.y = position.y + 5 - for i = -6, 6 do - toPositionLow.x = position.x + i - toPositionHigh.x = toPositionLow.x - position:sendDistanceEffect(toPositionLow, effect) - position:sendDistanceEffect(toPositionHigh, effect) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/ban.lua b/path_10_8/data/talkactions/scripts/ban.lua deleted file mode 100644 index fc46763f0..000000000 --- a/path_10_8/data/talkactions/scripts/ban.lua +++ /dev/null @@ -1,39 +0,0 @@ -local banDays = 7 - -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local name = param - local reason = '' - - local separatorPos = param:find(',') - if separatorPos ~= nil then - name = param:sub(0, separatorPos - 1) - reason = string.trim(param:sub(separatorPos + 1)) - end - - local accountId = getAccountNumberByPlayerName(name) - if accountId == 0 then - return false - end - - local resultId = db.storeQuery("SELECT 1 FROM `account_bans` WHERE `account_id` = " .. accountId) - if resultId ~= false then - result.free(resultId) - return false - end - - local timeNow = os.time() - db.query("INSERT INTO `account_bans` (`account_id`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" .. - accountId .. ", " .. db.escapeString(reason) .. ", " .. timeNow .. ", " .. timeNow + (banDays * 86400) .. ", " .. player:getGuid() .. ")") - - local target = Player(name) - if target ~= nil then - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, target:getName() .. " has been banned.") - target:remove() - else - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, name .. " has been banned.") - end -end diff --git a/path_10_8/data/talkactions/scripts/broadcast.lua b/path_10_8/data/talkactions/scripts/broadcast.lua deleted file mode 100644 index 1b7a1420b..000000000 --- a/path_10_8/data/talkactions/scripts/broadcast.lua +++ /dev/null @@ -1,11 +0,0 @@ -function onSay(player, words, param) - if not getPlayerFlagValue(player, PlayerFlag_CanBroadcast) then - return true - end - - print("> " .. player:getName() .. " broadcasted: \"" .. param .. "\".") - for _, targetPlayer in ipairs(Game.getPlayers()) do - targetPlayer:sendPrivateMessage(player, param, TALKTYPE_BROADCAST) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/buyhouse.lua b/path_10_8/data/talkactions/scripts/buyhouse.lua deleted file mode 100644 index 58e0c4545..000000000 --- a/path_10_8/data/talkactions/scripts/buyhouse.lua +++ /dev/null @@ -1,41 +0,0 @@ -function onSay(player, words, param) - local housePrice = configManager.getNumber(configKeys.HOUSE_PRICE) - if housePrice == -1 then - return true - end - - if not player:isPremium() then - player:sendCancelMessage("You need a premium account.") - return false - end - - local position = player:getPosition() - position:getNextPosition(player:getDirection()) - - local tile = Tile(position) - local house = tile and tile:getHouse() - if house == nil then - player:sendCancelMessage("You have to be looking at the door of the house you would like to buy.") - return false - end - - if house:getOwnerGuid() > 0 then - player:sendCancelMessage("This house already has an owner.") - return false - end - - if player:getHouse() then - player:sendCancelMessage("You are already the owner of a house.") - return false - end - - local price = house:getTileCount() * housePrice - if not player:removeMoney(price) then - player:sendCancelMessage("You do not have enough money.") - return false - end - - house:setOwnerGuid(player:getGuid()) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully bought this house, be sure to have the money for the rent in the bank.") - return false -end diff --git a/path_10_8/data/talkactions/scripts/buyprem.lua b/path_10_8/data/talkactions/scripts/buyprem.lua deleted file mode 100644 index 1aa4f5f0e..000000000 --- a/path_10_8/data/talkactions/scripts/buyprem.lua +++ /dev/null @@ -1,25 +0,0 @@ -local config = { - days = 90, - maxDays = 365, - price = 10000 -} - -function onSay(player, words, param) - if configManager.getBoolean(configKeys.FREE_PREMIUM) then - return true - end - - if player:getPremiumDays() <= config.maxDays then - if player:removeMoney(config.price) then - player:addPremiumDays(config.days) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have bought " .. config.days .." days of premium account.") - else - player:sendCancelMessage("You don't have enough money, " .. config.maxDays .. " days premium account costs " .. config.price .. " gold coins.") - player:getPosition():sendMagicEffect(CONST_ME_POFF) - end - else - player:sendCancelMessage("You can not buy more than " .. config.maxDays .. " days of premium account.") - player:getPosition():sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/chameleon.lua b/path_10_8/data/talkactions/scripts/chameleon.lua deleted file mode 100644 index d3fcbe2f7..000000000 --- a/path_10_8/data/talkactions/scripts/chameleon.lua +++ /dev/null @@ -1,25 +0,0 @@ -local condition = Condition(CONDITION_OUTFIT, CONDITIONID_COMBAT) -condition:setTicks(-1) - -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local itemType = ItemType(param) - if itemType:getId() == 0 then - itemType = ItemType(tonumber(param)) - if itemType:getId() == 0 then - player:sendCancelMessage("There is no item with that id or name.") - return false - end - end - - condition:setOutfit(itemType:getId()) - player:addCondition(condition) - return false -end diff --git a/path_10_8/data/talkactions/scripts/changesex.lua b/path_10_8/data/talkactions/scripts/changesex.lua deleted file mode 100644 index 3b71fe0cc..000000000 --- a/path_10_8/data/talkactions/scripts/changesex.lua +++ /dev/null @@ -1,19 +0,0 @@ -local premiumDaysCost = 3 - -function onSay(player, words, param) - if player:getGroup():getAccess() then - player:setSex(player:getSex() == PLAYERSEX_FEMALE and PLAYERSEX_MALE or PLAYERSEX_FEMALE) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have changed your sex.") - return false - end - - if player:getPremiumDays() >= premiumDaysCost then - player:removePremiumDays(premiumDaysCost) - player:setSex(player:getSex() == PLAYERSEX_FEMALE and PLAYERSEX_MALE or PLAYERSEX_FEMALE) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have changed your sex for " .. premiumDaysCost .. " days of your premium account.") - else - player:sendCancelMessage("You do not have enough premium days, changing sex costs " .. premiumDaysCost .. " days of your premium account.") - player:getPosition():sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/clean.lua b/path_10_8/data/talkactions/scripts/clean.lua deleted file mode 100644 index 0d5f7aa95..000000000 --- a/path_10_8/data/talkactions/scripts/clean.lua +++ /dev/null @@ -1,15 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local itemCount = cleanMap() - if itemCount > 0 then - player:sendTextMessage(MESSAGE_STATUS_WARNING, "Cleaned " .. itemCount .. " item" .. (itemCount > 1 and "s" or "") .. " from the map.") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/closeserver.lua b/path_10_8/data/talkactions/scripts/closeserver.lua deleted file mode 100644 index 2f7c95ec3..000000000 --- a/path_10_8/data/talkactions/scripts/closeserver.lua +++ /dev/null @@ -1,17 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - if param == "shutdown" then - Game.setGameState(GAME_STATE_SHUTDOWN) - else - Game.setGameState(GAME_STATE_CLOSED) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server is now closed.") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/create_item.lua b/path_10_8/data/talkactions/scripts/create_item.lua deleted file mode 100644 index 1a7bf4148..000000000 --- a/path_10_8/data/talkactions/scripts/create_item.lua +++ /dev/null @@ -1,52 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local split = param:split(",") - - local itemType = ItemType(split[1]) - if itemType:getId() == 0 then - itemType = ItemType(tonumber(split[1])) - if itemType:getId() == 0 then - player:sendCancelMessage("There is no item with that id or name.") - return false - end - end - - local count = tonumber(split[2]) - if count ~= nil then - if itemType:isStackable() then - count = math.min(10000, math.max(1, count)) - elseif not itemType:isFluidContainer() then - count = math.min(100, math.max(1, count)) - else - count = math.max(0, count) - end - else - if not itemType:isFluidContainer() then - count = 1 - else - count = 0 - end - end - - local result = player:addItem(itemType:getId(), count) - if result ~= nil then - if not itemType:isStackable() then - if type(result) == "table" then - for _, item in ipairs(result) do - item:decay() - end - else - result:decay() - end - end - player:getPosition():sendMagicEffect(CONST_ME_MAGIC_GREEN) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/deathlist.lua b/path_10_8/data/talkactions/scripts/deathlist.lua deleted file mode 100644 index c1066a960..000000000 --- a/path_10_8/data/talkactions/scripts/deathlist.lua +++ /dev/null @@ -1,62 +0,0 @@ -local function getArticle(str) - return str:find("[AaEeIiOoUuYy]") == 1 and "an" or "a" -end - -local function getMonthDayEnding(day) - if day == "01" or day == "21" or day == "31" then - return "st" - elseif day == "02" or day == "22" then - return "nd" - elseif day == "03" or day == "23" then - return "rd" - else - return "th" - end -end - -local function getMonthString(m) - return os.date("%B", os.time{year = 1970, month = m, day = 1}) -end - -function onSay(player, words, param) - local resultId = db.storeQuery("SELECT `id`, `name` FROM `players` WHERE `name` = " .. db.escapeString(param)) - if resultId ~= false then - local targetGUID = result.getDataInt(resultId, "id") - local targetName = result.getDataString(resultId, "name") - result.free(resultId) - local str = "" - local breakline = "" - - local resultId = db.storeQuery("SELECT `time`, `level`, `killed_by`, `is_player` FROM `player_deaths` WHERE `player_id` = " .. targetGUID .. " ORDER BY `time` DESC") - if resultId ~= false then - repeat - if str ~= "" then - breakline = "\n" - end - local date = os.date("*t", result.getDataInt(resultId, "time")) - - local article = "" - local killed_by = result.getDataString(resultId, "killed_by") - if result.getDataInt(resultId, "is_player") == 0 then - article = getArticle(killed_by) .. " " - killed_by = string.lower(killed_by) - end - - if date.day < 10 then date.day = "0" .. date.day end - if date.hour < 10 then date.hour = "0" .. date.hour end - if date.min < 10 then date.min = "0" .. date.min end - if date.sec < 10 then date.sec = "0" .. date.sec end - str = str .. breakline .. " " .. date.day .. getMonthDayEnding(date.day) .. " " .. getMonthString(date.month) .. " " .. date.year .. " " .. date.hour .. ":" .. date.min .. ":" .. date.sec .. " Died at Level " .. result.getDataInt(resultId, "level") .. " by " .. article .. killed_by .. "." - until not result.next(resultId) - result.free(resultId) - end - - if str == "" then - str = "No deaths." - end - player:popupFYI("Deathlist for player, " .. targetName .. ".\n\n" .. str) - else - player:sendCancelMessage("A player with that name does not exist.") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/down.lua b/path_10_8/data/talkactions/scripts/down.lua deleted file mode 100644 index 460e0c490..000000000 --- a/path_10_8/data/talkactions/scripts/down.lua +++ /dev/null @@ -1,10 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local position = player:getPosition() - position.z = position.z + 1 - player:teleportTo(position) - return false -end diff --git a/path_10_8/data/talkactions/scripts/ghost.lua b/path_10_8/data/talkactions/scripts/ghost.lua deleted file mode 100644 index fa1fe48b0..000000000 --- a/path_10_8/data/talkactions/scripts/ghost.lua +++ /dev/null @@ -1,23 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local position = player:getPosition() - local isGhost = not player:isInGhostMode() - - player:setGhostMode(isGhost) - if isGhost then - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are now invisible.") - position:sendMagicEffect(CONST_ME_YALAHARIGHOST) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are visible again.") - position.x = position.x + 1 - position:sendMagicEffect(CONST_ME_SMOKE) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/hide.lua b/path_10_8/data/talkactions/scripts/hide.lua deleted file mode 100644 index 1e84352f2..000000000 --- a/path_10_8/data/talkactions/scripts/hide.lua +++ /dev/null @@ -1,12 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - player:setHiddenHealth(not player:isHealthHidden()) - return false -end diff --git a/path_10_8/data/talkactions/scripts/info.lua b/path_10_8/data/talkactions/scripts/info.lua deleted file mode 100644 index 8969b1cae..000000000 --- a/path_10_8/data/talkactions/scripts/info.lua +++ /dev/null @@ -1,37 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local target = Player(param) - if not target then - player:sendCancelMessage("Player not found.") - return false - end - - if target:getAccountType() > player:getAccountType() then - player:sendCancelMessage("You can not get info about this player.") - return false - end - - local targetIp = target:getIp() - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Name: " .. target:getName()) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Access: " .. (target:getGroup():getAccess() and "1" or "0")) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Level: " .. target:getLevel()) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Magic Level: " .. target:getMagicLevel()) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Speed: " .. target:getSpeed()) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Position: " .. string.format("(%0.5d / %0.5d / %0.3d)", target:getPosition().x, target:getPosition().y, target:getPosition().z)) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "IP: " .. Game.convertIpToString(targetIp)) - - local players = {} - for _, targetPlayer in ipairs(Game.getPlayers()) do - if targetPlayer:getIp() == targetIp and targetPlayer ~= target then - players[#players + 1] = targetPlayer:getName() .. " [" .. targetPlayer:getLevel() .. "]" - end - end - - if #players > 0 then - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Other players on same IP: " .. table.concat(players, ", ") .. ".") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/ipban.lua b/path_10_8/data/talkactions/scripts/ipban.lua deleted file mode 100644 index 1a393e2a9..000000000 --- a/path_10_8/data/talkactions/scripts/ipban.lua +++ /dev/null @@ -1,36 +0,0 @@ -local ipBanDays = 7 - -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local resultId = db.storeQuery("SELECT `account_id`, `lastip` FROM `players` WHERE `name` = " .. db.escapeString(param)) - if resultId == false then - return false - end - - local targetIp = result.getDataLong(resultId, "lastip") - result.free(resultId) - - local targetPlayer = Player(param) - if targetPlayer then - targetIp = targetPlayer:getIp() - targetPlayer:remove() - end - - if targetIp == 0 then - return false - end - - resultId = db.storeQuery("SELECT 1 FROM `ip_bans` WHERE `ip` = " .. targetIp) - if resultId ~= false then - result.free(resultId) - return false - end - - local timeNow = os.time() - db.query("INSERT INTO `ip_bans` (`ip`, `reason`, `banned_at`, `expires_at`, `banned_by`) VALUES (" .. - targetIp .. ", '', " .. timeNow .. ", " .. timeNow + (ipBanDays * 86400) .. ", " .. player:getGuid() .. ")") - return false -end diff --git a/path_10_8/data/talkactions/scripts/kick.lua b/path_10_8/data/talkactions/scripts/kick.lua deleted file mode 100644 index 67f8ec4aa..000000000 --- a/path_10_8/data/talkactions/scripts/kick.lua +++ /dev/null @@ -1,19 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local target = Player(param) - if target == nil then - player:sendCancelMessage("Player not found.") - return false - end - - if target:getGroup():getAccess() then - player:sendCancelMessage("You cannot kick this player.") - return false - end - - target:remove() - return false -end diff --git a/path_10_8/data/talkactions/scripts/kills.lua b/path_10_8/data/talkactions/scripts/kills.lua deleted file mode 100644 index 98dd37cc9..000000000 --- a/path_10_8/data/talkactions/scripts/kills.lua +++ /dev/null @@ -1,46 +0,0 @@ -function onSay(player, words, param) - local fragTime = configManager.getNumber(configKeys.FRAG_TIME) - if fragTime <= 0 then - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You do not have any unjustified kill.") - return false - end - - local skullTime = player:getSkullTime() - if skullTime <= 0 then - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You do not have any unjustified kill.") - return false - end - - local kills = math.ceil(skullTime / fragTime) - local remainingSeconds = math.floor((skullTime % fragTime) / 1000) - - local hours = math.floor(remainingSeconds / 3600) - local minutes = math.floor((remainingSeconds % 3600) / 60) - local seconds = remainingSeconds % 60 - - local message = "You have " .. kills .. " unjustified kill" .. (kills > 1 and "s" or "") .. ". The amount of unjustified kills will decrease after: " - if hours ~= 0 then - if hours == 1 then - message = message .. hours .. " hour, " - else - message = message .. hours .. " hours, " - end - end - - if hours ~= 0 or minutes ~= 0 then - if minutes == 1 then - message = message .. minutes .. " minute and " - else - message = message .. minutes .. " minutes and " - end - end - - if seconds == 1 then - message = message .. seconds .. " second." - else - message = message .. seconds .. " seconds." - end - - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, message) - return false -end diff --git a/path_10_8/data/talkactions/scripts/leavehouse.lua b/path_10_8/data/talkactions/scripts/leavehouse.lua deleted file mode 100644 index 18938cc7c..000000000 --- a/path_10_8/data/talkactions/scripts/leavehouse.lua +++ /dev/null @@ -1,21 +0,0 @@ -function onSay(player, words, param) - local position = player:getPosition() - local tile = Tile(position) - local house = tile and tile:getHouse() - if house == nil then - player:sendCancelMessage("You are not inside a house.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - if house:getOwnerGuid() ~= player:getGuid() then - player:sendCancelMessage("You are not the owner of this house.") - position:sendMagicEffect(CONST_ME_POFF) - return false - end - - house:setOwnerGuid(0) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully left your house.") - position:sendMagicEffect(CONST_ME_POFF) - return false -end diff --git a/path_10_8/data/talkactions/scripts/looktype.lua b/path_10_8/data/talkactions/scripts/looktype.lua deleted file mode 100644 index 1a1b11dc9..000000000 --- a/path_10_8/data/talkactions/scripts/looktype.lua +++ /dev/null @@ -1,15 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local lookType = tonumber(param) - if lookType >= 0 and lookType ~= 1 and lookType ~= 135 and lookType ~= 411 and lookType ~= 415 and lookType ~= 424 and (lookType <= 160 or lookType >= 192) and lookType ~= 439 and lookType ~= 440 and lookType ~= 468 and lookType ~= 469 and (lookType < 474 or lookType > 485) and lookType ~= 501 and lookType ~= 518 and lookType ~= 519 and lookType ~= 520 and lookType ~= 524 and lookType ~= 525 and lookType ~= 536 and lookType ~= 543 and lookType ~= 549 and lookType ~= 576 and lookType ~= 581 and lookType ~= 582 and lookType ~= 597 and lookType ~= 616 and lookType ~= 623 and lookType ~= 625 and (lookType <= 637 or lookType >= 644) and (lookType <= 644 or lookType >= 647) and (lookType <= 651 or lookType >= 664) and lookType <= 699 then - local playerOutfit = player:getOutfit() - playerOutfit.lookType = lookType - player:setOutfit(playerOutfit) - else - player:sendCancelMessage("A look type with that id does not exist.") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/magiceffect.lua b/path_10_8/data/talkactions/scripts/magiceffect.lua deleted file mode 100644 index ebc26b3ec..000000000 --- a/path_10_8/data/talkactions/scripts/magiceffect.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - player:getPosition():sendMagicEffect(tonumber(param)) - return false -end diff --git a/path_10_8/data/talkactions/scripts/mccheck.lua b/path_10_8/data/talkactions/scripts/mccheck.lua deleted file mode 100644 index 13ffbc970..000000000 --- a/path_10_8/data/talkactions/scripts/mccheck.lua +++ /dev/null @@ -1,40 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Multiclient Check List:") - - local ipList = {} - local players = Game.getPlayers() - for i = 1, #players do - local tmpPlayer = players[i] - local ip = tmpPlayer:getIp() - if ip ~= 0 then - local list = ipList[ip] - if not list then - ipList[ip] = {} - list = ipList[ip] - end - list[#list + 1] = tmpPlayer - end - end - - for ip, list in pairs(ipList) do - local listLength = #list - if listLength > 1 then - local tmpPlayer = list[1] - local message = ("%s: %s [%d]"):format(Game.convertIpToString(ip), tmpPlayer:getName(), tmpPlayer:getLevel()) - for i = 2, listLength do - tmpPlayer = list[i] - message = ("%s, %s [%d]"):format(message, tmpPlayer:getName(), tmpPlayer:getLevel()) - end - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, message .. ".") - end - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/online.lua b/path_10_8/data/talkactions/scripts/online.lua deleted file mode 100644 index da1c1a4bd..000000000 --- a/path_10_8/data/talkactions/scripts/online.lua +++ /dev/null @@ -1,36 +0,0 @@ -function onSay(player, words, param) - local hasAccess = player:getGroup():getAccess() - local players = Game.getPlayers() - local playerCount = Game.getPlayerCount() - - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, playerCount .. " players online.") - - local i = 0 - local msg = "" - for k, targetPlayer in ipairs(players) do - if hasAccess or not targetPlayer:isInGhostMode() then - if i > 0 then - msg = msg .. ", " - end - msg = msg .. targetPlayer:getName() .. " [" .. targetPlayer:getLevel() .. "]" - i = i + 1 - end - - if i == 10 then - if k == playerCount then - msg = msg .. "." - else - msg = msg .. "," - end - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg) - msg = "" - i = 0 - end - end - - if i > 0 then - msg = msg .. "." - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/openserver.lua b/path_10_8/data/talkactions/scripts/openserver.lua deleted file mode 100644 index c3896e728..000000000 --- a/path_10_8/data/talkactions/scripts/openserver.lua +++ /dev/null @@ -1,13 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - Game.setGameState(GAME_STATE_NORMAL) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server is now open.") - return false -end diff --git a/path_10_8/data/talkactions/scripts/owner.lua b/path_10_8/data/talkactions/scripts/owner.lua deleted file mode 100644 index d56f4897b..000000000 --- a/path_10_8/data/talkactions/scripts/owner.lua +++ /dev/null @@ -1,30 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local tile = Tile(player:getPosition()) - local house = tile and tile:getHouse() - if house == nil then - player:sendCancelMessage("You are not inside a house.") - return false - end - - if param == "" or param == "none" then - house:setOwnerGuid(0) - return false - end - - local targetPlayer = Player(param) - if targetPlayer == nil then - player:sendCancelMessage("Player not found.") - return false - end - - house:setOwnerGuid(targetPlayer:getGuid()) - return false -end diff --git a/path_10_8/data/talkactions/scripts/place_monster.lua b/path_10_8/data/talkactions/scripts/place_monster.lua deleted file mode 100644 index 8446c0b01..000000000 --- a/path_10_8/data/talkactions/scripts/place_monster.lua +++ /dev/null @@ -1,20 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local position = player:getPosition() - local monster = Game.createMonster(param, position) - if monster ~= nil then - monster:getPosition():sendMagicEffect(CONST_ME_TELEPORT) - position:sendMagicEffect(CONST_ME_MAGIC_RED) - else - player:sendCancelMessage("There is not enough room.") - position:sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/place_npc.lua b/path_10_8/data/talkactions/scripts/place_npc.lua deleted file mode 100644 index aaf6ef6e5..000000000 --- a/path_10_8/data/talkactions/scripts/place_npc.lua +++ /dev/null @@ -1,20 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local position = player:getPosition() - local npc = Game.createNpc(param, position) - if npc ~= nil then - npc:setMasterPos(position) - position:sendMagicEffect(CONST_ME_MAGIC_RED) - else - player:sendCancelMessage("There is not enough room.") - position:sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/place_summon.lua b/path_10_8/data/talkactions/scripts/place_summon.lua deleted file mode 100644 index f511d2083..000000000 --- a/path_10_8/data/talkactions/scripts/place_summon.lua +++ /dev/null @@ -1,20 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - if player:getAccountType() < ACCOUNT_TYPE_GOD then - return false - end - - local position = player:getPosition() - local monster = Game.createMonster(param, position) - if monster ~= nil then - monster:setMaster(player) - position:sendMagicEffect(CONST_ME_MAGIC_RED) - else - player:sendCancelMessage("There is not enough room.") - position:sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/position.lua b/path_10_8/data/talkactions/scripts/position.lua deleted file mode 100644 index 299ce6e56..000000000 --- a/path_10_8/data/talkactions/scripts/position.lua +++ /dev/null @@ -1,10 +0,0 @@ -function onSay(player, words, param) - if player:getGroup():getAccess() and param ~= "" then - local split = param:split(",") - player:teleportTo(Position(split[1], split[2], split[3])) - else - local position = player:getPosition() - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your current position is: " .. position.x .. ", " .. position.y .. ", " .. position.z .. ".") - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/remove_tutor.lua b/path_10_8/data/talkactions/scripts/remove_tutor.lua deleted file mode 100644 index 27b0bdb1b..000000000 --- a/path_10_8/data/talkactions/scripts/remove_tutor.lua +++ /dev/null @@ -1,27 +0,0 @@ -function onSay(player, words, param) - if player:getAccountType() <= ACCOUNT_TYPE_TUTOR then - return true - end - - local resultId = db.storeQuery("SELECT `name`, `account_id`, (SELECT `type` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `account_type` FROM `players` WHERE `name` = " .. db.escapeString(param)) - if resultId == false then - player:sendCancelMessage("A player with that name does not exist.") - return false - end - - if result.getDataInt(resultId, "account_type") ~= ACCOUNT_TYPE_TUTOR then - player:sendCancelMessage("You can only demote a tutor to a normal player.") - return false - end - - local target = Player(param) - if target ~= nil then - target:setAccountType(ACCOUNT_TYPE_NORMAL) - else - db.query("UPDATE `accounts` SET `type` = " .. ACCOUNT_TYPE_NORMAL .. " WHERE `id` = " .. result.getDataInt(resultId, "account_id")) - end - - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have demoted " .. result.getDataString(resultId, "name") .. " to a normal player.") - result.free(resultId) - return false -end diff --git a/path_10_8/data/talkactions/scripts/removething.lua b/path_10_8/data/talkactions/scripts/removething.lua deleted file mode 100644 index 8216e03ba..000000000 --- a/path_10_8/data/talkactions/scripts/removething.lua +++ /dev/null @@ -1,33 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local position = player:getPosition() - position:getNextPosition(player:getDirection()) - - local tile = Tile(position) - if not tile then - player:sendCancelMessage("Object not found.") - return false - end - - local thing = tile:getTopVisibleThing(player) - if not thing then - player:sendCancelMessage("Thing not found.") - return false - end - - if thing:isCreature() then - thing:remove() - elseif thing:isItem() then - if thing == tile:getGround() then - player:sendCancelMessage("You may not remove a ground tile.") - return false - end - thing:remove(tonumber(param) or -1) - end - - position:sendMagicEffect(CONST_ME_MAGIC_RED) - return false -end diff --git a/path_10_8/data/talkactions/scripts/serverinfo.lua b/path_10_8/data/talkactions/scripts/serverinfo.lua deleted file mode 100644 index 6b26b9814..000000000 --- a/path_10_8/data/talkactions/scripts/serverinfo.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onSay(player, words, param) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Server Info:" - .. "\nExp rate: " .. Game.getExperienceStage(player:getLevel()) - .. "\nSkill rate: " .. configManager.getNumber(configKeys.RATE_SKILL) - .. "\nMagic rate: " .. configManager.getNumber(configKeys.RATE_MAGIC) - .. "\nLoot rate: " .. configManager.getNumber(configKeys.RATE_LOOT)) - return false -end diff --git a/path_10_8/data/talkactions/scripts/teleport_creature_here.lua b/path_10_8/data/talkactions/scripts/teleport_creature_here.lua deleted file mode 100644 index ea3691991..000000000 --- a/path_10_8/data/talkactions/scripts/teleport_creature_here.lua +++ /dev/null @@ -1,24 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local creature = Creature(param) - if not creature then - player:sendCancelMessage("A creature with that name could not be found.") - return false - end - - local oldPosition = creature:getPosition() - local newPosition = creature:getClosestFreePosition(player:getPosition(), false) - if newPosition.x == 0 then - player:sendCancelMessage("You can not teleport " .. creature:getName() .. ".") - return false - elseif creature:teleportTo(newPosition) then - if not creature:isInGhostMode() then - oldPosition:sendMagicEffect(CONST_ME_POFF) - newPosition:sendMagicEffect(CONST_ME_TELEPORT) - end - end - return false -end diff --git a/path_10_8/data/talkactions/scripts/teleport_home.lua b/path_10_8/data/talkactions/scripts/teleport_home.lua deleted file mode 100644 index 64852301d..000000000 --- a/path_10_8/data/talkactions/scripts/teleport_home.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - player:teleportTo(player:getTown():getTemplePosition()) - return false -end diff --git a/path_10_8/data/talkactions/scripts/teleport_ntiles.lua b/path_10_8/data/talkactions/scripts/teleport_ntiles.lua deleted file mode 100644 index 28cbccb0f..000000000 --- a/path_10_8/data/talkactions/scripts/teleport_ntiles.lua +++ /dev/null @@ -1,22 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local steps = tonumber(param) - if not steps then - return false - end - - local position = player:getPosition() - position:getNextPosition(player:getDirection(), steps) - - position = player:getClosestFreePosition(position, false) - if position.x == 0 then - player:sendCancelMessage("You cannot teleport there.") - return false - end - - player:teleportTo(position) - return false -end diff --git a/path_10_8/data/talkactions/scripts/teleport_to_creature.lua b/path_10_8/data/talkactions/scripts/teleport_to_creature.lua deleted file mode 100644 index 17a7da995..000000000 --- a/path_10_8/data/talkactions/scripts/teleport_to_creature.lua +++ /dev/null @@ -1,14 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local target = Creature(param) - if target == nil then - player:sendCancelMessage("Creature not found.") - return false - end - - player:teleportTo(target:getPosition()) - return false -end diff --git a/path_10_8/data/talkactions/scripts/teleport_to_town.lua b/path_10_8/data/talkactions/scripts/teleport_to_town.lua deleted file mode 100644 index c7525ed11..000000000 --- a/path_10_8/data/talkactions/scripts/teleport_to_town.lua +++ /dev/null @@ -1,14 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local town = Town(param) - if town == nil then - player:sendCancelMessage("Town not found.") - return false - end - - player:teleportTo(town:getTemplePosition()) - return false -end diff --git a/path_10_8/data/talkactions/scripts/unban.lua b/path_10_8/data/talkactions/scripts/unban.lua deleted file mode 100644 index b65c4c705..000000000 --- a/path_10_8/data/talkactions/scripts/unban.lua +++ /dev/null @@ -1,16 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local resultId = db.storeQuery("SELECT `account_id`, `lastip` FROM `players` WHERE `name` = " .. db.escapeString(param)) - if resultId == false then - return false - end - - db.asyncQuery("DELETE FROM `account_bans` WHERE `account_id` = " .. result.getDataInt(resultId, "account_id")) - db.asyncQuery("DELETE FROM `ip_bans` WHERE `ip` = " .. result.getDataInt(resultId, "lastip")) - result.free(resultId) - player:sendTextMessage(MESSAGE_EVENT_ADVANCE, param .. " has been unbanned.") - return false -end diff --git a/path_10_8/data/talkactions/scripts/up.lua b/path_10_8/data/talkactions/scripts/up.lua deleted file mode 100644 index c48bfd726..000000000 --- a/path_10_8/data/talkactions/scripts/up.lua +++ /dev/null @@ -1,10 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local position = player:getPosition() - position.z = position.z - 1 - player:teleportTo(position) - return false -end diff --git a/path_10_8/data/talkactions/scripts/uptime.lua b/path_10_8/data/talkactions/scripts/uptime.lua deleted file mode 100644 index 7c0e291ed..000000000 --- a/path_10_8/data/talkactions/scripts/uptime.lua +++ /dev/null @@ -1,8 +0,0 @@ -function onSay(player, words, param) - local uptime = getWorldUpTime() - - local hours = math.floor(uptime / 3600) - local minutes = math.floor((uptime - (3600 * hours)) / 60) - player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Uptime: " .. hours .. " hours and " .. minutes .. " minutes.") - return false -end diff --git a/path_10_8/data/talkactions/talkactions.xml b/path_10_8/data/talkactions/talkactions.xml deleted file mode 100644 index 486868cc9..000000000 --- a/path_10_8/data/talkactions/talkactions.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/weapons/lib/weapons.lua b/path_10_8/data/weapons/lib/weapons.lua deleted file mode 100644 index e69de29bb..000000000 diff --git a/path_10_8/data/weapons/scripts/burst_arrow.lua b/path_10_8/data/weapons/scripts/burst_arrow.lua deleted file mode 100644 index eb8290173..000000000 --- a/path_10_8/data/weapons/scripts/burst_arrow.lua +++ /dev/null @@ -1,17 +0,0 @@ -local area = createCombatArea({ - {1, 1, 1}, - {1, 3, 1}, - {1, 1, 1} -}) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_BURSTARROW) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) -combat:setArea(area) - -function onUseWeapon(player, variant) - return combat:execute(player, variant) -end diff --git a/path_10_8/data/weapons/scripts/poison_arrow.lua b/path_10_8/data/weapons/scripts/poison_arrow.lua deleted file mode 100644 index 2e0f64a62..000000000 --- a/path_10_8/data/weapons/scripts/poison_arrow.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_POISONARROW) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) - -local condition = Condition(CONDITION_POISON) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(4, 4000, -3) -condition:addDamage(9, 4000, -2) -condition:addDamage(20, 4000, -1) -combat:setCondition(condition) - -function onUseWeapon(player, variant) - return combat:execute(player, variant) -end diff --git a/path_10_8/data/weapons/scripts/viper_star.lua b/path_10_8/data/weapons/scripts/viper_star.lua deleted file mode 100644 index 023325818..000000000 --- a/path_10_8/data/weapons/scripts/viper_star.lua +++ /dev/null @@ -1,29 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_GREENSTAR) -combat:setParameter(COMBAT_PARAM_BLOCKARMOR, true) -combat:setFormula(COMBAT_FORMULA_SKILL, 0, 0, 1, 0) - -local condition = Condition(CONDITION_POISON) -condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(10, 4000, -2) -condition:addDamage(20, 4000, -1) - -local secondCombat = Combat() -secondCombat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -secondCombat:setCondition(condition) - -function onUseWeapon(player, variant) - local boolean = combat:execute(player, variant) - if not boolean then - return false - end - - local target = variant:getNumber() - if target ~= 0 then - if math.random(1, 100) > 90 then - boolean = secondCombat:execute(player, variant) - end - end - return boolean -end diff --git a/path_10_8/data/weapons/weapons.xml b/path_10_8/data/weapons/weapons.xml deleted file mode 100644 index 7c921df73..000000000 --- a/path_10_8/data/weapons/weapons.xml +++ /dev/null @@ -1,697 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/world/forgotten-house.xml b/path_10_8/data/world/forgotten-house.xml deleted file mode 100644 index 25aa10d7a..000000000 --- a/path_10_8/data/world/forgotten-house.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/world/forgotten-spawn.xml b/path_10_8/data/world/forgotten-spawn.xml deleted file mode 100644 index ae5b3c842..000000000 --- a/path_10_8/data/world/forgotten-spawn.xml +++ /dev/null @@ -1,1550 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_10_8/data/world/forgotten.otbm b/path_10_8/data/world/forgotten.otbm deleted file mode 100644 index e2f70373e..000000000 Binary files a/path_10_8/data/world/forgotten.otbm and /dev/null differ diff --git a/path_10_8/schema.sql b/path_10_8/schema.sql deleted file mode 100644 index 804f1c746..000000000 --- a/path_10_8/schema.sql +++ /dev/null @@ -1,348 +0,0 @@ -CREATE TABLE IF NOT EXISTS `accounts` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(32) NOT NULL, - `password` char(40) NOT NULL, - `type` int(11) NOT NULL DEFAULT '1', - `premdays` int(11) NOT NULL DEFAULT '0', - `lastday` int(10) unsigned NOT NULL DEFAULT '0', - `email` varchar(255) NOT NULL DEFAULT '', - `creation` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `players` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(255) NOT NULL, - `group_id` int(11) NOT NULL DEFAULT '1', - `account_id` int(11) NOT NULL DEFAULT '0', - `level` int(11) NOT NULL DEFAULT '1', - `vocation` int(11) NOT NULL DEFAULT '0', - `health` int(11) NOT NULL DEFAULT '150', - `healthmax` int(11) NOT NULL DEFAULT '150', - `experience` bigint(20) NOT NULL DEFAULT '0', - `lookbody` int(11) NOT NULL DEFAULT '0', - `lookfeet` int(11) NOT NULL DEFAULT '0', - `lookhead` int(11) NOT NULL DEFAULT '0', - `looklegs` int(11) NOT NULL DEFAULT '0', - `looktype` int(11) NOT NULL DEFAULT '136', - `lookaddons` int(11) NOT NULL DEFAULT '0', - `maglevel` int(11) NOT NULL DEFAULT '0', - `mana` int(11) NOT NULL DEFAULT '0', - `manamax` int(11) NOT NULL DEFAULT '0', - `manaspent` int(11) unsigned NOT NULL DEFAULT '0', - `soul` int(10) unsigned NOT NULL DEFAULT '0', - `town_id` int(11) NOT NULL DEFAULT '0', - `posx` int(11) NOT NULL DEFAULT '0', - `posy` int(11) NOT NULL DEFAULT '0', - `posz` int(11) NOT NULL DEFAULT '0', - `conditions` blob NOT NULL, - `cap` int(11) NOT NULL DEFAULT '0', - `sex` int(11) NOT NULL DEFAULT '0', - `lastlogin` bigint(20) unsigned NOT NULL DEFAULT '0', - `lastip` int(10) unsigned NOT NULL DEFAULT '0', - `save` tinyint(1) NOT NULL DEFAULT '1', - `skull` tinyint(1) NOT NULL DEFAULT '0', - `skulltime` int(11) NOT NULL DEFAULT '0', - `lastlogout` bigint(20) unsigned NOT NULL DEFAULT '0', - `blessings` tinyint(2) NOT NULL DEFAULT '0', - `onlinetime` int(11) NOT NULL DEFAULT '0', - `deletion` bigint(15) NOT NULL DEFAULT '0', - `balance` bigint(20) unsigned NOT NULL DEFAULT '0', - `offlinetraining_time` smallint(5) unsigned NOT NULL DEFAULT '43200', - `offlinetraining_skill` int(11) NOT NULL DEFAULT '-1', - `stamina` smallint(5) unsigned NOT NULL DEFAULT '2520', - `skill_fist` int(10) unsigned NOT NULL DEFAULT 10, - `skill_fist_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_club` int(10) unsigned NOT NULL DEFAULT 10, - `skill_club_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_sword` int(10) unsigned NOT NULL DEFAULT 10, - `skill_sword_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_axe` int(10) unsigned NOT NULL DEFAULT 10, - `skill_axe_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_dist` int(10) unsigned NOT NULL DEFAULT 10, - `skill_dist_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_shielding` int(10) unsigned NOT NULL DEFAULT 10, - `skill_shielding_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - `skill_fishing` int(10) unsigned NOT NULL DEFAULT 10, - `skill_fishing_tries` bigint(20) unsigned NOT NULL DEFAULT 0, - PRIMARY KEY (`id`), - UNIQUE KEY `name` (`name`), - FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE, - KEY `vocation` (`vocation`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `account_bans` ( - `account_id` int(11) NOT NULL, - `reason` varchar(255) NOT NULL, - `banned_at` bigint(20) NOT NULL, - `expires_at` bigint(20) NOT NULL, - `banned_by` int(11) NOT NULL, - PRIMARY KEY (`account_id`), - FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `account_ban_history` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `account_id` int(11) NOT NULL, - `reason` varchar(255) NOT NULL, - `banned_at` bigint(20) NOT NULL, - `expired_at` bigint(20) NOT NULL, - `banned_by` int(11) NOT NULL, - PRIMARY KEY (`id`), - FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `ip_bans` ( - `ip` int(10) unsigned NOT NULL, - `reason` varchar(255) NOT NULL, - `banned_at` bigint(20) NOT NULL, - `expires_at` bigint(20) NOT NULL, - `banned_by` int(11) NOT NULL, - PRIMARY KEY (`ip`), - FOREIGN KEY (`banned_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_namelocks` ( - `player_id` int(11) NOT NULL, - `reason` varchar(255) NOT NULL, - `namelocked_at` bigint(20) NOT NULL, - `namelocked_by` int(11) NOT NULL, - PRIMARY KEY (`player_id`), - FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY (`namelocked_by`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `account_viplist` ( - `account_id` int(11) NOT NULL COMMENT 'id of account whose viplist entry it is', - `player_id` int(11) NOT NULL COMMENT 'id of target player of viplist entry', - `description` varchar(128) NOT NULL DEFAULT '', - `icon` tinyint(2) unsigned NOT NULL DEFAULT '0', - `notify` tinyint(1) NOT NULL DEFAULT '0', - UNIQUE KEY `account_player_index` (`account_id`,`player_id`), - FOREIGN KEY (`account_id`) REFERENCES `accounts` (`id`) ON DELETE CASCADE, - FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guilds` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(255) NOT NULL, - `ownerid` int(11) NOT NULL, - `creationdata` int(11) NOT NULL, - `motd` varchar(255) NOT NULL DEFAULT '', - PRIMARY KEY (`id`), - UNIQUE KEY (`name`), - UNIQUE KEY (`ownerid`), - FOREIGN KEY (`ownerid`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guild_invites` ( - `player_id` int(11) NOT NULL DEFAULT '0', - `guild_id` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`player_id`,`guild_id`), - FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE, - FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guild_ranks` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `guild_id` int(11) NOT NULL COMMENT 'guild', - `name` varchar(255) NOT NULL COMMENT 'rank name', - `level` int(11) NOT NULL COMMENT 'rank level - leader, vice, member, maybe something else', - PRIMARY KEY (`id`), - FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guild_membership` ( - `player_id` int(11) NOT NULL, - `guild_id` int(11) NOT NULL, - `rank_id` int(11) NOT NULL, - `nick` varchar(15) NOT NULL DEFAULT '', - PRIMARY KEY (`player_id`), - FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY (`guild_id`) REFERENCES `guilds` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, - FOREIGN KEY (`rank_id`) REFERENCES `guild_ranks` (`id`) ON DELETE CASCADE ON UPDATE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guild_wars` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `guild1` int(11) NOT NULL DEFAULT '0', - `guild2` int(11) NOT NULL DEFAULT '0', - `name1` varchar(255) NOT NULL, - `name2` varchar(255) NOT NULL, - `status` tinyint(2) NOT NULL DEFAULT '0', - `started` bigint(15) NOT NULL DEFAULT '0', - `ended` bigint(15) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - KEY `guild1` (`guild1`), - KEY `guild2` (`guild2`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `guildwar_kills` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `killer` varchar(50) NOT NULL, - `target` varchar(50) NOT NULL, - `killerguild` int(11) NOT NULL DEFAULT '0', - `targetguild` int(11) NOT NULL DEFAULT '0', - `warid` int(11) NOT NULL DEFAULT '0', - `time` bigint(15) NOT NULL, - PRIMARY KEY (`id`), - FOREIGN KEY (`warid`) REFERENCES `guild_wars` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `houses` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `owner` int(11) NOT NULL, - `paid` int(10) unsigned NOT NULL DEFAULT '0', - `warnings` int(11) NOT NULL DEFAULT '0', - `name` varchar(255) NOT NULL, - `rent` int(11) NOT NULL DEFAULT '0', - `town_id` int(11) NOT NULL DEFAULT '0', - `bid` int(11) NOT NULL DEFAULT '0', - `bid_end` int(11) NOT NULL DEFAULT '0', - `last_bid` int(11) NOT NULL DEFAULT '0', - `highest_bidder` int(11) NOT NULL DEFAULT '0', - `size` int(11) NOT NULL DEFAULT '0', - `beds` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - KEY `owner` (`owner`), - KEY `town_id` (`town_id`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `house_lists` ( - `house_id` int(11) NOT NULL, - `listid` int(11) NOT NULL, - `list` text NOT NULL, - FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `market_history` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `player_id` int(11) NOT NULL, - `sale` tinyint(1) NOT NULL DEFAULT '0', - `itemtype` int(10) unsigned NOT NULL, - `amount` smallint(5) unsigned NOT NULL, - `price` int(10) unsigned NOT NULL DEFAULT '0', - `expires_at` bigint(20) unsigned NOT NULL, - `inserted` bigint(20) unsigned NOT NULL, - `state` tinyint(1) unsigned NOT NULL, - PRIMARY KEY (`id`), - KEY `player_id` (`player_id`, `sale`), - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `market_offers` ( - `id` int(10) unsigned NOT NULL AUTO_INCREMENT, - `player_id` int(11) NOT NULL, - `sale` tinyint(1) NOT NULL DEFAULT '0', - `itemtype` int(10) unsigned NOT NULL, - `amount` smallint(5) unsigned NOT NULL, - `created` bigint(20) unsigned NOT NULL, - `anonymous` tinyint(1) NOT NULL DEFAULT '0', - `price` int(10) unsigned NOT NULL DEFAULT '0', - PRIMARY KEY (`id`), - KEY `sale` (`sale`,`itemtype`), - KEY `created` (`created`), - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `players_online` ( - `player_id` int(11) NOT NULL, - PRIMARY KEY (`player_id`) -) ENGINE=MEMORY; - -CREATE TABLE IF NOT EXISTS `player_deaths` ( - `player_id` int(11) NOT NULL, - `time` bigint(20) unsigned NOT NULL DEFAULT '0', - `level` int(11) NOT NULL DEFAULT '1', - `killed_by` varchar(255) NOT NULL, - `is_player` tinyint(1) NOT NULL DEFAULT '1', - `mostdamage_by` varchar(100) NOT NULL, - `mostdamage_is_player` tinyint(1) NOT NULL DEFAULT '0', - `unjustified` tinyint(1) NOT NULL DEFAULT '0', - `mostdamage_unjustified` tinyint(1) NOT NULL DEFAULT '0', - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE, - KEY `killed_by` (`killed_by`), - KEY `mostdamage_by` (`mostdamage_by`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_depotitems` ( - `player_id` int(11) NOT NULL, - `sid` int(11) NOT NULL COMMENT 'any given range eg 0-100 will be reserved for depot lockers and all > 100 will be then normal items inside depots', - `pid` int(11) NOT NULL DEFAULT '0', - `itemtype` smallint(6) NOT NULL, - `count` smallint(5) NOT NULL DEFAULT '0', - `attributes` blob NOT NULL, - UNIQUE KEY `player_id_2` (`player_id`, `sid`), - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_inboxitems` ( - `player_id` int(11) NOT NULL, - `sid` int(11) NOT NULL, - `pid` int(11) NOT NULL DEFAULT '0', - `itemtype` smallint(6) NOT NULL, - `count` smallint(5) NOT NULL DEFAULT '0', - `attributes` blob NOT NULL, - UNIQUE KEY `player_id_2` (`player_id`, `sid`), - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_items` ( - `player_id` int(11) NOT NULL DEFAULT '0', - `pid` int(11) NOT NULL DEFAULT '0', - `sid` int(11) NOT NULL DEFAULT '0', - `itemtype` smallint(6) NOT NULL DEFAULT '0', - `count` smallint(5) NOT NULL DEFAULT '0', - `attributes` blob NOT NULL, - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE, - KEY `sid` (`sid`) -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_spells` ( - `player_id` int(11) NOT NULL, - `name` varchar(255) NOT NULL, - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `player_storage` ( - `player_id` int(11) NOT NULL DEFAULT '0', - `key` int(10) unsigned NOT NULL DEFAULT '0', - `value` int(11) NOT NULL DEFAULT '0', - PRIMARY KEY (`player_id`,`key`), - FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -CREATE TABLE IF NOT EXISTS `server_config` ( - `config` varchar(50) NOT NULL, - `value` varchar(256) NOT NULL DEFAULT '', - PRIMARY KEY `config` (`config`) -) ENGINE=InnoDB; - -INSERT INTO `server_config` (`config`, `value`) VALUES ('db_version', '18'), ('motd_hash', ''), ('motd_num', '0'), ('players_record', '0'); - -CREATE TABLE IF NOT EXISTS `tile_store` ( - `house_id` int(11) NOT NULL, - `data` longblob NOT NULL, - FOREIGN KEY (`house_id`) REFERENCES `houses` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB; - -DROP TRIGGER IF EXISTS `ondelete_players`; -DROP TRIGGER IF EXISTS `oncreate_guilds`; - -DELIMITER // -CREATE TRIGGER `ondelete_players` BEFORE DELETE ON `players` - FOR EACH ROW BEGIN - UPDATE `houses` SET `owner` = 0 WHERE `owner` = OLD.`id`; -END -// -CREATE TRIGGER `oncreate_guilds` AFTER INSERT ON `guilds` - FOR EACH ROW BEGIN - INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('the Leader', 3, NEW.`id`); - INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('a Vice-Leader', 2, NEW.`id`); - INSERT INTO `guild_ranks` (`name`, `level`, `guild_id`) VALUES ('a Member', 1, NEW.`id`); -END -// -DELIMITER ; diff --git a/path_10_8/src/CMakeLists.txt b/path_10_8/src/CMakeLists.txt deleted file mode 100644 index 335710195..000000000 --- a/path_10_8/src/CMakeLists.txt +++ /dev/null @@ -1,78 +0,0 @@ -set(tfs_SRC - ${CMAKE_CURRENT_LIST_DIR}/otpch.cpp - ${CMAKE_CURRENT_LIST_DIR}/actions.cpp - ${CMAKE_CURRENT_LIST_DIR}/ban.cpp - ${CMAKE_CURRENT_LIST_DIR}/baseevents.cpp - ${CMAKE_CURRENT_LIST_DIR}/bed.cpp - ${CMAKE_CURRENT_LIST_DIR}/chat.cpp - ${CMAKE_CURRENT_LIST_DIR}/combat.cpp - ${CMAKE_CURRENT_LIST_DIR}/commands.cpp - ${CMAKE_CURRENT_LIST_DIR}/condition.cpp - ${CMAKE_CURRENT_LIST_DIR}/configmanager.cpp - ${CMAKE_CURRENT_LIST_DIR}/connection.cpp - ${CMAKE_CURRENT_LIST_DIR}/container.cpp - ${CMAKE_CURRENT_LIST_DIR}/creature.cpp - ${CMAKE_CURRENT_LIST_DIR}/creatureevent.cpp - ${CMAKE_CURRENT_LIST_DIR}/cylinder.cpp - ${CMAKE_CURRENT_LIST_DIR}/database.cpp - ${CMAKE_CURRENT_LIST_DIR}/databasemanager.cpp - ${CMAKE_CURRENT_LIST_DIR}/databasetasks.cpp - ${CMAKE_CURRENT_LIST_DIR}/depotchest.cpp - ${CMAKE_CURRENT_LIST_DIR}/depotlocker.cpp - ${CMAKE_CURRENT_LIST_DIR}/events.cpp - ${CMAKE_CURRENT_LIST_DIR}/fileloader.cpp - ${CMAKE_CURRENT_LIST_DIR}/game.cpp - ${CMAKE_CURRENT_LIST_DIR}/globalevent.cpp - ${CMAKE_CURRENT_LIST_DIR}/guild.cpp - ${CMAKE_CURRENT_LIST_DIR}/groups.cpp - ${CMAKE_CURRENT_LIST_DIR}/house.cpp - ${CMAKE_CURRENT_LIST_DIR}/housetile.cpp - ${CMAKE_CURRENT_LIST_DIR}/inbox.cpp - ${CMAKE_CURRENT_LIST_DIR}/ioguild.cpp - ${CMAKE_CURRENT_LIST_DIR}/iologindata.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomap.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomapserialize.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomarket.cpp - ${CMAKE_CURRENT_LIST_DIR}/item.cpp - ${CMAKE_CURRENT_LIST_DIR}/items.cpp - ${CMAKE_CURRENT_LIST_DIR}/luascript.cpp - ${CMAKE_CURRENT_LIST_DIR}/mailbox.cpp - ${CMAKE_CURRENT_LIST_DIR}/map.cpp - ${CMAKE_CURRENT_LIST_DIR}/monster.cpp - ${CMAKE_CURRENT_LIST_DIR}/monsters.cpp - ${CMAKE_CURRENT_LIST_DIR}/mounts.cpp - ${CMAKE_CURRENT_LIST_DIR}/movement.cpp - ${CMAKE_CURRENT_LIST_DIR}/networkmessage.cpp - ${CMAKE_CURRENT_LIST_DIR}/npc.cpp - ${CMAKE_CURRENT_LIST_DIR}/otserv.cpp - ${CMAKE_CURRENT_LIST_DIR}/outfit.cpp - ${CMAKE_CURRENT_LIST_DIR}/outputmessage.cpp - ${CMAKE_CURRENT_LIST_DIR}/party.cpp - ${CMAKE_CURRENT_LIST_DIR}/player.cpp - ${CMAKE_CURRENT_LIST_DIR}/position.cpp - ${CMAKE_CURRENT_LIST_DIR}/protocol.cpp - ${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp - ${CMAKE_CURRENT_LIST_DIR}/protocollogin.cpp - ${CMAKE_CURRENT_LIST_DIR}/protocolold.cpp - ${CMAKE_CURRENT_LIST_DIR}/protocolstatus.cpp - ${CMAKE_CURRENT_LIST_DIR}/quests.cpp - ${CMAKE_CURRENT_LIST_DIR}/raids.cpp - ${CMAKE_CURRENT_LIST_DIR}/rsa.cpp - ${CMAKE_CURRENT_LIST_DIR}/scheduler.cpp - ${CMAKE_CURRENT_LIST_DIR}/scriptmanager.cpp - ${CMAKE_CURRENT_LIST_DIR}/server.cpp - ${CMAKE_CURRENT_LIST_DIR}/spawn.cpp - ${CMAKE_CURRENT_LIST_DIR}/spells.cpp - ${CMAKE_CURRENT_LIST_DIR}/talkaction.cpp - ${CMAKE_CURRENT_LIST_DIR}/tasks.cpp - ${CMAKE_CURRENT_LIST_DIR}/teleport.cpp - ${CMAKE_CURRENT_LIST_DIR}/thing.cpp - ${CMAKE_CURRENT_LIST_DIR}/tile.cpp - ${CMAKE_CURRENT_LIST_DIR}/tools.cpp - ${CMAKE_CURRENT_LIST_DIR}/trashholder.cpp - ${CMAKE_CURRENT_LIST_DIR}/vocation.cpp - ${CMAKE_CURRENT_LIST_DIR}/waitlist.cpp - ${CMAKE_CURRENT_LIST_DIR}/weapons.cpp - ${CMAKE_CURRENT_LIST_DIR}/wildcardtree.cpp -) - diff --git a/path_10_8/src/account.h b/path_10_8/src/account.h deleted file mode 100644 index 55bbd24d1..000000000 --- a/path_10_8/src/account.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ACCOUNT_H_34817537BA2B4CB7B71AA562AFBB118F -#define FS_ACCOUNT_H_34817537BA2B4CB7B71AA562AFBB118F - -#include "enums.h" - -struct Account { - std::vector characters; - std::string name; - time_t lastDay; - uint32_t id; - uint16_t premiumDays; - AccountType_t accountType; - - Account() : lastDay(0), id(0), premiumDays(0), accountType(ACCOUNT_TYPE_NORMAL) {} -}; - -#endif diff --git a/path_10_8/src/actions.cpp b/path_10_8/src/actions.cpp deleted file mode 100644 index 9d98352ec..000000000 --- a/path_10_8/src/actions.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "actions.h" -#include "bed.h" -#include "configmanager.h" -#include "container.h" -#include "game.h" -#include "pugicast.h" -#include "spells.h" - -extern Game g_game; -extern Spells* g_spells; -extern Actions* g_actions; -extern ConfigManager g_config; - -Actions::Actions() : - m_scriptInterface("Action Interface") -{ - m_scriptInterface.initState(); -} - -Actions::~Actions() -{ - clear(); -} - -inline void Actions::clearMap(ActionUseMap& map) -{ - // Filter out duplicates to avoid double-free - std::unordered_set set; - for (const auto& it : map) { - set.insert(it.second); - } - map.clear(); - - for (Action* action : set) { - delete action; - } -} - -void Actions::clear() -{ - clearMap(useItemMap); - clearMap(uniqueItemMap); - clearMap(actionItemMap); - - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& Actions::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string Actions::getScriptBaseName() const -{ - return "actions"; -} - -Event* Actions::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "action") != 0) { - return nullptr; - } - return new Action(&m_scriptInterface); -} - -bool Actions::registerEvent(Event* event, const pugi::xml_node& node) -{ - Action* action = static_cast(event); //event is guaranteed to be an Action - - pugi::xml_attribute attr; - if ((attr = node.attribute("itemid"))) { - uint16_t id = pugi::cast(attr.value()); - - auto result = useItemMap.emplace(id, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with id: " << id << std::endl; - } - return result.second; - } else if ((attr = node.attribute("fromid"))) { - pugi::xml_attribute toIdAttribute = node.attribute("toid"); - if (!toIdAttribute) { - std::cout << "[Warning - Actions::registerEvent] Missing toid in fromid: " << attr.as_string() << std::endl; - return false; - } - - uint16_t fromId = pugi::cast(attr.value()); - uint16_t iterId = fromId; - uint16_t toId = pugi::cast(toIdAttribute.value()); - - auto result = useItemMap.emplace(iterId, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with id: " << iterId << " in fromid: " << fromId << ", toid: " << toId << std::endl; - } - - bool success = result.second; - while (++iterId <= toId) { - result = useItemMap.emplace(iterId, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with id: " << iterId << " in fromid: " << fromId << ", toid: " << toId << std::endl; - continue; - } - success = true; - } - return success; - } else if ((attr = node.attribute("uniqueid"))) { - uint16_t uid = pugi::cast(attr.value()); - - auto result = uniqueItemMap.emplace(uid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with uniqueid: " << uid << std::endl; - } - return result.second; - } else if ((attr = node.attribute("fromuid"))) { - pugi::xml_attribute toUidAttribute = node.attribute("touid"); - if (!toUidAttribute) { - std::cout << "[Warning - Actions::registerEvent] Missing touid in fromuid: " << attr.as_string() << std::endl; - return false; - } - - uint16_t fromUid = pugi::cast(attr.value()); - uint16_t iterUid = fromUid; - uint16_t toUid = pugi::cast(toUidAttribute.value()); - - auto result = uniqueItemMap.emplace(iterUid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with unique id: " << iterUid << " in fromuid: " << fromUid << ", touid: " << toUid << std::endl; - } - - bool success = result.second; - while (++iterUid <= toUid) { - result = uniqueItemMap.emplace(iterUid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with unique id: " << iterUid << " in fromuid: " << fromUid << ", touid: " << toUid << std::endl; - continue; - } - success = true; - } - return success; - } else if ((attr = node.attribute("actionid"))) { - uint16_t aid = pugi::cast(attr.value()); - - auto result = actionItemMap.emplace(aid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with actionid: " << aid << std::endl; - } - return result.second; - } else if ((attr = node.attribute("fromaid"))) { - pugi::xml_attribute toAidAttribute = node.attribute("toaid"); - if (!toAidAttribute) { - std::cout << "[Warning - Actions::registerEvent] Missing toaid in fromaid: " << attr.as_string() << std::endl; - return false; - } - - uint16_t fromAid = pugi::cast(attr.value()); - uint16_t iterAid = fromAid; - uint16_t toAid = pugi::cast(toAidAttribute.value()); - - auto result = actionItemMap.emplace(iterAid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with action id: " << iterAid << " in fromaid: " << fromAid << ", toaid: " << toAid << std::endl; - } - - bool success = result.second; - while (++iterAid <= toAid) { - result = actionItemMap.emplace(iterAid, action); - if (!result.second) { - std::cout << "[Warning - Actions::registerEvent] Duplicate registered item with action id: " << iterAid << " in fromaid: " << fromAid << ", toaid: " << toAid << std::endl; - continue; - } - success = true; - } - return success; - } - return false; -} - -ReturnValue Actions::canUse(const Player* player, const Position& pos) -{ - if (pos.x != 0xFFFF) { - const Position& playerPos = player->getPosition(); - if (playerPos.z != pos.z) { - return playerPos.z > pos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS; - } - - if (!Position::areInRange<1, 1>(playerPos, pos)) { - return RETURNVALUE_TOOFARAWAY; - } - } - return RETURNVALUE_NOERROR; -} - -ReturnValue Actions::canUse(const Player* player, const Position& pos, const Item* item) -{ - Action* action = getAction(item); - if (action) { - return action->canExecuteAction(player, pos); - } - return RETURNVALUE_NOERROR; -} - -ReturnValue Actions::canUseFar(const Creature* creature, const Position& toPos, bool checkLineOfSight, bool checkFloor) -{ - if (toPos.x == 0xFFFF) { - return RETURNVALUE_NOERROR; - } - - const Position& creaturePos = creature->getPosition(); - if (checkFloor && creaturePos.z != toPos.z) { - return creaturePos.z > toPos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS; - } - - if (!Position::areInRange<7, 5>(toPos, creaturePos)) { - return RETURNVALUE_TOOFARAWAY; - } - - if (checkLineOfSight && !g_game.canThrowObjectTo(creaturePos, toPos)) { - return RETURNVALUE_CANNOTTHROW; - } - - return RETURNVALUE_NOERROR; -} - -Action* Actions::getAction(const Item* item) -{ - if (item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - auto it = uniqueItemMap.find(item->getUniqueId()); - if (it != uniqueItemMap.end()) { - return it->second; - } - } - - if (item->hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) { - auto it = actionItemMap.find(item->getActionId()); - if (it != actionItemMap.end()) { - return it->second; - } - } - - auto it = useItemMap.find(item->getID()); - if (it != useItemMap.end()) { - return it->second; - } - - //rune items - Action* runeSpell = g_spells->getRuneSpell(item->getID()); - if (runeSpell) { - return runeSpell; - } - return nullptr; -} - -ReturnValue Actions::internalUseItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey) -{ - if (Door* door = item->getDoor()) { - if (!door->canUse(player)) { - return RETURNVALUE_CANNOTUSETHISOBJECT; - } - } - - Action* action = getAction(item); - if (action) { - if (action->isScripted()) { - if (action->executeUse(player, item, pos, nullptr, pos, isHotkey)) { - return RETURNVALUE_NOERROR; - } - } else if (action->function) { - if (action->function(player, item, pos, nullptr, pos, isHotkey)) { - return RETURNVALUE_NOERROR; - } - } - } - - if (BedItem* bed = item->getBed()) { - if (!bed->canUse(player)) { - return RETURNVALUE_CANNOTUSETHISOBJECT; - } - - if (bed->trySleep(player)) { - player->setBedItem(bed); - g_game.sendOfflineTrainingDialog(player); - } - - return RETURNVALUE_NOERROR; - } - - if (Container* container = item->getContainer()) { - Container* openContainer; - - //depot container - if (DepotLocker* depot = container->getDepotLocker()) { - DepotLocker* myDepotLocker = player->getDepotLocker(depot->getDepotId()); - myDepotLocker->setParent(depot->getParent()->getTile()); - openContainer = myDepotLocker; - player->setLastDepotId(depot->getDepotId()); - } else { - openContainer = container; - } - - uint32_t corpseOwner = container->getCorpseOwner(); - if (corpseOwner != 0 && !player->canOpenCorpse(corpseOwner)) { - return RETURNVALUE_YOUARENOTTHEOWNER; - } - - //open/close container - int32_t oldContainerId = player->getContainerID(openContainer); - if (oldContainerId != -1) { - player->onCloseContainer(openContainer); - player->closeContainer(oldContainerId); - } else { - player->addContainer(index, openContainer); - player->onSendContainer(openContainer); - } - - return RETURNVALUE_NOERROR; - } - - const ItemType& it = Item::items[item->getID()]; - if (it.canReadText) { - if (it.canWriteText) { - player->setWriteItem(item, it.maxTextLen); - player->sendTextWindow(item, it.maxTextLen, true); - } else { - player->setWriteItem(nullptr); - player->sendTextWindow(item, 0, false); - } - - return RETURNVALUE_NOERROR; - } - - return RETURNVALUE_CANNOTUSETHISOBJECT; -} - -bool Actions::useItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey) -{ - player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL)); - player->stopWalk(); - - if (isHotkey) { - showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), -1)); - } - - ReturnValue ret = internalUseItem(player, pos, index, item, isHotkey); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - return false; - } - return true; -} - -bool Actions::useItemEx(Player* player, const Position& fromPos, const Position& toPos, - uint8_t toStackPos, Item* item, bool isHotkey, Creature* creature/* = nullptr*/) -{ - player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::EX_ACTIONS_DELAY_INTERVAL)); - player->stopWalk(); - - Action* action = getAction(item); - if (!action) { - player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); - return false; - } - - ReturnValue ret = action->canExecuteAction(player, toPos); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - return false; - } - - if (isHotkey) { - showUseHotkeyMessage(player, item, player->getItemTypeCount(item->getID(), -1)); - } - - if (!action->executeUse(player, item, fromPos, action->getTarget(player, creature, toPos, toStackPos), toPos, isHotkey)) { - if (!action->hasOwnErrorHandler()) { - player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); - } - return false; - } - return true; -} - -void Actions::showUseHotkeyMessage(Player* player, const Item* item, uint32_t count) -{ - std::ostringstream ss; - - const ItemType& it = Item::items[item->getID()]; - if (!it.showCount) { - ss << "Using one of " << item->getName() << "..."; - } else if (count == 1) { - ss << "Using the last " << item->getName() << "..."; - } else { - ss << "Using one of " << count << ' ' << item->getPluralName() << "..."; - } - player->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); -} - -Action::Action(LuaScriptInterface* _interface) : - Event(_interface) -{ - allowFarUse = false; - checkFloor = true; - checkLineOfSight = true; - function = nullptr; -} - -Action::Action(const Action* copy) : - Event(copy) -{ - allowFarUse = copy->allowFarUse; - checkFloor = copy->checkFloor; - checkLineOfSight = copy->checkLineOfSight; - function = copy->function; -} - -bool Action::configureEvent(const pugi::xml_node& node) -{ - pugi::xml_attribute allowFarUseAttr = node.attribute("allowfaruse"); - if (allowFarUseAttr) { - setAllowFarUse(allowFarUseAttr.as_bool()); - } - - pugi::xml_attribute blockWallsAttr = node.attribute("blockwalls"); - if (blockWallsAttr) { - setCheckLineOfSight(blockWallsAttr.as_bool()); - } - - pugi::xml_attribute checkFloorAttr = node.attribute("checkfloor"); - if (checkFloorAttr) { - setCheckFloor(checkFloorAttr.as_bool()); - } - - return true; -} - -bool Action::loadFunction(const pugi::xml_attribute& attr) -{ - const char* functionName = attr.as_string(); - if (strcasecmp(functionName, "increaseitemid") == 0) { - function = increaseItemId; - } else if (strcasecmp(functionName, "decreaseitemid") == 0) { - function = decreaseItemId; - } else if (strcasecmp(functionName, "market") == 0) { - function = enterMarket; - } else { - std::cout << "[Warning - Action::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - m_scripted = false; - return true; -} - -bool Action::increaseItemId(Player*, Item* item, const Position&, Thing*, const Position&, bool) -{ - g_game.startDecay(g_game.transformItem(item, item->getID() + 1)); - return true; -} - -bool Action::decreaseItemId(Player*, Item* item, const Position&, Thing*, const Position&, bool) -{ - g_game.startDecay(g_game.transformItem(item, item->getID() - 1)); - return true; -} - -bool Action::enterMarket(Player* player, Item*, const Position&, Thing*, const Position&, bool) -{ - if (player->getLastDepotId() == -1) { - return false; - } - - player->sendMarketEnter(player->getLastDepotId()); - return true; -} - -std::string Action::getScriptEventName() const -{ - return "onUse"; -} - -ReturnValue Action::canExecuteAction(const Player* player, const Position& toPos) -{ - if (!getAllowFarUse()) { - return g_actions->canUse(player, toPos); - } else { - return g_actions->canUseFar(player, toPos, getCheckLineOfSight(), getCheckFloor()); - } -} - -Thing* Action::getTarget(Player* player, Creature* targetCreature, const Position& toPosition, uint8_t toStackPos) const -{ - if (targetCreature) { - return targetCreature; - } - return g_game.internalGetThing(player, toPosition, toStackPos, 0, STACKPOS_USETARGET); -} - -bool Action::executeUse(Player* player, Item* item, const Position& fromPos, Thing* target, const Position& toPos, bool isHotkey) -{ - //onUse(player, item, fromPosition, target, toPosition, isHotkey) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Action::executeUse] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushPosition(L, fromPos); - - LuaScriptInterface::pushThing(L, target); - LuaScriptInterface::pushPosition(L, toPos); - - LuaScriptInterface::pushBoolean(L, isHotkey); - return m_scriptInterface->callFunction(6); -} diff --git a/path_10_8/src/actions.h b/path_10_8/src/actions.h deleted file mode 100644 index f7ec155e8..000000000 --- a/path_10_8/src/actions.h +++ /dev/null @@ -1,126 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ACTIONS_H_87F60C5F587E4B84948F304A6451E6E6 -#define FS_ACTIONS_H_87F60C5F587E4B84948F304A6451E6E6 - -#include "baseevents.h" -#include "enums.h" -#include "luascript.h" - -typedef bool (ActionFunction)(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition, bool isHotkey); - -class Action : public Event -{ - public: - explicit Action(const Action* copy); - explicit Action(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) override; - bool loadFunction(const pugi::xml_attribute& attr) override; - - //scripting - virtual bool executeUse(Player* player, Item* item, const Position& fromPosition, - Thing* target, const Position& toPosition, bool isHotkey); - // - - bool getAllowFarUse() const { - return allowFarUse; - } - void setAllowFarUse(bool v) { - allowFarUse = v; - } - - bool getCheckLineOfSight() const { - return checkLineOfSight; - } - void setCheckLineOfSight(bool v) { - checkLineOfSight = v; - } - - bool getCheckFloor() const { - return checkFloor; - } - void setCheckFloor(bool v) { - checkFloor = v; - } - - virtual ReturnValue canExecuteAction(const Player* player, const Position& toPos); - virtual bool hasOwnErrorHandler() { - return false; - } - virtual Thing* getTarget(Player* player, Creature* targetCreature, const Position& toPosition, uint8_t toStackPos) const; - - ActionFunction* function; - - protected: - std::string getScriptEventName() const override; - - static ActionFunction increaseItemId; - static ActionFunction decreaseItemId; - static ActionFunction enterMarket; - - bool allowFarUse; - bool checkFloor; - bool checkLineOfSight; -}; - -class Actions final : public BaseEvents -{ - public: - Actions(); - ~Actions(); - - // non-copyable - Actions(const Actions&) = delete; - Actions& operator=(const Actions&) = delete; - - bool useItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey); - bool useItemEx(Player* player, const Position& fromPos, const Position& toPos, uint8_t toStackPos, Item* item, bool isHotkey, Creature* creature = nullptr); - - ReturnValue canUse(const Player* player, const Position& pos); - ReturnValue canUse(const Player* player, const Position& pos, const Item* item); - ReturnValue canUseFar(const Creature* creature, const Position& toPos, bool checkLineOfSight, bool checkFloor); - - protected: - ReturnValue internalUseItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey); - static void showUseHotkeyMessage(Player* player, const Item* item, uint32_t count); - - void clear() final; - LuaScriptInterface& getScriptInterface() final; - std::string getScriptBaseName() const final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - - void registerItemID(int32_t itemId, Event* event); - void registerActionID(int32_t actionId, Event* event); - void registerUniqueID(int32_t uniqueId, Event* event); - - typedef std::map ActionUseMap; - ActionUseMap useItemMap; - ActionUseMap uniqueItemMap; - ActionUseMap actionItemMap; - - Action* getAction(const Item* item); - void clearMap(ActionUseMap& map); - - LuaScriptInterface m_scriptInterface; -}; - -#endif diff --git a/path_10_8/src/ban.cpp b/path_10_8/src/ban.cpp deleted file mode 100644 index ebe974fd4..000000000 --- a/path_10_8/src/ban.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "ban.h" -#include "database.h" -#include "databasetasks.h" -#include "tools.h" - -bool Ban::acceptConnection(uint32_t clientip) -{ - std::lock_guard lockClass(lock); - - uint64_t currentTime = OTSYS_TIME(); - - auto it = ipConnectMap.find(clientip); - if (it == ipConnectMap.end()) { - ipConnectMap.emplace(clientip, ConnectBlock(currentTime, 0, 1)); - return true; - } - - ConnectBlock& connectBlock = it->second; - if (connectBlock.blockTime > currentTime) { - connectBlock.blockTime += 250; - return false; - } - - int64_t timeDiff = currentTime - connectBlock.lastAttempt; - connectBlock.lastAttempt = currentTime; - if (timeDiff <= 5000) { - if (++connectBlock.count > 5) { - connectBlock.count = 0; - if (timeDiff <= 500) { - connectBlock.blockTime = currentTime + 3000; - return false; - } - } - } else { - connectBlock.count = 1; - } - return true; -} - -bool IOBan::isAccountBanned(uint32_t accountId, BanInfo& banInfo) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `reason`, `expires_at`, `banned_at`, `banned_by`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `account_bans` WHERE `account_id` = " << accountId; - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - int64_t expiresAt = result->getNumber("expires_at"); - if (expiresAt != 0 && time(nullptr) > expiresAt) { - // Move the ban to history if it has expired - query.str(std::string()); - query << "INSERT INTO `account_ban_history` (`account_id`, `reason`, `banned_at`, `expired_at`, `banned_by`) VALUES (" << accountId << ',' << db->escapeString(result->getString("reason")) << ',' << result->getNumber("banned_at") << ',' << expiresAt << ',' << result->getNumber("banned_by") << ')'; - g_databaseTasks.addTask(query.str()); - - query.str(std::string()); - query << "DELETE FROM `account_bans` WHERE `account_id` = " << accountId; - g_databaseTasks.addTask(query.str()); - return false; - } - - banInfo.expiresAt = expiresAt; - banInfo.reason = result->getString("reason"); - banInfo.bannedBy = result->getString("name"); - return true; -} - -bool IOBan::isIpBanned(uint32_t clientip, BanInfo& banInfo) -{ - if (clientip == 0) { - return false; - } - - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `reason`, `expires_at`, (SELECT `name` FROM `players` WHERE `id` = `banned_by`) AS `name` FROM `ip_bans` WHERE `ip` = " << clientip; - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - int64_t expiresAt = result->getNumber("expires_at"); - if (expiresAt != 0 && time(nullptr) > expiresAt) { - query.str(std::string()); - query << "DELETE FROM `ip_bans` WHERE `ip` = " << clientip; - g_databaseTasks.addTask(query.str()); - return false; - } - - banInfo.expiresAt = expiresAt; - banInfo.reason = result->getString("reason"); - banInfo.bannedBy = result->getString("name"); - return true; -} - -bool IOBan::isPlayerNamelocked(uint32_t playerId) -{ - std::ostringstream query; - query << "SELECT 1 FROM `player_namelocks` WHERE `player_id` = " << playerId; - return Database::getInstance()->storeQuery(query.str()).get() != nullptr; -} diff --git a/path_10_8/src/ban.h b/path_10_8/src/ban.h deleted file mode 100644 index 994507dd6..000000000 --- a/path_10_8/src/ban.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_BAN_H_CADB975222D745F0BDA12D982F1006E3 -#define FS_BAN_H_CADB975222D745F0BDA12D982F1006E3 - -struct BanInfo { - std::string bannedBy; - std::string reason; - time_t expiresAt; -}; - -struct ConnectBlock { - ConnectBlock(uint64_t lastAttempt, uint64_t blockTime, uint32_t count) - : lastAttempt(lastAttempt), blockTime(blockTime), count(count) {} - - uint64_t lastAttempt; - uint64_t blockTime; - uint32_t count; -}; - -typedef std::map IpConnectMap; - -class Ban -{ - public: - bool acceptConnection(uint32_t clientip); - - protected: - IpConnectMap ipConnectMap; - std::recursive_mutex lock; -}; - -class IOBan -{ - public: - static bool isAccountBanned(uint32_t accountId, BanInfo& banInfo); - static bool isIpBanned(uint32_t ip, BanInfo& banInfo); - static bool isPlayerNamelocked(uint32_t playerId); -}; - -#endif diff --git a/path_10_8/src/baseevents.cpp b/path_10_8/src/baseevents.cpp deleted file mode 100644 index 2a968e06e..000000000 --- a/path_10_8/src/baseevents.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "baseevents.h" - -#include "pugicast.h" -#include "tools.h" - -extern LuaEnvironment g_luaEnvironment; - -BaseEvents::BaseEvents() -{ - m_loaded = false; -} - -bool BaseEvents::loadFromXml() -{ - if (m_loaded) { - std::cout << "[Error - BaseEvents::loadFromXml] It's already loaded." << std::endl; - return false; - } - - std::string scriptsName = getScriptBaseName(); - std::string basePath = "data/" + scriptsName + "/"; - if (getScriptInterface().loadFile(basePath + "lib/" + scriptsName + ".lua") == -1) { - std::cout << "[Warning - BaseEvents::loadFromXml] Can not load " << scriptsName << " lib/" << scriptsName << ".lua" << std::endl; - } - - std::string filename = basePath + scriptsName + ".xml"; - - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - if (!result) { - printXMLError("Error - BaseEvents::loadFromXml", filename, result); - return false; - } - - m_loaded = true; - - for (auto node : doc.child(scriptsName.c_str()).children()) { - Event* event = getEvent(node.name()); - if (!event) { - continue; - } - - if (!event->configureEvent(node)) { - std::cout << "[Warning - BaseEvents::loadFromXml] Failed to configure event" << std::endl; - delete event; - continue; - } - - bool success; - - pugi::xml_attribute scriptAttribute = node.attribute("script"); - if (scriptAttribute) { - std::string scriptFile = "scripts/" + std::string(scriptAttribute.as_string()); - success = event->checkScript(basePath, scriptsName, scriptFile) && event->loadScript(basePath + scriptFile); - } else { - success = event->loadFunction(node.attribute("function")); - } - - if (!success || !registerEvent(event, node)) { - delete event; - } - } - return true; -} - -bool BaseEvents::reload() -{ - m_loaded = false; - clear(); - return loadFromXml(); -} - -Event::Event(LuaScriptInterface* _interface) -{ - m_scriptInterface = _interface; - m_scriptId = 0; - m_scripted = false; -} - -Event::Event(const Event* copy) -{ - m_scriptInterface = copy->m_scriptInterface; - m_scriptId = copy->m_scriptId; - m_scripted = copy->m_scripted; -} - -bool Event::checkScript(const std::string& basePath, const std::string& scriptsName, const std::string& scriptFile) const -{ - LuaScriptInterface* testInterface = g_luaEnvironment.getTestInterface(); - testInterface->reInitState(); - - if (testInterface->loadFile(std::string(basePath + "lib/" + scriptsName + ".lua")) == -1) { - std::cout << "[Warning - Event::checkScript] Can not load " << scriptsName << " lib/" << scriptsName << ".lua" << std::endl; - } - - if (m_scriptId != 0) { - std::cout << "[Failure - Event::checkScript] scriptid = " << m_scriptId << std::endl; - return false; - } - - if (testInterface->loadFile(basePath + scriptFile) == -1) { - std::cout << "[Warning - Event::checkScript] Can not load script: " << scriptFile << std::endl; - std::cout << testInterface->getLastLuaError() << std::endl; - return false; - } - - int32_t id = testInterface->getEvent(getScriptEventName()); - if (id == -1) { - std::cout << "[Warning - Event::checkScript] Event " << getScriptEventName() << " not found. " << scriptFile << std::endl; - return false; - } - return true; -} - -bool Event::loadScript(const std::string& scriptFile) -{ - if (!m_scriptInterface || m_scriptId != 0) { - std::cout << "Failure: [Event::loadScript] m_scriptInterface == nullptr. scriptid = " << m_scriptId << std::endl; - return false; - } - - if (m_scriptInterface->loadFile(scriptFile) == -1) { - std::cout << "[Warning - Event::loadScript] Can not load script. " << scriptFile << std::endl; - std::cout << m_scriptInterface->getLastLuaError() << std::endl; - return false; - } - - int32_t id = m_scriptInterface->getEvent(getScriptEventName()); - if (id == -1) { - std::cout << "[Warning - Event::loadScript] Event " << getScriptEventName() << " not found. " << scriptFile << std::endl; - return false; - } - - m_scripted = true; - m_scriptId = id; - return true; -} - -CallBack::CallBack() -{ - m_scriptId = 0; - m_scriptInterface = nullptr; - m_loaded = false; -} - -bool CallBack::loadCallBack(LuaScriptInterface* _interface, const std::string& name) -{ - if (!_interface) { - std::cout << "Failure: [CallBack::loadCallBack] m_scriptInterface == nullptr" << std::endl; - return false; - } - - m_scriptInterface = _interface; - - int32_t id = m_scriptInterface->getEvent(name.c_str()); - if (id == -1) { - std::cout << "[Warning - CallBack::loadCallBack] Event " << name << " not found." << std::endl; - return false; - } - - m_callbackName = name; - m_scriptId = id; - m_loaded = true; - return true; -} diff --git a/path_10_8/src/baseevents.h b/path_10_8/src/baseevents.h deleted file mode 100644 index 13f2197d5..000000000 --- a/path_10_8/src/baseevents.h +++ /dev/null @@ -1,90 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_BASEEVENTS_H_9994E32C91CE4D95912A5FDD1F41884A -#define FS_BASEEVENTS_H_9994E32C91CE4D95912A5FDD1F41884A - -#include "luascript.h" - -class Event -{ - public: - explicit Event(LuaScriptInterface* _interface); - explicit Event(const Event* copy); - virtual ~Event() = default; - - virtual bool configureEvent(const pugi::xml_node& node) = 0; - - bool checkScript(const std::string& basePath, const std::string& scriptsName, const std::string& scriptFile) const; - bool loadScript(const std::string& scriptFile); - virtual bool loadFunction(const pugi::xml_attribute&) { - return false; - } - - bool isScripted() const { - return m_scripted; - } - - protected: - virtual std::string getScriptEventName() const = 0; - - bool m_scripted; - int32_t m_scriptId; - LuaScriptInterface* m_scriptInterface; -}; - -class BaseEvents -{ - public: - BaseEvents(); - virtual ~BaseEvents() = default; - - bool loadFromXml(); - bool reload(); - bool isLoaded() const { - return m_loaded; - } - - protected: - virtual LuaScriptInterface& getScriptInterface() = 0; - virtual std::string getScriptBaseName() const = 0; - virtual Event* getEvent(const std::string& nodeName) = 0; - virtual bool registerEvent(Event* event, const pugi::xml_node& node) = 0; - virtual void clear() = 0; - - bool m_loaded; -}; - -class CallBack -{ - public: - CallBack(); - - bool loadCallBack(LuaScriptInterface* _interface, const std::string& name); - - protected: - int32_t m_scriptId; - LuaScriptInterface* m_scriptInterface; - - bool m_loaded; - - std::string m_callbackName; -}; - -#endif diff --git a/path_10_8/src/bed.cpp b/path_10_8/src/bed.cpp deleted file mode 100644 index 196421450..000000000 --- a/path_10_8/src/bed.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "bed.h" -#include "game.h" -#include "iologindata.h" -#include "scheduler.h" - -extern Game g_game; - -BedItem::BedItem(uint16_t _id) : Item(_id) -{ - house = nullptr; - internalRemoveSleeper(); -} - -Attr_ReadValue BedItem::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - switch (attr) { - case ATTR_SLEEPERGUID: { - uint32_t guid; - if (!propStream.read(guid)) { - return ATTR_READ_ERROR; - } - - if (guid != 0) { - std::string name = IOLoginData::getNameByGuid(guid); - if (!name.empty()) { - setSpecialDescription(name + " is sleeping there."); - g_game.setBedSleeper(this, guid); - sleeperGUID = guid; - } - } - return ATTR_READ_CONTINUE; - } - - case ATTR_SLEEPSTART: { - uint32_t sleep_start; - if (!propStream.read(sleep_start)) { - return ATTR_READ_ERROR; - } - - sleepStart = static_cast(sleep_start); - return ATTR_READ_CONTINUE; - } - - default: - break; - } - return Item::readAttr(attr, propStream); -} - -void BedItem::serializeAttr(PropWriteStream& propWriteStream) const -{ - if (sleeperGUID != 0) { - propWriteStream.write(ATTR_SLEEPERGUID); - propWriteStream.write(sleeperGUID); - } - - if (sleepStart != 0) { - propWriteStream.write(ATTR_SLEEPSTART); - // FIXME: should be stored as 64-bit, but we need to retain backwards compatibility - propWriteStream.write(static_cast(sleepStart)); - } -} - -BedItem* BedItem::getNextBedItem() const -{ - Direction dir = Item::items[id].bedPartnerDir; - Position targetPos = getNextPosition(dir, getPosition()); - - Tile* tile = g_game.map.getTile(targetPos); - if (!tile) { - return nullptr; - } - return tile->getBedItem(); -} - -bool BedItem::canUse(Player* player) -{ - if (!player || !house || !player->isPremium()) { - return false; - } - - if (sleeperGUID == 0) { - return true; - } - - if (house->getHouseAccessLevel(player) == HOUSE_OWNER) { - return true; - } - - Player sleeper(nullptr); - if (!IOLoginData::loadPlayerById(&sleeper, sleeperGUID)) { - return false; - } - - if (house->getHouseAccessLevel(&sleeper) > house->getHouseAccessLevel(player)) { - return false; - } - return true; -} - -bool BedItem::trySleep(Player* player) -{ - if (!house || player->isRemoved()) { - return false; - } - - if (sleeperGUID != 0) { - if (Item::items[id].transformToFree != 0 && house->getOwner() == player->getGUID()) { - wakeUp(nullptr); - } - - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - return true; -} - -bool BedItem::sleep(Player* player) -{ - if (!house) { - return false; - } - - if (sleeperGUID != 0) { - return false; - } - - BedItem* nextBedItem = getNextBedItem(); - - internalSetSleeper(player); - - if (nextBedItem) { - nextBedItem->internalSetSleeper(player); - } - - // update the bedSleepersMap - g_game.setBedSleeper(this, player->getGUID()); - - // make the player walk onto the bed - g_game.map.moveCreature(*player, *getTile()); - - // display 'Zzzz'/sleep effect - g_game.addMagicEffect(player->getPosition(), CONST_ME_SLEEP); - - // kick player after he sees himself walk onto the bed and it change id - uint32_t playerId = player->getID(); - g_scheduler.addEvent(createSchedulerTask(SCHEDULER_MINTICKS, std::bind(&Game::kickPlayer, &g_game, playerId, false))); - - // change self and partner's appearance - updateAppearance(player); - - if (nextBedItem) { - nextBedItem->updateAppearance(player); - } - - return true; -} - -void BedItem::wakeUp(Player* player) -{ - if (!house) { - return; - } - - if (sleeperGUID != 0) { - if (!player) { - Player _player(nullptr); - if (IOLoginData::loadPlayerById(&_player, sleeperGUID)) { - regeneratePlayer(&_player); - IOLoginData::savePlayer(&_player); - } - } else { - regeneratePlayer(player); - g_game.addCreatureHealth(player); - } - } - - // update the bedSleepersMap - g_game.removeBedSleeper(sleeperGUID); - - BedItem* nextBedItem = getNextBedItem(); - - // unset sleep info - internalRemoveSleeper(); - - if (nextBedItem) { - nextBedItem->internalRemoveSleeper(); - } - - // change self and partner's appearance - updateAppearance(nullptr); - - if (nextBedItem) { - nextBedItem->updateAppearance(nullptr); - } -} - -void BedItem::regeneratePlayer(Player* player) const -{ - const uint32_t sleptTime = time(nullptr) - sleepStart; - - Condition* condition = player->getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); - if (condition) { - uint32_t regen; - if (condition->getTicks() != -1) { - regen = std::min((condition->getTicks() / 1000), sleptTime) / 30; - const int32_t newRegenTicks = condition->getTicks() - (regen * 30000); - if (newRegenTicks <= 0) { - player->removeCondition(condition); - } else { - condition->setTicks(newRegenTicks); - } - } else { - regen = sleptTime / 30; - } - - player->changeHealth(regen, false); - player->changeMana(regen); - } - - const int32_t soulRegen = sleptTime / (60 * 15); - player->changeSoul(soulRegen); -} - -void BedItem::updateAppearance(const Player* player) -{ - const ItemType& it = Item::items[id]; - if (it.type == ITEM_TYPE_BED) { - if (player && it.transformToOnUse[player->getSex()] != 0) { - const ItemType& newType = Item::items[it.transformToOnUse[player->getSex()]]; - if (newType.type == ITEM_TYPE_BED) { - g_game.transformItem(this, it.transformToOnUse[player->getSex()]); - } - } else if (it.transformToFree != 0) { - const ItemType& newType = Item::items[it.transformToFree]; - if (newType.type == ITEM_TYPE_BED) { - g_game.transformItem(this, it.transformToFree); - } - } - } -} - -void BedItem::internalSetSleeper(const Player* player) -{ - std::string desc_str = player->getName() + " is sleeping there."; - - sleeperGUID = player->getGUID(); - sleepStart = time(nullptr); - setSpecialDescription(desc_str); -} - -void BedItem::internalRemoveSleeper() -{ - sleeperGUID = 0; - sleepStart = 0; - setSpecialDescription("Nobody is sleeping there."); -} diff --git a/path_10_8/src/bed.h b/path_10_8/src/bed.h deleted file mode 100644 index 2296636cd..000000000 --- a/path_10_8/src/bed.h +++ /dev/null @@ -1,81 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_BED_H_84DE19758D424C6C9789189231946BFF -#define FS_BED_H_84DE19758D424C6C9789189231946BFF - -#include "item.h" - -class House; -class Player; - -class BedItem final : public Item -{ - public: - explicit BedItem(uint16_t id); - - BedItem* getBed() final { - return this; - } - const BedItem* getBed() const final { - return this; - } - - Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) final; - void serializeAttr(PropWriteStream& propWriteStream) const final; - - bool canRemove() const final { - return house == nullptr; - } - - uint32_t getSleeper() const { - return sleeperGUID; - } - - uint64_t getSleepStart() const { - return sleepStart; - } - - House* getHouse() const { - return house; - } - void setHouse(House* h) { - house = h; - } - - bool canUse(Player* player); - - bool trySleep(Player* player); - bool sleep(Player* player); - void wakeUp(Player* player); - - BedItem* getNextBedItem() const; - - protected: - void updateAppearance(const Player* player); - void regeneratePlayer(Player* player) const; - void internalSetSleeper(const Player* player); - void internalRemoveSleeper(); - - House* house; - uint64_t sleepStart; - uint32_t sleeperGUID; -}; - -#endif diff --git a/path_10_8/src/chat.cpp b/path_10_8/src/chat.cpp deleted file mode 100644 index e6b22653c..000000000 --- a/path_10_8/src/chat.cpp +++ /dev/null @@ -1,626 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "chat.h" -#include "game.h" -#include "pugicast.h" -#include "player.h" -#include "scheduler.h" - -extern Chat* g_chat; -extern Game g_game; - -bool PrivateChatChannel::isInvited(uint32_t guid) const -{ - if (guid == getOwner()) { - return true; - } - return invites.find(guid) != invites.end(); -} - -bool PrivateChatChannel::removeInvite(uint32_t guid) -{ - return invites.erase(guid) != 0; -} - -void PrivateChatChannel::invitePlayer(const Player& player, Player& invitePlayer) -{ - auto result = invites.emplace(invitePlayer.getGUID(), &invitePlayer); - if (!result.second) { - return; - } - - std::ostringstream ss; - ss << player.getName() << " invites you to " << (player.getSex() == PLAYERSEX_FEMALE ? "her" : "his") << " private chat channel."; - invitePlayer.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - ss.str(std::string()); - ss << invitePlayer.getName() << " has been invited."; - player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - for (const auto& it : users) { - it.second->sendChannelEvent(id, invitePlayer.getName(), CHANNELEVENT_INVITE); - } -} - -void PrivateChatChannel::excludePlayer(const Player& player, Player& excludePlayer) -{ - if (!removeInvite(excludePlayer.getGUID())) { - return; - } - - removeUser(excludePlayer); - - std::ostringstream ss; - ss << excludePlayer.getName() << " has been excluded."; - player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - excludePlayer.sendClosePrivate(id); - - for (const auto& it : users) { - it.second->sendChannelEvent(id, excludePlayer.getName(), CHANNELEVENT_EXCLUDE); - } -} - -void PrivateChatChannel::closeChannel() const -{ - for (const auto& it : users) { - it.second->sendClosePrivate(id); - } -} - -bool ChatChannel::addUser(Player& player) -{ - if (users.find(player.getID()) != users.end()) { - return false; - } - - if (!executeOnJoinEvent(player)) { - return false; - } - - // TODO: Move to script when guild channels can be scripted - if (id == CHANNEL_GUILD) { - Guild* guild = player.getGuild(); - if (guild && !guild->getMotd().empty()) { - g_scheduler.addEvent(createSchedulerTask(150, std::bind(&Game::sendGuildMotd, &g_game, player.getID()))); - } - } - - if (!publicChannel) { - for (const auto& it : users) { - it.second->sendChannelEvent(id, player.getName(), CHANNELEVENT_JOIN); - } - } - - users[player.getID()] = &player; - return true; -} - -bool ChatChannel::removeUser(const Player& player) -{ - auto iter = users.find(player.getID()); - if (iter == users.end()) { - return false; - } - - users.erase(iter); - - if (!publicChannel) { - for (const auto& it : users) { - it.second->sendChannelEvent(id, player.getName(), CHANNELEVENT_LEAVE); - } - } - - executeOnLeaveEvent(player); - return true; -} - -void ChatChannel::sendToAll(const std::string& message, SpeakClasses type) const -{ - for (const auto& it : users) { - it.second->sendChannelMessage("", message, type, id); - } -} - -bool ChatChannel::talk(const Player& fromPlayer, SpeakClasses type, const std::string& text) -{ - if (users.find(fromPlayer.getID()) == users.end()) { - return false; - } - - for (const auto& it : users) { - it.second->sendToChannel(&fromPlayer, type, text, id); - } - return true; -} - -bool ChatChannel::executeCanJoinEvent(const Player& player) -{ - if (canJoinEvent == -1) { - return true; - } - - //canJoin(player) - LuaScriptInterface* m_scriptInterface = g_chat->getScriptInterface(); - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CanJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(canJoinEvent, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(canJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return m_scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnJoinEvent(const Player& player) -{ - if (onJoinEvent == -1) { - return true; - } - - //onJoin(player) - LuaScriptInterface* m_scriptInterface = g_chat->getScriptInterface(); - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(onJoinEvent, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(onJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return m_scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnLeaveEvent(const Player& player) -{ - if (onLeaveEvent == -1) { - return true; - } - - //onLeave(player) - LuaScriptInterface* m_scriptInterface = g_chat->getScriptInterface(); - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnLeaveChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(onLeaveEvent, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(onLeaveEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return m_scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnSpeakEvent(const Player& player, SpeakClasses& type, const std::string& message) -{ - if (onSpeakEvent == -1) { - return true; - } - - //onSpeak(player, type, message) - LuaScriptInterface* m_scriptInterface = g_chat->getScriptInterface(); - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnSpeakChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(onSpeakEvent, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(onSpeakEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, type); - LuaScriptInterface::pushString(L, message); - - bool result = false; - int size0 = lua_gettop(L); - int ret = m_scriptInterface->protectedCall(L, 3, 1); - if (ret != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else if (lua_gettop(L) > 0) { - if (lua_isboolean(L, -1)) { - result = LuaScriptInterface::getBoolean(L, -1); - } else if (lua_isnumber(L, -1)) { - result = true; - type = LuaScriptInterface::getNumber(L, -1); - } - lua_pop(L, 1); - } - - if ((lua_gettop(L) + 4) != size0) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - m_scriptInterface->resetScriptEnv(); - return result; -} - -Chat::Chat(): - scriptInterface("Chat Interface"), - dummyPrivate(CHANNEL_PRIVATE, "Private Chat Channel") -{ - scriptInterface.initState(); -} - -bool Chat::load() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/chatchannels/chatchannels.xml"); - if (!result) { - printXMLError("Error - Chat::load", "data/chatchannels/chatchannels.xml", result); - return false; - } - - std::forward_list removedChannels; - for (auto& channelEntry : normalChannels) { - ChatChannel& channel = channelEntry.second; - channel.onSpeakEvent = -1; - channel.canJoinEvent = -1; - channel.onJoinEvent = -1; - channel.onLeaveEvent = -1; - removedChannels.push_front(channelEntry.first); - } - - for (auto channelNode : doc.child("channels").children()) { - ChatChannel channel(pugi::cast(channelNode.attribute("id").value()), channelNode.attribute("name").as_string()); - channel.publicChannel = channelNode.attribute("public").as_bool(); - - pugi::xml_attribute scriptAttribute = channelNode.attribute("script"); - if (scriptAttribute) { - if (scriptInterface.loadFile("data/chatchannels/scripts/" + std::string(scriptAttribute.as_string())) == 0) { - channel.onSpeakEvent = scriptInterface.getEvent("onSpeak"); - channel.canJoinEvent = scriptInterface.getEvent("canJoin"); - channel.onJoinEvent = scriptInterface.getEvent("onJoin"); - channel.onLeaveEvent = scriptInterface.getEvent("onLeave"); - } else { - std::cout << "[Warning - Chat::load] Can not load script: " << scriptAttribute.as_string() << std::endl; - } - } - - removedChannels.remove(channel.id); - normalChannels[channel.id] = channel; - } - - for (uint16_t channelId : removedChannels) { - normalChannels.erase(channelId); - } - return true; -} - -ChatChannel* Chat::createChannel(const Player& player, uint16_t channelId) -{ - if (getChannel(player, channelId)) { - return nullptr; - } - - switch (channelId) { - case CHANNEL_GUILD: { - Guild* guild = player.getGuild(); - if (guild) { - auto ret = guildChannels.emplace(std::make_pair(guild->getId(), ChatChannel(channelId, guild->getName()))); - return &ret.first->second; - } - break; - } - - case CHANNEL_PARTY: { - Party* party = player.getParty(); - if (party) { - auto ret = partyChannels.emplace(std::make_pair(party, ChatChannel(channelId, "Party"))); - return &ret.first->second; - } - break; - } - - case CHANNEL_PRIVATE: { - //only 1 private channel for each premium player - if (!player.isPremium() || getPrivateChannel(player)) { - return nullptr; - } - - //find a free private channel slot - for (uint16_t i = 100; i < 10000; ++i) { - auto ret = privateChannels.emplace(std::make_pair(i, PrivateChatChannel(i, player.getName() + "'s Channel"))); - if (ret.second) { //second is a bool that indicates that a new channel has been placed in the map - auto& newChannel = (*ret.first).second; - newChannel.setOwner(player.getGUID()); - return &newChannel; - } - } - break; - } - - default: - break; - } - return nullptr; -} - -bool Chat::deleteChannel(const Player& player, uint16_t channelId) -{ - switch (channelId) { - case CHANNEL_GUILD: { - Guild* guild = player.getGuild(); - if (!guild) { - return false; - } - - auto it = guildChannels.find(guild->getId()); - if (it == guildChannels.end()) { - return false; - } - - guildChannels.erase(it); - break; - } - - case CHANNEL_PARTY: { - Party* party = player.getParty(); - if (!party) { - return false; - } - - auto it = partyChannels.find(party); - if (it == partyChannels.end()) { - return false; - } - - partyChannels.erase(it); - break; - } - - default: { - auto it = privateChannels.find(channelId); - if (it == privateChannels.end()) { - return false; - } - - it->second.closeChannel(); - - privateChannels.erase(it); - break; - } - } - return true; -} - -ChatChannel* Chat::addUserToChannel(Player& player, uint16_t channelId) -{ - ChatChannel* channel = getChannel(player, channelId); - if (channel && channel->addUser(player)) { - return channel; - } - return nullptr; -} - -bool Chat::removeUserFromChannel(const Player& player, uint16_t channelId) -{ - ChatChannel* channel = getChannel(player, channelId); - if (!channel || !channel->removeUser(player)) { - return false; - } - - if (channel->getOwner() == player.getGUID()) { - deleteChannel(player, channelId); - } - return true; -} - -void Chat::removeUserFromAllChannels(const Player& player) -{ - for (auto& it : normalChannels) { - it.second.removeUser(player); - } - - for (auto& it : partyChannels) { - it.second.removeUser(player); - } - - for (auto& it : guildChannels) { - it.second.removeUser(player); - } - - auto it = privateChannels.begin(); - while (it != privateChannels.end()) { - PrivateChatChannel* channel = &it->second; - channel->removeInvite(player.getGUID()); - channel->removeUser(player); - if (channel->getOwner() == player.getGUID()) { - channel->closeChannel(); - it = privateChannels.erase(it); - } else { - ++it; - } - } -} - -bool Chat::talkToChannel(const Player& player, SpeakClasses type, const std::string& text, uint16_t channelId) -{ - ChatChannel* channel = getChannel(player, channelId); - if (!channel) { - return false; - } - - if (channelId == CHANNEL_GUILD) { - if (player.getGuildLevel() > 1) { - type = TALKTYPE_CHANNEL_O; - } else if (type != TALKTYPE_CHANNEL_Y) { - type = TALKTYPE_CHANNEL_Y; - } - } else if (type != TALKTYPE_CHANNEL_Y && (channelId == CHANNEL_PRIVATE || channelId == CHANNEL_PARTY)) { - type = TALKTYPE_CHANNEL_Y; - } - - if (!channel->executeOnSpeakEvent(player, type, text)) { - return false; - } - - return channel->talk(player, type, text); -} - -ChannelList Chat::getChannelList(const Player& player) -{ - ChannelList list; - if (player.getGuild()) { - ChatChannel* channel = getChannel(player, CHANNEL_GUILD); - if (channel) { - list.push_back(channel); - } else { - channel = createChannel(player, CHANNEL_GUILD); - if (channel) { - list.push_back(channel); - } - } - } - - if (player.getParty()) { - ChatChannel* channel = getChannel(player, CHANNEL_PARTY); - if (channel) { - list.push_back(channel); - } else { - channel = createChannel(player, CHANNEL_PARTY); - if (channel) { - list.push_back(channel); - } - } - } - - for (const auto& it : normalChannels) { - ChatChannel* channel = getChannel(player, it.first); - if (channel) { - list.push_back(channel); - } - } - - bool hasPrivate = false; - for (auto& it : privateChannels) { - if (PrivateChatChannel* channel = &it.second) { - uint32_t guid = player.getGUID(); - if (channel->isInvited(guid)) { - list.push_back(channel); - } - - if (channel->getOwner() == guid) { - hasPrivate = true; - } - } - } - - if (!hasPrivate && player.isPremium()) { - list.push_front(&dummyPrivate); - } - return list; -} - -ChatChannel* Chat::getChannel(const Player& player, uint16_t channelId) -{ - switch (channelId) { - case CHANNEL_GUILD: { - Guild* guild = player.getGuild(); - if (guild) { - auto it = guildChannels.find(guild->getId()); - if (it != guildChannels.end()) { - return &it->second; - } - } - break; - } - - case CHANNEL_PARTY: { - Party* party = player.getParty(); - if (party) { - auto it = partyChannels.find(party); - if (it != partyChannels.end()) { - return &it->second; - } - } - break; - } - - default: { - auto it = normalChannels.find(channelId); - if (it != normalChannels.end()) { - ChatChannel& channel = it->second; - if (!channel.executeCanJoinEvent(player)) { - return nullptr; - } - return &channel; - } else { - auto it2 = privateChannels.find(channelId); - if (it2 != privateChannels.end() && it2->second.isInvited(player.getGUID())) { - return &it2->second; - } - } - break; - } - } - return nullptr; -} - -ChatChannel* Chat::getGuildChannelById(uint32_t guildId) -{ - auto it = guildChannels.find(guildId); - if (it == guildChannels.end()) { - return nullptr; - } - return &it->second; -} - -ChatChannel* Chat::getChannelById(uint16_t channelId) -{ - auto it = normalChannels.find(channelId); - if (it == normalChannels.end()) { - return nullptr; - } - return &it->second; -} - -PrivateChatChannel* Chat::getPrivateChannel(const Player& player) -{ - for (auto& it : privateChannels) { - if (it.second.getOwner() == player.getGUID()) { - return &it.second; - } - } - return nullptr; -} diff --git a/path_10_8/src/chat.h b/path_10_8/src/chat.h deleted file mode 100644 index 9ac71706a..000000000 --- a/path_10_8/src/chat.h +++ /dev/null @@ -1,171 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CHAT_H_F1574642D0384ABFAB52B7ED906E5628 -#define FS_CHAT_H_F1574642D0384ABFAB52B7ED906E5628 - -#include "const.h" -#include "luascript.h" - -class Party; -class Player; - -typedef std::map UsersMap; -typedef std::map InvitedMap; - -class ChatChannel -{ - public: - ChatChannel() = default; - ChatChannel(uint16_t channelId, std::string channelName): - name(channelName), - canJoinEvent(-1), - onJoinEvent(-1), - onLeaveEvent(-1), - onSpeakEvent(-1), - id(channelId), - publicChannel(false) {} - - virtual ~ChatChannel() = default; - - bool addUser(Player& player); - bool removeUser(const Player& player); - - bool talk(const Player& fromPlayer, SpeakClasses type, const std::string& text); - void sendToAll(const std::string& message, SpeakClasses type) const; - - const std::string& getName() const { - return name; - } - uint16_t getId() const { - return id; - } - const UsersMap& getUsers() const { - return users; - } - virtual const InvitedMap* getInvitedUsersPtr() const { - return nullptr; - } - - virtual uint32_t getOwner() const { - return 0; - } - - bool isPublicChannel() const { return publicChannel; } - - bool executeOnJoinEvent(const Player& player); - bool executeCanJoinEvent(const Player& player); - bool executeOnLeaveEvent(const Player& player); - bool executeOnSpeakEvent(const Player& player, SpeakClasses& type, const std::string& message); - - protected: - UsersMap users; - - std::string name; - - int32_t canJoinEvent; - int32_t onJoinEvent; - int32_t onLeaveEvent; - int32_t onSpeakEvent; - - uint16_t id; - bool publicChannel; - - friend class Chat; -}; - -class PrivateChatChannel final : public ChatChannel -{ - public: - PrivateChatChannel(uint16_t channelId, std::string channelName) : ChatChannel(channelId, channelName), owner(0) {} - - uint32_t getOwner() const final { - return owner; - } - void setOwner(uint32_t owner) { - this->owner = owner; - } - - bool isInvited(uint32_t guid) const; - - void invitePlayer(const Player& player, Player& invitePlayer); - void excludePlayer(const Player& player, Player& excludePlayer); - - bool removeInvite(uint32_t guid); - - void closeChannel() const; - - const InvitedMap& getInvitedUsers() const { - return invites; - } - - const InvitedMap* getInvitedUsersPtr() const final { - return &invites; - } - - protected: - InvitedMap invites; - uint32_t owner; -}; - -typedef std::list ChannelList; - -class Chat -{ - public: - Chat(); - - // non-copyable - Chat(const Chat&) = delete; - Chat& operator=(const Chat&) = delete; - - bool load(); - - ChatChannel* createChannel(const Player& player, uint16_t channelId); - bool deleteChannel(const Player& player, uint16_t channelId); - - ChatChannel* addUserToChannel(Player& player, uint16_t channelId); - bool removeUserFromChannel(const Player& player, uint16_t channelId); - void removeUserFromAllChannels(const Player& player); - - bool talkToChannel(const Player& player, SpeakClasses type, const std::string& text, uint16_t channelId); - - ChannelList getChannelList(const Player& player); - - ChatChannel* getChannel(const Player& player, uint16_t channelId); - ChatChannel* getChannelById(uint16_t channelId); - ChatChannel* getGuildChannelById(uint32_t guildId); - PrivateChatChannel* getPrivateChannel(const Player& player); - - LuaScriptInterface* getScriptInterface() { - return &scriptInterface; - } - - private: - std::map normalChannels; - std::map privateChannels; - std::map partyChannels; - std::map guildChannels; - - LuaScriptInterface scriptInterface; - - PrivateChatChannel dummyPrivate; -}; - -#endif diff --git a/path_10_8/src/combat.cpp b/path_10_8/src/combat.cpp deleted file mode 100644 index 00e4d1b44..000000000 --- a/path_10_8/src/combat.cpp +++ /dev/null @@ -1,1412 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "combat.h" - -#include "game.h" -#include "weapons.h" -#include "configmanager.h" -#include "events.h" - -extern Game g_game; -extern Weapons* g_weapons; -extern ConfigManager g_config; -extern Events* g_events; - -Combat::Combat() : - formulaType(COMBAT_FORMULA_UNDEFINED), - mina(0.0), minb(0.0), maxa(0.0), maxb(0.0), - area(nullptr) -{ - // -} - -CombatDamage Combat::getCombatDamage(Creature* creature, Creature* target) const -{ - CombatDamage damage; - damage.origin = params.origin; - damage.primary.type = params.combatType; - - double damageModifier = 1.0; - if (auto chance = g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE)) { - if (boolean_random(static_cast(chance) / 100.0)) { - damageModifier += static_cast(g_config.getNumber(ConfigManager::CRITICAL_HIT_EXTRA)) / 100.0; - std::cout << "Critical hit!" << std::endl; - } - } - - auto mina = this->mina * damageModifier; - auto maxa = this->maxa * damageModifier; - - if (formulaType == COMBAT_FORMULA_DAMAGE) { - damage.primary.value = normal_random( - static_cast(mina), - static_cast(maxa) - ); - } else if (creature) { - int32_t min, max; - if (creature->getCombatValues(min, max)) { - damage.primary.value = normal_random(min, max); - } else if (Player* player = creature->getPlayer()) { - if (params.valueCallback) { - params.valueCallback->getMinMaxValues(player, damage, params.useCharges); - } else if (formulaType == COMBAT_FORMULA_LEVELMAGIC) { - int32_t levelFormula = player->getLevel() * 2 + player->getMagicLevel() * 3; - damage.primary.value = normal_random( - static_cast(levelFormula * mina + minb), - static_cast(levelFormula * maxa + maxb) - ); - } else if (formulaType == COMBAT_FORMULA_SKILL) { - Item* tool = player->getWeapon(); - const Weapon* weapon = g_weapons->getWeapon(tool); - if (weapon) { - damage.primary.value = normal_random( - static_cast(minb), - static_cast(weapon->getWeaponDamage(player, target, tool, true) * maxa + maxb) - ); - - damage.secondary.type = weapon->getElementType(); - damage.secondary.value = weapon->getElementDamage(player, target, tool); - if (params.useCharges) { - uint16_t charges = tool->getCharges(); - if (charges != 0) { - g_game.transformItem(tool, tool->getID(), charges - 1); - } - } - } else { - damage.primary.value = normal_random( - static_cast(minb), - static_cast(maxb) - ); - } - } - } - } - return damage; -} - -void Combat::getCombatArea(const Position& centerPos, const Position& targetPos, const AreaCombat* area, std::forward_list& list) -{ - if (targetPos.z >= MAP_MAX_LAYERS) { - return; - } - - if (area) { - area->getList(centerPos, targetPos, list); - } else { - Tile* tile = g_game.map.getTile(targetPos); - if (!tile) { - tile = new StaticTile(targetPos.x, targetPos.y, targetPos.z); - g_game.map.setTile(targetPos, tile); - } - list.push_front(tile); - } -} - -CombatType_t Combat::ConditionToDamageType(ConditionType_t type) -{ - switch (type) { - case CONDITION_FIRE: - return COMBAT_FIREDAMAGE; - - case CONDITION_ENERGY: - return COMBAT_ENERGYDAMAGE; - - case CONDITION_BLEEDING: - return COMBAT_PHYSICALDAMAGE; - - case CONDITION_DROWN: - return COMBAT_DROWNDAMAGE; - - case CONDITION_POISON: - return COMBAT_EARTHDAMAGE; - - case CONDITION_FREEZING: - return COMBAT_ICEDAMAGE; - - case CONDITION_DAZZLED: - return COMBAT_HOLYDAMAGE; - - case CONDITION_CURSED: - return COMBAT_DEATHDAMAGE; - - default: - break; - } - - return COMBAT_NONE; -} - -ConditionType_t Combat::DamageToConditionType(CombatType_t type) -{ - switch (type) { - case COMBAT_FIREDAMAGE: - return CONDITION_FIRE; - - case COMBAT_ENERGYDAMAGE: - return CONDITION_ENERGY; - - case COMBAT_DROWNDAMAGE: - return CONDITION_DROWN; - - case COMBAT_EARTHDAMAGE: - return CONDITION_POISON; - - case COMBAT_ICEDAMAGE: - return CONDITION_FREEZING; - - case COMBAT_HOLYDAMAGE: - return CONDITION_DAZZLED; - - case COMBAT_DEATHDAMAGE: - return CONDITION_CURSED; - - case COMBAT_PHYSICALDAMAGE: - return CONDITION_BLEEDING; - - default: - return CONDITION_NONE; - } -} - -bool Combat::isPlayerCombat(const Creature* target) -{ - if (target->getPlayer()) { - return true; - } - - if (target->isSummon() && target->getMaster()->getPlayer()) { - return true; - } - - return false; -} - -ReturnValue Combat::canTargetCreature(Player* player, Creature* target) -{ - if (player == target) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (!player->hasFlag(PlayerFlag_IgnoreProtectionZone)) { - //pz-zone - if (player->getZone() == ZONE_PROTECTION) { - return RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE; - } - - if (target->getZone() == ZONE_PROTECTION) { - return RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE; - } - - //nopvp-zone - if (isPlayerCombat(target)) { - if (player->getZone() == ZONE_NOPVP) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } - - if (target->getZone() == ZONE_NOPVP) { - return RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE; - } - } - } - - if (player->hasFlag(PlayerFlag_CannotUseCombat) || !target->isAttackable()) { - if (target->getPlayer()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } else { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - } - - if (target->getPlayer()) { - if (isProtected(player, target->getPlayer())) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (player->hasSecureMode() && !Combat::isInPvpZone(player, target) && player->getSkullClient(target->getPlayer()) == SKULL_NONE) { - return RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS; - } - } - - return Combat::canDoCombat(player, target); -} - -ReturnValue Combat::canDoCombat(Creature* caster, Tile* tile, bool aggressive) -{ - if (tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { - return RETURNVALUE_NOTENOUGHROOM; - } - - if (tile->floorChange()) { - return RETURNVALUE_NOTENOUGHROOM; - } - - if (tile->getTeleportItem()) { - return RETURNVALUE_NOTENOUGHROOM; - } - - if (caster) { - const Position& casterPosition = caster->getPosition(); - const Position& tilePosition = tile->getPosition(); - if (casterPosition.z < tilePosition.z) { - return RETURNVALUE_FIRSTGODOWNSTAIRS; - } else if (casterPosition.z > tilePosition.z) { - return RETURNVALUE_FIRSTGOUPSTAIRS; - } - - if (const Player* player = caster->getPlayer()) { - if (player->hasFlag(PlayerFlag_IgnoreProtectionZone)) { - return RETURNVALUE_NOERROR; - } - } - } - - //pz-zone - if (aggressive && tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE; - } - - return g_events->eventCreatureOnAreaCombat(caster, tile, aggressive); -} - -bool Combat::isInPvpZone(const Creature* attacker, const Creature* target) -{ - return attacker->getZone() == ZONE_PVP && target->getZone() == ZONE_PVP; -} - -bool Combat::isProtected(const Player* attacker, const Player* target) -{ - uint32_t protectionLevel = g_config.getNumber(ConfigManager::PROTECTION_LEVEL); - if (target->getLevel() < protectionLevel || attacker->getLevel() < protectionLevel) { - return true; - } - - if (attacker->getVocationId() == VOCATION_NONE || target->getVocationId() == VOCATION_NONE) { - return true; - } - - if (attacker->getSkull() == SKULL_BLACK && attacker->getSkullClient(target) == SKULL_NONE) { - return true; - } - - return false; -} - -ReturnValue Combat::canDoCombat(Creature* attacker, Creature* target) -{ - if (attacker) { - if (const Player* targetPlayer = target->getPlayer()) { - if (targetPlayer->hasFlag(PlayerFlag_CannotBeAttacked)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (const Player* attackerPlayer = attacker->getPlayer()) { - if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (isProtected(attackerPlayer, targetPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - //nopvp-zone - const Tile* targetPlayerTile = targetPlayer->getTile(); - if (targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } else if (attackerPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE) && !targetPlayerTile->hasFlag(TILESTATE_NOPVPZONE) && !targetPlayerTile->hasFlag(TILESTATE_PROTECTIONZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } - } - - if (attacker->isSummon()) { - if (const Player* masterAttackerPlayer = attacker->getMaster()->getPlayer()) { - if (masterAttackerPlayer->hasFlag(PlayerFlag_CannotAttackPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - - if (targetPlayer->getTile()->hasFlag(TILESTATE_NOPVPZONE)) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } - - if (isProtected(masterAttackerPlayer, targetPlayer)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - } - } else if (target->getMonster()) { - if (const Player* attackerPlayer = attacker->getPlayer()) { - if (attackerPlayer->hasFlag(PlayerFlag_CannotAttackMonster)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - - if (target->isSummon() && target->getMaster()->getPlayer() && target->getZone() == ZONE_NOPVP) { - return RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE; - } - } else if (attacker->getMonster()) { - const Creature* targetMaster = target->getMaster(); - - if (!targetMaster || !targetMaster->getPlayer()) { - const Creature* attackerMaster = attacker->getMaster(); - - if (!attackerMaster || !attackerMaster->getPlayer()) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - } - } - } - - if (g_game.getWorldType() == WORLD_TYPE_NO_PVP) { - if (attacker->getPlayer() || (attacker->isSummon() && attacker->getMaster()->getPlayer())) { - if (target->getPlayer()) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER; - } - } - - if (target->isSummon() && target->getMaster()->getPlayer()) { - if (!isInPvpZone(attacker, target)) { - return RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE; - } - } - } - } - } - return g_events->eventCreatureOnTargetCombat(attacker, target); -} - -void Combat::setPlayerCombatValues(formulaType_t _type, double _mina, double _minb, double _maxa, double _maxb) -{ - formulaType = _type; - mina = _mina; - minb = _minb; - maxa = _maxa; - maxb = _maxb; -} - -bool Combat::setParam(CombatParam_t param, uint32_t value) -{ - switch (param) { - case COMBAT_PARAM_TYPE: { - params.combatType = static_cast(value); - return true; - } - - case COMBAT_PARAM_EFFECT: { - params.impactEffect = static_cast(value); - return true; - } - - case COMBAT_PARAM_DISTANCEEFFECT: { - params.distanceEffect = static_cast(value); - return true; - } - - case COMBAT_PARAM_BLOCKARMOR: { - params.blockedByArmor = (value != 0); - return true; - } - - case COMBAT_PARAM_BLOCKSHIELD: { - params.blockedByShield = (value != 0); - return true; - } - - case COMBAT_PARAM_TARGETCASTERORTOPMOST: { - params.targetCasterOrTopMost = (value != 0); - return true; - } - - case COMBAT_PARAM_CREATEITEM: { - params.itemId = value; - return true; - } - - case COMBAT_PARAM_AGGRESSIVE: { - params.aggressive = (value != 0); - return true; - } - - case COMBAT_PARAM_DISPEL: { - params.dispelType = static_cast(value); - return true; - } - - case COMBAT_PARAM_USECHARGES: { - params.useCharges = (value != 0); - return true; - } - } - return false; -} - -bool Combat::setCallback(CallBackParam_t key) -{ - switch (key) { - case CALLBACK_PARAM_LEVELMAGICVALUE: { - params.valueCallback.reset(new ValueCallback(COMBAT_FORMULA_LEVELMAGIC)); - return true; - } - - case CALLBACK_PARAM_SKILLVALUE: { - params.valueCallback.reset(new ValueCallback(COMBAT_FORMULA_SKILL)); - return true; - } - - case CALLBACK_PARAM_TARGETTILE: { - params.tileCallback.reset(new TileCallback()); - return true; - } - - case CALLBACK_PARAM_TARGETCREATURE: { - params.targetCallback.reset(new TargetCallback()); - return true; - } - } - return false; -} - -CallBack* Combat::getCallback(CallBackParam_t key) -{ - switch (key) { - case CALLBACK_PARAM_LEVELMAGICVALUE: - case CALLBACK_PARAM_SKILLVALUE: { - return params.valueCallback.get(); - } - - case CALLBACK_PARAM_TARGETTILE: { - return params.tileCallback.get(); - } - - case CALLBACK_PARAM_TARGETCREATURE: { - return params.targetCallback.get(); - } - } - return nullptr; -} - -void Combat::CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data) -{ - assert(data); - CombatDamage damage = *data; - if (g_game.combatBlockHit(damage, caster, target, params.blockedByShield, params.blockedByArmor, params.itemId != 0)) { - return; - } - - if ((damage.primary.value < 0 || damage.secondary.value < 0) && caster) { - Player* targetPlayer = target->getPlayer(); - if (targetPlayer && caster->getPlayer() && targetPlayer->getSkull() != SKULL_BLACK) { - damage.primary.value /= 2; - damage.secondary.value /= 2; - } - } - - if (g_game.combatChangeHealth(caster, target, damage)) { - CombatConditionFunc(caster, target, params, nullptr); - CombatDispelFunc(caster, target, params, nullptr); - } -} - -void Combat::CombatManaFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data) -{ - assert(data); - CombatDamage damage = *data; - if (damage.primary.value < 0) { - if (caster && caster->getPlayer() && target->getPlayer()) { - damage.primary.value /= 2; - } - } - - if (g_game.combatChangeMana(caster, target, damage.primary.value, damage.origin)) { - CombatConditionFunc(caster, target, params, nullptr); - CombatDispelFunc(caster, target, params, nullptr); - } -} - -void Combat::CombatConditionFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage*) -{ - for (const auto& condition : params.conditionList) { - if (caster == target || !target->isImmune(condition->getType())) { - Condition* conditionCopy = condition->clone(); - if (caster) { - conditionCopy->setParam(CONDITION_PARAM_OWNER, caster->getID()); - } - - //TODO: infight condition until all aggressive conditions has ended - target->addCombatCondition(conditionCopy); - } - } -} - -void Combat::CombatDispelFunc(Creature*, Creature* target, const CombatParams& params, CombatDamage*) -{ - target->removeCombatCondition(params.dispelType); -} - -void Combat::CombatNullFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage*) -{ - CombatConditionFunc(caster, target, params, nullptr); - CombatDispelFunc(caster, target, params, nullptr); -} - -void Combat::combatTileEffects(const SpectatorVec& list, Creature* caster, Tile* tile, const CombatParams& params) -{ - if (params.itemId != 0) { - uint16_t itemId = params.itemId; - switch (itemId) { - case ITEM_FIREFIELD_PERSISTENT_FULL: - itemId = ITEM_FIREFIELD_PVP_FULL; - break; - - case ITEM_FIREFIELD_PERSISTENT_MEDIUM: - itemId = ITEM_FIREFIELD_PVP_MEDIUM; - break; - - case ITEM_FIREFIELD_PERSISTENT_SMALL: - itemId = ITEM_FIREFIELD_PVP_SMALL; - break; - - case ITEM_ENERGYFIELD_PERSISTENT: - itemId = ITEM_ENERGYFIELD_PVP; - break; - - case ITEM_POISONFIELD_PERSISTENT: - itemId = ITEM_POISONFIELD_PVP; - break; - - case ITEM_MAGICWALL_PERSISTENT: - itemId = ITEM_MAGICWALL; - break; - - case ITEM_WILDGROWTH_PERSISTENT: - itemId = ITEM_WILDGROWTH; - break; - - default: - break; - } - - if (caster) { - Player* casterPlayer; - if (caster->isSummon()) { - casterPlayer = caster->getMaster()->getPlayer(); - } else { - casterPlayer = caster->getPlayer(); - } - - if (casterPlayer) { - if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || tile->hasFlag(TILESTATE_NOPVPZONE)) { - if (itemId == ITEM_FIREFIELD_PVP_FULL) { - itemId = ITEM_FIREFIELD_NOPVP; - } else if (itemId == ITEM_POISONFIELD_PVP) { - itemId = ITEM_POISONFIELD_NOPVP; - } else if (itemId == ITEM_ENERGYFIELD_PVP) { - itemId = ITEM_ENERGYFIELD_NOPVP; - } - } else if (itemId == ITEM_FIREFIELD_PVP_FULL || itemId == ITEM_POISONFIELD_PVP || itemId == ITEM_ENERGYFIELD_PVP) { - casterPlayer->addInFightTicks(); - } - } - } - - Item* item = Item::CreateItem(itemId); - if (caster) { - item->setOwner(caster->getID()); - } - - ReturnValue ret = g_game.internalAddItem(tile, item); - if (ret == RETURNVALUE_NOERROR) { - g_game.startDecay(item); - } else { - delete item; - } - } - - if (params.tileCallback) { - params.tileCallback->onTileCombat(caster, tile); - } - - if (params.impactEffect != CONST_ME_NONE) { - Game::addMagicEffect(list, tile->getPosition(), params.impactEffect); - } -} - -void Combat::postCombatEffects(Creature* caster, const Position& pos, const CombatParams& params) -{ - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), pos, params.distanceEffect); - } -} - -void Combat::addDistanceEffect(Creature* caster, const Position& fromPos, const Position& toPos, uint8_t effect) -{ - if (effect == CONST_ANI_WEAPONTYPE) { - if (!caster) { - return; - } - - Player* player = caster->getPlayer(); - if (!player) { - return; - } - - switch (player->getWeaponType()) { - case WEAPON_AXE: - effect = CONST_ANI_WHIRLWINDAXE; - break; - case WEAPON_SWORD: - effect = CONST_ANI_WHIRLWINDSWORD; - break; - case WEAPON_CLUB: - effect = CONST_ANI_WHIRLWINDCLUB; - break; - default: - effect = CONST_ANI_NONE; - break; - } - } - - if (effect != CONST_ANI_NONE) { - g_game.addDistanceEffect(fromPos, toPos, effect); - } -} - -void Combat::CombatFunc(Creature* caster, const Position& pos, const AreaCombat* area, const CombatParams& params, COMBATFUNC func, CombatDamage* data) -{ - std::forward_list tileList; - - if (caster) { - getCombatArea(caster->getPosition(), pos, area, tileList); - } else { - getCombatArea(pos, pos, area, tileList); - } - - SpectatorVec list; - uint32_t maxX = 0; - uint32_t maxY = 0; - - //calculate the max viewable range - for (Tile* tile : tileList) { - const Position& tilePos = tile->getPosition(); - - uint32_t diff = Position::getDistanceX(tilePos, pos); - if (diff > maxX) { - maxX = diff; - } - - diff = Position::getDistanceY(tilePos, pos); - if (diff > maxY) { - maxY = diff; - } - } - - const int32_t rangeX = maxX + Map::maxViewportX; - const int32_t rangeY = maxY + Map::maxViewportY; - g_game.map.getSpectators(list, pos, true, true, rangeX, rangeX, rangeY, rangeY); - - for (Tile* tile : tileList) { - if (canDoCombat(caster, tile, params.aggressive) != RETURNVALUE_NOERROR) { - continue; - } - - if (CreatureVector* creatures = tile->getCreatures()) { - const Creature* topCreature = tile->getTopCreature(); - for (Creature* creature : *creatures) { - if (params.targetCasterOrTopMost) { - if (caster && caster->getTile() == tile) { - if (creature != caster) { - continue; - } - } else if (creature != topCreature) { - continue; - } - } - - if (!params.aggressive || (caster != creature && Combat::canDoCombat(caster, creature) == RETURNVALUE_NOERROR)) { - func(caster, creature, params, data); - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, creature); - } - - if (params.targetCasterOrTopMost) { - break; - } - } - } - } - combatTileEffects(list, caster, tile, params); - } - postCombatEffects(caster, pos, params); -} - -void Combat::doCombat(Creature* caster, Creature* target) const -{ - //target combat callback function - if (params.combatType != COMBAT_NONE) { - CombatDamage damage = getCombatDamage(caster, target); - if (damage.primary.type != COMBAT_MANADRAIN) { - doCombatHealth(caster, target, damage, params); - } else { - doCombatMana(caster, target, damage, params); - } - } else { - doCombatDefault(caster, target, params); - } -} - -void Combat::doCombat(Creature* caster, const Position& position) const -{ - //area combat callback function - if (params.combatType != COMBAT_NONE) { - CombatDamage damage = getCombatDamage(caster, nullptr); - if (damage.primary.type != COMBAT_MANADRAIN) { - doCombatHealth(caster, position, area.get(), damage, params); - } else { - doCombatMana(caster, position, area.get(), damage, params); - } - } else { - CombatFunc(caster, position, area.get(), params, CombatNullFunc, nullptr); - } -} - -void Combat::doCombatHealth(Creature* caster, Creature* target, CombatDamage& damage, const CombatParams& params) -{ - bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR); - if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) { - g_game.addMagicEffect(target->getPosition(), params.impactEffect); - } - - if (canCombat) { - CombatHealthFunc(caster, target, params, &damage); - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, target); - } - - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect); - } - } -} - -void Combat::doCombatHealth(Creature* caster, const Position& position, const AreaCombat* area, CombatDamage& damage, const CombatParams& params) -{ - CombatFunc(caster, position, area, params, CombatHealthFunc, &damage); -} - -void Combat::doCombatMana(Creature* caster, Creature* target, CombatDamage& damage, const CombatParams& params) -{ - bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR); - if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) { - g_game.addMagicEffect(target->getPosition(), params.impactEffect); - } - - if (canCombat) { - CombatManaFunc(caster, target, params, &damage); - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, target); - } - - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect); - } - } -} - -void Combat::doCombatMana(Creature* caster, const Position& position, const AreaCombat* area, CombatDamage& damage, const CombatParams& params) -{ - CombatFunc(caster, position, area, params, CombatManaFunc, &damage); -} - -void Combat::doCombatCondition(Creature* caster, const Position& position, const AreaCombat* area, const CombatParams& params) -{ - CombatFunc(caster, position, area, params, CombatConditionFunc, nullptr); -} - -void Combat::doCombatCondition(Creature* caster, Creature* target, const CombatParams& params) -{ - bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR); - if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) { - g_game.addMagicEffect(target->getPosition(), params.impactEffect); - } - - if (canCombat) { - CombatConditionFunc(caster, target, params, nullptr); - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, target); - } - - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect); - } - } -} - -void Combat::doCombatDispel(Creature* caster, const Position& position, const AreaCombat* area, const CombatParams& params) -{ - CombatFunc(caster, position, area, params, CombatDispelFunc, nullptr); -} - -void Combat::doCombatDispel(Creature* caster, Creature* target, const CombatParams& params) -{ - bool canCombat = !params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR); - if ((caster == target || canCombat) && params.impactEffect != CONST_ME_NONE) { - g_game.addMagicEffect(target->getPosition(), params.impactEffect); - } - - if (canCombat) { - CombatDispelFunc(caster, target, params, nullptr); - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, target); - } - - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect); - } - } -} - -void Combat::doCombatDefault(Creature* caster, Creature* target, const CombatParams& params) -{ - if (!params.aggressive || (caster != target && Combat::canDoCombat(caster, target) == RETURNVALUE_NOERROR)) { - SpectatorVec list; - g_game.map.getSpectators(list, target->getPosition(), true, true); - - CombatNullFunc(caster, target, params, nullptr); - combatTileEffects(list, caster, target->getTile(), params); - - if (params.targetCallback) { - params.targetCallback->onTargetCombat(caster, target); - } - - /* - if (params.impactEffect != CONST_ME_NONE) { - g_game.addMagicEffect(target->getPosition(), params.impactEffect); - } - */ - - if (caster && params.distanceEffect != CONST_ANI_NONE) { - addDistanceEffect(caster, caster->getPosition(), target->getPosition(), params.distanceEffect); - } - } -} - -//**********************************************************// - -void ValueCallback::getMinMaxValues(Player* player, CombatDamage& damage, bool useCharges) const -{ - //onGetPlayerMinMaxValues(...) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ValueCallback::getMinMaxValues] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - if (!env->setCallbackId(m_scriptId, m_scriptInterface)) { - m_scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - int parameters = 1; - switch (type) { - case COMBAT_FORMULA_LEVELMAGIC: { - //onGetPlayerMinMaxValues(player, level, maglevel) - lua_pushnumber(L, player->getLevel()); - lua_pushnumber(L, player->getMagicLevel()); - parameters += 2; - break; - } - - case COMBAT_FORMULA_SKILL: { - //onGetPlayerMinMaxValues(player, attackSkill, attackValue, attackFactor) - Item* tool = player->getWeapon(); - const Weapon* weapon = g_weapons->getWeapon(tool); - - int32_t attackValue = 7; - if (weapon) { - attackValue = tool->getAttack(); - if (tool->getWeaponType() == WEAPON_AMMO) { - Item* item = player->getWeapon(true); - if (item) { - attackValue += item->getAttack(); - } - } - - damage.secondary.type = weapon->getElementType(); - damage.secondary.value = weapon->getElementDamage(player, nullptr, tool); - if (useCharges) { - uint16_t charges = tool->getCharges(); - if (charges != 0) { - g_game.transformItem(tool, tool->getID(), charges - 1); - } - } - } - - lua_pushnumber(L, player->getWeaponSkill(tool)); - lua_pushnumber(L, attackValue); - lua_pushnumber(L, player->getAttackFactor()); - parameters += 3; - break; - } - - default: { - std::cout << "ValueCallback::getMinMaxValues - unknown callback type" << std::endl; - m_scriptInterface->resetScriptEnv(); - return; - } - } - - int size0 = lua_gettop(L); - if (lua_pcall(L, parameters, 2, 0) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - damage.primary.value = normal_random( - LuaScriptInterface::getNumber(L, -2), - LuaScriptInterface::getNumber(L, -1) - ); - lua_pop(L, 2); - } - - if ((lua_gettop(L) + parameters + 1) != size0) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - m_scriptInterface->resetScriptEnv(); -} - -//**********************************************************// - -void TileCallback::onTileCombat(Creature* creature, Tile* tile) const -{ - //onTileCombat(creature, pos) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TileCallback::onTileCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - if (!env->setCallbackId(m_scriptId, m_scriptInterface)) { - m_scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - LuaScriptInterface::pushPosition(L, tile->getPosition()); - - m_scriptInterface->callFunction(2); -} - -//**********************************************************// - -void TargetCallback::onTargetCombat(Creature* creature, Creature* target) const -{ - //onTargetCombat(creature, target) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TargetCallback::onTargetCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - if (!env->setCallbackId(m_scriptId, m_scriptInterface)) { - m_scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - - if (target) { - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setCreatureMetatable(L, -1, target); - } else { - lua_pushnil(L); - } - - int size0 = lua_gettop(L); - - if (lua_pcall(L, 2, 0 /*nReturnValues*/, 0) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } - - if ((lua_gettop(L) + 2 /*nParams*/ + 1) != size0) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - m_scriptInterface->resetScriptEnv(); -} - -//**********************************************************// - -void AreaCombat::clear() -{ - for (const auto& it : areas) { - delete it.second; - } - areas.clear(); -} - -AreaCombat::AreaCombat(const AreaCombat& rhs) -{ - hasExtArea = rhs.hasExtArea; - for (const auto& it : rhs.areas) { - areas[it.first] = new MatrixArea(*it.second); - } -} - -void AreaCombat::getList(const Position& centerPos, const Position& targetPos, std::forward_list& list) const -{ - const MatrixArea* area = getArea(centerPos, targetPos); - if (!area) { - return; - } - - uint32_t centerY, centerX; - area->getCenter(centerY, centerX); - - Position tmpPos(targetPos.x - centerX, targetPos.y - centerY, targetPos.z); - uint32_t cols = area->getCols(); - for (uint32_t y = 0, rows = area->getRows(); y < rows; ++y) { - for (uint32_t x = 0; x < cols; ++x) { - if (area->getValue(y, x) != 0) { - if (g_game.isSightClear(targetPos, tmpPos, true)) { - Tile* tile = g_game.map.getTile(tmpPos); - if (!tile) { - tile = new StaticTile(tmpPos.x, tmpPos.y, tmpPos.z); - g_game.map.setTile(tmpPos, tile); - } - list.push_front(tile); - } - } - tmpPos.x++; - } - tmpPos.x -= cols; - tmpPos.y++; - } -} - -void AreaCombat::copyArea(const MatrixArea* input, MatrixArea* output, MatrixOperation_t op) const -{ - uint32_t centerY, centerX; - input->getCenter(centerY, centerX); - - if (op == MATRIXOPERATION_COPY) { - for (uint32_t y = 0; y < input->getRows(); ++y) { - for (uint32_t x = 0; x < input->getCols(); ++x) { - (*output)[y][x] = (*input)[y][x]; - } - } - - output->setCenter(centerY, centerX); - } else if (op == MATRIXOPERATION_MIRROR) { - for (uint32_t y = 0; y < input->getRows(); ++y) { - uint32_t rx = 0; - for (int32_t x = input->getCols(); --x >= 0;) { - (*output)[y][rx++] = (*input)[y][x]; - } - } - - output->setCenter(centerY, (input->getRows() - 1) - centerX); - } else if (op == MATRIXOPERATION_FLIP) { - for (uint32_t x = 0; x < input->getCols(); ++x) { - uint32_t ry = 0; - for (int32_t y = input->getRows(); --y >= 0;) { - (*output)[ry++][x] = (*input)[y][x]; - } - } - - output->setCenter((input->getCols() - 1) - centerY, centerX); - } else { - // rotation - int32_t rotateCenterX = (output->getCols() / 2) - 1; - int32_t rotateCenterY = (output->getRows() / 2) - 1; - int32_t angle; - - switch (op) { - case MATRIXOPERATION_ROTATE90: - angle = 90; - break; - - case MATRIXOPERATION_ROTATE180: - angle = 180; - break; - - case MATRIXOPERATION_ROTATE270: - angle = 270; - break; - - default: - angle = 0; - break; - } - - double angleRad = M_PI * angle / 180.0; - - double a = std::cos(angleRad); - double b = -std::sin(angleRad); - double c = std::sin(angleRad); - double d = std::cos(angleRad); - - const uint32_t rows = input->getRows(); - for (uint32_t x = 0, cols = input->getCols(); x < cols; ++x) { - for (uint32_t y = 0; y < rows; ++y) { - //calculate new coordinates using rotation center - int32_t newX = x - centerX; - int32_t newY = y - centerY; - - //perform rotation - int32_t rotatedX = static_cast(round(newX * a + newY * b)); - int32_t rotatedY = static_cast(round(newX * c + newY * d)); - - //write in the output matrix using rotated coordinates - (*output)[rotatedY + rotateCenterY][rotatedX + rotateCenterX] = (*input)[y][x]; - } - } - - output->setCenter(rotateCenterY, rotateCenterX); - } -} - -MatrixArea* AreaCombat::createArea(const std::list& list, uint32_t rows) -{ - uint32_t cols; - if (rows == 0) { - cols = 0; - } else { - cols = list.size() / rows; - } - - MatrixArea* area = new MatrixArea(rows, cols); - - uint32_t x = 0; - uint32_t y = 0; - - for (uint32_t value : list) { - if (value == 1 || value == 3) { - area->setValue(y, x, true); - } - - if (value == 2 || value == 3) { - area->setCenter(y, x); - } - - ++x; - - if (cols == x) { - x = 0; - ++y; - } - } - return area; -} - -void AreaCombat::setupArea(const std::list& list, uint32_t rows) -{ - MatrixArea* area = createArea(list, rows); - - //NORTH - areas[DIRECTION_NORTH] = area; - - uint32_t maxOutput = std::max(area->getCols(), area->getRows()) * 2; - - //SOUTH - MatrixArea* southArea = new MatrixArea(maxOutput, maxOutput); - copyArea(area, southArea, MATRIXOPERATION_ROTATE180); - areas[DIRECTION_SOUTH] = southArea; - - //EAST - MatrixArea* eastArea = new MatrixArea(maxOutput, maxOutput); - copyArea(area, eastArea, MATRIXOPERATION_ROTATE90); - areas[DIRECTION_EAST] = eastArea; - - //WEST - MatrixArea* westArea = new MatrixArea(maxOutput, maxOutput); - copyArea(area, westArea, MATRIXOPERATION_ROTATE270); - areas[DIRECTION_WEST] = westArea; -} - -void AreaCombat::setupArea(int32_t length, int32_t spread) -{ - std::list list; - - uint32_t rows = length; - int32_t cols = 1; - - if (spread != 0) { - cols = ((length - (length % spread)) / spread) * 2 + 1; - } - - int32_t colSpread = cols; - - for (uint32_t y = 1; y <= rows; ++y) { - int32_t mincol = cols - colSpread + 1; - int32_t maxcol = cols - (cols - colSpread); - - for (int32_t x = 1; x <= cols; ++x) { - if (y == rows && x == ((cols - (cols % 2)) / 2) + 1) { - list.push_back(3); - } else if (x >= mincol && x <= maxcol) { - list.push_back(1); - } else { - list.push_back(0); - } - } - - if (spread > 0 && y % spread == 0) { - --colSpread; - } - } - - setupArea(list, rows); -} - -void AreaCombat::setupArea(int32_t radius) -{ - int32_t area[13][13] = { - {0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0}, - {0, 0, 0, 0, 8, 8, 7, 8, 8, 0, 0, 0, 0}, - {0, 0, 0, 8, 7, 6, 6, 6, 7, 8, 0, 0, 0}, - {0, 0, 8, 7, 6, 5, 5, 5, 6, 7, 8, 0, 0}, - {0, 8, 7, 6, 5, 4, 4, 4, 5, 6, 7, 8, 0}, - {0, 8, 6, 5, 4, 3, 2, 3, 4, 5, 6, 8, 0}, - {8, 7, 6, 5, 4, 2, 1, 2, 4, 5, 6, 7, 8}, - {0, 8, 6, 5, 4, 3, 2, 3, 4, 5, 6, 8, 0}, - {0, 8, 7, 6, 5, 4, 4, 4, 5, 6, 7, 8, 0}, - {0, 0, 8, 7, 6, 5, 5, 5, 6, 7, 8, 0, 0}, - {0, 0, 0, 8, 7, 6, 6, 6, 7, 8, 0, 0, 0}, - {0, 0, 0, 0, 8, 8, 7, 8, 8, 0, 0, 0, 0}, - {0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0} - }; - - std::list list; - - for (int32_t y = 0; y < 13; ++y) { - for (int32_t x = 0; x < 13; ++x) { - if (area[y][x] == 1) { - list.push_back(3); - } else if (area[y][x] > 0 && area[y][x] <= radius) { - list.push_back(1); - } else { - list.push_back(0); - } - } - } - - setupArea(list, 13); -} - -void AreaCombat::setupExtArea(const std::list& list, uint32_t rows) -{ - if (list.empty()) { - return; - } - - hasExtArea = true; - MatrixArea* area = createArea(list, rows); - - //NORTH-WEST - areas[DIRECTION_NORTHWEST] = area; - - uint32_t maxOutput = std::max(area->getCols(), area->getRows()) * 2; - - //NORTH-EAST - MatrixArea* neArea = new MatrixArea(maxOutput, maxOutput); - copyArea(area, neArea, MATRIXOPERATION_MIRROR); - areas[DIRECTION_NORTHEAST] = neArea; - - //SOUTH-WEST - MatrixArea* swArea = new MatrixArea(maxOutput, maxOutput); - copyArea(area, swArea, MATRIXOPERATION_FLIP); - areas[DIRECTION_SOUTHWEST] = swArea; - - //SOUTH-EAST - MatrixArea* seArea = new MatrixArea(maxOutput, maxOutput); - copyArea(swArea, seArea, MATRIXOPERATION_MIRROR); - areas[DIRECTION_SOUTHEAST] = seArea; -} - -//**********************************************************// - -void MagicField::onStepInField(Creature* creature) -{ - //remove magic walls/wild growth - if (id == ITEM_MAGICWALL || id == ITEM_WILDGROWTH || id == ITEM_MAGICWALL_SAFE || id == ITEM_WILDGROWTH_SAFE || isBlocking()) { - if (!creature->isInGhostMode()) { - g_game.internalRemoveItem(this, 1); - } - - return; - } - - const ItemType& it = items[getID()]; - if (it.conditionDamage) { - Condition* conditionCopy = it.conditionDamage->clone(); - uint32_t ownerId = getOwner(); - if (ownerId) { - bool harmfulField = true; - - if (g_game.getWorldType() == WORLD_TYPE_NO_PVP || getTile()->hasFlag(TILESTATE_NOPVPZONE)) { - Creature* owner = g_game.getCreatureByID(ownerId); - if (owner) { - if (owner->getPlayer() || (owner->isSummon() && owner->getMaster()->getPlayer())) { - harmfulField = false; - } - } - } - - Player* targetPlayer = creature->getPlayer(); - if (targetPlayer) { - Player* attackerPlayer = g_game.getPlayerByID(ownerId); - if (attackerPlayer) { - if (Combat::isProtected(attackerPlayer, targetPlayer)) { - harmfulField = false; - } - } - } - - if (!harmfulField || (OTSYS_TIME() - createTime <= 5000) || creature->hasBeenAttacked(ownerId)) { - conditionCopy->setParam(CONDITION_PARAM_OWNER, ownerId); - } - } - - creature->addCondition(conditionCopy); - } -} diff --git a/path_10_8/src/combat.h b/path_10_8/src/combat.h deleted file mode 100644 index 1be9f1160..000000000 --- a/path_10_8/src/combat.h +++ /dev/null @@ -1,382 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_COMBAT_H_B02CE79230FC43708699EE91FCC8F7CC -#define FS_COMBAT_H_B02CE79230FC43708699EE91FCC8F7CC - -#include "thing.h" -#include "condition.h" -#include "map.h" -#include "baseevents.h" - -class Condition; -class Creature; -class Item; - -struct Position; - -//for luascript callback -class ValueCallback final : public CallBack -{ - public: - explicit ValueCallback(formulaType_t _type) { - type = _type; - } - void getMinMaxValues(Player* player, CombatDamage& damage, bool useCharges) const; - - protected: - formulaType_t type; -}; - -class TileCallback final : public CallBack -{ - public: - void onTileCombat(Creature* creature, Tile* tile) const; - - protected: - formulaType_t type; -}; - -class TargetCallback final : public CallBack -{ - public: - void onTargetCombat(Creature* creature, Creature* target) const; - - protected: - formulaType_t type; -}; - -struct CombatParams { - CombatParams() { - dispelType = CONDITION_NONE; - combatType = COMBAT_NONE; - - blockedByArmor = false; - blockedByShield = false; - targetCasterOrTopMost = false; - aggressive = true; - itemId = 0; - impactEffect = CONST_ME_NONE; - distanceEffect = CONST_ANI_NONE; - useCharges = false; - - origin = ORIGIN_SPELL; - } - - std::forward_list> conditionList; - - std::unique_ptr valueCallback; - std::unique_ptr tileCallback; - std::unique_ptr targetCallback; - - uint16_t itemId; - - ConditionType_t dispelType; - CombatType_t combatType; - CombatOrigin origin; - - uint8_t impactEffect; - uint8_t distanceEffect; - - bool blockedByArmor; - bool blockedByShield; - bool targetCasterOrTopMost; - bool aggressive; - bool useCharges; -}; - -typedef void (*COMBATFUNC)(Creature*, Creature*, const CombatParams&, CombatDamage*); - -class MatrixArea -{ - public: - MatrixArea(uint32_t _rows, uint32_t _cols) { - centerX = 0; - centerY = 0; - - rows = _rows; - cols = _cols; - - data_ = new bool*[rows]; - - for (uint32_t row = 0; row < rows; ++row) { - data_[row] = new bool[cols]; - - for (uint32_t col = 0; col < cols; ++col) { - data_[row][col] = 0; - } - } - } - - MatrixArea(const MatrixArea& rhs) { - centerX = rhs.centerX; - centerY = rhs.centerY; - rows = rhs.rows; - cols = rhs.cols; - - data_ = new bool*[rows]; - - for (uint32_t row = 0; row < rows; ++row) { - data_[row] = new bool[cols]; - - for (uint32_t col = 0; col < cols; ++col) { - data_[row][col] = rhs.data_[row][col]; - } - } - } - - ~MatrixArea() { - for (uint32_t row = 0; row < rows; ++row) { - delete[] data_[row]; - } - - delete[] data_; - } - - // non-assignable - MatrixArea& operator=(const MatrixArea&) = delete; - - void setValue(uint32_t row, uint32_t col, bool value) const { - data_[row][col] = value; - } - bool getValue(uint32_t row, uint32_t col) const { - return data_[row][col]; - } - - void setCenter(uint32_t y, uint32_t x) { - centerX = x; - centerY = y; - } - void getCenter(uint32_t& y, uint32_t& x) const { - x = centerX; - y = centerY; - } - - uint32_t getRows() const { - return rows; - } - uint32_t getCols() const { - return cols; - } - - inline const bool* operator[](uint32_t i) const { - return data_[i]; - } - inline bool* operator[](uint32_t i) { - return data_[i]; - } - - protected: - uint32_t centerX; - uint32_t centerY; - - uint32_t rows; - uint32_t cols; - bool** data_; -}; - -class AreaCombat -{ - public: - AreaCombat() { - hasExtArea = false; - } - AreaCombat(const AreaCombat& rhs); - ~AreaCombat() { - clear(); - } - - // non-assignable - AreaCombat& operator=(const AreaCombat&) = delete; - - ReturnValue doCombat(Creature* attacker, const Position& pos, const Combat& combat) const; - void getList(const Position& centerPos, const Position& targetPos, std::forward_list& list) const; - - void setupArea(const std::list& list, uint32_t rows); - void setupArea(int32_t length, int32_t spread); - void setupArea(int32_t radius); - void setupExtArea(const std::list& list, uint32_t rows); - void clear(); - - protected: - enum MatrixOperation_t { - MATRIXOPERATION_COPY, - MATRIXOPERATION_MIRROR, - MATRIXOPERATION_FLIP, - MATRIXOPERATION_ROTATE90, - MATRIXOPERATION_ROTATE180, - MATRIXOPERATION_ROTATE270, - }; - - MatrixArea* createArea(const std::list& list, uint32_t rows); - void copyArea(const MatrixArea* input, MatrixArea* output, MatrixOperation_t op) const; - - MatrixArea* getArea(const Position& centerPos, const Position& targetPos) const { - int32_t dx = Position::getOffsetX(targetPos, centerPos); - int32_t dy = Position::getOffsetY(targetPos, centerPos); - - Direction dir; - if (dx < 0) { - dir = DIRECTION_WEST; - } else if (dx > 0) { - dir = DIRECTION_EAST; - } else if (dy < 0) { - dir = DIRECTION_NORTH; - } else { - dir = DIRECTION_SOUTH; - } - - if (hasExtArea) { - if (dx < 0 && dy < 0) { - dir = DIRECTION_NORTHWEST; - } else if (dx > 0 && dy < 0) { - dir = DIRECTION_NORTHEAST; - } else if (dx < 0 && dy > 0) { - dir = DIRECTION_SOUTHWEST; - } else if (dx > 0 && dy > 0) { - dir = DIRECTION_SOUTHEAST; - } - } - - auto it = areas.find(dir); - if (it == areas.end()) { - return nullptr; - } - return it->second; - } - - std::map areas; - bool hasExtArea; -}; - -class Combat -{ - public: - Combat(); - - // non-copyable - Combat(const Combat&) = delete; - Combat& operator=(const Combat&) = delete; - - static void doCombatHealth(Creature* caster, Creature* target, CombatDamage& damage, const CombatParams& params); - static void doCombatHealth(Creature* caster, const Position& position, const AreaCombat* area, CombatDamage& damage, const CombatParams& params); - - static void doCombatMana(Creature* caster, Creature* target, CombatDamage& damage, const CombatParams& params); - static void doCombatMana(Creature* caster, const Position& position, const AreaCombat* area, CombatDamage& damage, const CombatParams& params); - - static void doCombatCondition(Creature* caster, Creature* target, const CombatParams& params); - static void doCombatCondition(Creature* caster, const Position& position, const AreaCombat* area, const CombatParams& params); - - static void doCombatDispel(Creature* caster, Creature* target, const CombatParams& params); - static void doCombatDispel(Creature* caster, const Position& position, const AreaCombat* area, const CombatParams& params); - - static void getCombatArea(const Position& centerPos, const Position& targetPos, const AreaCombat* area, std::forward_list& list); - - static bool isInPvpZone(const Creature* attacker, const Creature* target); - static bool isProtected(const Player* attacker, const Player* target); - static bool isPlayerCombat(const Creature* target); - static CombatType_t ConditionToDamageType(ConditionType_t type); - static ConditionType_t DamageToConditionType(CombatType_t type); - static ReturnValue canTargetCreature(Player* attacker, Creature* target); - static ReturnValue canDoCombat(Creature* caster, Tile* tile, bool aggressive); - static ReturnValue canDoCombat(Creature* attacker, Creature* target); - static void postCombatEffects(Creature* caster, const Position& pos, const CombatParams& params); - - static void addDistanceEffect(Creature* caster, const Position& fromPos, const Position& toPos, uint8_t effect); - - void doCombat(Creature* caster, Creature* target) const; - void doCombat(Creature* caster, const Position& pos) const; - - bool setCallback(CallBackParam_t key); - CallBack* getCallback(CallBackParam_t key); - - bool setParam(CombatParam_t param, uint32_t value); - void setArea(AreaCombat* area) { - this->area.reset(area); - } - bool hasArea() const { - return area != nullptr; - } - void setCondition(const Condition* condition) { - params.conditionList.emplace_front(condition); - } - void setPlayerCombatValues(formulaType_t _type, double _mina, double _minb, double _maxa, double _maxb); - void postCombatEffects(Creature* caster, const Position& pos) const { - postCombatEffects(caster, pos, params); - } - - void setOrigin(CombatOrigin origin) { - params.origin = origin; - } - - protected: - static void doCombatDefault(Creature* caster, Creature* target, const CombatParams& params); - - static void CombatFunc(Creature* caster, const Position& pos, const AreaCombat* area, const CombatParams& params, COMBATFUNC func, CombatDamage* data); - - static void CombatHealthFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data); - static void CombatManaFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* damage); - static void CombatConditionFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data); - static void CombatDispelFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data); - static void CombatNullFunc(Creature* caster, Creature* target, const CombatParams& params, CombatDamage* data); - - static void combatTileEffects(const SpectatorVec& list, Creature* caster, Tile* tile, const CombatParams& params); - CombatDamage getCombatDamage(Creature* creature, Creature* target) const; - - //configureable - CombatParams params; - - //formula variables - formulaType_t formulaType; - double mina; - double minb; - double maxa; - double maxb; - - std::unique_ptr area; -}; - -class MagicField final : public Item -{ - public: - explicit MagicField(uint16_t _type) : Item(_type) { - createTime = OTSYS_TIME(); - } - - MagicField* getMagicField() final { - return this; - } - const MagicField* getMagicField() const final { - return this; - } - - bool isReplaceable() const { - return Item::items[getID()].replaceable; - } - CombatType_t getCombatType() const { - const ItemType& it = items[getID()]; - return it.combatType; - } - void onStepInField(Creature* creature); - - private: - int64_t createTime; -}; - -#endif diff --git a/path_10_8/src/commands.cpp b/path_10_8/src/commands.cpp deleted file mode 100644 index baa309f19..000000000 --- a/path_10_8/src/commands.cpp +++ /dev/null @@ -1,387 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "commands.h" -#include "player.h" -#include "npc.h" -#include "game.h" -#include "actions.h" -#include "iologindata.h" -#include "configmanager.h" -#include "spells.h" -#include "movement.h" -#include "weapons.h" -#include "globalevent.h" -#include "monster.h" -#include "scheduler.h" -#include "events.h" - -#include "pugicast.h" - -extern ConfigManager g_config; -extern Actions* g_actions; -extern Monsters g_monsters; -extern TalkActions* g_talkActions; -extern MoveEvents* g_moveEvents; -extern Spells* g_spells; -extern Weapons* g_weapons; -extern Game g_game; -extern CreatureEvents* g_creatureEvents; -extern GlobalEvents* g_globalEvents; -extern Events* g_events; -extern Chat* g_chat; -extern LuaEnvironment g_luaEnvironment; - -s_defcommands Commands::defined_commands[] = { - // TODO: move all commands to talkactions - - //admin commands - {"/reload", &Commands::reloadInfo}, - {"/raid", &Commands::forceRaid}, - - // player commands - {"!sellhouse", &Commands::sellHouse} -}; - -Commands::Commands() -{ - loaded = false; - - //setup command map - for (uint32_t i = 0; i < sizeof(defined_commands) / sizeof(defined_commands[0]); i++) { - Command* cmd = new Command; - cmd->loadedGroupId = false; - cmd->loadedAccountType = false; - cmd->loadedLogging = false; - cmd->logged = true; - cmd->groupId = 1; - cmd->f = defined_commands[i].f; - std::string key = defined_commands[i].name; - commandMap[key] = cmd; - } -} - -Commands::~Commands() -{ - for (const auto& it : commandMap) { - delete it.second; - } -} - -bool Commands::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/commands.xml"); - if (!result) { - printXMLError("Error - Commands::loadFromXml", "data/XML/commands.xml", result); - return false; - } - - loaded = true; - - for (auto commandNode : doc.child("commands").children()) { - pugi::xml_attribute cmdAttribute = commandNode.attribute("cmd"); - if (!cmdAttribute) { - std::cout << "[Warning - Commands::loadFromXml] Missing cmd" << std::endl; - continue; - } - - auto it = commandMap.find(cmdAttribute.as_string()); - if (it == commandMap.end()) { - std::cout << "[Warning - Commands::loadFromXml] Unknown command " << cmdAttribute.as_string() << std::endl; - continue; - } - - Command* command = it->second; - - pugi::xml_attribute groupAttribute = commandNode.attribute("group"); - if (groupAttribute) { - if (!command->loadedGroupId) { - command->groupId = pugi::cast(groupAttribute.value()); - command->loadedGroupId = true; - } else { - std::cout << "[Notice - Commands::loadFromXml] Duplicate command: " << it->first << std::endl; - } - } - - pugi::xml_attribute acctypeAttribute = commandNode.attribute("acctype"); - if (acctypeAttribute) { - if (!command->loadedAccountType) { - command->accountType = static_cast(pugi::cast(acctypeAttribute.value())); - command->loadedAccountType = true; - } else { - std::cout << "[Notice - Commands::loadFromXml] Duplicate command: " << it->first << std::endl; - } - } - - pugi::xml_attribute logAttribute = commandNode.attribute("log"); - if (logAttribute) { - if (!command->loadedLogging) { - command->logged = booleanString(logAttribute.as_string()); - command->loadedLogging = true; - } else { - std::cout << "[Notice - Commands::loadFromXml] Duplicate log tag for: " << it->first << std::endl; - } - } - } - - for (const auto& it : commandMap) { - Command* command = it.second; - if (!command->loadedGroupId) { - std::cout << "[Warning - Commands::loadFromXml] Missing group id for command " << it.first << std::endl; - } - - if (!command->loadedAccountType) { - std::cout << "[Warning - Commands::loadFromXml] Missing acctype level for command " << it.first << std::endl; - } - - if (!command->loadedLogging) { - std::cout << "[Warning - Commands::loadFromXml] Missing log command " << it.first << std::endl; - } - - g_game.addCommandTag(it.first.front()); - } - return loaded; -} - -bool Commands::reload() -{ - loaded = false; - - for (const auto& it : commandMap) { - Command* command = it.second; - command->groupId = 1; - command->accountType = ACCOUNT_TYPE_GOD; - command->loadedGroupId = false; - command->loadedAccountType = false; - command->logged = true; - command->loadedLogging = false; - } - - g_game.resetCommandTag(); - return loadFromXml(); -} - -bool Commands::exeCommand(Player& player, const std::string& cmd) -{ - std::string str_command; - std::string str_param; - - std::string::size_type loc = cmd.find(' ', 0); - if (loc != std::string::npos) { - str_command = std::string(cmd, 0, loc); - str_param = std::string(cmd, (loc + 1), cmd.size() - loc - 1); - } else { - str_command = cmd; - } - - //find command - auto it = commandMap.find(str_command); - if (it == commandMap.end()) { - return false; - } - - Command* command = it->second; - if (command->groupId > player.getGroup()->id || command->accountType > player.getAccountType()) { - if (player.getGroup()->access) { - player.sendTextMessage(MESSAGE_STATUS_SMALL, "You can not execute this command."); - } - - return false; - } - - //execute command - CommandFunc cfunc = command->f; - (this->*cfunc)(player, str_param); - - if (command->logged) { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, cmd); - - std::ostringstream logFile; - logFile << "data/logs/" << player.getName() << " commands.log"; - std::ofstream out(logFile.str(), std::ios::app); - if (out.is_open()) { - time_t ticks = time(nullptr); - const tm* now = localtime(&ticks); - char buf[32]; - strftime(buf, sizeof(buf), "%d/%m/%Y %H:%M", now); - - out << '[' << buf << "] " << cmd << std::endl; - out.close(); - } - } - return true; -} - -void Commands::reloadInfo(Player& player, const std::string& param) -{ - std::string tmpParam = asLowerCaseString(param); - if (tmpParam == "action" || tmpParam == "actions") { - g_actions->reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded actions."); - } else if (tmpParam == "config" || tmpParam == "configuration") { - g_config.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded config."); - } else if (tmpParam == "command" || tmpParam == "commands") { - reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded commands."); - } else if (tmpParam == "creaturescript" || tmpParam == "creaturescripts") { - g_creatureEvents->reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded creature scripts."); - } else if (tmpParam == "monster" || tmpParam == "monsters") { - g_monsters.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded monsters."); - } else if (tmpParam == "move" || tmpParam == "movement" || tmpParam == "movements" - || tmpParam == "moveevents" || tmpParam == "moveevent") { - g_moveEvents->reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded movements."); - } else if (tmpParam == "npc" || tmpParam == "npcs") { - Npcs::reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded npcs."); - } else if (tmpParam == "raid" || tmpParam == "raids") { - g_game.raids.reload(); - g_game.raids.startup(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded raids."); - } else if (tmpParam == "spell" || tmpParam == "spells") { - g_spells->reload(); - g_monsters.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded spells."); - } else if (tmpParam == "talk" || tmpParam == "talkaction" || tmpParam == "talkactions") { - g_talkActions->reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded talk actions."); - } else if (tmpParam == "items") { - Item::items.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded items."); - } else if (tmpParam == "weapon" || tmpParam == "weapons") { - g_weapons->reload(); - g_weapons->loadDefaults(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded weapons."); - } else if (tmpParam == "quest" || tmpParam == "quests") { - g_game.quests.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded quests."); - } else if (tmpParam == "mount" || tmpParam == "mounts") { - g_game.mounts.reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded mounts."); - } else if (tmpParam == "globalevents" || tmpParam == "globalevent") { - g_globalEvents->reload(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded globalevents."); - } else if (tmpParam == "events") { - g_events->load(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded events."); - } else if (tmpParam == "chat" || tmpParam == "channel" || tmpParam == "chatchannels") { - g_chat->load(); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded chatchannels."); - } else if (tmpParam == "global") { - g_luaEnvironment.loadFile("data/global.lua"); - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded global.lua."); - } else { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reload type not found."); - } - lua_gc(g_luaEnvironment.getLuaState(), LUA_GCCOLLECT, 0); -} - -void Commands::sellHouse(Player& player, const std::string& param) -{ - Player* tradePartner = g_game.getPlayerByName(param); - if (!tradePartner || tradePartner == &player) { - player.sendCancelMessage("Trade player not found."); - return; - } - - if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(), player.getPosition())) { - player.sendCancelMessage("Trade player is too far away."); - return; - } - - if (!tradePartner->isPremium()) { - player.sendCancelMessage("Trade player does not have a premium account."); - return; - } - - HouseTile* houseTile = dynamic_cast(player.getTile()); - if (!houseTile) { - player.sendCancelMessage("You must stand in your house to initiate the trade."); - return; - } - - House* house = houseTile->getHouse(); - if (!house || house->getOwner() != player.getGUID()) { - player.sendCancelMessage("You don't own this house."); - return; - } - - if (g_game.map.houses.getHouseByPlayerId(tradePartner->getGUID())) { - player.sendCancelMessage("Trade player already owns a house."); - return; - } - - if (IOLoginData::hasBiddedOnHouse(tradePartner->getGUID())) { - player.sendCancelMessage("Trade player is currently the highest bidder of an auctioned house."); - return; - } - - Item* transferItem = house->getTransferItem(); - if (!transferItem) { - player.sendCancelMessage("You can not trade this house."); - return; - } - - transferItem->getParent()->setParent(&player); - - if (!g_game.internalStartTrade(&player, tradePartner, transferItem)) { - house->resetTransferItem(); - } -} - -void Commands::forceRaid(Player& player, const std::string& param) -{ - Raid* raid = g_game.raids.getRaidByName(param); - if (!raid || !raid->isLoaded()) { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "No such raid exists."); - return; - } - - if (g_game.raids.getRunning()) { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Another raid is already being executed."); - return; - } - - g_game.raids.setRunning(raid); - - RaidEvent* event = raid->getNextRaidEvent(); - if (!event) { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "The raid does not contain any data."); - return; - } - - raid->setState(RAIDSTATE_EXECUTING); - - uint32_t ticks = event->getDelay(); - if (ticks > 0) { - g_scheduler.addEvent(createSchedulerTask(ticks, std::bind(&Raid::executeRaidEvent, raid, event))); - } else { - g_dispatcher.addTask(createTask(std::bind(&Raid::executeRaidEvent, raid, event))); - } - - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Raid started."); -} diff --git a/path_10_8/src/commands.h b/path_10_8/src/commands.h deleted file mode 100644 index 67c11b26b..000000000 --- a/path_10_8/src/commands.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_COMMANDS_H_C95A575CCADF434699D26CD042690970 -#define FS_COMMANDS_H_C95A575CCADF434699D26CD042690970 - -#include "enums.h" - -class Player; - -struct Command; -struct s_defcommands; - -class Commands -{ - public: - Commands(); - ~Commands(); - - // non-copyable - Commands(const Commands&) = delete; - Commands& operator=(const Commands&) = delete; - - bool loadFromXml(); - bool reload(); - - bool exeCommand(Player& player, const std::string& cmd); - - protected: - //commands - void reloadInfo(Player& player, const std::string& param); - void sellHouse(Player& player, const std::string& param); - void forceRaid(Player& player, const std::string& param); - - //table of commands - static s_defcommands defined_commands[]; - - std::map commandMap; - bool loaded; -}; - -typedef void (Commands::*CommandFunc)(Player&, const std::string&); - -struct Command { - CommandFunc f; - uint32_t groupId; - AccountType_t accountType; - bool loadedGroupId; - bool loadedAccountType; - bool logged; - bool loadedLogging; -}; - -struct s_defcommands { - const char* name; - CommandFunc f; -}; - -#endif diff --git a/path_10_8/src/condition.cpp b/path_10_8/src/condition.cpp deleted file mode 100644 index e84e6b9dc..000000000 --- a/path_10_8/src/condition.cpp +++ /dev/null @@ -1,1711 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "condition.h" -#include "game.h" - -extern Game g_game; - -Condition::Condition(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - subId(_subId), - ticks(_ticks), - conditionType(_type), - id(_id), - isBuff(_buff) -{ - if (_ticks == -1) { - endTime = std::numeric_limits::max(); - } else { - endTime = 0; - } -} - -bool Condition::setParam(ConditionParam_t param, int32_t value) -{ - switch (param) { - case CONDITION_PARAM_TICKS: { - ticks = value; - return true; - } - - case CONDITION_PARAM_BUFF_SPELL: { - isBuff = (value != 0); - return true; - } - - case CONDITION_PARAM_SUBID: { - subId = value; - return true; - } - - default: { - return false; - } - } -} - -bool Condition::unserialize(PropStream& propStream) -{ - uint8_t attr_type; - while (propStream.read(attr_type) && attr_type != CONDITIONATTR_END) { - if (!unserializeProp(static_cast(attr_type), propStream)) { - return false; - } - } - return true; -} - -bool Condition::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - switch (attr) { - case CONDITIONATTR_TYPE: { - int32_t value; - if (!propStream.read(value)) { - return false; - } - - conditionType = static_cast(value); - return true; - } - - case CONDITIONATTR_ID: { - int32_t value; - if (!propStream.read(value)) { - return false; - } - - id = static_cast(value); - return true; - } - - case CONDITIONATTR_TICKS: { - return propStream.read(ticks); - } - - case CONDITIONATTR_ISBUFF: { - uint8_t value; - if (!propStream.read(value)) { - return false; - } - - isBuff = (value != 0); - return true; - } - - case CONDITIONATTR_SUBID: { - return propStream.read(subId); - } - - case CONDITIONATTR_END: - return true; - - default: - return false; - } -} - -void Condition::serialize(PropWriteStream& propWriteStream) -{ - propWriteStream.write(CONDITIONATTR_TYPE); - propWriteStream.write(conditionType); - - propWriteStream.write(CONDITIONATTR_ID); - propWriteStream.write(id); - - propWriteStream.write(CONDITIONATTR_TICKS); - propWriteStream.write(ticks); - - propWriteStream.write(CONDITIONATTR_ISBUFF); - propWriteStream.write(isBuff); - - propWriteStream.write(CONDITIONATTR_SUBID); - propWriteStream.write(subId); -} - -void Condition::setTicks(int32_t newTicks) -{ - ticks = newTicks; - endTime = ticks + OTSYS_TIME(); -} - -bool Condition::executeCondition(Creature*, int32_t interval) -{ - if (ticks == -1) { - return true; - } - - //Not using set ticks here since it would reset endTime - ticks = std::max(0, ticks - interval); - return getEndTime() >= OTSYS_TIME(); -} - -Condition* Condition::createCondition(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, int32_t param/* = 0*/, bool _buff/* = false*/, uint32_t _subId/* = 0*/) -{ - switch (_type) { - case CONDITION_POISON: - case CONDITION_FIRE: - case CONDITION_ENERGY: - case CONDITION_DROWN: - case CONDITION_FREEZING: - case CONDITION_DAZZLED: - case CONDITION_CURSED: - case CONDITION_BLEEDING: - return new ConditionDamage(_id, _type, _buff, _subId); - - case CONDITION_HASTE: - case CONDITION_PARALYZE: - return new ConditionSpeed(_id, _type, _ticks, _buff, _subId, param); - - case CONDITION_INVISIBLE: - return new ConditionInvisible(_id, _type, _ticks, _buff, _subId); - - case CONDITION_OUTFIT: - return new ConditionOutfit(_id, _type, _ticks, _buff, _subId); - - case CONDITION_LIGHT: - return new ConditionLight(_id, _type, _ticks, _buff, _subId, param & 0xFF, (param & 0xFF00) >> 8); - - case CONDITION_REGENERATION: - return new ConditionRegeneration(_id, _type, _ticks, _buff, _subId); - - case CONDITION_SOUL: - return new ConditionSoul(_id, _type, _ticks, _buff, _subId); - - case CONDITION_ATTRIBUTES: - return new ConditionAttributes(_id, _type, _ticks, _buff, _subId); - - case CONDITION_SPELLCOOLDOWN: - return new ConditionSpellCooldown(_id, _type, _ticks, _buff, _subId); - - case CONDITION_SPELLGROUPCOOLDOWN: - return new ConditionSpellGroupCooldown(_id, _type, _ticks, _buff, _subId); - - case CONDITION_INFIGHT: - case CONDITION_DRUNK: - case CONDITION_EXHAUST_WEAPON: - case CONDITION_EXHAUST_COMBAT: - case CONDITION_EXHAUST_HEAL: - case CONDITION_MUTED: - case CONDITION_CHANNELMUTEDTICKS: - case CONDITION_YELLTICKS: - case CONDITION_PACIFIED: - case CONDITION_MANASHIELD: - return new ConditionGeneric(_id, _type, _ticks, _buff, _subId); - - default: - return nullptr; - } -} - -Condition* Condition::createCondition(PropStream& propStream) -{ - uint8_t attr; - if (!propStream.read(attr) || attr != CONDITIONATTR_TYPE) { - return nullptr; - } - - uint32_t _type; - if (!propStream.read(_type)) { - return nullptr; - } - - if (!propStream.read(attr) || attr != CONDITIONATTR_ID) { - return nullptr; - } - - uint32_t _id; - if (!propStream.read(_id)) { - return nullptr; - } - - if (!propStream.read(attr) || attr != CONDITIONATTR_TICKS) { - return nullptr; - } - - uint32_t _ticks; - if (!propStream.read(_ticks)) { - return nullptr; - } - - if (!propStream.read(attr) || attr != CONDITIONATTR_ISBUFF) { - return nullptr; - } - - uint8_t _buff; - if (!propStream.read(_buff)) { - return nullptr; - } - - if (!propStream.read(attr) || attr != CONDITIONATTR_SUBID) { - return nullptr; - } - - uint32_t _subId; - if (!propStream.read(_subId)) { - return nullptr; - } - - return createCondition(static_cast(_id), static_cast(_type), _ticks, 0, _buff != 0, _subId); -} - -bool Condition::startCondition(Creature*) -{ - if (ticks > 0) { - endTime = ticks + OTSYS_TIME(); - } - return true; -} - -bool Condition::isPersistent() const -{ - if (ticks == -1) { - return false; - } - - if (!(id == CONDITIONID_DEFAULT || id == CONDITIONID_COMBAT)) { - return false; - } - - return true; -} - -uint32_t Condition::getIcons() const -{ - return isBuff ? ICON_PARTY_BUFF : 0; -} - -bool Condition::updateCondition(const Condition* addCondition) -{ - if (conditionType != addCondition->getType()) { - return false; - } - - if (ticks == -1 && addCondition->getTicks() > 0) { - return false; - } - - if (addCondition->getTicks() >= 0 && getEndTime() > (OTSYS_TIME() + addCondition->getTicks())) { - return false; - } - - return true; -} - -ConditionGeneric::ConditionGeneric(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - Condition(_id, _type, _ticks, _buff, _subId) -{ - // -} - -bool ConditionGeneric::startCondition(Creature* creature) -{ - return Condition::startCondition(creature); -} - -bool ConditionGeneric::executeCondition(Creature* creature, int32_t interval) -{ - return Condition::executeCondition(creature, interval); -} - -void ConditionGeneric::endCondition(Creature*) -{ - // -} - -void ConditionGeneric::addCondition(Creature*, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - } -} - -uint32_t ConditionGeneric::getIcons() const -{ - uint32_t icons = Condition::getIcons(); - - switch (conditionType) { - case CONDITION_MANASHIELD: - icons |= ICON_MANASHIELD; - break; - - case CONDITION_INFIGHT: - icons |= ICON_SWORDS; - break; - - case CONDITION_DRUNK: - icons |= ICON_DRUNK; - break; - - default: - break; - } - - return icons; -} - -ConditionAttributes::ConditionAttributes(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : -ConditionGeneric(_id, _type, _ticks, _buff, _subId), skills(), skillsPercent(), stats(), statsPercent() -{ - currentSkill = 0; - currentStat = 0; -} - -void ConditionAttributes::addCondition(Creature* creature, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - const ConditionAttributes& conditionAttrs = static_cast(*addCondition); - //Remove the old condition - endCondition(creature); - - //Apply the new one - memcpy(skills, conditionAttrs.skills, sizeof(skills)); - memcpy(skillsPercent, conditionAttrs.skillsPercent, sizeof(skillsPercent)); - memcpy(stats, conditionAttrs.stats, sizeof(stats)); - memcpy(statsPercent, conditionAttrs.statsPercent, sizeof(statsPercent)); - - if (Player* player = creature->getPlayer()) { - updatePercentSkills(player); - updateSkills(player); - updatePercentStats(player); - updateStats(player); - } - } -} - -bool ConditionAttributes::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_SKILLS) { - return propStream.read(skills[currentSkill++]); - } else if (attr == CONDITIONATTR_STATS) { - return propStream.read(stats[currentStat++]); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionAttributes::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - propWriteStream.write(CONDITIONATTR_SKILLS); - propWriteStream.write(skills[i]); - } - - for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { - propWriteStream.write(CONDITIONATTR_STATS); - propWriteStream.write(stats[i]); - } -} - -bool ConditionAttributes::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - if (Player* player = creature->getPlayer()) { - updatePercentSkills(player); - updateSkills(player); - updatePercentStats(player); - updateStats(player); - } - - return true; -} - -void ConditionAttributes::updatePercentStats(Player* player) -{ - for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { - if (statsPercent[i] == 0) { - continue; - } - - switch (i) { - case STAT_MAXHITPOINTS: - stats[i] = static_cast(player->getMaxHealth() * ((statsPercent[i] - 100) / 100.f)); - break; - - case STAT_MAXMANAPOINTS: - stats[i] = static_cast(player->getMaxMana() * ((statsPercent[i] - 100) / 100.f)); - break; - - case STAT_MAGICPOINTS: - stats[i] = static_cast(player->getMagicLevel() * ((statsPercent[i] - 100) / 100.f)); - break; - } - } -} - -void ConditionAttributes::updateStats(Player* player) -{ - bool needUpdateStats = false; - - for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { - if (stats[i]) { - needUpdateStats = true; - player->setVarStats(static_cast(i), stats[i]); - } - } - - if (needUpdateStats) { - player->sendStats(); - } -} - -void ConditionAttributes::updatePercentSkills(Player* player) -{ - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - if (skillsPercent[i] == 0) { - continue; - } - - int32_t unmodifiedSkill = player->getBaseSkill(i); - skills[i] = static_cast(unmodifiedSkill * ((skillsPercent[i] - 100) / 100.f)); - } -} - -void ConditionAttributes::updateSkills(Player* player) -{ - bool needUpdateSkills = false; - - for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - if (skills[i]) { - needUpdateSkills = true; - player->setVarSkill(static_cast(i), skills[i]); - } - } - - if (needUpdateSkills) { - player->sendSkills(); - } -} - -bool ConditionAttributes::executeCondition(Creature* creature, int32_t interval) -{ - return ConditionGeneric::executeCondition(creature, interval); -} - -void ConditionAttributes::endCondition(Creature* creature) -{ - Player* player = creature->getPlayer(); - if (player) { - bool needUpdateSkills = false; - - for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - if (skills[i] || skillsPercent[i]) { - needUpdateSkills = true; - player->setVarSkill(static_cast(i), -skills[i]); - } - } - - if (needUpdateSkills) { - player->sendSkills(); - } - - bool needUpdateStats = false; - - for (int32_t i = STAT_FIRST; i <= STAT_LAST; ++i) { - if (stats[i]) { - needUpdateStats = true; - player->setVarStats(static_cast(i), -stats[i]); - } - } - - if (needUpdateStats) { - player->sendStats(); - } - } -} - -bool ConditionAttributes::setParam(ConditionParam_t param, int32_t value) -{ - bool ret = ConditionGeneric::setParam(param, value); - - switch (param) { - case CONDITION_PARAM_SKILL_MELEE: { - skills[SKILL_CLUB] = value; - skills[SKILL_AXE] = value; - skills[SKILL_SWORD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_MELEEPERCENT: { - skillsPercent[SKILL_CLUB] = value; - skillsPercent[SKILL_AXE] = value; - skillsPercent[SKILL_SWORD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_FIST: { - skills[SKILL_FIST] = value; - return true; - } - - case CONDITION_PARAM_SKILL_FISTPERCENT: { - skillsPercent[SKILL_FIST] = value; - return true; - } - - case CONDITION_PARAM_SKILL_CLUB: { - skills[SKILL_CLUB] = value; - return true; - } - - case CONDITION_PARAM_SKILL_CLUBPERCENT: { - skillsPercent[SKILL_CLUB] = value; - return true; - } - - case CONDITION_PARAM_SKILL_SWORD: { - skills[SKILL_SWORD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_SWORDPERCENT: { - skillsPercent[SKILL_SWORD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_AXE: { - skills[SKILL_AXE] = value; - return true; - } - - case CONDITION_PARAM_SKILL_AXEPERCENT: { - skillsPercent[SKILL_AXE] = value; - return true; - } - - case CONDITION_PARAM_SKILL_DISTANCE: { - skills[SKILL_DISTANCE] = value; - return true; - } - - case CONDITION_PARAM_SKILL_DISTANCEPERCENT: { - skillsPercent[SKILL_DISTANCE] = value; - return true; - } - - case CONDITION_PARAM_SKILL_SHIELD: { - skills[SKILL_SHIELD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_SHIELDPERCENT: { - skillsPercent[SKILL_SHIELD] = value; - return true; - } - - case CONDITION_PARAM_SKILL_FISHING: { - skills[SKILL_FISHING] = value; - return true; - } - - case CONDITION_PARAM_SKILL_FISHINGPERCENT: { - skillsPercent[SKILL_FISHING] = value; - return true; - } - - case CONDITION_PARAM_STAT_MAXHITPOINTS: { - stats[STAT_MAXHITPOINTS] = value; - return true; - } - - case CONDITION_PARAM_STAT_MAXMANAPOINTS: { - stats[STAT_MAXMANAPOINTS] = value; - return true; - } - - case CONDITION_PARAM_STAT_MAGICPOINTS: { - stats[STAT_MAGICPOINTS] = value; - return true; - } - - case CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT: { - statsPercent[STAT_MAXHITPOINTS] = std::max(0, value); - return true; - } - - case CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT: { - statsPercent[STAT_MAXMANAPOINTS] = std::max(0, value); - return true; - } - - case CONDITION_PARAM_STAT_MAGICPOINTSPERCENT: { - statsPercent[STAT_MAGICPOINTS] = std::max(0, value); - return true; - } - - default: - return ret; - } -} - -ConditionRegeneration::ConditionRegeneration(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - ConditionGeneric(_id, _type, _ticks, _buff, _subId) -{ - internalHealthTicks = 0; - internalManaTicks = 0; - - healthTicks = 1000; - manaTicks = 1000; - - healthGain = 0; - manaGain = 0; -} - -void ConditionRegeneration::addCondition(Creature*, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - const ConditionRegeneration& conditionRegen = static_cast(*addCondition); - - healthTicks = conditionRegen.healthTicks; - manaTicks = conditionRegen.manaTicks; - - healthGain = conditionRegen.healthGain; - manaGain = conditionRegen.manaGain; - } -} - -bool ConditionRegeneration::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_HEALTHTICKS) { - return propStream.read(healthTicks); - } else if (attr == CONDITIONATTR_HEALTHGAIN) { - return propStream.read(healthGain); - } else if (attr == CONDITIONATTR_MANATICKS) { - return propStream.read(manaTicks); - } else if (attr == CONDITIONATTR_MANAGAIN) { - return propStream.read(manaGain); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionRegeneration::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - propWriteStream.write(CONDITIONATTR_HEALTHTICKS); - propWriteStream.write(healthTicks); - - propWriteStream.write(CONDITIONATTR_HEALTHGAIN); - propWriteStream.write(healthGain); - - propWriteStream.write(CONDITIONATTR_MANATICKS); - propWriteStream.write(manaTicks); - - propWriteStream.write(CONDITIONATTR_MANAGAIN); - propWriteStream.write(manaGain); -} - -bool ConditionRegeneration::executeCondition(Creature* creature, int32_t interval) -{ - internalHealthTicks += interval; - internalManaTicks += interval; - - if (creature->getZone() != ZONE_PROTECTION) { - if (internalHealthTicks >= healthTicks) { - internalHealthTicks = 0; - - int32_t realHealthGain = creature->getHealth(); - creature->changeHealth(healthGain); - realHealthGain = creature->getHealth() - realHealthGain; - - if (isBuff && realHealthGain > 0) { - Player* player = creature->getPlayer(); - if (player) { - std::string healString = std::to_string(realHealthGain) + (realHealthGain != 1 ? " hitpoints." : " hitpoint."); - - TextMessage message(MESSAGE_HEALED, "You were healed for " + healString); - message.position = player->getPosition(); - message.primary.value = realHealthGain; - message.primary.color = TEXTCOLOR_MAYABLUE; - player->sendTextMessage(message); - - SpectatorVec list; - g_game.map.getSpectators(list, player->getPosition(), false, true); - list.erase(player); - if (!list.empty()) { - message.type = MESSAGE_HEALED_OTHERS; - message.text = player->getName() + " was healed for " + healString; - for (Creature* spectator : list) { - spectator->getPlayer()->sendTextMessage(message); - } - } - } - } - } - - if (internalManaTicks >= manaTicks) { - internalManaTicks = 0; - creature->changeMana(manaGain); - } - } - - return ConditionGeneric::executeCondition(creature, interval); -} - -bool ConditionRegeneration::setParam(ConditionParam_t param, int32_t value) -{ - bool ret = ConditionGeneric::setParam(param, value); - - switch (param) { - case CONDITION_PARAM_HEALTHGAIN: - healthGain = value; - return true; - - case CONDITION_PARAM_HEALTHTICKS: - healthTicks = value; - return true; - - case CONDITION_PARAM_MANAGAIN: - manaGain = value; - return true; - - case CONDITION_PARAM_MANATICKS: - manaTicks = value; - return true; - - default: - return ret; - } -} - -ConditionSoul::ConditionSoul(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - ConditionGeneric(_id, _type, _ticks, _buff, _subId) -{ - internalSoulTicks = 0; - soulTicks = 0; - soulGain = 0; -} - -void ConditionSoul::addCondition(Creature*, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - const ConditionSoul& conditionSoul = static_cast(*addCondition); - - soulTicks = conditionSoul.soulTicks; - soulGain = conditionSoul.soulGain; - } -} - -bool ConditionSoul::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_SOULGAIN) { - return propStream.read(soulGain); - } else if (attr == CONDITIONATTR_SOULTICKS) { - return propStream.read(soulTicks); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionSoul::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - propWriteStream.write(CONDITIONATTR_SOULGAIN); - propWriteStream.write(soulGain); - - propWriteStream.write(CONDITIONATTR_SOULTICKS); - propWriteStream.write(soulTicks); -} - -bool ConditionSoul::executeCondition(Creature* creature, int32_t interval) -{ - internalSoulTicks += interval; - - if (Player* player = creature->getPlayer()) { - if (player->getZone() != ZONE_PROTECTION) { - if (internalSoulTicks >= soulTicks) { - internalSoulTicks = 0; - player->changeSoul(soulGain); - } - } - } - - return ConditionGeneric::executeCondition(creature, interval); -} - -bool ConditionSoul::setParam(ConditionParam_t param, int32_t value) -{ - bool ret = ConditionGeneric::setParam(param, value); - switch (param) { - case CONDITION_PARAM_SOULGAIN: - soulGain = value; - return true; - - case CONDITION_PARAM_SOULTICKS: - soulTicks = value; - return true; - - default: - return ret; - } -} - -ConditionDamage::ConditionDamage(ConditionId_t _id, ConditionType_t _type, bool _buff, uint32_t _subId) : - Condition(_id, _type, 0, _buff, _subId) -{ - delayed = false; - forceUpdate = false; - field = false; - owner = 0; - minDamage = 0; - maxDamage = 0; - startDamage = 0; - periodDamage = 0; - periodDamageTick = 0; - tickInterval = 2000; -} - -bool ConditionDamage::setParam(ConditionParam_t param, int32_t value) -{ - bool ret = Condition::setParam(param, value); - - switch (param) { - case CONDITION_PARAM_OWNER: - owner = value; - return true; - - case CONDITION_PARAM_FORCEUPDATE: - forceUpdate = (value != 0); - return true; - - case CONDITION_PARAM_DELAYED: - delayed = (value != 0); - return true; - - case CONDITION_PARAM_MAXVALUE: - maxDamage = std::abs(value); - break; - - case CONDITION_PARAM_MINVALUE: - minDamage = std::abs(value); - break; - - case CONDITION_PARAM_STARTVALUE: - startDamage = std::abs(value); - break; - - case CONDITION_PARAM_TICKINTERVAL: - tickInterval = std::abs(value); - break; - - case CONDITION_PARAM_PERIODICDAMAGE: - periodDamage = value; - break; - - case CONDITION_PARAM_FIELD: - field = (value != 0); - break; - - default: - return false; - } - - return ret; -} - -bool ConditionDamage::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_DELAYED) { - uint8_t value; - if (!propStream.read(value)) { - return false; - } - - delayed = (value != 0); - return true; - } else if (attr == CONDITIONATTR_PERIODDAMAGE) { - return propStream.read(periodDamage); - } else if (attr == CONDITIONATTR_OWNER) { - return propStream.skip(4); - } else if (attr == CONDITIONATTR_INTERVALDATA) { - IntervalInfo damageInfo; - if (!propStream.read(damageInfo)) { - return false; - } - - damageList.push_back(damageInfo); - if (ticks != -1) { - setTicks(ticks + damageInfo.interval); - } - return true; - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionDamage::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - propWriteStream.write(CONDITIONATTR_DELAYED); - propWriteStream.write(delayed); - - propWriteStream.write(CONDITIONATTR_PERIODDAMAGE); - propWriteStream.write(periodDamage); - - for (const IntervalInfo& intervalInfo : damageList) { - propWriteStream.write(CONDITIONATTR_INTERVALDATA); - propWriteStream.write(intervalInfo); - } -} - -bool ConditionDamage::updateCondition(const Condition* addCondition) -{ - const ConditionDamage& conditionDamage = static_cast(*addCondition); - if (conditionDamage.doForceUpdate()) { - return true; - } - - if (ticks == -1 && conditionDamage.ticks > 0) { - return false; - } - - return conditionDamage.getTotalDamage() > getTotalDamage(); -} - -bool ConditionDamage::addDamage(int32_t rounds, int32_t time, int32_t value) -{ - time = std::max(time, EVENT_CREATURE_THINK_INTERVAL); - if (rounds == -1) { - //periodic damage - periodDamage = value; - setParam(CONDITION_PARAM_TICKINTERVAL, time); - setParam(CONDITION_PARAM_TICKS, -1); - return true; - } - - if (periodDamage > 0) { - return false; - } - - //rounds, time, damage - for (int32_t i = 0; i < rounds; ++i) { - IntervalInfo damageInfo; - damageInfo.interval = time; - damageInfo.timeLeft = time; - damageInfo.value = value; - - damageList.push_back(damageInfo); - - if (ticks != -1) { - setTicks(ticks + damageInfo.interval); - } - } - - return true; -} - -bool ConditionDamage::init() -{ - if (periodDamage != 0) { - return true; - } - - if (damageList.empty()) { - setTicks(0); - - int32_t amount = uniform_random(minDamage, maxDamage); - if (amount != 0) { - if (startDamage > maxDamage) { - startDamage = maxDamage; - } else if (startDamage == 0) { - startDamage = std::max(1, std::ceil(amount / 20.0)); - } - - std::list list; - ConditionDamage::generateDamageList(amount, startDamage, list); - for (int32_t value : list) { - addDamage(1, tickInterval, -value); - } - } - } - return !damageList.empty(); -} - -bool ConditionDamage::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - if (!init()) { - return false; - } - - if (!delayed) { - int32_t damage; - if (getNextDamage(damage)) { - return doDamage(creature, damage); - } - } - return true; -} - -bool ConditionDamage::executeCondition(Creature* creature, int32_t interval) -{ - if (periodDamage != 0) { - periodDamageTick += interval; - - if (periodDamageTick >= tickInterval) { - periodDamageTick = 0; - doDamage(creature, periodDamage); - } - } else if (!damageList.empty()) { - IntervalInfo& damageInfo = damageList.front(); - - bool bRemove = (ticks != -1); - creature->onTickCondition(getType(), bRemove); - damageInfo.timeLeft -= interval; - - if (damageInfo.timeLeft <= 0) { - int32_t damage = damageInfo.value; - - if (bRemove) { - damageList.pop_front(); - } else { - damageInfo.timeLeft = damageInfo.interval; - } - - doDamage(creature, damage); - } - - if (!bRemove) { - if (ticks > 0) { - endTime += interval; - } - - interval = 0; - } - } - - return Condition::executeCondition(creature, interval); -} - -bool ConditionDamage::getNextDamage(int32_t& damage) -{ - if (periodDamage != 0) { - damage = periodDamage; - return true; - } else if (!damageList.empty()) { - IntervalInfo& damageInfo = damageList.front(); - damage = damageInfo.value; - if (ticks != -1) { - damageList.pop_front(); - } - return true; - } - return false; -} - -bool ConditionDamage::doDamage(Creature* creature, int32_t healthChange) -{ - if (creature->isSuppress(getType())) { - return true; - } - - CombatDamage damage; - damage.origin = ORIGIN_CONDITION; - damage.primary.value = healthChange; - damage.primary.type = Combat::ConditionToDamageType(conditionType); - - Creature* attacker = g_game.getCreatureByID(owner); - if (!creature->isAttackable() || Combat::canDoCombat(attacker, creature) != RETURNVALUE_NOERROR) { - if (!creature->isInGhostMode()) { - g_game.addMagicEffect(creature->getPosition(), CONST_ME_POFF); - } - return false; - } - - if (g_game.combatBlockHit(damage, attacker, creature, false, false, field)) { - return false; - } - return g_game.combatChangeHealth(attacker, creature, damage); -} - -void ConditionDamage::endCondition(Creature*) -{ - // -} - -void ConditionDamage::addCondition(Creature* creature, const Condition* addCondition) -{ - if (addCondition->getType() != conditionType) { - return; - } - - if (!updateCondition(addCondition)) { - return; - } - - const ConditionDamage& conditionDamage = static_cast(*addCondition); - - setTicks(addCondition->getTicks()); - owner = conditionDamage.owner; - maxDamage = conditionDamage.maxDamage; - minDamage = conditionDamage.minDamage; - startDamage = conditionDamage.startDamage; - tickInterval = conditionDamage.tickInterval; - periodDamage = conditionDamage.periodDamage; - int32_t nextTimeLeft = tickInterval; - - if (!damageList.empty()) { - //save previous timeLeft - IntervalInfo& damageInfo = damageList.front(); - nextTimeLeft = damageInfo.timeLeft; - damageList.clear(); - } - - damageList = conditionDamage.damageList; - - if (init()) { - if (!damageList.empty()) { - //restore last timeLeft - IntervalInfo& damageInfo = damageList.front(); - damageInfo.timeLeft = nextTimeLeft; - } - - if (!delayed) { - int32_t damage; - if (getNextDamage(damage)) { - doDamage(creature, damage); - } - } - } -} - -int32_t ConditionDamage::getTotalDamage() const -{ - int32_t result; - if (!damageList.empty()) { - result = 0; - for (const IntervalInfo& intervalInfo : damageList) { - result += intervalInfo.value; - } - } else { - result = minDamage + (maxDamage - minDamage) / 2; - } - return std::abs(result); -} - -uint32_t ConditionDamage::getIcons() const -{ - uint32_t icons = Condition::getIcons(); - switch (conditionType) { - case CONDITION_FIRE: - icons |= ICON_BURN; - break; - - case CONDITION_ENERGY: - icons |= ICON_ENERGY; - break; - - case CONDITION_DROWN: - icons |= ICON_DROWNING; - break; - - case CONDITION_POISON: - icons |= ICON_POISON; - break; - - case CONDITION_FREEZING: - icons |= ICON_FREEZING; - break; - - case CONDITION_DAZZLED: - icons |= ICON_DAZZLED; - break; - - case CONDITION_CURSED: - icons |= ICON_CURSED; - break; - - case CONDITION_BLEEDING: - icons |= ICON_BLEEDING; - break; - - default: - break; - } - return icons; -} - -void ConditionDamage::generateDamageList(int32_t amount, int32_t start, std::list& list) -{ - amount = std::abs(amount); - int32_t sum = 0; - double x1, x2; - - for (int32_t i = start; i > 0; --i) { - int32_t n = start + 1 - i; - int32_t med = (n * amount) / start; - - do { - sum += i; - list.push_back(i); - - x1 = std::fabs(1.0 - ((static_cast(sum)) + i) / med); - x2 = std::fabs(1.0 - (static_cast(sum) / med)); - } while (x1 < x2); - } -} - -ConditionSpeed::ConditionSpeed(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId, int32_t changeSpeed) : - Condition(_id, _type, _ticks, _buff, _subId) -{ - speedDelta = changeSpeed; - mina = 0.0f; - minb = 0.0f; - maxa = 0.0f; - maxb = 0.0f; -} - -void ConditionSpeed::setFormulaVars(float _mina, float _minb, float _maxa, float _maxb) -{ - mina = _mina; - minb = _minb; - maxa = _maxa; - maxb = _maxb; -} - -void ConditionSpeed::getFormulaValues(int32_t var, int32_t& min, int32_t& max) const -{ - min = (var * mina) + minb; - max = (var * maxa) + maxb; -} - -bool ConditionSpeed::setParam(ConditionParam_t param, int32_t value) -{ - Condition::setParam(param, value); - if (param != CONDITION_PARAM_SPEED) { - return false; - } - - speedDelta = value; - - if (value > 0) { - conditionType = CONDITION_HASTE; - } else { - conditionType = CONDITION_PARALYZE; - } - return true; -} - -bool ConditionSpeed::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_SPEEDDELTA) { - return propStream.read(speedDelta); - } else if (attr == CONDITIONATTR_FORMULA_MINA) { - return propStream.read(mina); - } else if (attr == CONDITIONATTR_FORMULA_MINB) { - return propStream.read(minb); - } else if (attr == CONDITIONATTR_FORMULA_MAXA) { - return propStream.read(maxa); - } else if (attr == CONDITIONATTR_FORMULA_MAXB) { - return propStream.read(maxb); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionSpeed::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - propWriteStream.write(CONDITIONATTR_SPEEDDELTA); - propWriteStream.write(speedDelta); - - propWriteStream.write(CONDITIONATTR_FORMULA_MINA); - propWriteStream.write(mina); - - propWriteStream.write(CONDITIONATTR_FORMULA_MINB); - propWriteStream.write(minb); - - propWriteStream.write(CONDITIONATTR_FORMULA_MAXA); - propWriteStream.write(maxa); - - propWriteStream.write(CONDITIONATTR_FORMULA_MAXB); - propWriteStream.write(maxb); -} - -bool ConditionSpeed::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - if (speedDelta == 0) { - int32_t min, max; - getFormulaValues(creature->getBaseSpeed(), min, max); - speedDelta = uniform_random(min, max); - } - - g_game.changeSpeed(creature, speedDelta); - return true; -} - -bool ConditionSpeed::executeCondition(Creature* creature, int32_t interval) -{ - return Condition::executeCondition(creature, interval); -} - -void ConditionSpeed::endCondition(Creature* creature) -{ - g_game.changeSpeed(creature, -speedDelta); -} - -void ConditionSpeed::addCondition(Creature* creature, const Condition* addCondition) -{ - if (conditionType != addCondition->getType()) { - return; - } - - if (ticks == -1 && addCondition->getTicks() > 0) { - return; - } - - setTicks(addCondition->getTicks()); - - const ConditionSpeed& conditionSpeed = static_cast(*addCondition); - int32_t oldSpeedDelta = speedDelta; - speedDelta = conditionSpeed.speedDelta; - mina = conditionSpeed.mina; - maxa = conditionSpeed.maxa; - minb = conditionSpeed.minb; - maxb = conditionSpeed.maxb; - - if (speedDelta == 0) { - int32_t min; - int32_t max; - getFormulaValues(creature->getBaseSpeed(), min, max); - speedDelta = uniform_random(min, max); - } - - int32_t newSpeedChange = (speedDelta - oldSpeedDelta); - if (newSpeedChange != 0) { - g_game.changeSpeed(creature, newSpeedChange); - } -} - -uint32_t ConditionSpeed::getIcons() const -{ - uint32_t icons = Condition::getIcons(); - switch (conditionType) { - case CONDITION_HASTE: - icons |= ICON_HASTE; - break; - - case CONDITION_PARALYZE: - icons |= ICON_PARALYZE; - break; - - default: - break; - } - return icons; -} - -ConditionInvisible::ConditionInvisible(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - ConditionGeneric(_id, _type, _ticks, _buff, _subId) -{ - // -} - -bool ConditionInvisible::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - g_game.internalCreatureChangeVisible(creature, false); - return true; -} - -void ConditionInvisible::endCondition(Creature* creature) -{ - if (!creature->isInvisible()) { - g_game.internalCreatureChangeVisible(creature, true); - } -} - -ConditionOutfit::ConditionOutfit(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - Condition(_id, _type, _ticks, _buff, _subId) -{ - // -} - -void ConditionOutfit::setOutfit(const Outfit_t& outfit) -{ - this->outfit = outfit; -} - -bool ConditionOutfit::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_OUTFIT) { - return propStream.read(outfit); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionOutfit::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - propWriteStream.write(CONDITIONATTR_OUTFIT); - propWriteStream.write(outfit); -} - -bool ConditionOutfit::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - g_game.internalCreatureChangeOutfit(creature, outfit); - return true; -} - -bool ConditionOutfit::executeCondition(Creature* creature, int32_t interval) -{ - return Condition::executeCondition(creature, interval); -} - -void ConditionOutfit::endCondition(Creature* creature) -{ - g_game.internalCreatureChangeOutfit(creature, creature->getDefaultOutfit()); -} - -void ConditionOutfit::addCondition(Creature* creature, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - const ConditionOutfit& conditionOutfit = static_cast(*addCondition); - outfit = conditionOutfit.outfit; - - g_game.internalCreatureChangeOutfit(creature, outfit); - } -} - -ConditionLight::ConditionLight(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId, uint8_t _lightlevel, uint8_t _lightcolor) : - Condition(_id, _type, _ticks, _buff, _subId) -{ - lightInfo.level = _lightlevel; - lightInfo.color = _lightcolor; - internalLightTicks = 0; - lightChangeInterval = 0; -} - -bool ConditionLight::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - internalLightTicks = 0; - lightChangeInterval = ticks / lightInfo.level; - creature->setCreatureLight(lightInfo); - g_game.changeLight(creature); - return true; -} - -bool ConditionLight::executeCondition(Creature* creature, int32_t interval) -{ - internalLightTicks += interval; - - if (internalLightTicks >= lightChangeInterval) { - internalLightTicks = 0; - LightInfo creatureLight; - creature->getCreatureLight(creatureLight); - - if (creatureLight.level > 0) { - --creatureLight.level; - creature->setCreatureLight(creatureLight); - g_game.changeLight(creature); - } - } - - return Condition::executeCondition(creature, interval); -} - -void ConditionLight::endCondition(Creature* creature) -{ - creature->setNormalCreatureLight(); - g_game.changeLight(creature); -} - -void ConditionLight::addCondition(Creature* creature, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - const ConditionLight& conditionLight = static_cast(*addCondition); - lightInfo.level = conditionLight.lightInfo.level; - lightInfo.color = conditionLight.lightInfo.color; - lightChangeInterval = ticks / lightInfo.level; - internalLightTicks = 0; - creature->setCreatureLight(lightInfo); - g_game.changeLight(creature); - } -} - -bool ConditionLight::setParam(ConditionParam_t param, int32_t value) -{ - bool ret = Condition::setParam(param, value); - if (ret) { - return false; - } - - switch (param) { - case CONDITION_PARAM_LIGHT_LEVEL: - lightInfo.level = value; - return true; - - case CONDITION_PARAM_LIGHT_COLOR: - lightInfo.color = value; - return true; - - default: - return false; - } -} - -bool ConditionLight::unserializeProp(ConditionAttr_t attr, PropStream& propStream) -{ - if (attr == CONDITIONATTR_LIGHTCOLOR) { - uint32_t value; - if (!propStream.read(value)) { - return false; - } - - lightInfo.color = value; - return true; - } else if (attr == CONDITIONATTR_LIGHTLEVEL) { - uint32_t value; - if (!propStream.read(value)) { - return false; - } - - lightInfo.level = value; - return true; - } else if (attr == CONDITIONATTR_LIGHTTICKS) { - return propStream.read(internalLightTicks); - } else if (attr == CONDITIONATTR_LIGHTINTERVAL) { - return propStream.read(lightChangeInterval); - } - return Condition::unserializeProp(attr, propStream); -} - -void ConditionLight::serialize(PropWriteStream& propWriteStream) -{ - Condition::serialize(propWriteStream); - - // TODO: color and level could be serialized as 8-bit if we can retain backwards - // compatibility, but perhaps we should keep it like this in case they increase - // in the future... - propWriteStream.write(CONDITIONATTR_LIGHTCOLOR); - propWriteStream.write(lightInfo.color); - - propWriteStream.write(CONDITIONATTR_LIGHTLEVEL); - propWriteStream.write(lightInfo.level); - - propWriteStream.write(CONDITIONATTR_LIGHTTICKS); - propWriteStream.write(internalLightTicks); - - propWriteStream.write(CONDITIONATTR_LIGHTINTERVAL); - propWriteStream.write(lightChangeInterval); -} - -ConditionSpellCooldown::ConditionSpellCooldown(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - ConditionGeneric(_id, _type, _ticks, _buff, _subId) -{ - // -} - -void ConditionSpellCooldown::addCondition(Creature* creature, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - if (subId != 0 && ticks > 0) { - Player* player = creature->getPlayer(); - if (player) { - player->sendSpellCooldown(subId, ticks); - } - } - } -} - -bool ConditionSpellCooldown::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - if (subId != 0 && ticks > 0) { - Player* player = creature->getPlayer(); - if (player) { - player->sendSpellCooldown(subId, ticks); - } - } - return true; -} - -ConditionSpellGroupCooldown::ConditionSpellGroupCooldown(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId) : - ConditionGeneric(_id, _type, _ticks, _buff, _subId) -{ - // -} - -void ConditionSpellGroupCooldown::addCondition(Creature* creature, const Condition* addCondition) -{ - if (updateCondition(addCondition)) { - setTicks(addCondition->getTicks()); - - if (subId != 0 && ticks > 0) { - Player* player = creature->getPlayer(); - if (player) { - player->sendSpellGroupCooldown(static_cast(subId), ticks); - } - } - } -} - -bool ConditionSpellGroupCooldown::startCondition(Creature* creature) -{ - if (!Condition::startCondition(creature)) { - return false; - } - - if (subId != 0 && ticks > 0) { - Player* player = creature->getPlayer(); - if (player) { - player->sendSpellGroupCooldown(static_cast(subId), ticks); - } - } - return true; -} diff --git a/path_10_8/src/condition.h b/path_10_8/src/condition.h deleted file mode 100644 index 1962975e9..000000000 --- a/path_10_8/src/condition.h +++ /dev/null @@ -1,405 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CONDITION_H_F92FF8BDDD5B4EA59E2B1BB5C9C0A086 -#define FS_CONDITION_H_F92FF8BDDD5B4EA59E2B1BB5C9C0A086 - -#include "fileloader.h" -#include "enums.h" - -class Creature; -class Player; -class PropStream; - -enum ConditionAttr_t { - CONDITIONATTR_TYPE = 1, - CONDITIONATTR_ID, - CONDITIONATTR_TICKS, - CONDITIONATTR_HEALTHTICKS, - CONDITIONATTR_HEALTHGAIN, - CONDITIONATTR_MANATICKS, - CONDITIONATTR_MANAGAIN, - CONDITIONATTR_DELAYED, - CONDITIONATTR_OWNER, - CONDITIONATTR_INTERVALDATA, - CONDITIONATTR_SPEEDDELTA, - CONDITIONATTR_FORMULA_MINA, - CONDITIONATTR_FORMULA_MINB, - CONDITIONATTR_FORMULA_MAXA, - CONDITIONATTR_FORMULA_MAXB, - CONDITIONATTR_LIGHTCOLOR, - CONDITIONATTR_LIGHTLEVEL, - CONDITIONATTR_LIGHTTICKS, - CONDITIONATTR_LIGHTINTERVAL, - CONDITIONATTR_SOULTICKS, - CONDITIONATTR_SOULGAIN, - CONDITIONATTR_SKILLS, - CONDITIONATTR_STATS, - CONDITIONATTR_OUTFIT, - CONDITIONATTR_PERIODDAMAGE, - CONDITIONATTR_ISBUFF, - CONDITIONATTR_SUBID, - - //reserved for serialization - CONDITIONATTR_END = 254, -}; - -struct IntervalInfo { - int32_t timeLeft; - int32_t value; - int32_t interval; -}; - -class Condition -{ - public: - Condition() = default; - Condition(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - virtual ~Condition() = default; - - virtual bool startCondition(Creature* creature); - virtual bool executeCondition(Creature* creature, int32_t interval); - virtual void endCondition(Creature* creature) = 0; - virtual void addCondition(Creature* creature, const Condition* condition) = 0; - virtual uint32_t getIcons() const; - ConditionId_t getId() const { - return id; - } - uint32_t getSubId() const { - return subId; - } - - virtual Condition* clone() const = 0; - - ConditionType_t getType() const { - return conditionType; - } - int64_t getEndTime() const { - return endTime; - } - int32_t getTicks() const { - return ticks; - } - void setTicks(int32_t newTicks); - - static Condition* createCondition(ConditionId_t _id, ConditionType_t _type, int32_t ticks, int32_t param = 0, bool _buff = false, uint32_t _subId = 0); - static Condition* createCondition(PropStream& propStream); - - virtual bool setParam(ConditionParam_t param, int32_t value); - - //serialization - bool unserialize(PropStream& propStream); - virtual void serialize(PropWriteStream& propWriteStream); - virtual bool unserializeProp(ConditionAttr_t attr, PropStream& propStream); - - bool isPersistent() const; - - protected: - int64_t endTime; - uint32_t subId; - int32_t ticks; - ConditionType_t conditionType; - ConditionId_t id; - bool isBuff; - - virtual bool updateCondition(const Condition* addCondition); -}; - -class ConditionGeneric : public Condition -{ - public: - ConditionGeneric(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) override; - bool executeCondition(Creature* creature, int32_t interval) override; - void endCondition(Creature* creature) override; - void addCondition(Creature* creature, const Condition* condition) override; - uint32_t getIcons() const override; - - ConditionGeneric* clone() const override { - return new ConditionGeneric(*this); - } -}; - -class ConditionAttributes final : public ConditionGeneric -{ - public: - ConditionAttributes(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) final; - bool executeCondition(Creature* creature, int32_t interval) final; - void endCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - - bool setParam(ConditionParam_t param, int32_t value) final; - - ConditionAttributes* clone() const final { - return new ConditionAttributes(*this); - } - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - int32_t skills[SKILL_LAST + 1]; - int32_t skillsPercent[SKILL_LAST + 1]; - int32_t stats[STAT_LAST + 1]; - int32_t statsPercent[STAT_LAST + 1]; - int32_t currentSkill; - int32_t currentStat; - - void updatePercentStats(Player* player); - void updateStats(Player* player); - void updatePercentSkills(Player* player); - void updateSkills(Player* player); -}; - -class ConditionRegeneration final : public ConditionGeneric -{ - public: - ConditionRegeneration(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - void addCondition(Creature* creature, const Condition* addCondition) final; - bool executeCondition(Creature* creature, int32_t interval) final; - - bool setParam(ConditionParam_t param, int32_t value) final; - - ConditionRegeneration* clone() const final { - return new ConditionRegeneration(*this); - } - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - uint32_t internalHealthTicks; - uint32_t internalManaTicks; - - uint32_t healthTicks; - uint32_t manaTicks; - uint32_t healthGain; - uint32_t manaGain; -}; - -class ConditionSoul final : public ConditionGeneric -{ - public: - ConditionSoul(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - void addCondition(Creature* creature, const Condition* addCondition) final; - bool executeCondition(Creature* creature, int32_t interval) final; - - bool setParam(ConditionParam_t param, int32_t value) final; - - ConditionSoul* clone() const final { - return new ConditionSoul(*this); - } - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - uint32_t internalSoulTicks; - uint32_t soulTicks; - uint32_t soulGain; -}; - -class ConditionInvisible final : public ConditionGeneric -{ - public: - ConditionInvisible(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) final; - void endCondition(Creature* creature) final; - - ConditionInvisible* clone() const final { - return new ConditionInvisible(*this); - } -}; - -class ConditionDamage final : public Condition -{ - public: - ConditionDamage() = default; - ConditionDamage(ConditionId_t _id, ConditionType_t _type, bool _buff = false, uint32_t _subId = 0); - - static void generateDamageList(int32_t amount, int32_t start, std::list& list); - - bool startCondition(Creature* creature) final; - bool executeCondition(Creature* creature, int32_t interval) final; - void endCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - uint32_t getIcons() const final; - - ConditionDamage* clone() const final { - return new ConditionDamage(*this); - } - - bool setParam(ConditionParam_t param, int32_t value) final; - - bool addDamage(int32_t rounds, int32_t time, int32_t value); - bool doForceUpdate() const { - return forceUpdate; - } - int32_t getTotalDamage() const; - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - int32_t maxDamage; - int32_t minDamage; - int32_t startDamage; - int32_t periodDamage; - int32_t periodDamageTick; - int32_t tickInterval; - - bool forceUpdate; - bool delayed; - bool field; - uint32_t owner; - - bool init(); - - std::list damageList; - - bool getNextDamage(int32_t& damage); - bool doDamage(Creature* creature, int32_t healthChange); - - bool updateCondition(const Condition* addCondition) final; -}; - -class ConditionSpeed final : public Condition -{ - public: - ConditionSpeed(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId, int32_t changeSpeed); - - bool startCondition(Creature* creature) final; - bool executeCondition(Creature* creature, int32_t interval) final; - void endCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - uint32_t getIcons() const final; - - ConditionSpeed* clone() const final { - return new ConditionSpeed(*this); - } - - bool setParam(ConditionParam_t param, int32_t value) final; - - void setFormulaVars(float _mina, float _minb, float _maxa, float _maxb); - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - void getFormulaValues(int32_t var, int32_t& min, int32_t& max) const; - - int32_t speedDelta; - - //formula variables - float mina; - float minb; - float maxa; - float maxb; -}; - -class ConditionOutfit final : public Condition -{ - public: - ConditionOutfit(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) final; - bool executeCondition(Creature* creature, int32_t interval) final; - void endCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - - ConditionOutfit* clone() const final { - return new ConditionOutfit(*this); - } - - void setOutfit(const Outfit_t& outfit); - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - Outfit_t outfit; - - void changeOutfit(Creature* creature); -}; - -class ConditionLight final : public Condition -{ - public: - ConditionLight(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff, uint32_t _subId, uint8_t _lightlevel, uint8_t _lightcolor); - - bool startCondition(Creature* creature) final; - bool executeCondition(Creature* creature, int32_t interval) final; - void endCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* addCondition) final; - - ConditionLight* clone() const final { - return new ConditionLight(*this); - } - - bool setParam(ConditionParam_t param, int32_t value) final; - - //serialization - void serialize(PropWriteStream& propWriteStream) final; - bool unserializeProp(ConditionAttr_t attr, PropStream& propStream) final; - - protected: - LightInfo lightInfo; - uint32_t internalLightTicks; - uint32_t lightChangeInterval; -}; - -class ConditionSpellCooldown final : public ConditionGeneric -{ - public: - ConditionSpellCooldown(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - - ConditionSpellCooldown* clone() const final { - return new ConditionSpellCooldown(*this); - } -}; - -class ConditionSpellGroupCooldown final : public ConditionGeneric -{ - public: - ConditionSpellGroupCooldown(ConditionId_t _id, ConditionType_t _type, int32_t _ticks, bool _buff = false, uint32_t _subId = 0); - - bool startCondition(Creature* creature) final; - void addCondition(Creature* creature, const Condition* condition) final; - - ConditionSpellGroupCooldown* clone() const final { - return new ConditionSpellGroupCooldown(*this); - } -}; - -#endif diff --git a/path_10_8/src/configmanager.cpp b/path_10_8/src/configmanager.cpp deleted file mode 100644 index 634b4b18b..000000000 --- a/path_10_8/src/configmanager.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "game.h" - -#if LUA_VERSION_NUM >= 502 -#define lua_strlen lua_rawlen -#endif - -extern Game g_game; - -ConfigManager::ConfigManager() -{ - loaded = false; -} - -bool ConfigManager::load() -{ - lua_State* L = luaL_newstate(); - if (!L) { - throw std::runtime_error("Failed to allocate memory"); - } - - luaL_openlibs(L); - - if (luaL_dofile(L, "config.lua")) { - std::cout << "[Error - ConfigManager::load] " << lua_tostring(L, -1) << std::endl; - lua_close(L); - return false; - } - - //parse config - if (!loaded) { //info that must be loaded one time (unless we reset the modules involved) - boolean[BIND_ONLY_GLOBAL_ADDRESS] = getGlobalBoolean(L, "bindOnlyGlobalAddress", false); - boolean[OPTIMIZE_DATABASE] = getGlobalBoolean(L, "startupDatabaseOptimization", true); - - string[IP] = getGlobalString(L, "ip", "127.0.0.1"); - string[MAP_NAME] = getGlobalString(L, "mapName", "forgotten"); - string[MAP_AUTHOR] = getGlobalString(L, "mapAuthor", "Unknown"); - string[HOUSE_RENT_PERIOD] = getGlobalString(L, "houseRentPeriod", "never"); - string[MYSQL_HOST] = getGlobalString(L, "mysqlHost", "127.0.0.1"); - string[MYSQL_USER] = getGlobalString(L, "mysqlUser", "forgottenserver"); - string[MYSQL_PASS] = getGlobalString(L, "mysqlPass", ""); - string[MYSQL_DB] = getGlobalString(L, "mysqlDatabase", "forgottenserver"); - string[MYSQL_SOCK] = getGlobalString(L, "mysqlSock", ""); - - integer[SQL_PORT] = getGlobalNumber(L, "mysqlPort", 3306); - integer[GAME_PORT] = getGlobalNumber(L, "gameProtocolPort", 7172); - integer[LOGIN_PORT] = getGlobalNumber(L, "loginProtocolPort", 7171); - integer[STATUS_PORT] = getGlobalNumber(L, "statusProtocolPort", 7171); - - integer[MARKET_OFFER_DURATION] = getGlobalNumber(L, "marketOfferDuration", 30 * 24 * 60 * 60); - } - - boolean[ALLOW_CHANGEOUTFIT] = getGlobalBoolean(L, "allowChangeOutfit", true); - boolean[ONE_PLAYER_ON_ACCOUNT] = getGlobalBoolean(L, "onePlayerOnlinePerAccount", true); - boolean[AIMBOT_HOTKEY_ENABLED] = getGlobalBoolean(L, "hotkeyAimbotEnabled", true); - boolean[REMOVE_RUNE_CHARGES] = getGlobalBoolean(L, "removeChargesFromRunes", true); - boolean[EXPERIENCE_FROM_PLAYERS] = getGlobalBoolean(L, "experienceByKillingPlayers", false); - boolean[FREE_PREMIUM] = getGlobalBoolean(L, "freePremium", false); - boolean[REPLACE_KICK_ON_LOGIN] = getGlobalBoolean(L, "replaceKickOnLogin", true); - boolean[ALLOW_CLONES] = getGlobalBoolean(L, "allowClones", false); - boolean[MARKET_PREMIUM] = getGlobalBoolean(L, "premiumToCreateMarketOffer", true); - boolean[EMOTE_SPELLS] = getGlobalBoolean(L, "emoteSpells", false); - boolean[STAMINA_SYSTEM] = getGlobalBoolean(L, "staminaSystem", true); - boolean[WARN_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "warnUnsafeScripts", true); - boolean[CONVERT_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "convertUnsafeScripts", true); - boolean[CLASSIC_EQUIPMENT_SLOTS] = getGlobalBoolean(L, "classicEquipmentSlots", false); - boolean[ALLOW_WALKTHROUGH] = getGlobalBoolean(L, "allowWalkthrough", true); - - string[DEFAULT_PRIORITY] = getGlobalString(L, "defaultPriority", "high"); - string[SERVER_NAME] = getGlobalString(L, "serverName", ""); - string[OWNER_NAME] = getGlobalString(L, "ownerName", ""); - string[OWNER_EMAIL] = getGlobalString(L, "ownerEmail", ""); - string[URL] = getGlobalString(L, "url", ""); - string[LOCATION] = getGlobalString(L, "location", ""); - string[MOTD] = getGlobalString(L, "motd", ""); - string[WORLD_TYPE] = getGlobalString(L, "worldType", "pvp"); - - integer[MAX_PLAYERS] = getGlobalNumber(L, "maxPlayers"); - integer[PZ_LOCKED] = getGlobalNumber(L, "pzLocked", 60000); - integer[DEFAULT_DESPAWNRANGE] = getGlobalNumber(L, "deSpawnRange", 2); - integer[DEFAULT_DESPAWNRADIUS] = getGlobalNumber(L, "deSpawnRadius", 50); - integer[RATE_EXPERIENCE] = getGlobalNumber(L, "rateExp", 5); - integer[RATE_SKILL] = getGlobalNumber(L, "rateSkill", 3); - integer[RATE_LOOT] = getGlobalNumber(L, "rateLoot", 2); - integer[RATE_MAGIC] = getGlobalNumber(L, "rateMagic", 3); - integer[RATE_SPAWN] = getGlobalNumber(L, "rateSpawn", 1); - integer[HOUSE_PRICE] = getGlobalNumber(L, "housePriceEachSQM", 1000); - integer[KILLS_TO_RED] = getGlobalNumber(L, "killsToRedSkull", 3); - integer[KILLS_TO_BLACK] = getGlobalNumber(L, "killsToBlackSkull", 6); - integer[ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenActions", 200); - integer[EX_ACTIONS_DELAY_INTERVAL] = getGlobalNumber(L, "timeBetweenExActions", 1000); - integer[MAX_MESSAGEBUFFER] = getGlobalNumber(L, "maxMessageBuffer", 4); - integer[KICK_AFTER_MINUTES] = getGlobalNumber(L, "kickIdlePlayerAfterMinutes", 15); - integer[PROTECTION_LEVEL] = getGlobalNumber(L, "protectionLevel", 1); - integer[DEATH_LOSE_PERCENT] = getGlobalNumber(L, "deathLosePercent", -1); - integer[STATUSQUERY_TIMEOUT] = getGlobalNumber(L, "statusTimeout", 5000); - integer[FRAG_TIME] = getGlobalNumber(L, "timeToDecreaseFrags", 24 * 60 * 60 * 1000); - integer[WHITE_SKULL_TIME] = getGlobalNumber(L, "whiteSkullTime", 15 * 60 * 1000); - integer[STAIRHOP_DELAY] = getGlobalNumber(L, "stairJumpExhaustion", 2000); - integer[EXP_FROM_PLAYERS_LEVEL_RANGE] = getGlobalNumber(L, "expFromPlayersLevelRange", 75); - integer[CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES] = getGlobalNumber(L, "checkExpiredMarketOffersEachMinutes", 60); - integer[MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER] = getGlobalNumber(L, "maxMarketOffersAtATimePerPlayer", 100); - integer[MAX_PACKETS_PER_SECOND] = getGlobalNumber(L, "maxPacketsPerSecond", 25); - integer[CRITICAL_HIT_CHANCE] = getGlobalNumber(L, "criticalChance", 0); - integer[CRITICAL_HIT_EXTRA] = getGlobalNumber(L, "criticalExtra", 0); - - loaded = true; - lua_close(L); - return true; -} - -bool ConfigManager::reload() -{ - bool result = load(); - if (transformToSHA1(getString(ConfigManager::MOTD)) != g_game.getMotdHash()) { - g_game.incrementMotdNum(); - } - return result; -} - -const std::string& ConfigManager::getString(string_config_t _what) const -{ - if (_what >= LAST_STRING_CONFIG) { - std::cout << "[Warning - ConfigManager::getString] Accessing invalid index: " << _what << std::endl; - return string[DUMMY_STR]; - } - return string[_what]; -} - -int32_t ConfigManager::getNumber(integer_config_t _what) const -{ - if (_what >= LAST_INTEGER_CONFIG) { - std::cout << "[Warning - ConfigManager::getNumber] Accessing invalid index: " << _what << std::endl; - return 0; - } - return integer[_what]; -} - -bool ConfigManager::getBoolean(boolean_config_t _what) const -{ - if (_what >= LAST_BOOLEAN_CONFIG) { - std::cout << "[Warning - ConfigManager::getBoolean] Accessing invalid index: " << _what << std::endl; - return false; - } - return boolean[_what]; -} - -std::string ConfigManager::getGlobalString(lua_State* L, const char* identifier, const char* _default) -{ - lua_getglobal(L, identifier); - if (!lua_isstring(L, -1)) { - return _default; - } - - size_t len = lua_strlen(L, -1); - std::string ret(lua_tostring(L, -1), len); - lua_pop(L, 1); - return ret; -} - -int32_t ConfigManager::getGlobalNumber(lua_State* L, const char* identifier, const int32_t _default) -{ - lua_getglobal(L, identifier); - if (!lua_isnumber(L, -1)) { - return _default; - } - - int32_t val = lua_tonumber(L, -1); - lua_pop(L, 1); - return val; -} - -bool ConfigManager::getGlobalBoolean(lua_State* L, const char* identifier, const bool _default) -{ - lua_getglobal(L, identifier); - if (!lua_isboolean(L, -1)) { - if (!lua_isstring(L, -1)) { - return _default; - } - - size_t len = lua_strlen(L, -1); - std::string ret(lua_tostring(L, -1), len); - lua_pop(L, 1); - return booleanString(ret); - } - - int val = lua_toboolean(L, -1); - lua_pop(L, 1); - return val != 0; -} diff --git a/path_10_8/src/configmanager.h b/path_10_8/src/configmanager.h deleted file mode 100644 index 0a16f8a16..000000000 --- a/path_10_8/src/configmanager.h +++ /dev/null @@ -1,132 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CONFIGMANAGER_H_6BDD23BD0B8344F4B7C40E8BE6AF6F39 -#define FS_CONFIGMANAGER_H_6BDD23BD0B8344F4B7C40E8BE6AF6F39 - -#include - -class ConfigManager -{ - public: - ConfigManager(); - - enum boolean_config_t { - ALLOW_CHANGEOUTFIT, - ONE_PLAYER_ON_ACCOUNT, - AIMBOT_HOTKEY_ENABLED, - REMOVE_RUNE_CHARGES, - EXPERIENCE_FROM_PLAYERS, - FREE_PREMIUM, - REPLACE_KICK_ON_LOGIN, - ALLOW_CLONES, - BIND_ONLY_GLOBAL_ADDRESS, - OPTIMIZE_DATABASE, - MARKET_PREMIUM, - EMOTE_SPELLS, - STAMINA_SYSTEM, - WARN_UNSAFE_SCRIPTS, - CONVERT_UNSAFE_SCRIPTS, - CLASSIC_EQUIPMENT_SLOTS, - ALLOW_WALKTHROUGH, - - LAST_BOOLEAN_CONFIG /* this must be the last one */ - }; - - enum string_config_t { - DUMMY_STR, - MAP_NAME, - HOUSE_RENT_PERIOD, - SERVER_NAME, - OWNER_NAME, - OWNER_EMAIL, - URL, - LOCATION, - IP, - MOTD, - WORLD_TYPE, - MYSQL_HOST, - MYSQL_USER, - MYSQL_PASS, - MYSQL_DB, - MYSQL_SOCK, - DEFAULT_PRIORITY, - MAP_AUTHOR, - - LAST_STRING_CONFIG /* this must be the last one */ - }; - - enum integer_config_t { - SQL_PORT, - MAX_PLAYERS, - PZ_LOCKED, - DEFAULT_DESPAWNRANGE, - DEFAULT_DESPAWNRADIUS, - RATE_EXPERIENCE, - RATE_SKILL, - RATE_LOOT, - RATE_MAGIC, - RATE_SPAWN, - HOUSE_PRICE, - KILLS_TO_RED, - KILLS_TO_BLACK, - MAX_MESSAGEBUFFER, - ACTIONS_DELAY_INTERVAL, - EX_ACTIONS_DELAY_INTERVAL, - KICK_AFTER_MINUTES, - PROTECTION_LEVEL, - DEATH_LOSE_PERCENT, - STATUSQUERY_TIMEOUT, - FRAG_TIME, - WHITE_SKULL_TIME, - GAME_PORT, - LOGIN_PORT, - STATUS_PORT, - STAIRHOP_DELAY, - MARKET_OFFER_DURATION, - CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES, - MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER, - EXP_FROM_PLAYERS_LEVEL_RANGE, - MAX_PACKETS_PER_SECOND, - CRITICAL_HIT_CHANCE, - CRITICAL_HIT_EXTRA, - - LAST_INTEGER_CONFIG /* this must be the last one */ - }; - - bool load(); - bool reload(); - - const std::string& getString(string_config_t _what) const; - int32_t getNumber(integer_config_t _what) const; - bool getBoolean(boolean_config_t _what) const; - - private: - static std::string getGlobalString(lua_State* L, const char* identifier, const char* _default); - static int32_t getGlobalNumber(lua_State* L, const char* identifier, const int32_t _default = 0); - static bool getGlobalBoolean(lua_State* L, const char* identifier, const bool _default); - - std::string string[LAST_STRING_CONFIG]; - int32_t integer[LAST_INTEGER_CONFIG]; - bool boolean[LAST_BOOLEAN_CONFIG]; - - bool loaded; -}; - -#endif diff --git a/path_10_8/src/connection.cpp b/path_10_8/src/connection.cpp deleted file mode 100644 index 7f6242618..000000000 --- a/path_10_8/src/connection.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "connection.h" -#include "outputmessage.h" -#include "protocol.h" -#include "scheduler.h" -#include "server.h" - -extern ConfigManager g_config; - -Connection_ptr ConnectionManager::createConnection(boost::asio::io_service& io_service, ConstServicePort_ptr servicePort) -{ - std::lock_guard lockClass(connectionManagerLock); - - auto connection = std::make_shared(io_service, servicePort); - connections.insert(connection); - return connection; -} - -void ConnectionManager::releaseConnection(const Connection_ptr& connection) -{ - std::lock_guard lockClass(connectionManagerLock); - - connections.erase(connection); -} - -void ConnectionManager::closeAll() -{ - std::lock_guard lockClass(connectionManagerLock); - - for (const auto& connection : connections) { - try { - boost::system::error_code error; - connection->socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error); - connection->socket.close(error); - } catch (boost::system::system_error&) { - } - } - connections.clear(); -} - -// Connection - -void Connection::close(bool force) -{ - //any thread - ConnectionManager::getInstance().releaseConnection(shared_from_this()); - - std::lock_guard lockClass(connectionLock); - if (connectionState != CONNECTION_STATE_OPEN) { - return; - } - connectionState = CONNECTION_STATE_CLOSED; - - if (protocol) { - g_dispatcher.addTask( - createTask(std::bind(&Protocol::release, protocol))); - } - - if (messageQueue.empty() || force) { - closeSocket(); - } else { - //will be closed by the destructor or onWriteOperation - } -} - -void Connection::closeSocket() -{ - if (socket.is_open()) { - try { - readTimer.cancel(); - writeTimer.cancel(); - boost::system::error_code error; - socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, error); - socket.close(error); - } catch (boost::system::system_error& e) { - std::cout << "[Network error - Connection::closeSocket] " << e.what() << std::endl; - } - } -} - -Connection::~Connection() -{ - closeSocket(); -} - -void Connection::accept(Protocol_ptr protocol) -{ - this->protocol = protocol; - g_dispatcher.addTask(createTask(std::bind(&Protocol::onConnect, protocol))); - - accept(); -} - -void Connection::accept() -{ - std::lock_guard lockClass(connectionLock); - try { - readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), std::placeholders::_1)); - - // Read size of the first packet - boost::asio::async_read(socket, - boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), - std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); - } catch (boost::system::system_error& e) { - std::cout << "[Network error - Connection::accept] " << e.what() << std::endl; - close(FORCE_CLOSE); - } -} - -void Connection::parseHeader(const boost::system::error_code& error) -{ - std::lock_guard lockClass(connectionLock); - readTimer.cancel(); - - int32_t size = msg.decodeHeader(); - if (error || size <= 0 || size >= NETWORKMESSAGE_MAXSIZE - 16) { - close(FORCE_CLOSE); - } - - if (connectionState != CONNECTION_STATE_OPEN) { - return; - } - - uint32_t timePassed = std::max(1, (time(nullptr) - timeConnected) + 1); - if ((++packetsSent / timePassed) > static_cast(g_config.getNumber(ConfigManager::MAX_PACKETS_PER_SECOND))) { - std::cout << convertIPToString(getIP()) << " disconnected for exceeding packet per second limit." << std::endl; - close(); - return; - } - - if (timePassed > 2) { - timeConnected = time(nullptr); - packetsSent = 0; - } - - try { - readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), - std::placeholders::_1)); - - // Read packet content - msg.setLength(size + NetworkMessage::HEADER_LENGTH); - boost::asio::async_read(socket, boost::asio::buffer(msg.getBodyBuffer(), size), - std::bind(&Connection::parsePacket, shared_from_this(), std::placeholders::_1)); - } catch (boost::system::system_error& e) { - std::cout << "[Network error - Connection::parseHeader] " << e.what() << std::endl; - close(FORCE_CLOSE); - } -} - -void Connection::parsePacket(const boost::system::error_code& error) -{ - std::lock_guard lockClass(connectionLock); - readTimer.cancel(); - - if (error) { - close(FORCE_CLOSE); - } - - if (connectionState != CONNECTION_STATE_OPEN) { - return; - } - - //Check packet checksum - uint32_t checksum; - int32_t len = msg.getLength() - msg.getBufferPosition() - NetworkMessage::CHECKSUM_LENGTH; - if (len > 0) { - checksum = adlerChecksum(msg.getBuffer() + msg.getBufferPosition() + NetworkMessage::CHECKSUM_LENGTH, len); - } else { - checksum = 0; - } - - uint32_t recvChecksum = msg.get(); - if (recvChecksum != checksum) { - // it might not have been the checksum, step back - msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH); - } - - if (!receivedFirst) { - // First message received - receivedFirst = true; - - if (!protocol) { - // Game protocol has already been created at this point - protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this()); - if (!protocol) { - close(FORCE_CLOSE); - return; - } - } else { - msg.skipBytes(1); // Skip protocol ID - } - - protocol->onRecvFirstMessage(msg); - } else { - protocol->onRecvMessage(msg); // Send the packet to the current protocol - } - - try { - readTimer.expires_from_now(boost::posix_time::seconds(Connection::read_timeout)); - readTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), - std::placeholders::_1)); - - // Wait to the next packet - boost::asio::async_read(socket, - boost::asio::buffer(msg.getBuffer(), NetworkMessage::HEADER_LENGTH), - std::bind(&Connection::parseHeader, shared_from_this(), std::placeholders::_1)); - } catch (boost::system::system_error& e) { - std::cout << "[Network error - Connection::parsePacket] " << e.what() << std::endl; - close(FORCE_CLOSE); - } -} - -void Connection::send(const OutputMessage_ptr& msg) -{ - std::lock_guard lockClass(connectionLock); - if (connectionState != CONNECTION_STATE_OPEN) { - return; - } - - bool noPendingWrite = messageQueue.empty(); - messageQueue.emplace_back(msg); - if (noPendingWrite) { - internalSend(msg); - } -} - -void Connection::internalSend(const OutputMessage_ptr& msg) -{ - protocol->onSendMessage(msg); - try { - writeTimer.expires_from_now(boost::posix_time::seconds(Connection::write_timeout)); - writeTimer.async_wait(std::bind(&Connection::handleTimeout, std::weak_ptr(shared_from_this()), - std::placeholders::_1)); - - boost::asio::async_write(socket, - boost::asio::buffer(msg->getOutputBuffer(), msg->getLength()), - std::bind(&Connection::onWriteOperation, shared_from_this(), std::placeholders::_1)); - } catch (boost::system::system_error& e) { - std::cout << "[Network error - Connection::internalSend] " << e.what() << std::endl; - close(FORCE_CLOSE); - } -} - -uint32_t Connection::getIP() -{ - std::lock_guard lockClass(connectionLock); - - // IP-address is expressed in network byte order - boost::system::error_code error; - const boost::asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(error); - if (error) { - return 0; - } - - return htonl(endpoint.address().to_v4().to_ulong()); -} - -void Connection::onWriteOperation(const boost::system::error_code& error) -{ - std::lock_guard lockClass(connectionLock); - writeTimer.cancel(); - messageQueue.pop_front(); - - if (error) { - messageQueue.clear(); - close(FORCE_CLOSE); - return; - } - - if (!messageQueue.empty()) { - internalSend(messageQueue.front()); - } else if (connectionState == CONNECTION_STATE_CLOSED) { - closeSocket(); - } -} - -void Connection::handleTimeout(ConnectionWeak_ptr connectionWeak, const boost::system::error_code& error) -{ - if (error == boost::asio::error::operation_aborted) { - //The timer has been manually cancelled - return; - } - - if (auto connection = connectionWeak.lock()) { - connection->close(FORCE_CLOSE); - } -} diff --git a/path_10_8/src/connection.h b/path_10_8/src/connection.h deleted file mode 100644 index b2c242cb6..000000000 --- a/path_10_8/src/connection.h +++ /dev/null @@ -1,137 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CONNECTION_H_FC8E1B4392D24D27A2F129D8B93A6348 -#define FS_CONNECTION_H_FC8E1B4392D24D27A2F129D8B93A6348 - -#include - -#include "networkmessage.h" - -class Protocol; -typedef std::shared_ptr Protocol_ptr; -class OutputMessage; -typedef std::shared_ptr OutputMessage_ptr; -class Connection; -typedef std::shared_ptr Connection_ptr; -typedef std::weak_ptr ConnectionWeak_ptr; -class ServiceBase; -typedef std::shared_ptr Service_ptr; -class ServicePort; -typedef std::shared_ptr ServicePort_ptr; -typedef std::shared_ptr ConstServicePort_ptr; - -class ConnectionManager -{ - public: - static ConnectionManager& getInstance() { - static ConnectionManager instance; - return instance; - } - - Connection_ptr createConnection(boost::asio::io_service& io_service, ConstServicePort_ptr servicePort); - void releaseConnection(const Connection_ptr& connection); - void closeAll(); - - protected: - ConnectionManager() = default; - - std::unordered_set connections; - std::mutex connectionManagerLock; -}; - -class Connection : public std::enable_shared_from_this -{ - public: - // non-copyable - Connection(const Connection&) = delete; - Connection& operator=(const Connection&) = delete; - - enum { write_timeout = 30 }; - enum { read_timeout = 30 }; - - enum ConnectionState_t { - CONNECTION_STATE_OPEN, - CONNECTION_STATE_CLOSED, - }; - - enum { FORCE_CLOSE = true }; - - Connection(boost::asio::io_service& io_service, - ConstServicePort_ptr service_port) : - readTimer(io_service), - writeTimer(io_service), - service_port(service_port), - socket(io_service) { - connectionState = CONNECTION_STATE_OPEN; - receivedFirst = false; - packetsSent = 0; - timeConnected = time(nullptr); - } - ~Connection(); - - friend class ConnectionManager; - - void close(bool force = false); - // Used by protocols that require server to send first - void accept(Protocol_ptr protocol); - void accept(); - - void send(const OutputMessage_ptr& msg); - - uint32_t getIP(); - - private: - void parseHeader(const boost::system::error_code& error); - void parsePacket(const boost::system::error_code& error); - - void onWriteOperation(const boost::system::error_code& error); - - static void handleTimeout(ConnectionWeak_ptr connectionWeak, const boost::system::error_code& error); - - void closeSocket(); - void internalSend(const OutputMessage_ptr& msg); - - boost::asio::ip::tcp::socket& getSocket() { - return socket; - } - friend class ServicePort; - - NetworkMessage msg; - - boost::asio::deadline_timer readTimer; - boost::asio::deadline_timer writeTimer; - - std::recursive_mutex connectionLock; - - std::list messageQueue; - - ConstServicePort_ptr service_port; - Protocol_ptr protocol; - - boost::asio::ip::tcp::socket socket; - - time_t timeConnected; - uint32_t packetsSent; - - bool connectionState; - bool receivedFirst; -}; - -#endif diff --git a/path_10_8/src/const.h b/path_10_8/src/const.h deleted file mode 100644 index 16a31dbe5..000000000 --- a/path_10_8/src/const.h +++ /dev/null @@ -1,542 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CONST_H_0A49B5996F074465BF44B90F4F780E8B -#define FS_CONST_H_0A49B5996F074465BF44B90F4F780E8B - -#define NETWORKMESSAGE_MAXSIZE 24590 - -enum MagicEffectClasses : uint8_t { - CONST_ME_NONE, - - CONST_ME_DRAWBLOOD = 1, - CONST_ME_LOSEENERGY = 2, - CONST_ME_POFF = 3, - CONST_ME_BLOCKHIT = 4, - CONST_ME_EXPLOSIONAREA = 5, - CONST_ME_EXPLOSIONHIT = 6, - CONST_ME_FIREAREA = 7, - CONST_ME_YELLOW_RINGS = 8, - CONST_ME_GREEN_RINGS = 9, - CONST_ME_HITAREA = 10, - CONST_ME_TELEPORT = 11, - CONST_ME_ENERGYHIT = 12, - CONST_ME_MAGIC_BLUE = 13, - CONST_ME_MAGIC_RED = 14, - CONST_ME_MAGIC_GREEN = 15, - CONST_ME_HITBYFIRE = 16, - CONST_ME_HITBYPOISON = 17, - CONST_ME_MORTAREA = 18, - CONST_ME_SOUND_GREEN = 19, - CONST_ME_SOUND_RED = 20, - CONST_ME_POISONAREA = 21, - CONST_ME_SOUND_YELLOW = 22, - CONST_ME_SOUND_PURPLE = 23, - CONST_ME_SOUND_BLUE = 24, - CONST_ME_SOUND_WHITE = 25, - CONST_ME_BUBBLES = 26, - CONST_ME_CRAPS = 27, - CONST_ME_GIFT_WRAPS = 28, - CONST_ME_FIREWORK_YELLOW = 29, - CONST_ME_FIREWORK_RED = 30, - CONST_ME_FIREWORK_BLUE = 31, - CONST_ME_STUN = 32, - CONST_ME_SLEEP = 33, - CONST_ME_WATERCREATURE = 34, - CONST_ME_GROUNDSHAKER = 35, - CONST_ME_HEARTS = 36, - CONST_ME_FIREATTACK = 37, - CONST_ME_ENERGYAREA = 38, - CONST_ME_SMALLCLOUDS = 39, - CONST_ME_HOLYDAMAGE = 40, - CONST_ME_BIGCLOUDS = 41, - CONST_ME_ICEAREA = 42, - CONST_ME_ICETORNADO = 43, - CONST_ME_ICEATTACK = 44, - CONST_ME_STONES = 45, - CONST_ME_SMALLPLANTS = 46, - CONST_ME_CARNIPHILA = 47, - CONST_ME_PURPLEENERGY = 48, - CONST_ME_YELLOWENERGY = 49, - CONST_ME_HOLYAREA = 50, - CONST_ME_BIGPLANTS = 51, - CONST_ME_CAKE = 52, - CONST_ME_GIANTICE = 53, - CONST_ME_WATERSPLASH = 54, - CONST_ME_PLANTATTACK = 55, - CONST_ME_TUTORIALARROW = 56, - CONST_ME_TUTORIALSQUARE = 57, - CONST_ME_MIRRORHORIZONTAL = 58, - CONST_ME_MIRRORVERTICAL = 59, - CONST_ME_SKULLHORIZONTAL = 60, - CONST_ME_SKULLVERTICAL = 61, - CONST_ME_ASSASSIN = 62, - CONST_ME_STEPSHORIZONTAL = 63, - CONST_ME_BLOODYSTEPS = 64, - CONST_ME_STEPSVERTICAL = 65, - CONST_ME_YALAHARIGHOST = 66, - CONST_ME_BATS = 67, - CONST_ME_SMOKE = 68, - CONST_ME_INSECTS = 69, - CONST_ME_DRAGONHEAD = 70, - CONST_ME_ORCSHAMAN = 71, - CONST_ME_ORCSHAMAN_FIRE = 72, - CONST_ME_THUNDER = 73, - CONST_ME_FERUMBRAS = 74, - CONST_ME_CONFETTI_HORIZONTAL = 75, - CONST_ME_CONFETTI_VERTICAL = 76, - // 77-157 are empty - CONST_ME_BLACKSMOKE = 158, - // 159-166 are empty - CONST_ME_REDSMOKE = 167, - CONST_ME_YELLOWSMOKE = 168, - CONST_ME_GREENSMOKE = 169, - CONST_ME_PURPLESMOKE = 170, - - CONST_ME_LAST = CONST_ME_PURPLESMOKE, -}; - -enum ShootType_t : uint8_t { - CONST_ANI_NONE, - - CONST_ANI_SPEAR = 1, - CONST_ANI_BOLT = 2, - CONST_ANI_ARROW = 3, - CONST_ANI_FIRE = 4, - CONST_ANI_ENERGY = 5, - CONST_ANI_POISONARROW = 6, - CONST_ANI_BURSTARROW = 7, - CONST_ANI_THROWINGSTAR = 8, - CONST_ANI_THROWINGKNIFE = 9, - CONST_ANI_SMALLSTONE = 10, - CONST_ANI_DEATH = 11, - CONST_ANI_LARGEROCK = 12, - CONST_ANI_SNOWBALL = 13, - CONST_ANI_POWERBOLT = 14, - CONST_ANI_POISON = 15, - CONST_ANI_INFERNALBOLT = 16, - CONST_ANI_HUNTINGSPEAR = 17, - CONST_ANI_ENCHANTEDSPEAR = 18, - CONST_ANI_REDSTAR = 19, - CONST_ANI_GREENSTAR = 20, - CONST_ANI_ROYALSPEAR = 21, - CONST_ANI_SNIPERARROW = 22, - CONST_ANI_ONYXARROW = 23, - CONST_ANI_PIERCINGBOLT = 24, - CONST_ANI_WHIRLWINDSWORD = 25, - CONST_ANI_WHIRLWINDAXE = 26, - CONST_ANI_WHIRLWINDCLUB = 27, - CONST_ANI_ETHEREALSPEAR = 28, - CONST_ANI_ICE = 29, - CONST_ANI_EARTH = 30, - CONST_ANI_HOLY = 31, - CONST_ANI_SUDDENDEATH = 32, - CONST_ANI_FLASHARROW = 33, - CONST_ANI_FLAMMINGARROW = 34, - CONST_ANI_SHIVERARROW = 35, - CONST_ANI_ENERGYBALL = 36, - CONST_ANI_SMALLICE = 37, - CONST_ANI_SMALLHOLY = 38, - CONST_ANI_SMALLEARTH = 39, - CONST_ANI_EARTHARROW = 40, - CONST_ANI_EXPLOSION = 41, - CONST_ANI_CAKE = 42, - - CONST_ANI_TARSALARROW = 44, - CONST_ANI_VORTEXBOLT = 45, - - CONST_ANI_PRISMATICBOLT = 48, - CONST_ANI_CRYSTALLINEARROW = 49, - CONST_ANI_DRILLBOLT = 50, - CONST_ANI_ENVENOMEDARROW = 51, - - CONST_ANI_GLOOTHSPEAR = 53, - CONST_ANI_SIMPLEARROW = 54, - - CONST_ANI_LAST = CONST_ANI_SIMPLEARROW, - - // for internal use, don't send to client - CONST_ANI_WEAPONTYPE = 0xFE, // 254 -}; - -enum SpeakClasses : uint8_t { - TALKTYPE_SAY = 1, - TALKTYPE_WHISPER = 2, - TALKTYPE_YELL = 3, - TALKTYPE_PRIVATE_FROM = 4, - TALKTYPE_PRIVATE_TO = 5, - TALKTYPE_CHANNEL_Y = 7, - TALKTYPE_CHANNEL_O = 8, - TALKTYPE_PRIVATE_NP = 10, - TALKTYPE_PRIVATE_PN = 12, - TALKTYPE_BROADCAST = 13, - TALKTYPE_CHANNEL_R1 = 14, //red - #c text - TALKTYPE_PRIVATE_RED_FROM = 15, //@name@text - TALKTYPE_PRIVATE_RED_TO = 16, //@name@text - TALKTYPE_MONSTER_SAY = 36, - TALKTYPE_MONSTER_YELL = 37, - - TALKTYPE_CHANNEL_R2 = 0xFF, //#d -}; - -enum MessageClasses : uint8_t { - MESSAGE_STATUS_CONSOLE_BLUE = 4, /*FIXME Blue message in the console*/ - - MESSAGE_STATUS_CONSOLE_RED = 13, /*Red message in the console*/ - - MESSAGE_STATUS_DEFAULT = 17, /*White message at the bottom of the game window and in the console*/ - MESSAGE_STATUS_WARNING = 18, /*Red message in game window and in the console*/ - MESSAGE_EVENT_ADVANCE = 19, /*White message in game window and in the console*/ - - MESSAGE_STATUS_SMALL = 21, /*White message at the bottom of the game window"*/ - MESSAGE_INFO_DESCR = 22, /*Green message in game window and in the console*/ - MESSAGE_DAMAGE_DEALT = 23, - MESSAGE_DAMAGE_RECEIVED = 24, - MESSAGE_HEALED = 25, - MESSAGE_EXPERIENCE = 26, - MESSAGE_DAMAGE_OTHERS = 27, - MESSAGE_HEALED_OTHERS = 28, - MESSAGE_EXPERIENCE_OTHERS = 29, - MESSAGE_EVENT_DEFAULT = 30, /*White message at the bottom of the game window and in the console*/ - MESSAGE_LOOT = 31, - - MESSAGE_EVENT_ORANGE = 36, /*Orange message in the console*/ - MESSAGE_STATUS_CONSOLE_ORANGE = 37, /*Orange message in the console*/ -}; - -enum FluidColors_t : uint8_t { - FLUID_EMPTY, - FLUID_BLUE, - FLUID_RED, - FLUID_BROWN, - FLUID_GREEN, - FLUID_YELLOW, - FLUID_WHITE, - FLUID_PURPLE, -}; - -enum FluidTypes_t : uint8_t { - FLUID_NONE = FLUID_EMPTY, - FLUID_WATER = FLUID_BLUE, - FLUID_BLOOD = FLUID_RED, - FLUID_BEER = FLUID_BROWN, - FLUID_SLIME = FLUID_GREEN, - FLUID_LEMONADE = FLUID_YELLOW, - FLUID_MILK = FLUID_WHITE, - FLUID_MANA = FLUID_PURPLE, - - FLUID_LIFE = FLUID_RED + 8, - FLUID_OIL = FLUID_BROWN + 8, - FLUID_URINE = FLUID_YELLOW + 8, - FLUID_COCONUTMILK = FLUID_WHITE + 8, - FLUID_WINE = FLUID_PURPLE + 8, - - FLUID_MUD = FLUID_BROWN + 16, - FLUID_FRUITJUICE = FLUID_YELLOW + 16, - - FLUID_LAVA = FLUID_RED + 24, - FLUID_RUM = FLUID_BROWN + 24, - FLUID_SWAMP = FLUID_GREEN + 24, - - FLUID_TEA = FLUID_BROWN + 32, - - FLUID_MEAD = FLUID_BROWN + 40, -}; - -const uint8_t reverseFluidMap[] = { - FLUID_EMPTY, - FLUID_WATER, - FLUID_MANA, - FLUID_BEER, - FLUID_EMPTY, - FLUID_BLOOD, - FLUID_SLIME, - FLUID_EMPTY, - FLUID_LEMONADE, - FLUID_MILK, -}; - -const uint8_t clientToServerFluidMap[] = { - FLUID_EMPTY, - FLUID_WATER, - FLUID_MANA, - FLUID_BEER, - FLUID_MUD, - FLUID_BLOOD, - FLUID_SLIME, - FLUID_RUM, - FLUID_LEMONADE, - FLUID_MILK, - FLUID_WINE, - FLUID_LIFE, - FLUID_URINE, - FLUID_OIL, - FLUID_FRUITJUICE, - FLUID_COCONUTMILK, - FLUID_TEA, - FLUID_MEAD, -}; - -enum ClientFluidTypes_t : uint8_t { - CLIENTFLUID_EMPTY = 0, - CLIENTFLUID_BLUE = 1, - CLIENTFLUID_PURPLE = 2, - CLIENTFLUID_BROWN_1 = 3, - CLIENTFLUID_BROWN_2 = 4, - CLIENTFLUID_RED = 5, - CLIENTFLUID_GREEN = 6, - CLIENTFLUID_BROWN = 7, - CLIENTFLUID_YELLOW = 8, - CLIENTFLUID_WHITE = 9, -}; - -const uint8_t fluidMap[] = { - CLIENTFLUID_EMPTY, - CLIENTFLUID_BLUE, - CLIENTFLUID_RED, - CLIENTFLUID_BROWN_1, - CLIENTFLUID_GREEN, - CLIENTFLUID_YELLOW, - CLIENTFLUID_WHITE, - CLIENTFLUID_PURPLE, -}; - -enum SquareColor_t : uint8_t { - SQ_COLOR_BLACK = 0, -}; - -enum TextColor_t : uint8_t { - TEXTCOLOR_BLUE = 5, - TEXTCOLOR_LIGHTGREEN = 30, - TEXTCOLOR_LIGHTBLUE = 35, - TEXTCOLOR_MAYABLUE = 95, - TEXTCOLOR_DARKRED = 108, - TEXTCOLOR_LIGHTGREY = 129, - TEXTCOLOR_SKYBLUE = 143, - TEXTCOLOR_PURPLE = 154, - TEXTCOLOR_RED = 180, - TEXTCOLOR_ORANGE = 198, - TEXTCOLOR_YELLOW = 210, - TEXTCOLOR_WHITE_EXP = 215, - TEXTCOLOR_NONE = 255, -}; - -enum Icons_t { - ICON_POISON = 1 << 0, - ICON_BURN = 1 << 1, - ICON_ENERGY = 1 << 2, - ICON_DRUNK = 1 << 3, - ICON_MANASHIELD = 1 << 4, - ICON_PARALYZE = 1 << 5, - ICON_HASTE = 1 << 6, - ICON_SWORDS = 1 << 7, - ICON_DROWNING = 1 << 8, - ICON_FREEZING = 1 << 9, - ICON_DAZZLED = 1 << 10, - ICON_CURSED = 1 << 11, - ICON_PARTY_BUFF = 1 << 12, - ICON_REDSWORDS = 1 << 13, - ICON_PIGEON = 1 << 14, - ICON_BLEEDING = 1 << 15, -}; - -enum WeaponType_t : uint8_t { - WEAPON_NONE, - WEAPON_SWORD, - WEAPON_CLUB, - WEAPON_AXE, - WEAPON_SHIELD, - WEAPON_DISTANCE, - WEAPON_WAND, - WEAPON_AMMO, -}; - -enum Ammo_t : uint8_t { - AMMO_NONE, - AMMO_BOLT, - AMMO_ARROW, - AMMO_SPEAR, - AMMO_THROWINGSTAR, - AMMO_THROWINGKNIFE, - AMMO_STONE, - AMMO_SNOWBALL, -}; - -enum WeaponAction_t : uint8_t { - WEAPONACTION_NONE, - WEAPONACTION_REMOVECOUNT, - WEAPONACTION_REMOVECHARGE, - WEAPONACTION_MOVE, -}; - -enum WieldInfo_t { - WIELDINFO_LEVEL = 1 << 0, - WIELDINFO_MAGLV = 1 << 1, - WIELDINFO_VOCREQ = 1 << 2, - WIELDINFO_PREMIUM = 1 << 3, -}; - -enum Skulls_t : uint8_t { - SKULL_NONE = 0, - SKULL_YELLOW = 1, - SKULL_GREEN = 2, - SKULL_WHITE = 3, - SKULL_RED = 4, - SKULL_BLACK = 5, - SKULL_ORANGE = 6, -}; - -enum PartyShields_t : uint8_t { - SHIELD_NONE = 0, - SHIELD_WHITEYELLOW = 1, - SHIELD_WHITEBLUE = 2, - SHIELD_BLUE = 3, - SHIELD_YELLOW = 4, - SHIELD_BLUE_SHAREDEXP = 5, - SHIELD_YELLOW_SHAREDEXP = 6, - SHIELD_BLUE_NOSHAREDEXP_BLINK = 7, - SHIELD_YELLOW_NOSHAREDEXP_BLINK = 8, - SHIELD_BLUE_NOSHAREDEXP = 9, - SHIELD_YELLOW_NOSHAREDEXP = 10, - SHIELD_GRAY = 11, -}; - -enum GuildEmblems_t : uint8_t { - GUILDEMBLEM_NONE = 0, - GUILDEMBLEM_ALLY = 1, - GUILDEMBLEM_ENEMY = 2, - GUILDEMBLEM_NEUTRAL = 3, - GUILDEMBLEM_MEMBER = 4, - GUILDEMBLEM_OTHER = 5, -}; - -enum item_t : uint16_t { - ITEM_BROWSEFIELD = 460, // for internal use - - ITEM_FIREFIELD_PVP_FULL = 1487, - ITEM_FIREFIELD_PVP_MEDIUM = 1488, - ITEM_FIREFIELD_PVP_SMALL = 1489, - ITEM_FIREFIELD_PERSISTENT_FULL = 1492, - ITEM_FIREFIELD_PERSISTENT_MEDIUM = 1493, - ITEM_FIREFIELD_PERSISTENT_SMALL = 1494, - ITEM_FIREFIELD_NOPVP = 1500, - - ITEM_POISONFIELD_PVP = 1490, - ITEM_POISONFIELD_PERSISTENT = 1496, - ITEM_POISONFIELD_NOPVP = 1503, - - ITEM_ENERGYFIELD_PVP = 1491, - ITEM_ENERGYFIELD_PERSISTENT = 1495, - ITEM_ENERGYFIELD_NOPVP = 1504, - - ITEM_MAGICWALL = 1497, - ITEM_MAGICWALL_PERSISTENT = 1498, - ITEM_MAGICWALL_SAFE = 11098, - - ITEM_WILDGROWTH = 1499, - ITEM_WILDGROWTH_PERSISTENT = 2721, - ITEM_WILDGROWTH_SAFE = 11099, - - ITEM_BAG = 1987, - - ITEM_GOLD_COIN = 2148, - ITEM_PLATINUM_COIN = 2152, - ITEM_CRYSTAL_COIN = 2160, - - ITEM_DEPOT = 2594, - ITEM_LOCKER1 = 2589, - ITEM_INBOX = 14404, - ITEM_MARKET = 14405, - - ITEM_MALE_CORPSE = 3058, - ITEM_FEMALE_CORPSE = 3065, - - ITEM_FULLSPLASH = 2016, - ITEM_SMALLSPLASH = 2019, - - ITEM_PARCEL = 2595, - ITEM_LETTER = 2597, - ITEM_LETTER_STAMPED = 2598, - ITEM_LABEL = 2599, - - ITEM_AMULETOFLOSS = 2173, - - ITEM_DOCUMENT_RO = 1968, //read-only -}; - -enum PlayerFlags : uint64_t { - PlayerFlag_CannotUseCombat = 1 << 0, - PlayerFlag_CannotAttackPlayer = 1 << 1, - PlayerFlag_CannotAttackMonster = 1 << 2, - PlayerFlag_CannotBeAttacked = 1 << 3, - PlayerFlag_CanConvinceAll = 1 << 4, - PlayerFlag_CanSummonAll = 1 << 5, - PlayerFlag_CanIllusionAll = 1 << 6, - PlayerFlag_CanSenseInvisibility = 1 << 7, - PlayerFlag_IgnoredByMonsters = 1 << 8, - PlayerFlag_NotGainInFight = 1 << 9, - PlayerFlag_HasInfiniteMana = 1 << 10, - PlayerFlag_HasInfiniteSoul = 1 << 11, - PlayerFlag_HasNoExhaustion = 1 << 12, - PlayerFlag_CannotUseSpells = 1 << 13, - PlayerFlag_CannotPickupItem = 1 << 14, - PlayerFlag_CanAlwaysLogin = 1 << 15, - PlayerFlag_CanBroadcast = 1 << 16, - PlayerFlag_CanEditHouses = 1 << 17, - PlayerFlag_CannotBeBanned = 1 << 18, - PlayerFlag_CannotBePushed = 1 << 19, - PlayerFlag_HasInfiniteCapacity = 1 << 20, - PlayerFlag_CanPushAllCreatures = 1 << 21, - PlayerFlag_CanTalkRedPrivate = 1 << 22, - PlayerFlag_CanTalkRedChannel = 1 << 23, - PlayerFlag_TalkOrangeHelpChannel = 1 << 24, - PlayerFlag_NotGainExperience = 1 << 25, - PlayerFlag_NotGainMana = 1 << 26, - PlayerFlag_NotGainHealth = 1 << 27, - PlayerFlag_NotGainSkill = 1 << 28, - PlayerFlag_SetMaxSpeed = 1 << 29, - PlayerFlag_SpecialVIP = 1 << 30, - PlayerFlag_NotGenerateLoot = static_cast(1) << 31, - PlayerFlag_CanTalkRedChannelAnonymous = static_cast(1) << 32, - PlayerFlag_IgnoreProtectionZone = static_cast(1) << 33, - PlayerFlag_IgnoreSpellCheck = static_cast(1) << 34, - PlayerFlag_IgnoreWeaponCheck = static_cast(1) << 35, - PlayerFlag_CannotBeMuted = static_cast(1) << 36, - PlayerFlag_IsAlwaysPremium = static_cast(1) << 37, -}; - -#define CHANNEL_GUILD 0x00 -#define CHANNEL_PARTY 0x01 -#define CHANNEL_PRIVATE 0xFFFF - -//Reserved player storage key ranges -//[10000000 - 20000000] -#define PSTRG_RESERVED_RANGE_START 10000000 -#define PSTRG_RESERVED_RANGE_SIZE 10000000 -//[1000 - 1500] -#define PSTRG_OUTFITS_RANGE_START (PSTRG_RESERVED_RANGE_START + 1000) -#define PSTRG_OUTFITS_RANGE_SIZE 500 -//[2001 - 2011] -#define PSTRG_MOUNTS_RANGE_START (PSTRG_RESERVED_RANGE_START + 2001) -#define PSTRG_MOUNTS_RANGE_SIZE 10 -#define PSTRG_MOUNTS_CURRENTMOUNT (PSTRG_MOUNTS_RANGE_START + 10) - -#define IS_IN_KEYRANGE(key, range) (key >= PSTRG_##range##_START && ((key - PSTRG_##range##_START) <= PSTRG_##range##_SIZE)) - -#endif diff --git a/path_10_8/src/container.cpp b/path_10_8/src/container.cpp deleted file mode 100644 index aab03675f..000000000 --- a/path_10_8/src/container.cpp +++ /dev/null @@ -1,739 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "container.h" -#include "iomap.h" -#include "game.h" - -extern Game g_game; - -Container::Container(uint16_t _type) : Item(_type) -{ - maxSize = items[_type].maxItems; - totalWeight = 0; - serializationCount = 0; - unlocked = true; - pagination = false; -} - -Container::Container(uint16_t _type, uint16_t _size) : Item(_type) -{ - maxSize = _size; - totalWeight = 0; - serializationCount = 0; - unlocked = true; - pagination = false; -} - -Container::Container(Tile* tile) : Item(ITEM_BROWSEFIELD) -{ - TileItemVector* itemVector = tile->getItemList(); - if (itemVector) { - for (Item* item : *itemVector) { - if (item->getContainer() || item->hasProperty(CONST_PROP_MOVEABLE)) { - itemlist.push_front(item); - item->setParent(this); - } - } - } - - maxSize = 30; - totalWeight = 0; - serializationCount = 0; - unlocked = false; - pagination = true; - setParent(tile); -} - -Container::~Container() -{ - if (getID() == ITEM_BROWSEFIELD) { - g_game.browseFields.erase(getTile()); - - for (Item* item : itemlist) { - item->setParent(parent); - } - } else { - for (Item* item : itemlist) { - item->setParent(nullptr); - item->decrementReferenceCounter(); - } - } -} - -Item* Container::clone() const -{ - Container* clone = static_cast(Item::clone()); - for (Item* item : itemlist) { - clone->addItem(item->clone()); - } - clone->totalWeight = totalWeight; - return clone; -} - -Container* Container::getParentContainer() -{ - Thing* thing = getParent(); - if (!thing) { - return nullptr; - } - return thing->getContainer(); -} - -bool Container::hasParent() const -{ - return getID() != ITEM_BROWSEFIELD && dynamic_cast(getParent()) == nullptr; -} - -void Container::addItem(Item* item) -{ - itemlist.push_back(item); - item->setParent(this); -} - -Attr_ReadValue Container::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - if (attr == ATTR_CONTAINER_ITEMS) { - if (!propStream.read(serializationCount)) { - return ATTR_READ_ERROR; - } - return ATTR_READ_END; - } - return Item::readAttr(attr, propStream); -} - -bool Container::unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream) -{ - bool ret = Item::unserializeItemNode(f, node, propStream); - if (!ret) { - return false; - } - - uint32_t type; - NODE nodeItem = f.getChildNode(node, type); - while (nodeItem) { - //load container items - if (type != OTBM_ITEM) { - // unknown type - return false; - } - - PropStream itemPropStream; - if (!f.getProps(nodeItem, itemPropStream)) { - return false; - } - - Item* item = Item::CreateItem(itemPropStream); - if (!item) { - return false; - } - - if (!item->unserializeItemNode(f, nodeItem, itemPropStream)) { - return false; - } - - addItem(item); - updateItemWeight(item->getWeight()); - - nodeItem = f.getNextNode(nodeItem, type); - } - return true; -} - -void Container::updateItemWeight(int32_t diff) -{ - totalWeight += diff; - if (Container* parentContainer = getParentContainer()) { - parentContainer->updateItemWeight(diff); - } -} - -uint32_t Container::getWeight() const -{ - return Item::getWeight() + totalWeight; -} - -std::string Container::getContentDescription() const -{ - std::ostringstream os; - return getContentDescription(os).str(); -} - -std::ostringstream& Container::getContentDescription(std::ostringstream& os) const -{ - bool firstitem = true; - for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - Item* item = *it; - - Container* container = item->getContainer(); - if (container && !container->empty()) { - continue; - } - - if (firstitem) { - firstitem = false; - } else { - os << ", "; - } - - os << item->getNameDescription(); - } - - if (firstitem) { - os << "nothing"; - } - return os; -} - -Item* Container::getItemByIndex(size_t index) const -{ - if (index >= size()) { - return nullptr; - } - return itemlist[index]; -} - -uint32_t Container::getItemHoldingCount() const -{ - uint32_t counter = 0; - for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - ++counter; - } - return counter; -} - -bool Container::isHoldingItem(const Item* item) const -{ - for (ContainerIterator it = iterator(); it.hasNext(); it.advance()) { - if (*it == item) { - return true; - } - } - return false; -} - -void Container::onAddContainerItem(Item* item) -{ - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2); - - //send to client - for (Creature* spectator : list) { - spectator->getPlayer()->sendAddContainerItem(this, item); - } - - //event methods - for (Creature* spectator : list) { - spectator->getPlayer()->onAddContainerItem(item); - } -} - -void Container::onUpdateContainerItem(uint32_t index, Item* oldItem, Item* newItem) -{ - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2); - - //send to client - for (Creature* spectator : list) { - spectator->getPlayer()->sendUpdateContainerItem(this, index, newItem); - } - - //event methods - for (Creature* spectator : list) { - spectator->getPlayer()->onUpdateContainerItem(this, oldItem, newItem); - } -} - -void Container::onRemoveContainerItem(uint32_t index, Item* item) -{ - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), false, true, 2, 2, 2, 2); - - //send change to client - for (Creature* spectator : list) { - spectator->getPlayer()->sendRemoveContainerItem(this, index); - } - - //event methods - for (Creature* spectator : list) { - spectator->getPlayer()->onRemoveContainerItem(this, item); - } -} - -ReturnValue Container::queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor/* = nullptr*/) const -{ - bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); - if (childIsOwner) { - //a child container is querying, since we are the top container (not carried by a player) - //just return with no error. - return RETURNVALUE_NOERROR; - } - - if (!unlocked) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (!item->isPickupable()) { - return RETURNVALUE_CANNOTPICKUP; - } - - if (item == this) { - return RETURNVALUE_THISISIMPOSSIBLE; - } - - const Cylinder* cylinder = getParent(); - if (!hasBitSet(FLAG_NOLIMIT, flags)) { - while (cylinder) { - if (cylinder == &thing) { - return RETURNVALUE_THISISIMPOSSIBLE; - } - - if (dynamic_cast(cylinder)) { - return RETURNVALUE_CONTAINERNOTENOUGHROOM; - } - - cylinder = cylinder->getParent(); - } - - if (index == INDEX_WHEREEVER && size() >= capacity()) { - return RETURNVALUE_CONTAINERNOTENOUGHROOM; - } - } else { - while (cylinder) { - if (cylinder == &thing) { - return RETURNVALUE_THISISIMPOSSIBLE; - } - - cylinder = cylinder->getParent(); - } - } - - const Cylinder* topParent = getTopParent(); - if (topParent != this) { - return topParent->queryAdd(INDEX_WHEREEVER, *item, count, flags | FLAG_CHILDISOWNER, actor); - } else { - return RETURNVALUE_NOERROR; - } -} - -ReturnValue Container::queryMaxCount(int32_t index, const Thing& thing, uint32_t count, - uint32_t& maxQueryCount, uint32_t flags) const -{ - const Item* item = thing.getItem(); - if (item == nullptr) { - maxQueryCount = 0; - return RETURNVALUE_NOTPOSSIBLE; - } - - if (hasBitSet(FLAG_NOLIMIT, flags)) { - maxQueryCount = std::max(1, count); - return RETURNVALUE_NOERROR; - } - - int32_t freeSlots = std::max(capacity() - size(), 0); - - if (item->isStackable()) { - uint32_t n = 0; - - if (index == INDEX_WHEREEVER) { - //Iterate through every item and check how much free stackable slots there is. - uint32_t slotIndex = 0; - for (Item* containerItem : itemlist) { - if (containerItem != item && containerItem->equals(item) && containerItem->getItemCount() < 100) { - uint32_t remainder = (100 - containerItem->getItemCount()); - if (queryAdd(slotIndex++, *item, remainder, flags) == RETURNVALUE_NOERROR) { - n += remainder; - } - } - } - } else { - const Item* destItem = getItemByIndex(index); - if (item->equals(destItem) && destItem->getItemCount() < 100) { - uint32_t remainder = 100 - destItem->getItemCount(); - if (queryAdd(index, *item, remainder, flags) == RETURNVALUE_NOERROR) { - n = remainder; - } - } - } - - maxQueryCount = freeSlots * 100 + n; - if (maxQueryCount < count) { - return RETURNVALUE_CONTAINERNOTENOUGHROOM; - } - } else { - maxQueryCount = freeSlots; - if (maxQueryCount == 0) { - return RETURNVALUE_CONTAINERNOTENOUGHROOM; - } - } - return RETURNVALUE_NOERROR; -} - -ReturnValue Container::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const -{ - int32_t index = getThingIndex(&thing); - if (index == -1) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (count == 0 || (item->isStackable() && count > item->getItemCount())) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) { - return RETURNVALUE_NOTMOVEABLE; - } - return RETURNVALUE_NOERROR; -} - -Cylinder* Container::queryDestination(int32_t& index, const Thing &thing, Item** destItem, - uint32_t& flags) -{ - if (!unlocked) { - *destItem = nullptr; - return this; - } - - if (index == 254 /*move up*/) { - index = INDEX_WHEREEVER; - *destItem = nullptr; - - Container* parentContainer = dynamic_cast(getParent()); - if (parentContainer) { - return parentContainer; - } - return this; - } - - if (index == 255 /*add wherever*/) { - index = INDEX_WHEREEVER; - *destItem = nullptr; - } else if (index >= static_cast(capacity())) { - /* - if you have a container, maximize it to show all 20 slots - then you open a bag that is inside the container you will have a bag with 8 slots - and a "grey" area where the other 12 slots where from the container - if you drop the item on that grey area - the client calculates the slot position as if the bag has 20 slots - */ - index = INDEX_WHEREEVER; - *destItem = nullptr; - } - - const Item* item = thing.getItem(); - if (!item) { - return this; - } - - bool autoStack = !hasBitSet(FLAG_IGNOREAUTOSTACK, flags); - if (autoStack && item->isStackable() && item->getParent() != this) { - //try find a suitable item to stack with - uint32_t n = 0; - for (Item* listItem : itemlist) { - if (listItem != item && listItem->equals(item) && listItem->getItemCount() < 100) { - *destItem = listItem; - index = n; - return this; - } - ++n; - } - } - - if (index != INDEX_WHEREEVER) { - Item* itemFromIndex = getItemByIndex(index); - if (itemFromIndex) { - *destItem = itemFromIndex; - } - - Cylinder* subCylinder = dynamic_cast(*destItem); - if (subCylinder) { - index = INDEX_WHEREEVER; - *destItem = nullptr; - return subCylinder; - } - } - return this; -} - -void Container::addThing(Thing* thing) -{ - return addThing(0, thing); -} - -void Container::addThing(int32_t index, Thing* thing) -{ - if (index >= static_cast(capacity())) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - item->setParent(this); - itemlist.push_front(item); - updateItemWeight(item->getWeight()); - - //send change to client - if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) { - onAddContainerItem(item); - } -} - -void Container::addItemBack(Item* item) -{ - addItem(item); - updateItemWeight(item->getWeight()); - - //send change to client - if (getParent() && (getParent() != VirtualCylinder::virtualCylinder)) { - onAddContainerItem(item); - } -} - -void Container::updateThing(Thing* thing, uint16_t itemId, uint32_t count) -{ - int32_t index = getThingIndex(thing); - if (index == -1) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - const int32_t oldWeight = item->getWeight(); - item->setID(itemId); - item->setSubType(count); - updateItemWeight(-oldWeight + item->getWeight()); - - //send change to client - if (getParent()) { - onUpdateContainerItem(index, item, item); - } -} - -void Container::replaceThing(uint32_t index, Thing* thing) -{ - Item* item = thing->getItem(); - if (!item) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* replacedItem = getItemByIndex(index); - if (!replacedItem) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - itemlist[index] = item; - item->setParent(this); - updateItemWeight(-static_cast(replacedItem->getWeight()) + item->getWeight()); - - //send change to client - if (getParent()) { - onUpdateContainerItem(index, replacedItem, item); - } - - replacedItem->setParent(nullptr); -} - -void Container::removeThing(Thing* thing, uint32_t count) -{ - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - int32_t index = getThingIndex(thing); - if (index == -1) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - if (item->isStackable() && count != item->getItemCount()) { - uint8_t newCount = static_cast(std::max(0, item->getItemCount() - count)); - const int32_t oldWeight = item->getWeight(); - item->setItemCount(newCount); - updateItemWeight(-oldWeight + item->getWeight()); - - //send change to client - if (getParent()) { - onUpdateContainerItem(index, item, item); - } - } else { - updateItemWeight(-static_cast(item->getWeight())); - - //send change to client - if (getParent()) { - onRemoveContainerItem(index, item); - } - - item->setParent(nullptr); - itemlist.erase(itemlist.begin() + index); - } -} - -int32_t Container::getThingIndex(const Thing* thing) const -{ - int32_t index = 0; - for (Item* item : itemlist) { - if (item == thing) { - return index; - } - ++index; - } - return -1; -} - -size_t Container::getFirstIndex() const -{ - return 0; -} - -size_t Container::getLastIndex() const -{ - return size(); -} - -uint32_t Container::getItemTypeCount(uint16_t itemId, int32_t subType/* = -1*/) const -{ - uint32_t count = 0; - for (Item* item : itemlist) { - if (item->getID() == itemId) { - count += countByType(item, subType); - } - } - return count; -} - -std::map& Container::getAllItemTypeCount(std::map &countMap) const -{ - for (Item* item : itemlist) { - countMap[item->getID()] += item->getItemCount(); - } - return countMap; -} - -Thing* Container::getThing(size_t index) const -{ - return getItemByIndex(index); -} - -void Container::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - Cylinder* topParent = getTopParent(); - if (topParent->getCreature()) { - topParent->postAddNotification(thing, oldParent, index, LINK_TOPPARENT); - } else if (topParent == this) { - //let the tile class notify surrounding players - if (topParent->getParent()) { - topParent->getParent()->postAddNotification(thing, oldParent, index, LINK_NEAR); - } - } else { - topParent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void Container::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - Cylinder* topParent = getTopParent(); - if (topParent->getCreature()) { - topParent->postRemoveNotification(thing, newParent, index, LINK_TOPPARENT); - } else if (topParent == this) { - //let the tile class notify surrounding players - if (topParent->getParent()) { - topParent->getParent()->postRemoveNotification(thing, newParent, index, LINK_NEAR); - } - } else { - topParent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} - -void Container::internalAddThing(Thing* thing) -{ - internalAddThing(0, thing); -} - -void Container::internalAddThing(uint32_t, Thing* thing) -{ - Item* item = thing->getItem(); - if (item == nullptr) { - return; - } - - item->setParent(this); - itemlist.push_front(item); - updateItemWeight(item->getWeight()); -} - -void Container::startDecaying() -{ - for (Item* item : itemlist) { - item->startDecaying(); - } -} - -ContainerIterator Container::iterator() const -{ - ContainerIterator cit; - if (!itemlist.empty()) { - cit.over.push_back(this); - cit.cur = itemlist.begin(); - } - return cit; -} - -Item* ContainerIterator::operator*() -{ - return *cur; -} - -void ContainerIterator::advance() -{ - if (Item* i = *cur) { - if (Container* c = i->getContainer()) { - if (!c->empty()) { - over.push_back(c); - } - } - } - - ++cur; - - if (cur == over.front()->itemlist.end()) { - over.pop_front(); - if (!over.empty()) { - cur = over.front()->itemlist.begin(); - } - } -} diff --git a/path_10_8/src/container.h b/path_10_8/src/container.h deleted file mode 100644 index bcd5d1b85..000000000 --- a/path_10_8/src/container.h +++ /dev/null @@ -1,174 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CONTAINER_H_5590165FD8A2451B98D71F13CD3ED8DC -#define FS_CONTAINER_H_5590165FD8A2451B98D71F13CD3ED8DC - -#include - -#include "cylinder.h" -#include "item.h" - -class Container; -class DepotChest; -class DepotLocker; - -class ContainerIterator -{ - public: - bool hasNext() const { - return !over.empty(); - } - - void advance(); - Item* operator*(); - - protected: - std::list over; - ItemDeque::const_iterator cur; - - friend class Container; -}; - -class Container : public Item, public Cylinder -{ - public: - explicit Container(uint16_t _type); - Container(uint16_t _type, uint16_t _size); - explicit Container(Tile* tile); - ~Container(); - - // non-copyable - Container(const Container&) = delete; - Container& operator=(const Container&) = delete; - - Item* clone() const final; - - Container* getContainer() final { - return this; - } - const Container* getContainer() const final { - return this; - } - - virtual DepotLocker* getDepotLocker() { - return nullptr; - } - virtual const DepotLocker* getDepotLocker() const { - return nullptr; - } - - Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) override; - bool unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream) override; - std::string getContentDescription() const; - - size_t size() const { - return itemlist.size(); - } - bool empty() const { - return itemlist.empty(); - } - uint32_t capacity() const { - return maxSize; - } - - ContainerIterator iterator() const; - - const ItemDeque& getItemList() const { - return itemlist; - } - - ItemDeque::const_reverse_iterator getReversedItems() const { - return itemlist.rbegin(); - } - ItemDeque::const_reverse_iterator getReversedEnd() const { - return itemlist.rend(); - } - - bool hasParent() const; - void addItem(Item* item); - Item* getItemByIndex(size_t index) const; - bool isHoldingItem(const Item* item) const; - - uint32_t getItemHoldingCount() const; - uint32_t getWeight() const final; - - bool isUnlocked() const { - return unlocked; - } - bool hasPagination() const { - return pagination; - } - - //cylinder implementations - virtual ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const override; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount, - uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) final; - - void addThing(Thing* thing) final; - void addThing(int32_t index, Thing* thing) final; - void addItemBack(Item* item); - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - int32_t getThingIndex(const Thing* thing) const final; - size_t getFirstIndex() const final; - size_t getLastIndex() const final; - uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const final; - std::map& getAllItemTypeCount(std::map &countMap) const final; - Thing*getThing(size_t index) const final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) override; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) override; - - void internalAddThing(Thing* thing) final; - void internalAddThing(uint32_t index, Thing* thing) final; - void startDecaying() final; - - private: - void onAddContainerItem(Item* item); - void onUpdateContainerItem(uint32_t index, Item* oldItem, Item* newItem); - void onRemoveContainerItem(uint32_t index, Item* item); - - Container* getParentContainer(); - void updateItemWeight(int32_t diff); - - protected: - std::ostringstream& getContentDescription(std::ostringstream& os) const; - - uint32_t maxSize; - uint32_t totalWeight; - ItemDeque itemlist; - uint32_t serializationCount; - - bool unlocked; - bool pagination; - - friend class ContainerIterator; - friend class IOMapSerialize; -}; - -#endif diff --git a/path_10_8/src/creature.cpp b/path_10_8/src/creature.cpp deleted file mode 100644 index 677785835..000000000 --- a/path_10_8/src/creature.cpp +++ /dev/null @@ -1,1650 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "creature.h" -#include "game.h" -#include "monster.h" -#include "configmanager.h" -#include "scheduler.h" - -double Creature::speedA = 857.36; -double Creature::speedB = 261.29; -double Creature::speedC = -4795.01; - -extern Game g_game; -extern ConfigManager g_config; -extern CreatureEvents* g_creatureEvents; - -Creature::Creature() : - localMapCache(), isInternalRemoved(false) -{ - referenceCounter = 0; - - id = 0; - _tile = nullptr; - direction = DIRECTION_SOUTH; - master = nullptr; - lootDrop = true; - skillLoss = true; - - health = 1000; - healthMax = 1000; - mana = 0; - - lastStep = 0; - lastStepCost = 1; - baseSpeed = 220; - varSpeed = 0; - - followCreature = nullptr; - hasFollowPath = false; - eventWalk = 0; - cancelNextWalk = false; - forceUpdateFollowPath = false; - isMapLoaded = false; - isUpdatingPath = false; - - attackedCreature = nullptr; - - lastHitCreature = 0; - blockCount = 0; - blockTicks = 0; - walkUpdateTicks = 0; - creatureCheck = false; - inCheckCreaturesVector = false; - scriptEventsBitField = 0; - - hiddenHealth = false; - - skull = SKULL_NONE; - - onIdleStatus(); -} - -Creature::~Creature() -{ - for (Creature* summon : summons) { - summon->setAttackedCreature(nullptr); - summon->setMaster(nullptr); - summon->decrementReferenceCounter(); - } - - for (Condition* condition : conditions) { - condition->endCondition(this); - delete condition; - } -} - -bool Creature::canSee(const Position& myPos, const Position& pos, int32_t viewRangeX, int32_t viewRangeY) -{ - if (myPos.z <= 7) { - //we are on ground level or above (7 -> 0) - //view is from 7 -> 0 - if (pos.z > 7) { - return false; - } - } else if (myPos.z >= 8) { - //we are underground (8 -> 15) - //view is +/- 2 from the floor we stand on - if (Position::getDistanceZ(myPos, pos) > 2) { - return false; - } - } - - const int_fast32_t offsetz = myPos.getZ() - pos.getZ(); - return (pos.getX() >= myPos.getX() - viewRangeX + offsetz) && (pos.getX() <= myPos.getX() + viewRangeX + offsetz) - && (pos.getY() >= myPos.getY() - viewRangeY + offsetz) && (pos.getY() <= myPos.getY() + viewRangeY + offsetz); -} - -bool Creature::canSee(const Position& pos) const -{ - return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY); -} - -bool Creature::canSeeCreature(const Creature* creature) const -{ - if (!canSeeInvisibility() && creature->isInvisible()) { - return false; - } - return true; -} - -void Creature::setSkull(Skulls_t newSkull) -{ - skull = newSkull; - g_game.updateCreatureSkull(this); -} - -int64_t Creature::getTimeSinceLastMove() const -{ - if (lastStep) { - return OTSYS_TIME() - lastStep; - } - return std::numeric_limits::max(); -} - -int32_t Creature::getWalkDelay(Direction dir) const -{ - if (lastStep == 0) { - return 0; - } - - int64_t ct = OTSYS_TIME(); - int64_t stepDuration = getStepDuration(dir); - return stepDuration - (ct - lastStep); -} - -int32_t Creature::getWalkDelay() const -{ - //Used for auto-walking - if (lastStep == 0) { - return 0; - } - - int64_t ct = OTSYS_TIME(); - int64_t stepDuration = getStepDuration() * lastStepCost; - return stepDuration - (ct - lastStep); -} - -void Creature::onThink(uint32_t interval) -{ - if (!isMapLoaded && useCacheMap()) { - isMapLoaded = true; - updateMapCache(); - } - - if (followCreature && master != followCreature && !canSeeCreature(followCreature)) { - onCreatureDisappear(followCreature, false); - } - - if (attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature)) { - onCreatureDisappear(attackedCreature, false); - } - - blockTicks += interval; - if (blockTicks >= 1000) { - blockCount = std::min(blockCount + 1, 2); - blockTicks = 0; - } - - if (followCreature) { - walkUpdateTicks += interval; - if (forceUpdateFollowPath || walkUpdateTicks >= 2000) { - walkUpdateTicks = 0; - forceUpdateFollowPath = false; - isUpdatingPath = true; - } - } - - if (isUpdatingPath) { - isUpdatingPath = false; - goToFollowCreature(); - } - - //scripting event - onThink - const CreatureEventList& thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK); - for (CreatureEvent* thinkEvent : thinkEvents) { - thinkEvent->executeOnThink(this, interval); - } -} - -void Creature::onAttacking(uint32_t interval) -{ - if (!attackedCreature) { - return; - } - - onAttacked(); - attackedCreature->onAttacked(); - - if (g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true)) { - doAttacking(interval); - } -} - -void Creature::onIdleStatus() -{ - if (getHealth() > 0) { - damageMap.clear(); - lastHitCreature = 0; - } -} - -void Creature::onWalk() -{ - if (getWalkDelay() <= 0) { - Direction dir; - uint32_t flags = FLAG_IGNOREFIELDDAMAGE; - if (getNextStep(dir, flags)) { - ReturnValue ret = g_game.internalMoveCreature(this, dir, flags); - if (ret != RETURNVALUE_NOERROR) { - if (Player* player = getPlayer()) { - player->sendCancelMessage(ret); - player->sendCancelWalk(); - } - - forceUpdateFollowPath = true; - } - } else { - if (listWalkDir.empty()) { - onWalkComplete(); - } - - stopEventWalk(); - } - } - - if (cancelNextWalk) { - listWalkDir.clear(); - onWalkAborted(); - cancelNextWalk = false; - } - - if (eventWalk != 0) { - eventWalk = 0; - addEventWalk(); - } -} - -void Creature::onWalk(Direction& dir) -{ - if (hasCondition(CONDITION_DRUNK)) { - uint32_t r = uniform_random(0, 20); - if (r <= DIRECTION_DIAGONAL_MASK) { - if (r < DIRECTION_DIAGONAL_MASK) { - dir = static_cast(r); - } - g_game.internalCreatureSay(this, TALKTYPE_MONSTER_SAY, "Hicks!", false); - } - } -} - -bool Creature::getNextStep(Direction& dir, uint32_t&) -{ - if (listWalkDir.empty()) { - return false; - } - - dir = listWalkDir.front(); - listWalkDir.pop_front(); - onWalk(dir); - return true; -} - -void Creature::startAutoWalk(const std::forward_list& listDir) -{ - listWalkDir = listDir; - - size_t size = 0; - for (auto it = listDir.begin(); it != listDir.end() && size <= 1; ++it) { - size++; - } - addEventWalk(size == 1); -} - -void Creature::addEventWalk(bool firstStep) -{ - cancelNextWalk = false; - - if (getStepSpeed() <= 0) { - return; - } - - if (eventWalk != 0) { - return; - } - - int64_t ticks = getEventStepTicks(firstStep); - if (ticks <= 0) { - return; - } - - // Take first step right away, but still queue the next - if (ticks == 1) { - g_game.checkCreatureWalk(getID()); - } - - eventWalk = g_scheduler.addEvent(createSchedulerTask(ticks, std::bind(&Game::checkCreatureWalk, &g_game, getID()))); -} - -void Creature::stopEventWalk() -{ - if (eventWalk != 0) { - g_scheduler.stopEvent(eventWalk); - eventWalk = 0; - } -} - -void Creature::updateMapCache() -{ - Tile* tile; - const Position& myPos = getPosition(); - Position pos(0, 0, myPos.z); - - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - pos.x = myPos.getX() + x; - pos.y = myPos.getY() + y; - tile = g_game.map.getTile(pos); - updateTileCache(tile, pos); - } - } -} - -void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy) -{ - if (std::abs(dx) <= maxWalkCacheWidth && std::abs(dy) <= maxWalkCacheHeight) { - localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx] = tile && tile->queryAdd(0, *this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RETURNVALUE_NOERROR; - } -} - -void Creature::updateTileCache(const Tile* tile, const Position& pos) -{ - const Position& myPos = getPosition(); - if (pos.z == myPos.z) { - int32_t dx = Position::getOffsetX(pos, myPos); - int32_t dy = Position::getOffsetY(pos, myPos); - updateTileCache(tile, dx, dy); - } -} - -int32_t Creature::getWalkCache(const Position& pos) const -{ - if (!useCacheMap()) { - return 2; - } - - const Position& myPos = getPosition(); - if (myPos.z != pos.z) { - return 0; - } - - if (pos == myPos) { - return 1; - } - - int32_t dx = Position::getOffsetX(pos, myPos); - if (std::abs(dx) <= maxWalkCacheWidth) { - int32_t dy = Position::getOffsetY(pos, myPos); - if (std::abs(dy) <= maxWalkCacheHeight) { - if (localMapCache[maxWalkCacheHeight + dy][maxWalkCacheWidth + dx]) { - return 1; - } else { - return 0; - } - } - } - - //out of range - return 2; -} - -void Creature::onAddTileItem(const Tile* tile, const Position& pos) -{ - if (isMapLoaded && pos.z == getPosition().z) { - updateTileCache(tile, pos); - } -} - -void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item*, - const ItemType& oldType, const Item*, const ItemType& newType) -{ - if (!isMapLoaded) { - return; - } - - if (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind || newType.blockSolid) { - if (pos.z == getPosition().z) { - updateTileCache(tile, pos); - } - } -} - -void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item*) -{ - if (!isMapLoaded) { - return; - } - - if (iType.blockSolid || iType.blockPathFind || iType.isGroundTile()) { - if (pos.z == getPosition().z) { - updateTileCache(tile, pos); - } - } -} - -void Creature::onCreatureAppear(Creature* creature, bool isLogin) -{ - if (creature == this) { - if (useCacheMap()) { - isMapLoaded = true; - updateMapCache(); - } - - if (isLogin) { - setLastPosition(getPosition()); - } - } else if (isMapLoaded) { - if (creature->getPosition().z == getPosition().z) { - updateTileCache(creature->getTile(), creature->getPosition()); - } - } -} - -void Creature::onRemoveCreature(Creature* creature, bool) -{ - onCreatureDisappear(creature, true); - if (creature == this) { - if (master && !master->isRemoved()) { - master->removeSummon(this); - } - } else if (isMapLoaded) { - if (creature->getPosition().z == getPosition().z) { - updateTileCache(creature->getTile(), creature->getPosition()); - } - } -} - -void Creature::onCreatureDisappear(const Creature* creature, bool isLogout) -{ - if (attackedCreature == creature) { - setAttackedCreature(nullptr); - onAttackedCreatureDisappear(isLogout); - } - - if (followCreature == creature) { - setFollowCreature(nullptr); - onFollowCreatureDisappear(isLogout); - } -} - -void Creature::onChangeZone(ZoneType_t zone) -{ - if (attackedCreature && zone == ZONE_PROTECTION) { - onCreatureDisappear(attackedCreature, false); - } -} - -void Creature::onAttackedCreatureChangeZone(ZoneType_t zone) -{ - if (zone == ZONE_PROTECTION) { - onCreatureDisappear(attackedCreature, false); - } -} - -void Creature::onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) -{ - if (creature == this) { - lastStep = OTSYS_TIME(); - lastStepCost = 1; - - if (!teleport) { - if (oldPos.z != newPos.z) { - //floor change extra cost - lastStepCost = 2; - } else if (Position::getDistanceX(newPos, oldPos) >= 1 && Position::getDistanceY(newPos, oldPos) >= 1) { - //diagonal extra cost - lastStepCost = 3; - } - } else { - stopEventWalk(); - } - - if (!summons.empty()) { - //check if any of our summons is out of range (+/- 2 floors or 30 tiles away) - std::forward_list despawnList; - for (Creature* summon : summons) { - const Position pos = summon->getPosition(); - if (Position::getDistanceZ(newPos, pos) > 2 || (std::max(Position::getDistanceX(newPos, pos), Position::getDistanceY(newPos, pos)) > 30)) { - despawnList.push_front(summon); - } - } - - for (Creature* despawnCreature : despawnList) { - g_game.removeCreature(despawnCreature, true); - } - } - - if (newTile->getZone() != oldTile->getZone()) { - onChangeZone(getZone()); - } - - //update map cache - if (isMapLoaded) { - if (teleport || oldPos.z != newPos.z) { - updateMapCache(); - } else { - Tile* tile; - const Position& myPos = getPosition(); - Position pos; - - if (oldPos.y > newPos.y) { //north - //shift y south - for (int32_t y = mapWalkHeight - 1; --y >= 0;) { - memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y])); - } - - //update 0 - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - tile = g_game.map.getTile(myPos.getX() + x, myPos.getY() - maxWalkCacheHeight, myPos.z); - updateTileCache(tile, x, -maxWalkCacheHeight); - } - } else if (oldPos.y < newPos.y) { // south - //shift y north - for (int32_t y = 0; y <= mapWalkHeight - 2; ++y) { - memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y])); - } - - //update mapWalkHeight - 1 - for (int32_t x = -maxWalkCacheWidth; x <= maxWalkCacheWidth; ++x) { - tile = g_game.map.getTile(myPos.getX() + x, myPos.getY() + maxWalkCacheHeight, myPos.z); - updateTileCache(tile, x, maxWalkCacheHeight); - } - } - - if (oldPos.x < newPos.x) { // east - //shift y west - int32_t starty = 0; - int32_t endy = mapWalkHeight - 1; - int32_t dy = Position::getDistanceY(oldPos, newPos); - - if (dy < 0) { - endy += dy; - } else if (dy > 0) { - starty = dy; - } - - for (int32_t y = starty; y <= endy; ++y) { - for (int32_t x = 0; x <= mapWalkWidth - 2; ++x) { - localMapCache[y][x] = localMapCache[y][x + 1]; - } - } - - //update mapWalkWidth - 1 - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - tile = g_game.map.getTile(myPos.x + maxWalkCacheWidth, myPos.y + y, myPos.z); - updateTileCache(tile, maxWalkCacheWidth, y); - } - } else if (oldPos.x > newPos.x) { // west - //shift y east - int32_t starty = 0; - int32_t endy = mapWalkHeight - 1; - int32_t dy = Position::getDistanceY(oldPos, newPos); - - if (dy < 0) { - endy += dy; - } else if (dy > 0) { - starty = dy; - } - - for (int32_t y = starty; y <= endy; ++y) { - for (int32_t x = mapWalkWidth - 1; --x >= 0;) { - localMapCache[y][x + 1] = localMapCache[y][x]; - } - } - - //update 0 - for (int32_t y = -maxWalkCacheHeight; y <= maxWalkCacheHeight; ++y) { - tile = g_game.map.getTile(myPos.x - maxWalkCacheWidth, myPos.y + y, myPos.z); - updateTileCache(tile, -maxWalkCacheWidth, y); - } - } - - updateTileCache(oldTile, oldPos); - } - } - } else { - if (isMapLoaded) { - const Position& myPos = getPosition(); - - if (newPos.z == myPos.z) { - updateTileCache(newTile, newPos); - } - - if (oldPos.z == myPos.z) { - updateTileCache(oldTile, oldPos); - } - } - } - - if (creature == followCreature || (creature == this && followCreature)) { - if (hasFollowPath) { - isUpdatingPath = true; - } - - if (newPos.z != oldPos.z || !canSee(followCreature->getPosition())) { - onCreatureDisappear(followCreature, false); - } - } - - if (creature == attackedCreature || (creature == this && attackedCreature)) { - if (newPos.z != oldPos.z || !canSee(attackedCreature->getPosition())) { - onCreatureDisappear(attackedCreature, false); - } else { - if (hasExtraSwing()) { - //our target is moving lets see if we can get in hit - g_dispatcher.addTask(createTask(std::bind(&Game::checkCreatureAttack, &g_game, getID()))); - } - - if (newTile->getZone() != oldTile->getZone()) { - onAttackedCreatureChangeZone(attackedCreature->getZone()); - } - } - } -} - -void Creature::onDeath() -{ - bool lastHitUnjustified = false; - bool mostDamageUnjustified = false; - Creature* _lastHitCreature = g_game.getCreatureByID(lastHitCreature); - Creature* lastHitCreatureMaster; - if (_lastHitCreature) { - lastHitUnjustified = _lastHitCreature->onKilledCreature(this); - lastHitCreatureMaster = _lastHitCreature->getMaster(); - } else { - lastHitCreatureMaster = nullptr; - } - - Creature* mostDamageCreature = nullptr; - - const int64_t timeNow = OTSYS_TIME(); - const uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED); - int32_t mostDamage = 0; - std::map experienceMap; - for (const auto& it : damageMap) { - if (Creature* attacker = g_game.getCreatureByID(it.first)) { - CountBlock_t cb = it.second; - if ((cb.total > mostDamage && (timeNow - cb.ticks <= inFightTicks))) { - mostDamage = cb.total; - mostDamageCreature = attacker; - } - - if (attacker != this) { - uint64_t gainExp = getGainedExperience(attacker); - if (Player* player = attacker->getPlayer()) { - Party* party = player->getParty(); - if (party && party->getLeader() && party->isSharedExperienceActive() && party->isSharedExperienceEnabled()) { - attacker = party->getLeader(); - } - } - - auto tmpIt = experienceMap.find(attacker); - if (tmpIt == experienceMap.end()) { - experienceMap[attacker] = gainExp; - } else { - tmpIt->second += gainExp; - } - } - } - } - - for (const auto& it : experienceMap) { - it.first->onGainExperience(it.second, this); - } - - if (mostDamageCreature) { - if (mostDamageCreature != _lastHitCreature && mostDamageCreature != lastHitCreatureMaster) { - Creature* mostDamageCreatureMaster = mostDamageCreature->getMaster(); - if (_lastHitCreature != mostDamageCreatureMaster && (lastHitCreatureMaster == nullptr || mostDamageCreatureMaster != lastHitCreatureMaster)) { - mostDamageUnjustified = mostDamageCreature->onKilledCreature(this, false); - } - } - } - - bool droppedCorpse = dropCorpse(_lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); - death(_lastHitCreature); - - if (master) { - master->removeSummon(this); - } - - if (droppedCorpse) { - g_game.removeCreature(this, false); - } -} - -bool Creature::dropCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) -{ - if (!lootDrop && getMonster()) { - if (master) { - //scripting event - onDeath - const CreatureEventList& deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH); - for (CreatureEvent* deathEvent : deathEvents) { - deathEvent->executeOnDeath(this, nullptr, _lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); - } - } - - g_game.addMagicEffect(getPosition(), CONST_ME_POFF); - } else { - Item* splash; - switch (getRace()) { - case RACE_VENOM: - splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN); - break; - - case RACE_BLOOD: - splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD); - break; - - default: - splash = nullptr; - break; - } - - Tile* tile = getTile(); - - if (splash) { - g_game.internalAddItem(tile, splash, INDEX_WHEREEVER, FLAG_NOLIMIT); - g_game.startDecay(splash); - } - - Item* corpse = getCorpse(_lastHitCreature, mostDamageCreature); - if (corpse) { - g_game.internalAddItem(tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT); - g_game.startDecay(corpse); - } - - //scripting event - onDeath - for (CreatureEvent* deathEvent : getCreatureEvents(CREATURE_EVENT_DEATH)) { - deathEvent->executeOnDeath(this, corpse, _lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); - } - - if (corpse) { - dropLoot(corpse->getContainer(), _lastHitCreature); - } - } - - return true; -} - -bool Creature::hasBeenAttacked(uint32_t attackerId) -{ - auto it = damageMap.find(attackerId); - if (it == damageMap.end()) { - return false; - } - return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED); -} - -Item* Creature::getCorpse(Creature*, Creature*) -{ - return Item::CreateItem(getLookCorpse()); -} - -void Creature::changeHealth(int32_t healthChange, bool sendHealthChange/* = true*/) -{ - int32_t oldHealth = health; - - if (healthChange > 0) { - health += std::min(healthChange, getMaxHealth() - health); - } else { - health = std::max(0, health + healthChange); - } - - if (sendHealthChange && oldHealth != health) { - g_game.addCreatureHealth(this); - } -} - -void Creature::changeMana(int32_t manaChange) -{ - if (manaChange > 0) { - mana += std::min(manaChange, getMaxMana() - mana); - } else { - mana = std::max(0, mana + manaChange); - } -} - -void Creature::gainHealth(Creature* healer, int32_t healthGain) -{ - changeHealth(healthGain); - if (healer) { - healer->onTargetCreatureGainHealth(this, healthGain); - } -} - -void Creature::drainHealth(Creature* attacker, int32_t damage) -{ - changeHealth(-damage, false); - - if (attacker) { - attacker->onAttackedCreatureDrainHealth(this, damage); - } -} - -void Creature::drainMana(Creature* attacker, int32_t manaLoss) -{ - onAttacked(); - changeMana(-manaLoss); - - if (attacker) { - addDamagePoints(attacker, manaLoss); - } -} - -BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense /* = false */, bool checkArmor /* = false */, bool /* field = false */) -{ - BlockType_t blockType = BLOCK_NONE; - - if (isImmune(combatType)) { - damage = 0; - blockType = BLOCK_IMMUNITY; - } else if (checkDefense || checkArmor) { - bool hasDefense = false; - - if (blockCount > 0) { - --blockCount; - hasDefense = true; - } - - if (checkDefense && hasDefense) { - int32_t defense = getDefense(); - damage -= uniform_random(defense / 2, defense); - if (damage <= 0) { - damage = 0; - blockType = BLOCK_DEFENSE; - checkArmor = false; - } - } - - if (checkArmor) { - int32_t armorValue = getArmor(); - if (armorValue > 1) { - double armorFormula = armorValue * 0.475; - int32_t armorReduction = static_cast(std::ceil(armorFormula)); - damage -= uniform_random( - armorReduction, - armorReduction + static_cast(std::floor(armorFormula)) - ); - } else if (armorValue == 1) { - --damage; - } - - if (damage <= 0) { - damage = 0; - blockType = BLOCK_ARMOR; - } - } - - if (hasDefense && blockType != BLOCK_NONE) { - onBlockHit(); - } - } - - if (attacker) { - attacker->onAttackedCreature(this); - attacker->onAttackedCreatureBlockHit(blockType); - } - - onAttacked(); - return blockType; -} - -bool Creature::setAttackedCreature(Creature* creature) -{ - if (creature) { - const Position& creaturePos = creature->getPosition(); - if (creaturePos.z != getPosition().z || !canSee(creaturePos)) { - attackedCreature = nullptr; - return false; - } - - attackedCreature = creature; - onAttackedCreature(attackedCreature); - attackedCreature->onAttacked(); - } else { - attackedCreature = nullptr; - } - - for (Creature* summon : summons) { - summon->setAttackedCreature(creature); - } - return true; -} - -void Creature::getPathSearchParams(const Creature*, FindPathParams& fpp) const -{ - fpp.fullPathSearch = !hasFollowPath; - fpp.clearSight = true; - fpp.maxSearchDist = 12; - fpp.minTargetDist = 1; - fpp.maxTargetDist = 1; -} - -void Creature::goToFollowCreature() -{ - if (followCreature) { - FindPathParams fpp; - getPathSearchParams(followCreature, fpp); - - Monster* monster = getMonster(); - if (monster && !monster->getMaster() && (monster->isFleeing() || fpp.maxTargetDist > 1)) { - Direction dir = DIRECTION_NONE; - - if (monster->isFleeing()) { - monster->getDistanceStep(followCreature->getPosition(), dir, true); - } else { //maxTargetDist > 1 - if (!monster->getDistanceStep(followCreature->getPosition(), dir)) { - // if we can't get anything then let the A* calculate - listWalkDir.clear(); - if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { - hasFollowPath = true; - startAutoWalk(listWalkDir); - } else { - hasFollowPath = false; - } - - return; - } - } - - if (dir != DIRECTION_NONE) { - listWalkDir.clear(); - listWalkDir.push_front(dir); - - hasFollowPath = true; - startAutoWalk(listWalkDir); - } - } else { - listWalkDir.clear(); - if (getPathTo(followCreature->getPosition(), listWalkDir, fpp)) { - hasFollowPath = true; - startAutoWalk(listWalkDir); - } else { - hasFollowPath = false; - } - } - } - - onFollowCreatureComplete(followCreature); -} - -bool Creature::setFollowCreature(Creature* creature) -{ - if (creature) { - if (followCreature == creature) { - return true; - } - - const Position& creaturePos = creature->getPosition(); - if (creaturePos.z != getPosition().z || !canSee(creaturePos)) { - followCreature = nullptr; - return false; - } - - if (!listWalkDir.empty()) { - listWalkDir.clear(); - onWalkAborted(); - } - - hasFollowPath = false; - forceUpdateFollowPath = false; - followCreature = creature; - isUpdatingPath = true; - } else { - isUpdatingPath = false; - followCreature = nullptr; - } - - onFollowCreature(creature); - return true; -} - -double Creature::getDamageRatio(Creature* attacker) const -{ - uint32_t totalDamage = 0; - uint32_t attackerDamage = 0; - - for (const auto& it : damageMap) { - const CountBlock_t& cb = it.second; - totalDamage += cb.total; - if (it.first == attacker->getID()) { - attackerDamage += cb.total; - } - } - - if (totalDamage == 0) { - return 0; - } - - return (static_cast(attackerDamage) / totalDamage); -} - -uint64_t Creature::getGainedExperience(Creature* attacker) const -{ - return std::floor(getDamageRatio(attacker) * getLostExperience()); -} - -void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints) -{ - if (damagePoints <= 0) { - return; - } - - uint32_t attackerId = attacker->id; - - auto it = damageMap.find(attackerId); - if (it == damageMap.end()) { - CountBlock_t cb; - cb.ticks = OTSYS_TIME(); - cb.total = damagePoints; - damageMap[attackerId] = cb; - } else { - it->second.total += damagePoints; - it->second.ticks = OTSYS_TIME(); - } - - lastHitCreature = attackerId; -} - -void Creature::onAddCondition(ConditionType_t type) -{ - if (type == CONDITION_PARALYZE && hasCondition(CONDITION_HASTE)) { - removeCondition(CONDITION_HASTE); - } else if (type == CONDITION_HASTE && hasCondition(CONDITION_PARALYZE)) { - removeCondition(CONDITION_PARALYZE); - } -} - -void Creature::onAddCombatCondition(ConditionType_t) -{ - // -} - -void Creature::onEndCondition(ConditionType_t) -{ - // -} - -void Creature::onTickCondition(ConditionType_t type, bool& bRemove) -{ - const MagicField* field = getTile()->getFieldItem(); - if (!field) { - return; - } - - switch (type) { - case CONDITION_FIRE: - bRemove = (field->getCombatType() != COMBAT_FIREDAMAGE); - break; - case CONDITION_ENERGY: - bRemove = (field->getCombatType() != COMBAT_ENERGYDAMAGE); - break; - case CONDITION_POISON: - bRemove = (field->getCombatType() != COMBAT_EARTHDAMAGE); - break; - case CONDITION_FREEZING: - bRemove = (field->getCombatType() != COMBAT_ICEDAMAGE); - break; - case CONDITION_DAZZLED: - bRemove = (field->getCombatType() != COMBAT_HOLYDAMAGE); - break; - case CONDITION_CURSED: - bRemove = (field->getCombatType() != COMBAT_DEATHDAMAGE); - break; - case CONDITION_DROWN: - bRemove = (field->getCombatType() != COMBAT_DROWNDAMAGE); - break; - case CONDITION_BLEEDING: - bRemove = (field->getCombatType() != COMBAT_PHYSICALDAMAGE); - break; - default: - break; - } -} - -void Creature::onCombatRemoveCondition(Condition* condition) -{ - removeCondition(condition); -} - -void Creature::onAttacked() -{ - // -} - -void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points) -{ - target->addDamagePoints(this, points); -} - -bool Creature::onKilledCreature(Creature* target, bool) -{ - if (master) { - master->onKilledCreature(target); - } - - //scripting event - onKill - const CreatureEventList& killEvents = getCreatureEvents(CREATURE_EVENT_KILL); - for (CreatureEvent* killEvent : killEvents) { - killEvent->executeOnKill(this, target); - } - return false; -} - -void Creature::onGainExperience(uint64_t gainExp, Creature* target) -{ - if (gainExp == 0 || !master) { - return; - } - - gainExp /= 2; - master->onGainExperience(gainExp, target); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - if (list.empty()) { - return; - } - - TextMessage message(MESSAGE_EXPERIENCE_OTHERS, ucfirst(getNameDescription()) + " gained " + std::to_string(gainExp) + (gainExp != 1 ? " experience points." : " experience point.")); - message.position = _position; - message.primary.color = TEXTCOLOR_WHITE_EXP; - message.primary.value = gainExp; - - for (Creature* spectator : list) { - spectator->getPlayer()->sendTextMessage(message); - } -} - -void Creature::addSummon(Creature* creature) -{ - creature->setDropLoot(false); - creature->setLossSkill(false); - creature->setMaster(this); - creature->incrementReferenceCounter(); - summons.push_back(creature); -} - -void Creature::removeSummon(Creature* creature) -{ - auto cit = std::find(summons.begin(), summons.end(), creature); - if (cit != summons.end()) { - creature->setDropLoot(false); - creature->setLossSkill(true); - creature->setMaster(nullptr); - creature->decrementReferenceCounter(); - summons.erase(cit); - } -} - -bool Creature::addCondition(Condition* condition, bool force/* = false*/) -{ - if (condition == nullptr) { - return false; - } - - if (!force && condition->getType() == CONDITION_HASTE && hasCondition(CONDITION_PARALYZE)) { - int64_t walkDelay = getWalkDelay(); - if (walkDelay > 0) { - g_scheduler.addEvent(createSchedulerTask(walkDelay, std::bind(&Game::forceAddCondition, &g_game, getID(), condition))); - return false; - } - } - - Condition* prevCond = getCondition(condition->getType(), condition->getId(), condition->getSubId()); - if (prevCond) { - prevCond->addCondition(this, condition); - delete condition; - return true; - } - - if (condition->startCondition(this)) { - conditions.push_back(condition); - onAddCondition(condition->getType()); - return true; - } - - delete condition; - return false; -} - -bool Creature::addCombatCondition(Condition* condition) -{ - //Caution: condition variable could be deleted after the call to addCondition - ConditionType_t type = condition->getType(); - - if (!addCondition(condition)) { - return false; - } - - onAddCombatCondition(type); - return true; -} - -void Creature::removeCondition(ConditionType_t type, bool force/* = false*/) -{ - auto it = conditions.begin(), end = conditions.end(); - while (it != end) { - Condition* condition = *it; - if (condition->getType() != type) { - ++it; - continue; - } - - if (!force && type == CONDITION_PARALYZE) { - int64_t walkDelay = getWalkDelay(); - if (walkDelay > 0) { - g_scheduler.addEvent(createSchedulerTask(walkDelay, std::bind(&Game::forceRemoveCondition, &g_game, getID(), type))); - return; - } - } - - it = conditions.erase(it); - - condition->endCondition(this); - delete condition; - - onEndCondition(type); - } -} - -void Creature::removeCondition(ConditionType_t type, ConditionId_t conditionId, bool force/* = false*/) -{ - auto it = conditions.begin(), end = conditions.end(); - while (it != end) { - Condition* condition = *it; - if (condition->getType() != type || condition->getId() != conditionId) { - ++it; - continue; - } - - if (!force && type == CONDITION_PARALYZE) { - int64_t walkDelay = getWalkDelay(); - if (walkDelay > 0) { - g_scheduler.addEvent(createSchedulerTask(walkDelay, std::bind(&Game::forceRemoveCondition, &g_game, getID(), type))); - return; - } - } - - it = conditions.erase(it); - - condition->endCondition(this); - delete condition; - - onEndCondition(type); - } -} - -void Creature::removeCombatCondition(ConditionType_t type) -{ - std::vector removeConditions; - for (Condition* condition : conditions) { - if (condition->getType() == type) { - removeConditions.push_back(condition); - } - } - - for (Condition* condition : removeConditions) { - onCombatRemoveCondition(condition); - } -} - -void Creature::removeCondition(Condition* condition, bool force/* = false*/) -{ - auto it = std::find(conditions.begin(), conditions.end(), condition); - if (it == conditions.end()) { - return; - } - - if (!force && condition->getType() == CONDITION_PARALYZE) { - int64_t walkDelay = getWalkDelay(); - if (walkDelay > 0) { - g_scheduler.addEvent(createSchedulerTask(walkDelay, std::bind(&Game::forceRemoveCondition, &g_game, getID(), condition->getType()))); - return; - } - } - - conditions.erase(it); - - condition->endCondition(this); - onEndCondition(condition->getType()); - delete condition; -} - -Condition* Creature::getCondition(ConditionType_t type) const -{ - for (Condition* condition : conditions) { - if (condition->getType() == type) { - return condition; - } - } - return nullptr; -} - -Condition* Creature::getCondition(ConditionType_t type, ConditionId_t conditionId, uint32_t subId/* = 0*/) const -{ - for (Condition* condition : conditions) { - if (condition->getType() == type && condition->getId() == conditionId && condition->getSubId() == subId) { - return condition; - } - } - return nullptr; -} - -void Creature::executeConditions(uint32_t interval) -{ - auto it = conditions.begin(), end = conditions.end(); - while (it != end) { - Condition* condition = *it; - if (!condition->executeCondition(this, interval)) { - ConditionType_t type = condition->getType(); - - it = conditions.erase(it); - - condition->endCondition(this); - delete condition; - - onEndCondition(type); - } else { - ++it; - } - } -} - -bool Creature::hasCondition(ConditionType_t type, uint32_t subId/* = 0*/) const -{ - if (isSuppress(type)) { - return false; - } - - int64_t timeNow = OTSYS_TIME(); - for (Condition* condition : conditions) { - if (condition->getType() != type || condition->getSubId() != subId) { - continue; - } - - if (condition->getEndTime() >= timeNow) { - return true; - } - } - return false; -} - -bool Creature::isImmune(CombatType_t type) const -{ - return hasBitSet(static_cast(type), getDamageImmunities()); -} - -bool Creature::isImmune(ConditionType_t type) const -{ - return hasBitSet(static_cast(type), getConditionImmunities()); -} - -bool Creature::isSuppress(ConditionType_t type) const -{ - return hasBitSet(static_cast(type), getConditionSuppressions()); -} - -int64_t Creature::getStepDuration(Direction dir) const -{ - int64_t stepDuration = getStepDuration(); - if ((dir & DIRECTION_DIAGONAL_MASK) != 0) { - stepDuration *= 3; - } - return stepDuration; -} - -int64_t Creature::getStepDuration() const -{ - if (isRemoved()) { - return 0; - } - - uint32_t calculatedStepSpeed; - uint32_t groundSpeed; - - int32_t stepSpeed = getStepSpeed(); - if (stepSpeed > -Creature::speedB) { - calculatedStepSpeed = floor((Creature::speedA * log((stepSpeed / 2) + Creature::speedB) + Creature::speedC) + 0.5); - if (calculatedStepSpeed <= 0) { - calculatedStepSpeed = 1; - } - } else { - calculatedStepSpeed = 1; - } - - Item* ground = _tile->getGround(); - if (ground) { - groundSpeed = Item::items[ground->getID()].speed; - if (groundSpeed == 0) { - groundSpeed = 150; - } - } else { - groundSpeed = 150; - } - - double duration = std::floor(1000 * groundSpeed / calculatedStepSpeed); - int64_t stepDuration = std::ceil(duration / 50) * 50; - - const Monster* monster = getMonster(); - if (monster && monster->isTargetNearby() && !monster->isFleeing() && !monster->getMaster()) { - stepDuration *= 2; - } - - return stepDuration; -} - -int64_t Creature::getEventStepTicks(bool onlyDelay) const -{ - int64_t ret = getWalkDelay(); - if (ret <= 0) { - int64_t stepDuration = getStepDuration(); - if (onlyDelay && stepDuration > 0) { - ret = 1; - } else { - ret = stepDuration * lastStepCost; - } - } - return ret; -} - -void Creature::getCreatureLight(LightInfo& light) const -{ - light = internalLight; -} - -void Creature::setNormalCreatureLight() -{ - internalLight.level = 0; - internalLight.color = 0; -} - -bool Creature::registerCreatureEvent(const std::string& name) -{ - CreatureEvent* event = g_creatureEvents->getEventByName(name); - if (!event) { - return false; - } - - CreatureEventType_t type = event->getEventType(); - if (hasEventRegistered(type)) { - for (CreatureEvent* creatureEvent : eventsList) { - if (creatureEvent == event) { - return false; - } - } - } else { - scriptEventsBitField |= static_cast(1) << type; - } - - eventsList.push_back(event); - return true; -} - -bool Creature::unregisterCreatureEvent(const std::string& name) -{ - CreatureEvent* event = g_creatureEvents->getEventByName(name); - if (!event) { - return false; - } - - CreatureEventType_t type = event->getEventType(); - if (!hasEventRegistered(type)) { - return false; - } - - bool resetTypeBit = true; - - auto it = eventsList.begin(), end = eventsList.end(); - while (it != end) { - CreatureEvent* curEvent = *it; - if (curEvent == event) { - it = eventsList.erase(it); - continue; - } - - if (curEvent->getEventType() == type) { - resetTypeBit = false; - } - ++it; - } - - if (resetTypeBit) { - scriptEventsBitField &= ~(static_cast(1) << type); - } - return true; -} - -CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type) -{ - CreatureEventList tmpEventList; - - if (!hasEventRegistered(type)) { - return tmpEventList; - } - - for (CreatureEvent* creatureEvent : eventsList) { - if (creatureEvent->getEventType() == type) { - tmpEventList.push_back(creatureEvent); - } - } - - return tmpEventList; -} - -bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos, - const FindPathParams& fpp) const -{ - if (fpp.fullPathSearch) { - if (testPos.x > targetPos.x + fpp.maxTargetDist) { - return false; - } - - if (testPos.x < targetPos.x - fpp.maxTargetDist) { - return false; - } - - if (testPos.y > targetPos.y + fpp.maxTargetDist) { - return false; - } - - if (testPos.y < targetPos.y - fpp.maxTargetDist) { - return false; - } - } else { - int_fast32_t dx = Position::getOffsetX(startPos, targetPos); - - int32_t dxMax = (dx >= 0 ? fpp.maxTargetDist : 0); - if (testPos.x > targetPos.x + dxMax) { - return false; - } - - int32_t dxMin = (dx <= 0 ? fpp.maxTargetDist : 0); - if (testPos.x < targetPos.x - dxMin) { - return false; - } - - int_fast32_t dy = Position::getOffsetY(startPos, targetPos); - - int32_t dyMax = (dy >= 0 ? fpp.maxTargetDist : 0); - if (testPos.y > targetPos.y + dyMax) { - return false; - } - - int32_t dyMin = (dy <= 0 ? fpp.maxTargetDist : 0); - if (testPos.y < targetPos.y - dyMin) { - return false; - } - } - return true; -} - -bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos, - const FindPathParams& fpp, int32_t& bestMatchDist) const -{ - if (!isInRange(startPos, testPos, fpp)) { - return false; - } - - if (fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true)) { - return false; - } - - int32_t testDist = std::max(Position::getDistanceX(targetPos, testPos), Position::getDistanceY(targetPos, testPos)); - if (fpp.maxTargetDist == 1) { - if (testDist < fpp.minTargetDist || testDist > fpp.maxTargetDist) { - return false; - } - - return true; - } else if (testDist <= fpp.maxTargetDist) { - if (testDist < fpp.minTargetDist) { - return false; - } - - if (testDist == fpp.maxTargetDist) { - bestMatchDist = 0; - return true; - } else if (testDist > bestMatchDist) { - //not quite what we want, but the best so far - bestMatchDist = testDist; - return true; - } - } - return false; -} - -bool Creature::isInvisible() const -{ - return std::find_if(conditions.begin(), conditions.end(), [] (const Condition* condition) { - return condition->getType() == CONDITION_INVISIBLE; - }) != conditions.end(); -} - -bool Creature::getPathTo(const Position& targetPos, std::forward_list& dirList, const FindPathParams& fpp) const -{ - return g_game.map.getPathMatching(*this, dirList, FrozenPathingConditionCall(targetPos), fpp); -} - -bool Creature::getPathTo(const Position& targetPos, std::forward_list& dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch /*= true*/, bool clearSight /*= true*/, int32_t maxSearchDist /*= 0*/) const -{ - FindPathParams fpp; - fpp.fullPathSearch = fullPathSearch; - fpp.maxSearchDist = maxSearchDist; - fpp.clearSight = clearSight; - fpp.minTargetDist = minTargetDist; - fpp.maxTargetDist = maxTargetDist; - return getPathTo(targetPos, dirList, fpp); -} diff --git a/path_10_8/src/creature.h b/path_10_8/src/creature.h deleted file mode 100644 index de4c426c4..000000000 --- a/path_10_8/src/creature.h +++ /dev/null @@ -1,578 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CREATURE_H_5363C04015254E298F84E6D59A139508 -#define FS_CREATURE_H_5363C04015254E298F84E6D59A139508 - -#include "map.h" -#include "position.h" -#include "condition.h" -#include "const.h" -#include "tile.h" -#include "enums.h" -#include "creatureevent.h" - -typedef std::list ConditionList; -typedef std::list CreatureEventList; - -enum slots_t : uint8_t { - CONST_SLOT_WHEREEVER = 0, - CONST_SLOT_HEAD = 1, - CONST_SLOT_NECKLACE = 2, - CONST_SLOT_BACKPACK = 3, - CONST_SLOT_ARMOR = 4, - CONST_SLOT_RIGHT = 5, - CONST_SLOT_LEFT = 6, - CONST_SLOT_LEGS = 7, - CONST_SLOT_FEET = 8, - CONST_SLOT_RING = 9, - CONST_SLOT_AMMO = 10, - - CONST_SLOT_FIRST = CONST_SLOT_HEAD, - CONST_SLOT_LAST = CONST_SLOT_AMMO, -}; - -struct FindPathParams { - bool fullPathSearch; - bool clearSight; - bool allowDiagonal; - bool keepDistance; - int32_t maxSearchDist; - int32_t minTargetDist; - int32_t maxTargetDist; - - FindPathParams() { - fullPathSearch = true; - clearSight = true; - allowDiagonal = true; - keepDistance = false; - maxSearchDist = 0; - minTargetDist = -1; - maxTargetDist = -1; - } -}; - -class Map; -class Thing; -class Container; -class Player; -class Monster; -class Npc; -class Item; -class Tile; - -#define EVENT_CREATURECOUNT 10 -#define EVENT_CREATURE_THINK_INTERVAL 1000 -#define EVENT_CHECK_CREATURE_INTERVAL (EVENT_CREATURE_THINK_INTERVAL / EVENT_CREATURECOUNT) - -class FrozenPathingConditionCall -{ - public: - explicit FrozenPathingConditionCall(Position targetPos) : targetPos(targetPos) {} - - bool operator()(const Position& startPos, const Position& testPos, - const FindPathParams& fpp, int32_t& bestMatchDist) const; - - bool isInRange(const Position& startPos, const Position& testPos, - const FindPathParams& fpp) const; - - protected: - Position targetPos; -}; - -////////////////////////////////////////////////////////////////////// -// Defines the Base class for all creatures and base functions which -// every creature has - -class Creature : virtual public Thing -{ - protected: - Creature(); - - public: - static double speedA, speedB, speedC; - - virtual ~Creature(); - - // non-copyable - Creature(const Creature&) = delete; - Creature& operator=(const Creature&) = delete; - - Creature* getCreature() final { - return this; - } - const Creature* getCreature() const final { - return this; - } - virtual Player* getPlayer() { - return nullptr; - } - virtual const Player* getPlayer() const { - return nullptr; - } - virtual Npc* getNpc() { - return nullptr; - } - virtual const Npc* getNpc() const { - return nullptr; - } - virtual Monster* getMonster() { - return nullptr; - } - virtual const Monster* getMonster() const { - return nullptr; - } - - virtual const std::string& getName() const = 0; - virtual const std::string& getNameDescription() const = 0; - - virtual CreatureType_t getType() const = 0; - - virtual void setID() = 0; - void setRemoved() { - isInternalRemoved = true; - } - - uint32_t getID() const { - return id; - } - virtual void removeList() = 0; - virtual void addList() = 0; - - const Position& getLastPosition() const { - return lastPosition; - } - void setLastPosition(const Position& newLastPos) { - lastPosition = newLastPos; - } - - virtual bool canSee(const Position& pos) const; - virtual bool canSeeCreature(const Creature* creature) const; - - virtual RaceType_t getRace() const { - return RACE_NONE; - } - virtual Skulls_t getSkull() const { - return skull; - } - virtual Skulls_t getSkullClient(const Creature* creature) const { - return creature->getSkull(); - } - void setSkull(Skulls_t newSkull); - Direction getDirection() const { - return direction; - } - void setDirection(Direction dir) { - direction = dir; - } - - bool isHealthHidden() const { - return hiddenHealth; - } - void setHiddenHealth(bool b) { - hiddenHealth = b; - } - - int32_t getThrowRange() const final { - return 1; - } - bool isPushable() const override { - return getWalkDelay() <= 0; - } - bool isRemoved() const final { - return isInternalRemoved; - } - virtual bool canSeeInvisibility() const { - return false; - } - virtual bool isInGhostMode() const { - return false; - } - - int32_t getWalkDelay(Direction dir) const; - int32_t getWalkDelay() const; - int64_t getTimeSinceLastMove() const; - - int64_t getEventStepTicks(bool onlyDelay = false) const; - int64_t getStepDuration(Direction dir) const; - int64_t getStepDuration() const; - virtual int32_t getStepSpeed() const { - return getSpeed(); - } - int32_t getSpeed() const { - return baseSpeed + varSpeed; - } - void setSpeed(int32_t varSpeedDelta) { - int32_t oldSpeed = getSpeed(); - varSpeed = varSpeedDelta; - - if (getSpeed() <= 0) { - stopEventWalk(); - cancelNextWalk = true; - } else if (oldSpeed <= 0 && !listWalkDir.empty()) { - addEventWalk(); - } - } - - void setBaseSpeed(uint32_t newBaseSpeed) { - baseSpeed = newBaseSpeed; - } - uint32_t getBaseSpeed() const { - return baseSpeed; - } - - int32_t getHealth() const { - return health; - } - virtual int32_t getMaxHealth() const { - return healthMax; - } - uint32_t getMana() const { - return mana; - } - virtual uint32_t getMaxMana() const { - return 0; - } - - const Outfit_t getCurrentOutfit() const { - return currentOutfit; - } - void setCurrentOutfit(Outfit_t outfit) { - currentOutfit = outfit; - } - const Outfit_t getDefaultOutfit() const { - return defaultOutfit; - } - bool isInvisible() const; - ZoneType_t getZone() const { - return getTile()->getZone(); - } - - //walk functions - void startAutoWalk(const std::forward_list& listDir); - void addEventWalk(bool firstStep = false); - void stopEventWalk(); - virtual void goToFollowCreature(); - - //walk events - virtual void onWalk(Direction& dir); - virtual void onWalkAborted() {} - virtual void onWalkComplete() {} - - //follow functions - Creature* getFollowCreature() const { - return followCreature; - } - virtual bool setFollowCreature(Creature* creature); - - //follow events - virtual void onFollowCreature(const Creature*) {} - virtual void onFollowCreatureComplete(const Creature*) {} - - //combat functions - Creature* getAttackedCreature() { - return attackedCreature; - } - virtual bool setAttackedCreature(Creature* creature); - virtual BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense = false, bool checkArmor = false, bool field = false); - - void setMaster(Creature* creature) { - master = creature; - } - bool isSummon() const { - return master != nullptr; - } - Creature* getMaster() const { - return master; - } - - void addSummon(Creature* creature); - void removeSummon(Creature* creature); - const std::list& getSummons() const { - return summons; - } - - virtual int32_t getArmor() const { - return 0; - } - virtual int32_t getDefense() const { - return 0; - } - virtual float getAttackFactor() const { - return 1.0f; - } - virtual float getDefenseFactor() const { - return 1.0f; - } - - virtual uint8_t getSpeechBubble() const { - return SPEECHBUBBLE_NONE; - } - - bool addCondition(Condition* condition, bool force = false); - bool addCombatCondition(Condition* condition); - void removeCondition(ConditionType_t type, ConditionId_t conditionId, bool force = false); - void removeCondition(ConditionType_t type, bool force = false); - void removeCondition(Condition* condition, bool force = false); - void removeCombatCondition(ConditionType_t type); - Condition* getCondition(ConditionType_t type) const; - Condition* getCondition(ConditionType_t type, ConditionId_t conditionId, uint32_t subId = 0) const; - void executeConditions(uint32_t interval); - bool hasCondition(ConditionType_t type, uint32_t subId = 0) const; - virtual bool isImmune(ConditionType_t type) const; - virtual bool isImmune(CombatType_t type) const; - virtual bool isSuppress(ConditionType_t type) const; - virtual uint32_t getDamageImmunities() const { - return 0; - } - virtual uint32_t getConditionImmunities() const { - return 0; - } - virtual uint32_t getConditionSuppressions() const { - return 0; - } - virtual bool isAttackable() const { - return true; - } - - virtual void changeHealth(int32_t healthChange, bool sendHealthChange = true); - virtual void changeMana(int32_t manaChange); - - void gainHealth(Creature* attacker, int32_t healthGain); - virtual void drainHealth(Creature* attacker, int32_t damage); - virtual void drainMana(Creature* attacker, int32_t manaLoss); - - virtual bool challengeCreature(Creature*) { - return false; - } - virtual bool convinceCreature(Creature*) { - return false; - } - - void onDeath(); - virtual uint64_t getGainedExperience(Creature* attacker) const; - void addDamagePoints(Creature* attacker, int32_t damagePoints); - bool hasBeenAttacked(uint32_t attackerId); - - //combat event functions - virtual void onAddCondition(ConditionType_t type); - virtual void onAddCombatCondition(ConditionType_t type); - virtual void onEndCondition(ConditionType_t type); - void onTickCondition(ConditionType_t type, bool& bRemove); - virtual void onCombatRemoveCondition(Condition* condition); - virtual void onAttackedCreature(Creature*) {} - virtual void onAttacked(); - virtual void onAttackedCreatureDrainHealth(Creature* target, int32_t points); - virtual void onTargetCreatureGainHealth(Creature*, int32_t) {} - virtual bool onKilledCreature(Creature* target, bool lastHit = true); - virtual void onGainExperience(uint64_t gainExp, Creature* target); - virtual void onAttackedCreatureBlockHit(BlockType_t) {} - virtual void onBlockHit() {} - virtual void onChangeZone(ZoneType_t zone); - virtual void onAttackedCreatureChangeZone(ZoneType_t zone); - virtual void onIdleStatus(); - - virtual void getCreatureLight(LightInfo& light) const; - virtual void setNormalCreatureLight(); - void setCreatureLight(LightInfo light) { - internalLight = light; - } - - virtual void onThink(uint32_t interval); - void onAttacking(uint32_t interval); - virtual void onWalk(); - virtual bool getNextStep(Direction& dir, uint32_t& flags); - - void onAddTileItem(const Tile* tile, const Position& pos); - virtual void onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, - const ItemType& oldType, const Item* newItem, const ItemType& newType); - virtual void onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, - const Item* item); - - virtual void onCreatureAppear(Creature* creature, bool isLogin); - virtual void onRemoveCreature(Creature* creature, bool isLogout); - virtual void onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport); - - virtual void onAttackedCreatureDisappear(bool) {} - virtual void onFollowCreatureDisappear(bool) {} - - virtual void onCreatureSay(Creature*, SpeakClasses, const std::string&) {} - - virtual void onCreatureConvinced(const Creature*, const Creature*) {} - virtual void onPlacedCreature() {} - - virtual bool getCombatValues(int32_t&, int32_t&) { - return false; - } - - size_t getSummonCount() const { - return summons.size(); - } - void setDropLoot(bool _lootDrop) { - lootDrop = _lootDrop; - } - void setLossSkill(bool _skillLoss) { - skillLoss = _skillLoss; - } - - //creature script events - bool registerCreatureEvent(const std::string& name); - bool unregisterCreatureEvent(const std::string& name); - - Cylinder* getParent() const final { - return _tile; - } - void setParent(Cylinder* cylinder) final { - _tile = static_cast(cylinder); - _position = _tile->getPosition(); - } - - inline const Position& getPosition() const final { - return _position; - } - - Tile* getTile() final { - return _tile; - } - const Tile* getTile() const final { - return _tile; - } - - int32_t getWalkCache(const Position& pos) const; - - static bool canSee(const Position& myPos, const Position& pos, int32_t viewRangeX, int32_t viewRangeY); - - double getDamageRatio(Creature* attacker) const; - - bool getPathTo(const Position& targetPos, std::forward_list& dirList, const FindPathParams& fpp) const; - bool getPathTo(const Position& targetPos, std::forward_list& dirList, int32_t minTargetDist, int32_t maxTargetDist, bool fullPathSearch = true, bool clearSight = true, int32_t maxSearchDist = 0) const; - - void incrementReferenceCounter() { - ++referenceCounter; - } - void decrementReferenceCounter() { - if (--referenceCounter == 0) { - delete this; - } - } - - protected: - virtual bool useCacheMap() const { - return false; - } - - struct CountBlock_t { - int32_t total; - int64_t ticks; - }; - - static const int32_t mapWalkWidth = Map::maxViewportX * 2 + 1; - static const int32_t mapWalkHeight = Map::maxViewportY * 2 + 1; - static const int32_t maxWalkCacheWidth = (mapWalkWidth - 1) / 2; - static const int32_t maxWalkCacheHeight = (mapWalkHeight - 1) / 2; - - Position _position; - - typedef std::map CountMap; - CountMap damageMap; - - std::list summons; - CreatureEventList eventsList; - ConditionList conditions; - - std::forward_list listWalkDir; - - Tile* _tile; - Creature* attackedCreature; - Creature* master; - Creature* followCreature; - - uint64_t lastStep; - uint32_t referenceCounter; - uint32_t id; - uint32_t scriptEventsBitField; - uint32_t eventWalk; - uint32_t walkUpdateTicks; - uint32_t lastHitCreature; - uint32_t blockCount; - uint32_t blockTicks; - uint32_t lastStepCost; - uint32_t baseSpeed; - uint32_t mana; - int32_t varSpeed; - int32_t health; - int32_t healthMax; - - Outfit_t currentOutfit; - Outfit_t defaultOutfit; - - Position lastPosition; - LightInfo internalLight; - - Direction direction; - Skulls_t skull; - - bool localMapCache[mapWalkHeight][mapWalkWidth]; - bool isInternalRemoved; - bool isMapLoaded; - bool isUpdatingPath; - bool creatureCheck; - bool inCheckCreaturesVector; - bool skillLoss; - bool lootDrop; - bool cancelNextWalk; - bool hasFollowPath; - bool forceUpdateFollowPath; - bool hiddenHealth; - - //creature script events - bool hasEventRegistered(CreatureEventType_t event) const { - return (0 != (scriptEventsBitField & (static_cast(1) << event))); - } - CreatureEventList getCreatureEvents(CreatureEventType_t type); - - void updateMapCache(); - void updateTileCache(const Tile* tile, int32_t dx, int32_t dy); - void updateTileCache(const Tile* tile, const Position& pos); - void onCreatureDisappear(const Creature* creature, bool isLogout); - virtual void doAttacking(uint32_t) {} - virtual bool hasExtraSwing() { - return false; - } - - virtual uint64_t getLostExperience() const { - return 0; - } - virtual void dropLoot(Container*, Creature*) {} - virtual uint16_t getLookCorpse() const { - return 0; - } - virtual void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const; - virtual void death(Creature*) {} - virtual bool dropCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified); - virtual Item* getCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature); - - friend class Game; - friend class Map; - friend class LuaScriptInterface; -}; - -#endif diff --git a/path_10_8/src/creatureevent.cpp b/path_10_8/src/creatureevent.cpp deleted file mode 100644 index 999a2137a..000000000 --- a/path_10_8/src/creatureevent.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "creatureevent.h" -#include "tools.h" -#include "player.h" - -CreatureEvents::CreatureEvents() : - m_scriptInterface("CreatureScript Interface") -{ - m_scriptInterface.initState(); -} - -CreatureEvents::~CreatureEvents() -{ - for (const auto& it : m_creatureEvents) { - delete it.second; - } -} - -void CreatureEvents::clear() -{ - //clear creature events - for (const auto& it : m_creatureEvents) { - it.second->clearEvent(); - } - - //clear lua state - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& CreatureEvents::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string CreatureEvents::getScriptBaseName() const -{ - return "creaturescripts"; -} - -Event* CreatureEvents::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "event") != 0) { - return nullptr; - } - return new CreatureEvent(&m_scriptInterface); -} - -bool CreatureEvents::registerEvent(Event* event, const pugi::xml_node&) -{ - CreatureEvent* creatureEvent = static_cast(event); //event is guaranteed to be a CreatureEvent - if (creatureEvent->getEventType() == CREATURE_EVENT_NONE) { - std::cout << "Error: [CreatureEvents::registerEvent] Trying to register event without type!" << std::endl; - return false; - } - - CreatureEvent* oldEvent = getEventByName(creatureEvent->getName(), false); - if (oldEvent) { - //if there was an event with the same that is not loaded - //(happens when realoading), it is reused - if (!oldEvent->isLoaded() && oldEvent->getEventType() == creatureEvent->getEventType()) { - oldEvent->copyEvent(creatureEvent); - } - - return false; - } else { - //if not, register it normally - m_creatureEvents[creatureEvent->getName()] = creatureEvent; - return true; - } -} - -CreatureEvent* CreatureEvents::getEventByName(const std::string& name, bool forceLoaded /*= true*/) -{ - CreatureEventList::iterator it = m_creatureEvents.find(name); - if (it != m_creatureEvents.end()) { - if (!forceLoaded || it->second->isLoaded()) { - return it->second; - } - } - return nullptr; -} - -bool CreatureEvents::playerLogin(Player* player) const -{ - //fire global event if is registered - for (const auto& it : m_creatureEvents) { - if (it.second->getEventType() == CREATURE_EVENT_LOGIN) { - if (!it.second->executeOnLogin(player)) { - return false; - } - } - } - return true; -} - -bool CreatureEvents::playerLogout(Player* player) const -{ - //fire global event if is registered - for (const auto& it : m_creatureEvents) { - if (it.second->getEventType() == CREATURE_EVENT_LOGOUT) { - if (!it.second->executeOnLogout(player)) { - return false; - } - } - } - return true; -} - -bool CreatureEvents::playerAdvance(Player* player, skills_t skill, uint32_t oldLevel, - uint32_t newLevel) -{ - for (const auto& it : m_creatureEvents) { - if (it.second->getEventType() == CREATURE_EVENT_ADVANCE) { - if (!it.second->executeAdvance(player, skill, oldLevel, newLevel)) { - return false; - } - } - } - return true; -} - -///////////////////////////////////// - -CreatureEvent::CreatureEvent(LuaScriptInterface* _interface) : - Event(_interface) -{ - m_type = CREATURE_EVENT_NONE; - m_isLoaded = false; -} - -bool CreatureEvent::configureEvent(const pugi::xml_node& node) -{ - // Name that will be used in monster xml files and - // lua function to register events to reference this event - pugi::xml_attribute nameAttribute = node.attribute("name"); - if (!nameAttribute) { - std::cout << "[Error - CreatureEvent::configureEvent] Missing name for creature event" << std::endl; - return false; - } - - m_eventName = nameAttribute.as_string(); - - pugi::xml_attribute typeAttribute = node.attribute("type"); - if (!typeAttribute) { - std::cout << "[Error - CreatureEvent::configureEvent] Missing type for creature event: " << m_eventName << std::endl; - return false; - } - - std::string tmpStr = asLowerCaseString(typeAttribute.as_string()); - if (tmpStr == "login") { - m_type = CREATURE_EVENT_LOGIN; - } else if (tmpStr == "logout") { - m_type = CREATURE_EVENT_LOGOUT; - } else if (tmpStr == "think") { - m_type = CREATURE_EVENT_THINK; - } else if (tmpStr == "preparedeath") { - m_type = CREATURE_EVENT_PREPAREDEATH; - } else if (tmpStr == "death") { - m_type = CREATURE_EVENT_DEATH; - } else if (tmpStr == "kill") { - m_type = CREATURE_EVENT_KILL; - } else if (tmpStr == "advance") { - m_type = CREATURE_EVENT_ADVANCE; - } else if (tmpStr == "modalwindow") { - m_type = CREATURE_EVENT_MODALWINDOW; - } else if (tmpStr == "textedit") { - m_type = CREATURE_EVENT_TEXTEDIT; - } else if (tmpStr == "healthchange") { - m_type = CREATURE_EVENT_HEALTHCHANGE; - } else if (tmpStr == "manachange") { - m_type = CREATURE_EVENT_MANACHANGE; - } else if (tmpStr == "extendedopcode") { - m_type = CREATURE_EVENT_EXTENDED_OPCODE; - } else { - std::cout << "[Error - CreatureEvent::configureEvent] Invalid type for creature event: " << m_eventName << std::endl; - return false; - } - - m_isLoaded = true; - return true; -} - -std::string CreatureEvent::getScriptEventName() const -{ - //Depending on the type script event name is different - switch (m_type) { - case CREATURE_EVENT_LOGIN: - return "onLogin"; - - case CREATURE_EVENT_LOGOUT: - return "onLogout"; - - case CREATURE_EVENT_THINK: - return "onThink"; - - case CREATURE_EVENT_PREPAREDEATH: - return "onPrepareDeath"; - - case CREATURE_EVENT_DEATH: - return "onDeath"; - - case CREATURE_EVENT_KILL: - return "onKill"; - - case CREATURE_EVENT_ADVANCE: - return "onAdvance"; - - case CREATURE_EVENT_MODALWINDOW: - return "onModalWindow"; - - case CREATURE_EVENT_TEXTEDIT: - return "onTextEdit"; - - case CREATURE_EVENT_HEALTHCHANGE: - return "onHealthChange"; - - case CREATURE_EVENT_MANACHANGE: - return "onManaChange"; - - case CREATURE_EVENT_EXTENDED_OPCODE: - return "onExtendedOpcode"; - - case CREATURE_EVENT_NONE: - default: - return std::string(); - } -} - -void CreatureEvent::copyEvent(CreatureEvent* creatureEvent) -{ - m_scriptId = creatureEvent->m_scriptId; - m_scriptInterface = creatureEvent->m_scriptInterface; - m_scripted = creatureEvent->m_scripted; - m_isLoaded = creatureEvent->m_isLoaded; -} - -void CreatureEvent::clearEvent() -{ - m_scriptId = 0; - m_scriptInterface = nullptr; - m_scripted = false; - m_isLoaded = false; -} - -bool CreatureEvent::executeOnLogin(Player* player) -{ - //onLogin(player) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogin] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return m_scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnLogout(Player* player) -{ - //onLogout(player) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogout] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return m_scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnThink(Creature* creature, uint32_t interval) -{ - //onThink(creature, interval) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnThink] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, interval); - - return m_scriptInterface->callFunction(2); -} - -bool CreatureEvent::executeOnPrepareDeath(Creature* creature, Creature* killer) -{ - //onPrepareDeath(creature, killer) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnPrepareDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - if (killer) { - LuaScriptInterface::pushUserdata(L, killer); - LuaScriptInterface::setCreatureMetatable(L, -1, killer); - } else { - lua_pushnil(L); - } - - return m_scriptInterface->callFunction(2); -} - -bool CreatureEvent::executeOnDeath(Creature* creature, Item* corpse, Creature* killer, Creature* mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified) -{ - //onDeath(creature, corpse, lasthitkiller, mostdamagekiller, lasthitunjustified, mostdamageunjustified) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushThing(L, corpse); - - if (killer) { - LuaScriptInterface::pushUserdata(L, killer); - LuaScriptInterface::setCreatureMetatable(L, -1, killer); - } else { - lua_pushnil(L); - } - - if (mostDamageKiller) { - LuaScriptInterface::pushUserdata(L, mostDamageKiller); - LuaScriptInterface::setCreatureMetatable(L, -1, mostDamageKiller); - } else { - lua_pushnil(L); - } - - LuaScriptInterface::pushBoolean(L, lastHitUnjustified); - LuaScriptInterface::pushBoolean(L, mostDamageUnjustified); - - return m_scriptInterface->callFunction(6); -} - -bool CreatureEvent::executeAdvance(Player* player, skills_t skill, uint32_t oldLevel, - uint32_t newLevel) -{ - //onAdvance(player, skill, oldLevel, newLevel) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeAdvance] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - lua_pushnumber(L, static_cast(skill)); - lua_pushnumber(L, oldLevel); - lua_pushnumber(L, newLevel); - - return m_scriptInterface->callFunction(4); -} - -void CreatureEvent::executeOnKill(Creature* creature, Creature* target) -{ - //onKill(creature, target) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnKill] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setCreatureMetatable(L, -1, target); - m_scriptInterface->callVoidFunction(2); -} - -void CreatureEvent::executeModalWindow(Player* player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId) -{ - //onModalWindow(player, modalWindowId, buttonId, choiceId) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeModalWindow] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, modalWindowId); - lua_pushnumber(L, buttonId); - lua_pushnumber(L, choiceId); - - m_scriptInterface->callVoidFunction(4); -} - -bool CreatureEvent::executeTextEdit(Player* player, Item* item, const std::string& text) -{ - //onTextEdit(player, item, text) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeTextEdit] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushString(L, text); - - return m_scriptInterface->callFunction(3); -} - -void CreatureEvent::executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage) -{ - //onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeHealthChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - if (attacker) { - LuaScriptInterface::pushUserdata(L, attacker); - LuaScriptInterface::setCreatureMetatable(L, -1, attacker); - } else { - lua_pushnil(L); - } - - lua_pushnumber(L, damage.primary.value); - lua_pushnumber(L, damage.primary.type); - lua_pushnumber(L, damage.secondary.value); - lua_pushnumber(L, damage.secondary.type); - lua_pushnumber(L, damage.origin); - - if (m_scriptInterface->protectedCall(L, 7, 4) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - damage.primary.value = std::abs(LuaScriptInterface::getNumber(L, -4)); - damage.primary.type = LuaScriptInterface::getNumber(L, -3); - damage.secondary.value = std::abs(LuaScriptInterface::getNumber(L, -2)); - damage.secondary.type = LuaScriptInterface::getNumber(L, -1); - - lua_pop(L, 4); - if (damage.primary.type != COMBAT_HEALING) { - damage.primary.value = -damage.primary.value; - damage.secondary.value = -damage.secondary.value; - } - } - - m_scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeManaChange(Creature* creature, Creature* attacker, int32_t& manaChange, CombatOrigin origin) -{ - //onManaChange(creature, attacker, manaChange, origin) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeManaChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - if (attacker) { - LuaScriptInterface::pushUserdata(L, attacker); - LuaScriptInterface::setCreatureMetatable(L, -1, attacker); - } else { - lua_pushnil(L); - } - - lua_pushnumber(L, manaChange); - lua_pushnumber(L, origin); - - if (m_scriptInterface->protectedCall(L, 4, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(L, -1)); - } else { - manaChange = LuaScriptInterface::getNumber(L, -1); - } - lua_pop(L, 1); - - m_scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer) -{ - //onExtendedOpcode(player, opcode, buffer) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeExtendedOpcode] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, opcode); - LuaScriptInterface::pushString(L, buffer); - - m_scriptInterface->callVoidFunction(3); -} diff --git a/path_10_8/src/creatureevent.h b/path_10_8/src/creatureevent.h deleted file mode 100644 index 19c2c2a5b..000000000 --- a/path_10_8/src/creatureevent.h +++ /dev/null @@ -1,119 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CREATUREEVENT_H_73FCAF4608CB41399D53C919316646A9 -#define FS_CREATUREEVENT_H_73FCAF4608CB41399D53C919316646A9 - -#include "luascript.h" -#include "baseevents.h" -#include "enums.h" - -enum CreatureEventType_t { - CREATURE_EVENT_NONE, - CREATURE_EVENT_LOGIN, - CREATURE_EVENT_LOGOUT, - CREATURE_EVENT_THINK, - CREATURE_EVENT_PREPAREDEATH, - CREATURE_EVENT_DEATH, - CREATURE_EVENT_KILL, - CREATURE_EVENT_ADVANCE, - CREATURE_EVENT_MODALWINDOW, - CREATURE_EVENT_TEXTEDIT, - CREATURE_EVENT_HEALTHCHANGE, - CREATURE_EVENT_MANACHANGE, - CREATURE_EVENT_EXTENDED_OPCODE, // otclient additional network opcodes -}; - -class CreatureEvent; - -class CreatureEvents final : public BaseEvents -{ - public: - CreatureEvents(); - ~CreatureEvents(); - - // non-copyable - CreatureEvents(const CreatureEvents&) = delete; - CreatureEvents& operator=(const CreatureEvents&) = delete; - - // global events - bool playerLogin(Player* player) const; - bool playerLogout(Player* player) const; - bool playerAdvance(Player* player, skills_t, uint32_t, uint32_t); - - CreatureEvent* getEventByName(const std::string& name, bool forceLoaded = true); - - protected: - LuaScriptInterface& getScriptInterface() final; - std::string getScriptBaseName() const final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - void clear() final; - - //creature events - typedef std::map CreatureEventList; - CreatureEventList m_creatureEvents; - - LuaScriptInterface m_scriptInterface; -}; - -class CreatureEvent final : public Event -{ - public: - explicit CreatureEvent(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - - CreatureEventType_t getEventType() const { - return m_type; - } - const std::string& getName() const { - return m_eventName; - } - bool isLoaded() const { - return m_isLoaded; - } - - void clearEvent(); - void copyEvent(CreatureEvent* creatureEvent); - - //scripting - bool executeOnLogin(Player* player); - bool executeOnLogout(Player* player); - bool executeOnThink(Creature* creature, uint32_t interval); - bool executeOnPrepareDeath(Creature* creature, Creature* killer); - bool executeOnDeath(Creature* creature, Item* corpse, Creature* killer, Creature* mostDamageKiller, bool lastHitUnjustified, bool mostDamageUnjustified); - void executeOnKill(Creature* creature, Creature* target); - bool executeAdvance(Player* player, skills_t, uint32_t, uint32_t); - void executeModalWindow(Player* player, uint32_t modalWindowId, uint8_t buttonId, uint8_t choiceId); - bool executeTextEdit(Player* player, Item* item, const std::string& text); - void executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage); - void executeManaChange(Creature* creature, Creature* attacker, int32_t& manaChange, CombatOrigin origin); - void executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer); - // - - protected: - std::string getScriptEventName() const final; - - std::string m_eventName; - CreatureEventType_t m_type; - bool m_isLoaded; -}; - -#endif diff --git a/path_10_8/src/cylinder.cpp b/path_10_8/src/cylinder.cpp deleted file mode 100644 index 4d4a22ede..000000000 --- a/path_10_8/src/cylinder.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "cylinder.h" - -VirtualCylinder* VirtualCylinder::virtualCylinder = new VirtualCylinder; - -int32_t Cylinder::getThingIndex(const Thing*) const -{ - return -1; -} - -size_t Cylinder::getFirstIndex() const -{ - return 0; -} - -size_t Cylinder::getLastIndex() const -{ - return 0; -} - -uint32_t Cylinder::getItemTypeCount(uint16_t, int32_t) const -{ - return 0; -} - -std::map& Cylinder::getAllItemTypeCount(std::map &countMap) const -{ - return countMap; -} - -Thing* Cylinder::getThing(size_t) const -{ - return nullptr; -} - -void Cylinder::internalAddThing(Thing*) -{ - // -} - -void Cylinder::internalAddThing(uint32_t, Thing*) -{ - // -} - -void Cylinder::startDecaying() -{ - // -} diff --git a/path_10_8/src/cylinder.h b/path_10_8/src/cylinder.h deleted file mode 100644 index 2c61889ea..000000000 --- a/path_10_8/src/cylinder.h +++ /dev/null @@ -1,249 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_CYLINDER_H_54BBCEB2A5B7415DAD837E4D58115150 -#define FS_CYLINDER_H_54BBCEB2A5B7415DAD837E4D58115150 - -#include "enums.h" -#include "thing.h" - -class Item; -class Creature; - -#define INDEX_WHEREEVER -1 - -enum cylinderflags_t { - FLAG_NOLIMIT = 1 << 0, //Bypass limits like capacity/container limits, blocking items/creatures etc. - FLAG_IGNOREBLOCKITEM = 1 << 1, //Bypass movable blocking item checks - FLAG_IGNOREBLOCKCREATURE = 1 << 2, //Bypass creature checks - FLAG_CHILDISOWNER = 1 << 3, //Used by containers to query capacity of the carrier (player) - FLAG_PATHFINDING = 1 << 4, //An additional check is done for floor changing/teleport items - FLAG_IGNOREFIELDDAMAGE = 1 << 5, //Bypass field damage checks - FLAG_IGNORENOTMOVEABLE = 1 << 6, //Bypass check for mobility - FLAG_IGNOREAUTOSTACK = 1 << 7, //queryDestination will not try to stack items together -}; - -enum cylinderlink_t { - LINK_OWNER, - LINK_PARENT, - LINK_TOPPARENT, - LINK_NEAR, -}; - -class Cylinder : virtual public Thing -{ - public: - /** - * Query if the cylinder can add an object - * \param index points to the destination index (inventory slot/container position) - * -1 is a internal value and means add to a empty position, with no destItem - * \param thing the object to move/add - * \param count is the amount that we want to move/add - * \param flags if FLAG_CHILDISOWNER if set the query is from a child-cylinder (check cap etc.) - * if FLAG_NOLIMIT is set blocking items/container limits is ignored - * \param actor the creature trying to add the thing - * \returns ReturnValue holds the return value - */ - virtual ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const = 0; - - /** - * Query the cylinder how much it can accept - * \param index points to the destination index (inventory slot/container position) - * -1 is a internal value and means add to a empty position, with no destItem - * \param thing the object to move/add - * \param count is the amount that we want to move/add - * \param maxQueryCount is the max amount that the cylinder can accept - * \param flags optional flags to modify the default behaviour - * \returns ReturnValue holds the return value - */ - virtual ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount, - uint32_t flags) const = 0; - - /** - * Query if the cylinder can remove an object - * \param thing the object to move/remove - * \param count is the amount that we want to remove - * \param flags optional flags to modify the default behaviour - * \returns ReturnValue holds the return value - */ - virtual ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const = 0; - - /** - * Query the destination cylinder - * \param index points to the destination index (inventory slot/container position), - * -1 is a internal value and means add to a empty position, with no destItem - * this method can change the index to point to the new cylinder index - * \param destItem is the destination object - * \param flags optional flags to modify the default behaviour - * this method can modify the flags - * \returns Cylinder returns the destination cylinder - */ - virtual Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) = 0; - - /** - * Add the object to the cylinder - * \param thing is the object to add - */ - virtual void addThing(Thing* thing) = 0; - - /** - * Add the object to the cylinder - * \param index points to the destination index (inventory slot/container position) - * \param thing is the object to add - */ - virtual void addThing(int32_t index, Thing* thing) = 0; - - /** - * Update the item count or type for an object - * \param thing is the object to update - * \param itemId is the new item id - * \param count is the new count value - */ - virtual void updateThing(Thing* thing, uint16_t itemId, uint32_t count) = 0; - - /** - * Replace an object with a new - * \param index is the position to change (inventory slot/container position) - * \param thing is the object to update - */ - virtual void replaceThing(uint32_t index, Thing* thing) = 0; - - /** - * Remove an object - * \param thing is the object to delete - * \param count is the new count value - */ - virtual void removeThing(Thing* thing, uint32_t count) = 0; - - /** - * Is sent after an operation (move/add) to update internal values - * \param thing is the object that has been added - * \param index is the objects new index value - * \param link holds the relation the object has to the cylinder - */ - virtual void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) = 0; - - /** - * Is sent after an operation (move/remove) to update internal values - * \param thing is the object that has been removed - * \param index is the previous index of the removed object - * \param link holds the relation the object has to the cylinder - */ - virtual void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) = 0; - - /** - * Gets the index of an object - * \param thing the object to get the index value from - * \returns the index of the object, returns -1 if not found - */ - virtual int32_t getThingIndex(const Thing* thing) const; - - /** - * Returns the first index - * \returns the first index, if not implemented 0 is returned - */ - virtual size_t getFirstIndex() const; - - /** - * Returns the last index - * \returns the last index, if not implemented 0 is returned - */ - virtual size_t getLastIndex() const; - - /** - * Gets the object based on index - * \returns the object, returns nullptr if not found - */ - virtual Thing* getThing(size_t index) const; - - /** - * Get the amount of items of a certain type - * \param itemId is the item type to the get the count of - * \param subType is the extra type an item can have such as charges/fluidtype, -1 means not used - * \returns the amount of items of the asked item type - */ - virtual uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const; - - /** - * Get the amount of items of a all types - * \param countMap a map to put the itemID:count mapping in - * \returns a map mapping item id to count (same as first argument) - */ - virtual std::map& getAllItemTypeCount(std::map &countMap) const; - - /** - * Adds an object to the cylinder without sending to the client(s) - * \param thing is the object to add - */ - virtual void internalAddThing(Thing* thing); - - /** - * Adds an object to the cylinder without sending to the client(s) - * \param thing is the object to add - * \param index points to the destination index (inventory slot/container position) - */ - virtual void internalAddThing(uint32_t index, Thing* thing); - - virtual void startDecaying(); -}; - -class VirtualCylinder final : public Cylinder -{ - public: - static VirtualCylinder* virtualCylinder; - - virtual ReturnValue queryAdd(int32_t, const Thing&, uint32_t, uint32_t, Creature* = nullptr) const override { - return RETURNVALUE_NOTPOSSIBLE; - } - virtual ReturnValue queryMaxCount(int32_t, const Thing&, uint32_t, uint32_t&, uint32_t) const override { - return RETURNVALUE_NOTPOSSIBLE; - } - virtual ReturnValue queryRemove(const Thing&, uint32_t, uint32_t) const override { - return RETURNVALUE_NOTPOSSIBLE; - } - virtual Cylinder* queryDestination(int32_t&, const Thing&, Item**, uint32_t&) override { - return nullptr; - } - - virtual void addThing(Thing*) override {} - virtual void addThing(int32_t, Thing*) override {} - virtual void updateThing(Thing*, uint16_t, uint32_t) override {} - virtual void replaceThing(uint32_t, Thing*) override {} - virtual void removeThing(Thing*, uint32_t) override {} - - virtual void postAddNotification(Thing*, const Cylinder*, int32_t, cylinderlink_t = LINK_OWNER) override {} - virtual void postRemoveNotification(Thing*, const Cylinder*, int32_t, cylinderlink_t = LINK_OWNER) override {} - - bool isPushable() const override { - return false; - } - int32_t getThrowRange() const override { - return 1; - } - std::string getDescription(int32_t) const override { - return std::string(); - } - bool isRemoved() const override { - return false; - } -}; - -#endif diff --git a/path_10_8/src/database.cpp b/path_10_8/src/database.cpp deleted file mode 100644 index a10524ff3..000000000 --- a/path_10_8/src/database.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "database.h" - -#include - -extern ConfigManager g_config; - -Database::Database() -{ - handle = nullptr; - maxPacketSize = 1048576; -} - -Database::~Database() -{ - if (handle != nullptr) { - mysql_close(handle); - } -} - -bool Database::connect() -{ - // connection handle initialization - handle = mysql_init(nullptr); - if (!handle) { - std::cout << std::endl << "Failed to initialize MySQL connection handle." << std::endl; - return false; - } - - // automatic reconnect - my_bool reconnect = true; - mysql_options(handle, MYSQL_OPT_RECONNECT, &reconnect); - - // connects to database - if (!mysql_real_connect(handle, g_config.getString(ConfigManager::MYSQL_HOST).c_str(), g_config.getString(ConfigManager::MYSQL_USER).c_str(), g_config.getString(ConfigManager::MYSQL_PASS).c_str(), g_config.getString(ConfigManager::MYSQL_DB).c_str(), g_config.getNumber(ConfigManager::SQL_PORT), g_config.getString(ConfigManager::MYSQL_SOCK).c_str(), 0)) { - std::cout << std::endl << "MySQL Error Message: " << mysql_error(handle) << std::endl; - return false; - } - - DBResult_ptr result = storeQuery("SHOW VARIABLES LIKE 'max_allowed_packet'"); - if (result) { - maxPacketSize = result->getNumber("Value"); - } - return true; -} - -bool Database::beginTransaction() -{ - if (!executeQuery("BEGIN")) { - return false; - } - - databaseLock.lock(); - return true; -} - -bool Database::rollback() -{ - if (mysql_rollback(handle) != 0) { - std::cout << "[Error - mysql_rollback] Message: " << mysql_error(handle) << std::endl; - databaseLock.unlock(); - return false; - } - - databaseLock.unlock(); - return true; -} - -bool Database::commit() -{ - if (mysql_commit(handle) != 0) { - std::cout << "[Error - mysql_commit] Message: " << mysql_error(handle) << std::endl; - databaseLock.unlock(); - return false; - } - - databaseLock.unlock(); - return true; -} - -bool Database::executeQuery(const std::string& query) -{ - bool success = true; - - // executes the query - databaseLock.lock(); - - while (mysql_real_query(handle, query.c_str(), query.length()) != 0) { - std::cout << "[Error - mysql_real_query] Query: " << query.substr(0, 256) << std::endl << "Message: " << mysql_error(handle) << std::endl; - auto error = mysql_errno(handle); - if (error != CR_SERVER_LOST && error != CR_SERVER_GONE_ERROR && error != CR_CONN_HOST_ERROR && error != 1053/*ER_SERVER_SHUTDOWN*/ && error != CR_CONNECTION_ERROR) { - success = false; - break; - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - MYSQL_RES* m_res = mysql_store_result(handle); - databaseLock.unlock(); - - if (m_res) { - mysql_free_result(m_res); - } - - return success; -} - -DBResult_ptr Database::storeQuery(const std::string& query) -{ - databaseLock.lock(); - - retry: - while (mysql_real_query(handle, query.c_str(), query.length()) != 0) { - std::cout << "[Error - mysql_real_query] Query: " << query << std::endl << "Message: " << mysql_error(handle) << std::endl; - auto error = mysql_errno(handle); - if (error != CR_SERVER_LOST && error != CR_SERVER_GONE_ERROR && error != CR_CONN_HOST_ERROR && error != 1053/*ER_SERVER_SHUTDOWN*/ && error != CR_CONNECTION_ERROR) { - break; - } - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - // we should call that every time as someone would call executeQuery('SELECT...') - // as it is described in MySQL manual: "it doesn't hurt" :P - MYSQL_RES* res = mysql_store_result(handle); - if (res == nullptr) { - std::cout << "[Error - mysql_store_result] Query: " << query << std::endl << "Message: " << mysql_error(handle) << std::endl; - auto error = mysql_errno(handle); - if (error != CR_SERVER_LOST && error != CR_SERVER_GONE_ERROR && error != CR_CONN_HOST_ERROR && error != 1053/*ER_SERVER_SHUTDOWN*/ && error != CR_CONNECTION_ERROR) { - databaseLock.unlock(); - return nullptr; - } - goto retry; - } - databaseLock.unlock(); - - // retrieving results of query - DBResult_ptr result = std::make_shared(res); - if (!result->hasNext()) { - return nullptr; - } - return result; -} - -std::string Database::escapeString(const std::string& s) const -{ - return escapeBlob(s.c_str(), s.length()); -} - -std::string Database::escapeBlob(const char* s, uint32_t length) const -{ - // the worst case is 2n + 1 - size_t maxLength = (length * 2) + 1; - - std::string escaped; - escaped.reserve(maxLength + 2); - escaped.push_back('\''); - - if (length != 0) { - char* output = new char[maxLength]; - mysql_real_escape_string(handle, output, s, length); - escaped.append(output); - delete[] output; - } - - escaped.push_back('\''); - return escaped; -} - -DBResult::DBResult(MYSQL_RES* res) -{ - handle = res; - - size_t i = 0; - - MYSQL_FIELD* field = mysql_fetch_field(handle); - while (field) { - listNames[field->name] = i++; - field = mysql_fetch_field(handle); - } - - row = mysql_fetch_row(handle); -} - -DBResult::~DBResult() -{ - mysql_free_result(handle); -} - -std::string DBResult::getString(const std::string& s) const -{ - auto it = listNames.find(s); - if (it == listNames.end()) { - std::cout << "[Error - DBResult::getString] Column '" << s << "' does not exist in result set." << std::endl; - return std::string(); - } - - if (row[it->second] == nullptr) { - return std::string(); - } - - return std::string(row[it->second]); -} - -const char* DBResult::getStream(const std::string& s, unsigned long& size) const -{ - auto it = listNames.find(s); - if (it == listNames.end()) { - std::cout << "[Error - DBResult::getStream] Column '" << s << "' doesn't exist in the result set" << std::endl; - size = 0; - return nullptr; - } - - if (row[it->second] == nullptr) { - size = 0; - return nullptr; - } - - size = mysql_fetch_lengths(handle)[it->second]; - return row[it->second]; -} - -bool DBResult::hasNext() const -{ - return row != nullptr; -} - -bool DBResult::next() -{ - row = mysql_fetch_row(handle); - return row != nullptr; -} - -DBInsert::DBInsert(std::string query) : query(query) -{ - this->length = this->query.length(); -} - -bool DBInsert::addRow(const std::string& row) -{ - // adds new row to buffer - const size_t rowLength = row.length(); - length += rowLength; - if (length > Database::getInstance()->getMaxPacketSize() && !execute()) { - return false; - } - - if (values.empty()) { - values.reserve(rowLength + 2); - values.push_back('('); - values.append(row); - values.push_back(')'); - } else { - values.reserve(values.length() + rowLength + 3); - values.push_back(','); - values.push_back('('); - values.append(row); - values.push_back(')'); - } - return true; -} - -bool DBInsert::addRow(std::ostringstream& row) -{ - bool ret = addRow(row.str()); - row.str(std::string()); - return ret; -} - -bool DBInsert::execute() -{ - if (values.empty()) { - return true; - } - - // executes buffer - bool res = Database::getInstance()->executeQuery(query + values); - values.clear(); - length = query.length(); - return res; -} diff --git a/path_10_8/src/database.h b/path_10_8/src/database.h deleted file mode 100644 index d3f2c8b8e..000000000 --- a/path_10_8/src/database.h +++ /dev/null @@ -1,245 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DATABASE_H_A484B0CDFDE542838F506DCE3D40C693 -#define FS_DATABASE_H_A484B0CDFDE542838F506DCE3D40C693 - -#include - -#include - -class DBResult; -typedef std::shared_ptr DBResult_ptr; - -class Database -{ - public: - Database(); - ~Database(); - - // non-copyable - Database(const Database&) = delete; - Database& operator=(const Database&) = delete; - - /** - * Singleton implementation. - * - * @return database connection handler singleton - */ - static Database* getInstance() - { - static Database instance; - return &instance; - } - - /** - * Connects to the database - * - * @return true on successful connection, false on error - */ - bool connect(); - - /** - * Executes command. - * - * Executes query which doesn't generates results (eg. INSERT, UPDATE, DELETE...). - * - * @param query command - * @return true on success, false on error - */ - bool executeQuery(const std::string& query); - - /** - * Queries database. - * - * Executes query which generates results (mostly SELECT). - * - * @return results object (nullptr on error) - */ - DBResult_ptr storeQuery(const std::string& query); - - /** - * Escapes string for query. - * - * Prepares string to fit SQL queries including quoting it. - * - * @param s string to be escaped - * @return quoted string - */ - std::string escapeString(const std::string& s) const; - - /** - * Escapes binary stream for query. - * - * Prepares binary stream to fit SQL queries. - * - * @param s binary stream - * @param length stream length - * @return quoted string - */ - std::string escapeBlob(const char* s, uint32_t length) const; - - /** - * Retrieve id of last inserted row - * - * @return id on success, 0 if last query did not result on any rows with auto_increment keys - */ - uint64_t getLastInsertId() const { - return static_cast(mysql_insert_id(handle)); - } - - /** - * Get database engine version - * - * @return the database engine version - */ - static const char* getClientVersion() { - return mysql_get_client_info(); - } - - uint64_t getMaxPacketSize() const { - return maxPacketSize; - } - - protected: - /** - * Transaction related methods. - * - * Methods for starting, commiting and rolling back transaction. Each of the returns boolean value. - * - * @return true on success, false on error - */ - bool beginTransaction(); - bool rollback(); - bool commit(); - - private: - MYSQL* handle; - std::recursive_mutex databaseLock; - uint64_t maxPacketSize; - - friend class DBTransaction; -}; - -class DBResult -{ - public: - explicit DBResult(MYSQL_RES* res); - ~DBResult(); - - // non-copyable - DBResult(const DBResult&) = delete; - DBResult& operator=(const DBResult&) = delete; - - template - T getNumber(const std::string& s) const - { - auto it = listNames.find(s); - if (it == listNames.end()) { - std::cout << "[Error - DBResult::getNumber] Column '" << s << "' doesn't exist in the result set" << std::endl; - return static_cast(0); - } - - if (row[it->second] == nullptr) { - return static_cast(0); - } - - T data; - try { - data = boost::lexical_cast(row[it->second]); - } catch (boost::bad_lexical_cast&) { - data = 0; - } - return data; - } - - std::string getString(const std::string& s) const; - const char* getStream(const std::string& s, unsigned long& size) const; - - bool hasNext() const; - bool next(); - - private: - MYSQL_RES* handle; - MYSQL_ROW row; - - std::map listNames; - - friend class Database; -}; - -/** - * INSERT statement. - */ -class DBInsert -{ - public: - explicit DBInsert(std::string query); - bool addRow(const std::string& row); - bool addRow(std::ostringstream& row); - bool execute(); - - protected: - std::string query; - std::string values; - size_t length; -}; - -class DBTransaction -{ - public: - DBTransaction() { - state = STATE_NO_START; - } - - ~DBTransaction() { - if (state == STATE_START) { - Database::getInstance()->rollback(); - } - } - - // non-copyable - DBTransaction(const DBTransaction&) = delete; - DBTransaction& operator=(const DBTransaction&) = delete; - - bool begin() { - state = STATE_START; - return Database::getInstance()->beginTransaction(); - } - - bool commit() { - if (state != STATE_START) { - return false; - } - - state = STEATE_COMMIT; - return Database::getInstance()->commit(); - } - - private: - enum TransactionStates_t { - STATE_NO_START, - STATE_START, - STEATE_COMMIT, - }; - - TransactionStates_t state; -}; - -#endif diff --git a/path_10_8/src/databasemanager.cpp b/path_10_8/src/databasemanager.cpp deleted file mode 100644 index 2940f201e..000000000 --- a/path_10_8/src/databasemanager.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "databasemanager.h" -#include "luascript.h" - -extern ConfigManager g_config; - -bool DatabaseManager::optimizeTables() -{ - Database* db = Database::getInstance(); - std::ostringstream query; - - query << "SELECT `TABLE_NAME` FROM `information_schema`.`TABLES` WHERE `TABLE_SCHEMA` = " << db->escapeString(g_config.getString(ConfigManager::MYSQL_DB)) << " AND `DATA_FREE` > 0"; - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - do { - std::string tableName = result->getString("TABLE_NAME"); - std::cout << "> Optimizing table " << tableName << "..." << std::flush; - - query.str(std::string()); - query << "OPTIMIZE TABLE `" << tableName << '`'; - - if (db->executeQuery(query.str())) { - std::cout << " [success]" << std::endl; - } else { - std::cout << " [failed]" << std::endl; - } - } while (result->next()); - return true; -} - -bool DatabaseManager::tableExists(const std::string& tableName) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = " << db->escapeString(g_config.getString(ConfigManager::MYSQL_DB)) << " AND `TABLE_NAME` = " << db->escapeString(tableName) << " LIMIT 1"; - return db->storeQuery(query.str()).get() != nullptr; -} - -bool DatabaseManager::isDatabaseSetup() -{ - Database* db = Database::getInstance(); - std::ostringstream query; - query << "SELECT `TABLE_NAME` FROM `information_schema`.`tables` WHERE `TABLE_SCHEMA` = " << db->escapeString(g_config.getString(ConfigManager::MYSQL_DB)); - return db->storeQuery(query.str()).get() != nullptr; -} - -int32_t DatabaseManager::getDatabaseVersion() -{ - if (!tableExists("server_config")) { - Database* db = Database::getInstance(); - db->executeQuery("CREATE TABLE `server_config` (`config` VARCHAR(50) NOT nullptr, `value` VARCHAR(256) NOT nullptr DEFAULT '', UNIQUE(`config`)) ENGINE = InnoDB"); - db->executeQuery("INSERT INTO `server_config` VALUES ('db_version', 0)"); - return 0; - } - - int32_t version = 0; - if (getDatabaseConfig("db_version", version)) { - return version; - } - return -1; -} - -void DatabaseManager::updateDatabase() -{ - lua_State* L = luaL_newstate(); - if (!L) { - return; - } - - luaL_openlibs(L); - -#ifndef LUAJIT_VERSION - //bit operations for Lua, based on bitlib project release 24 - //bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift - luaL_register(L, "bit", LuaScriptInterface::luaBitReg); -#endif - - //db table - luaL_register(L, "db", LuaScriptInterface::luaDatabaseTable); - - //result table - luaL_register(L, "result", LuaScriptInterface::luaResultTable); - - int32_t version = getDatabaseVersion(); - do { - std::ostringstream ss; - ss << "data/migrations/" << version << ".lua"; - if (luaL_dofile(L, ss.str().c_str()) != 0) { - std::cout << "[Error - DatabaseManager::updateDatabase - Version: " << version << "] " << lua_tostring(L, -1) << std::endl; - break; - } - - if (!LuaScriptInterface::reserveScriptEnv()) { - break; - } - - lua_getglobal(L, "onUpdateDatabase"); - if (lua_pcall(L, 0, 1, 0) != 0) { - LuaScriptInterface::resetScriptEnv(); - std::cout << "[Error - DatabaseManager::updateDatabase - Version: " << version << "] " << lua_tostring(L, -1) << std::endl; - break; - } - - if (!LuaScriptInterface::getBoolean(L, -1, false)) { - LuaScriptInterface::resetScriptEnv(); - break; - } - - version++; - std::cout << "> Database has been updated to version " << version << '.' << std::endl; - registerDatabaseConfig("db_version", version); - - LuaScriptInterface::resetScriptEnv(); - } while (true); - lua_close(L); -} - -bool DatabaseManager::getDatabaseConfig(const std::string& config, int32_t& value) -{ - Database* db = Database::getInstance(); - std::ostringstream query; - query << "SELECT `value` FROM `server_config` WHERE `config` = " << db->escapeString(config); - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - value = result->getNumber("value"); - return true; -} - -void DatabaseManager::registerDatabaseConfig(const std::string& config, int32_t value) -{ - Database* db = Database::getInstance(); - std::ostringstream query; - - int32_t tmp; - - if (!getDatabaseConfig(config, tmp)) { - query << "INSERT INTO `server_config` VALUES (" << db->escapeString(config) << ", '" << value << "')"; - } else { - query << "UPDATE `server_config` SET `value` = '" << value << "' WHERE `config` = " << db->escapeString(config); - } - - db->executeQuery(query.str()); -} diff --git a/path_10_8/src/databasemanager.h b/path_10_8/src/databasemanager.h deleted file mode 100644 index 128827578..000000000 --- a/path_10_8/src/databasemanager.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DATABASEMANAGER_H_2B75821C555E4D1D83E32B20D683217C -#define FS_DATABASEMANAGER_H_2B75821C555E4D1D83E32B20D683217C -#include "database.h" - -class DatabaseManager -{ - public: - static bool tableExists(const std::string& table); - - static int32_t getDatabaseVersion(); - static bool isDatabaseSetup(); - - static bool optimizeTables(); - static void updateDatabase(); - - static bool getDatabaseConfig(const std::string& config, int32_t& value); - static void registerDatabaseConfig(const std::string& config, int32_t value); -}; -#endif diff --git a/path_10_8/src/databasetasks.cpp b/path_10_8/src/databasetasks.cpp deleted file mode 100644 index f479500dc..000000000 --- a/path_10_8/src/databasetasks.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "databasetasks.h" -#include "tasks.h" - -extern Dispatcher g_dispatcher; - - -void DatabaseTasks::start() -{ - db.connect(); - ThreadHolder::start(); -} - -void DatabaseTasks::threadMain() -{ - std::unique_lock taskLockUnique(taskLock, std::defer_lock); - while (getState() != THREAD_STATE_TERMINATED) { - taskLockUnique.lock(); - if (tasks.empty()) { - taskSignal.wait(taskLockUnique); - } - - if (!tasks.empty()) { - DatabaseTask task = std::move(tasks.front()); - tasks.pop_front(); - taskLockUnique.unlock(); - runTask(task); - } else { - taskLockUnique.unlock(); - } - } -} - -void DatabaseTasks::addTask(const std::string& query, const std::function& callback/* = nullptr*/, bool store/* = false*/) -{ - bool signal = false; - taskLock.lock(); - if (getState() == THREAD_STATE_RUNNING) { - signal = tasks.empty(); - tasks.emplace_back(query, callback, store); - } - taskLock.unlock(); - - if (signal) { - taskSignal.notify_one(); - } -} - -void DatabaseTasks::runTask(const DatabaseTask& task) -{ - bool success; - DBResult_ptr result; - if (task.store) { - result = db.storeQuery(task.query); - success = true; - } else { - result = nullptr; - success = db.executeQuery(task.query); - } - - if (task.callback) { - g_dispatcher.addTask(createTask(std::bind(task.callback, result, success))); - } -} - -void DatabaseTasks::flush() -{ - while (!tasks.empty()) { - runTask(tasks.front()); - tasks.pop_front(); - } -} - -void DatabaseTasks::shutdown() -{ - taskLock.lock(); - setState(THREAD_STATE_TERMINATED); - flush(); - taskLock.unlock(); - taskSignal.notify_one(); -} diff --git a/path_10_8/src/databasetasks.h b/path_10_8/src/databasetasks.h deleted file mode 100644 index 1d8738f40..000000000 --- a/path_10_8/src/databasetasks.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DATABASETASKS_H_9CBA08E9F5FEBA7275CCEE6560059576 -#define FS_DATABASETASKS_H_9CBA08E9F5FEBA7275CCEE6560059576 - -#include -#include "thread_holder_base.h" -#include "database.h" -#include "enums.h" - -struct DatabaseTask { - DatabaseTask(std::string query, const std::function& callback, bool store) : - query(query), callback(callback), store(store) {} - - std::string query; - std::function callback; - bool store; -}; - -class DatabaseTasks : public ThreadHolder -{ - public: - DatabaseTasks() = default; - void start(); - void flush(); - void shutdown(); - - void addTask(const std::string& query, const std::function& callback = nullptr, bool store = false); - - void threadMain(); - private: - void runTask(const DatabaseTask& task); - - Database db; - std::thread thread; - std::list tasks; - std::mutex taskLock; - std::condition_variable taskSignal; -}; - -extern DatabaseTasks g_databaseTasks; - -#endif diff --git a/path_10_8/src/definitions.h b/path_10_8/src/definitions.h deleted file mode 100644 index 88aa7141d..000000000 --- a/path_10_8/src/definitions.h +++ /dev/null @@ -1,79 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DEFINITIONS_H_877452FEC245450C9F96B8FD268D8963 -#define FS_DEFINITIONS_H_877452FEC245450C9F96B8FD268D8963 - -#define STATUS_SERVER_NAME "OTX Server" -#define STATUS_SERVER_VERSION "3" -#define MINOR_VERSION "2" -#define REVISION_VERSION "-" -#define SOFTWARE_CODENAME "The Second" -#define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" -#define GIT_REPO "https://github.com/mattyx14/otxserver/" - -#define CLIENT_VERSION_MIN 1090 -#define CLIENT_VERSION_MAX 1090 -#define CLIENT_VERSION_STR "10.90" - -#ifndef __FUNCTION__ -#define __FUNCTION__ __func__ -#endif - -#ifndef _USE_MATH_DEFINES -#define _USE_MATH_DEFINES -#endif - -#include - -#ifdef _WIN32 -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#define WIN32_LEAN_AND_MEAN - -#ifdef _MSC_VER -#ifdef NDEBUG -#define _SECURE_SCL 0 -#define HAS_ITERATOR_DEBUGGING 0 -#endif - -#pragma warning(disable:4127) // conditional expression is constant -#pragma warning(disable:4244) // 'argument' : conversion from 'type1' to 'type2', possible loss of data -#pragma warning(disable:4250) // 'class1' : inherits 'class2::member' via dominance -#pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data -#pragma warning(disable:4351) // new behavior: elements of array will be default initialized -#pragma warning(disable:4458) // declaration hides class member -#endif - -#define strcasecmp _stricmp -#define strncasecmp _strnicmp - -#ifndef _WIN32_WINNT -// 0x0602: Windows 7 -#define _WIN32_WINNT 0x0602 -#endif -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#endif diff --git a/path_10_8/src/depotchest.cpp b/path_10_8/src/depotchest.cpp deleted file mode 100644 index 6f09380b1..000000000 --- a/path_10_8/src/depotchest.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "depotchest.h" -#include "tools.h" - -DepotChest::DepotChest(uint16_t _type) : - Container(_type) -{ - maxDepotItems = 1500; -} - -ReturnValue DepotChest::queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor/* = nullptr*/) const -{ - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); - if (!skipLimit) { - int32_t addCount = 0; - - if ((item->isStackable() && item->getItemCount() != count)) { - addCount = 1; - } - - if (item->getTopParent() != this) { - if (const Container* container = item->getContainer()) { - addCount = container->getItemHoldingCount() + 1; - } else { - addCount = 1; - } - } - - if (getItemHoldingCount() + addCount > maxDepotItems) { - return RETURNVALUE_DEPOTISFULL; - } - } - - return Container::queryAdd(index, thing, count, flags, actor); -} - -void DepotChest::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - Cylinder* parent = getParent(); - if (parent != nullptr) { - parent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void DepotChest::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - Cylinder* parent = getParent(); - if (parent != nullptr) { - parent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} - -Cylinder* DepotChest::getParent() const -{ - if (parent) { - return parent->getParent(); - } - return nullptr; -} diff --git a/path_10_8/src/depotchest.h b/path_10_8/src/depotchest.h deleted file mode 100644 index 14e258566..000000000 --- a/path_10_8/src/depotchest.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DEPOTCHEST_H_6538526014684E3DBC92CC12815B6766 -#define FS_DEPOTCHEST_H_6538526014684E3DBC92CC12815B6766 - -#include "container.h" - -class DepotChest final : public Container -{ - public: - explicit DepotChest(uint16_t _type); - - //serialization - void setMaxDepotItems(uint32_t maxitems) { - maxDepotItems = maxitems; - } - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER); - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER); - - //overrides - bool canRemove() const { - return false; - } - - Cylinder* getParent() const; - Cylinder* getRealParent() const { - return parent; - } - - private: - uint32_t maxDepotItems; -}; - -#endif - diff --git a/path_10_8/src/depotlocker.cpp b/path_10_8/src/depotlocker.cpp deleted file mode 100644 index 92fd49dd8..000000000 --- a/path_10_8/src/depotlocker.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "depotlocker.h" - -DepotLocker::DepotLocker(uint16_t _type) : - Container(_type) -{ - depotId = 0; - maxSize = 3; -} - -Attr_ReadValue DepotLocker::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - if (attr == ATTR_DEPOT_ID) { - if (!propStream.read(depotId)) { - return ATTR_READ_ERROR; - } - return ATTR_READ_CONTINUE; - } - return Item::readAttr(attr, propStream); -} - -ReturnValue DepotLocker::queryAdd(int32_t, const Thing&, uint32_t, uint32_t, Creature*) const -{ - return RETURNVALUE_NOTENOUGHROOM; -} - -void DepotLocker::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - if (parent != nullptr) { - parent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void DepotLocker::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - if (parent != nullptr) { - parent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} - -void DepotLocker::removeInbox(Inbox* inbox) -{ - auto cit = std::find(itemlist.begin(), itemlist.end(), inbox); - if (cit == itemlist.end()) { - return; - } - itemlist.erase(cit); -} diff --git a/path_10_8/src/depotlocker.h b/path_10_8/src/depotlocker.h deleted file mode 100644 index 2168b9e9c..000000000 --- a/path_10_8/src/depotlocker.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 -#define FS_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 - -#include "container.h" -#include "inbox.h" - -class DepotLocker final : public Container -{ - public: - explicit DepotLocker(uint16_t _type); - - DepotLocker* getDepotLocker() final { - return this; - } - const DepotLocker* getDepotLocker() const final { - return this; - } - - void removeInbox(Inbox* inbox); - - //serialization - Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) final; - - uint16_t getDepotId() const { - return depotId; - } - void setDepotId(uint16_t depotId) { - this->depotId = depotId; - } - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - bool canRemove() const final { - return false; - } - - private: - uint16_t depotId; -}; - -#endif - diff --git a/path_10_8/src/enums.h b/path_10_8/src/enums.h deleted file mode 100644 index 0d12fdb9d..000000000 --- a/path_10_8/src/enums.h +++ /dev/null @@ -1,579 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ENUMS_H_003445999FEE4A67BCECBE918B0124CE -#define FS_ENUMS_H_003445999FEE4A67BCECBE918B0124CE - -enum BugReportType_t : uint8_t { - BUG_CATEGORY_MAP = 0, - BUG_CATEGORY_TYPO = 1, - BUG_CATEGORY_TECHNICAL = 2, - BUG_CATEGORY_OTHER = 3 -}; - -enum ThreadState { - THREAD_STATE_RUNNING, - THREAD_STATE_CLOSING, - THREAD_STATE_TERMINATED, -}; - -enum itemAttrTypes : uint32_t { - ITEM_ATTRIBUTE_NONE, - - ITEM_ATTRIBUTE_ACTIONID = 1 << 0, - ITEM_ATTRIBUTE_UNIQUEID = 1 << 1, - ITEM_ATTRIBUTE_DESCRIPTION = 1 << 2, - ITEM_ATTRIBUTE_TEXT = 1 << 3, - ITEM_ATTRIBUTE_DATE = 1 << 4, - ITEM_ATTRIBUTE_WRITER = 1 << 5, - ITEM_ATTRIBUTE_NAME = 1 << 6, - ITEM_ATTRIBUTE_ARTICLE = 1 << 7, - ITEM_ATTRIBUTE_PLURALNAME = 1 << 8, - ITEM_ATTRIBUTE_WEIGHT = 1 << 9, - ITEM_ATTRIBUTE_ATTACK = 1 << 10, - ITEM_ATTRIBUTE_DEFENSE = 1 << 11, - ITEM_ATTRIBUTE_EXTRADEFENSE = 1 << 12, - ITEM_ATTRIBUTE_ARMOR = 1 << 13, - ITEM_ATTRIBUTE_HITCHANCE = 1 << 14, - ITEM_ATTRIBUTE_SHOOTRANGE = 1 << 15, - ITEM_ATTRIBUTE_OWNER = 1 << 16, - ITEM_ATTRIBUTE_DURATION = 1 << 17, - ITEM_ATTRIBUTE_DECAYSTATE = 1 << 18, - ITEM_ATTRIBUTE_CORPSEOWNER = 1 << 19, - ITEM_ATTRIBUTE_CHARGES = 1 << 20, - ITEM_ATTRIBUTE_FLUIDTYPE = 1 << 21, - ITEM_ATTRIBUTE_DOORID = 1 << 22, -}; - -enum VipStatus_t : uint8_t { - VIPSTATUS_OFFLINE = 0, - VIPSTATUS_ONLINE = 1, - VIPSTATUS_PENDING = 2 -}; - -enum MarketAction_t { - MARKETACTION_BUY = 0, - MARKETACTION_SELL = 1, -}; - -enum MarketRequest_t { - MARKETREQUEST_OWN_OFFERS = 0xFFFE, - MARKETREQUEST_OWN_HISTORY = 0xFFFF, -}; - -enum MarketOfferState_t { - OFFERSTATE_ACTIVE = 0, - OFFERSTATE_CANCELLED = 1, - OFFERSTATE_EXPIRED = 2, - OFFERSTATE_ACCEPTED = 3, - - OFFERSTATE_ACCEPTEDEX = 255, -}; - -enum ChannelEvent_t : uint8_t { - CHANNELEVENT_JOIN = 0, - CHANNELEVENT_LEAVE = 1, - CHANNELEVENT_INVITE = 2, - CHANNELEVENT_EXCLUDE = 3, -}; - -enum CreatureType_t : uint8_t { - CREATURETYPE_PLAYER = 0, - CREATURETYPE_MONSTER = 1, - CREATURETYPE_NPC = 2, - CREATURETYPE_SUMMON_OWN = 3, - CREATURETYPE_SUMMON_OTHERS = 4, -}; - -enum OperatingSystem_t : uint8_t { - CLIENTOS_LINUX = 1, - CLIENTOS_WINDOWS = 2, - CLIENTOS_FLASH = 3, - - CLIENTOS_OTCLIENT_LINUX = 10, - CLIENTOS_OTCLIENT_WINDOWS = 11, - CLIENTOS_OTCLIENT_MAC = 12, -}; - -enum SpellGroup_t : uint8_t { - SPELLGROUP_NONE = 0, - SPELLGROUP_ATTACK = 1, - SPELLGROUP_HEALING = 2, - SPELLGROUP_SUPPORT = 3, - SPELLGROUP_SPECIAL = 4, -}; - -enum AccountType_t : uint8_t { - ACCOUNT_TYPE_NORMAL = 1, - ACCOUNT_TYPE_TUTOR = 2, - ACCOUNT_TYPE_SENIORTUTOR = 3, - ACCOUNT_TYPE_GAMEMASTER = 4, - ACCOUNT_TYPE_GOD = 5 -}; - -enum RaceType_t : uint8_t { - RACE_NONE, - RACE_VENOM, - RACE_BLOOD, - RACE_UNDEAD, - RACE_FIRE, - RACE_ENERGY, -}; - -enum CombatType_t { - COMBAT_NONE, - - COMBAT_PHYSICALDAMAGE = 1 << 0, - COMBAT_ENERGYDAMAGE = 1 << 1, - COMBAT_EARTHDAMAGE = 1 << 2, - COMBAT_FIREDAMAGE = 1 << 3, - COMBAT_UNDEFINEDDAMAGE = 1 << 4, - COMBAT_LIFEDRAIN = 1 << 5, - COMBAT_MANADRAIN = 1 << 6, - COMBAT_HEALING = 1 << 7, - COMBAT_DROWNDAMAGE = 1 << 8, - COMBAT_ICEDAMAGE = 1 << 9, - COMBAT_HOLYDAMAGE = 1 << 10, - COMBAT_DEATHDAMAGE = 1 << 11, - - COMBAT_COUNT = 12 -}; - -enum CombatParam_t { - COMBAT_PARAM_TYPE, - COMBAT_PARAM_EFFECT, - COMBAT_PARAM_DISTANCEEFFECT, - COMBAT_PARAM_BLOCKSHIELD, - COMBAT_PARAM_BLOCKARMOR, - COMBAT_PARAM_TARGETCASTERORTOPMOST, - COMBAT_PARAM_CREATEITEM, - COMBAT_PARAM_AGGRESSIVE, - COMBAT_PARAM_DISPEL, - COMBAT_PARAM_USECHARGES, -}; - -enum CallBackParam_t { - CALLBACK_PARAM_LEVELMAGICVALUE, - CALLBACK_PARAM_SKILLVALUE, - CALLBACK_PARAM_TARGETTILE, - CALLBACK_PARAM_TARGETCREATURE, -}; - -enum ConditionParam_t { - CONDITION_PARAM_OWNER = 1, - CONDITION_PARAM_TICKS = 2, - //CONDITION_PARAM_OUTFIT = 3, - CONDITION_PARAM_HEALTHGAIN = 4, - CONDITION_PARAM_HEALTHTICKS = 5, - CONDITION_PARAM_MANAGAIN = 6, - CONDITION_PARAM_MANATICKS = 7, - CONDITION_PARAM_DELAYED = 8, - CONDITION_PARAM_SPEED = 9, - CONDITION_PARAM_LIGHT_LEVEL = 10, - CONDITION_PARAM_LIGHT_COLOR = 11, - CONDITION_PARAM_SOULGAIN = 12, - CONDITION_PARAM_SOULTICKS = 13, - CONDITION_PARAM_MINVALUE = 14, - CONDITION_PARAM_MAXVALUE = 15, - CONDITION_PARAM_STARTVALUE = 16, - CONDITION_PARAM_TICKINTERVAL = 17, - CONDITION_PARAM_FORCEUPDATE = 18, - CONDITION_PARAM_SKILL_MELEE = 19, - CONDITION_PARAM_SKILL_FIST = 20, - CONDITION_PARAM_SKILL_CLUB = 21, - CONDITION_PARAM_SKILL_SWORD = 22, - CONDITION_PARAM_SKILL_AXE = 23, - CONDITION_PARAM_SKILL_DISTANCE = 24, - CONDITION_PARAM_SKILL_SHIELD = 25, - CONDITION_PARAM_SKILL_FISHING = 26, - CONDITION_PARAM_STAT_MAXHITPOINTS = 27, - CONDITION_PARAM_STAT_MAXMANAPOINTS = 28, - // CONDITION_PARAM_STAT_SOULPOINTS = 29, - CONDITION_PARAM_STAT_MAGICPOINTS = 30, - CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT = 31, - CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT = 32, - // CONDITION_PARAM_STAT_SOULPOINTSPERCENT = 33, - CONDITION_PARAM_STAT_MAGICPOINTSPERCENT = 34, - CONDITION_PARAM_PERIODICDAMAGE = 35, - CONDITION_PARAM_SKILL_MELEEPERCENT = 36, - CONDITION_PARAM_SKILL_FISTPERCENT = 37, - CONDITION_PARAM_SKILL_CLUBPERCENT = 38, - CONDITION_PARAM_SKILL_SWORDPERCENT = 39, - CONDITION_PARAM_SKILL_AXEPERCENT = 40, - CONDITION_PARAM_SKILL_DISTANCEPERCENT = 41, - CONDITION_PARAM_SKILL_SHIELDPERCENT = 42, - CONDITION_PARAM_SKILL_FISHINGPERCENT = 43, - CONDITION_PARAM_BUFF_SPELL = 44, - CONDITION_PARAM_SUBID = 45, - CONDITION_PARAM_FIELD = 46, -}; - -enum BlockType_t : uint8_t { - BLOCK_NONE, - BLOCK_DEFENSE, - BLOCK_ARMOR, - BLOCK_IMMUNITY -}; - -enum skills_t : uint8_t { - SKILL_FIST = 0, - SKILL_CLUB = 1, - SKILL_SWORD = 2, - SKILL_AXE = 3, - SKILL_DISTANCE = 4, - SKILL_SHIELD = 5, - SKILL_FISHING = 6, - - SKILL_MAGLEVEL = 7, - SKILL_LEVEL = 8, - - SKILL_FIRST = SKILL_FIST, - SKILL_LAST = SKILL_FISHING -}; - -enum stats_t { - STAT_MAXHITPOINTS, - STAT_MAXMANAPOINTS, - STAT_SOULPOINTS, // unused - STAT_MAGICPOINTS, - - STAT_FIRST = STAT_MAXHITPOINTS, - STAT_LAST = STAT_MAGICPOINTS -}; - -enum formulaType_t { - COMBAT_FORMULA_UNDEFINED, - COMBAT_FORMULA_LEVELMAGIC, - COMBAT_FORMULA_SKILL, - COMBAT_FORMULA_DAMAGE, -}; - -enum ConditionType_t { - CONDITION_NONE, - - CONDITION_POISON = 1 << 0, - CONDITION_FIRE = 1 << 1, - CONDITION_ENERGY = 1 << 2, - CONDITION_BLEEDING = 1 << 3, - CONDITION_HASTE = 1 << 4, - CONDITION_PARALYZE = 1 << 5, - CONDITION_OUTFIT = 1 << 6, - CONDITION_INVISIBLE = 1 << 7, - CONDITION_LIGHT = 1 << 8, - CONDITION_MANASHIELD = 1 << 9, - CONDITION_INFIGHT = 1 << 10, - CONDITION_DRUNK = 1 << 11, - CONDITION_EXHAUST_WEAPON = 1 << 12, // unused - CONDITION_REGENERATION = 1 << 13, - CONDITION_SOUL = 1 << 14, - CONDITION_DROWN = 1 << 15, - CONDITION_MUTED = 1 << 16, - CONDITION_CHANNELMUTEDTICKS = 1 << 17, - CONDITION_YELLTICKS = 1 << 18, - CONDITION_ATTRIBUTES = 1 << 19, - CONDITION_FREEZING = 1 << 20, - CONDITION_DAZZLED = 1 << 21, - CONDITION_CURSED = 1 << 22, - CONDITION_EXHAUST_COMBAT = 1 << 23, // unused - CONDITION_EXHAUST_HEAL = 1 << 24, // unused - CONDITION_PACIFIED = 1 << 25, - CONDITION_SPELLCOOLDOWN = 1 << 26, - CONDITION_SPELLGROUPCOOLDOWN = 1 << 27, -}; - -enum ConditionId_t : int8_t { - CONDITIONID_DEFAULT = -1, - CONDITIONID_COMBAT, - CONDITIONID_HEAD, - CONDITIONID_NECKLACE, - CONDITIONID_BACKPACK, - CONDITIONID_ARMOR, - CONDITIONID_RIGHT, - CONDITIONID_LEFT, - CONDITIONID_LEGS, - CONDITIONID_FEET, - CONDITIONID_RING, - CONDITIONID_AMMO, -}; - -enum PlayerSex_t : uint8_t { - PLAYERSEX_FEMALE = 0, - PLAYERSEX_MALE = 1, - - PLAYERSEX_LAST = PLAYERSEX_MALE -}; - -enum Vocation_t : uint16_t { - VOCATION_NONE = 0 -}; - -enum ReturnValue { - RETURNVALUE_NOERROR, - RETURNVALUE_NOTPOSSIBLE, - RETURNVALUE_NOTENOUGHROOM, - RETURNVALUE_PLAYERISPZLOCKED, - RETURNVALUE_PLAYERISNOTINVITED, - RETURNVALUE_CANNOTTHROW, - RETURNVALUE_THEREISNOWAY, - RETURNVALUE_DESTINATIONOUTOFREACH, - RETURNVALUE_CREATUREBLOCK, - RETURNVALUE_NOTMOVEABLE, - RETURNVALUE_DROPTWOHANDEDITEM, - RETURNVALUE_BOTHHANDSNEEDTOBEFREE, - RETURNVALUE_CANONLYUSEONEWEAPON, - RETURNVALUE_NEEDEXCHANGE, - RETURNVALUE_CANNOTBEDRESSED, - RETURNVALUE_PUTTHISOBJECTINYOURHAND, - RETURNVALUE_PUTTHISOBJECTINBOTHHANDS, - RETURNVALUE_TOOFARAWAY, - RETURNVALUE_FIRSTGODOWNSTAIRS, - RETURNVALUE_FIRSTGOUPSTAIRS, - RETURNVALUE_CONTAINERNOTENOUGHROOM, - RETURNVALUE_NOTENOUGHCAPACITY, - RETURNVALUE_CANNOTPICKUP, - RETURNVALUE_THISISIMPOSSIBLE, - RETURNVALUE_DEPOTISFULL, - RETURNVALUE_CREATUREDOESNOTEXIST, - RETURNVALUE_CANNOTUSETHISOBJECT, - RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE, - RETURNVALUE_NOTREQUIREDLEVELTOUSERUNE, - RETURNVALUE_YOUAREALREADYTRADING, - RETURNVALUE_THISPLAYERISALREADYTRADING, - RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT, - RETURNVALUE_DIRECTPLAYERSHOOT, - RETURNVALUE_NOTENOUGHLEVEL, - RETURNVALUE_NOTENOUGHMAGICLEVEL, - RETURNVALUE_NOTENOUGHMANA, - RETURNVALUE_NOTENOUGHSOUL, - RETURNVALUE_YOUAREEXHAUSTED, - RETURNVALUE_PLAYERISNOTREACHABLE, - RETURNVALUE_CANONLYUSETHISRUNEONCREATURES, - RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE, - RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER, - RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE, - RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE, - RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE, - RETURNVALUE_YOUCANONLYUSEITONCREATURES, - RETURNVALUE_CREATUREISNOTREACHABLE, - RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS, - RETURNVALUE_YOUNEEDPREMIUMACCOUNT, - RETURNVALUE_YOUNEEDTOLEARNTHISSPELL, - RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL, - RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL, - RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE, - RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE, - RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE, - RETURNVALUE_YOUCANNOTLOGOUTHERE, - RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL, - RETURNVALUE_CANNOTCONJUREITEMHERE, - RETURNVALUE_YOUNEEDTOSPLITYOURSPEARS, - RETURNVALUE_NAMEISTOOAMBIGIOUS, - RETURNVALUE_CANONLYUSEONESHIELD, - RETURNVALUE_NOPARTYMEMBERSINRANGE, - RETURNVALUE_YOUARENOTTHEOWNER, - RETURNVALUE_NOTENOUGHFISTLEVEL, - RETURNVALUE_NOTENOUGHCLUBLEVEL, - RETURNVALUE_NOTENOUGHSWORDLEVEL, - RETURNVALUE_NOTENOUGHAXELEVEL, - RETURNVALUE_NOTENOUGHDISTANCELEVEL, - RETURNVALUE_NOTENOUGHSHIELDLEVEL, - RETURNVALUE_NOTENOUGHFISHLEVEL -}; - -enum SpeechBubble_t -{ - SPEECHBUBBLE_NONE = 0, - SPEECHBUBBLE_NORMAL = 1, - SPEECHBUBBLE_TRADE = 2, - SPEECHBUBBLE_QUEST = 3, - SPEECHBUBBLE_QUESTTRADER = 4, -}; - -enum MapMark_t -{ - MAPMARK_TICK = 0, - MAPMARK_QUESTION = 1, - MAPMARK_EXCLAMATION = 2, - MAPMARK_STAR = 3, - MAPMARK_CROSS = 4, - MAPMARK_TEMPLE = 5, - MAPMARK_KISS = 6, - MAPMARK_SHOVEL = 7, - MAPMARK_SWORD = 8, - MAPMARK_FLAG = 9, - MAPMARK_LOCK = 10, - MAPMARK_BAG = 11, - MAPMARK_SKULL = 12, - MAPMARK_DOLLAR = 13, - MAPMARK_REDNORTH = 14, - MAPMARK_REDSOUTH = 15, - MAPMARK_REDEAST = 16, - MAPMARK_REDWEST = 17, - MAPMARK_GREENNORTH = 18, - MAPMARK_GREENSOUTH = 19, -}; - -struct Outfit_t { - Outfit_t() { - reset(); - } - - void reset() { - lookType = 0; - lookTypeEx = 0; - lookMount = 0; - lookHead = 0; - lookBody = 0; - lookLegs = 0; - lookFeet = 0; - lookAddons = 0; - } - - uint16_t lookType; - uint16_t lookTypeEx; - uint16_t lookMount; - uint8_t lookHead; - uint8_t lookBody; - uint8_t lookLegs; - uint8_t lookFeet; - uint8_t lookAddons; -}; - -struct LightInfo { - uint8_t level; - uint8_t color; - LightInfo() { - level = 0; - color = 0; - } - LightInfo(uint8_t _level, uint8_t _color) { - level = _level; - color = _color; - } -}; - -struct ShopInfo { - uint16_t itemId; - int32_t subType; - uint32_t buyPrice; - uint32_t sellPrice; - std::string realName; - - ShopInfo() { - itemId = 0; - subType = 1; - buyPrice = 0; - sellPrice = 0; - } - - ShopInfo(uint16_t itemId, int32_t subType = 0, uint32_t buyPrice = 0, uint32_t sellPrice = 0, std::string realName = "") - : itemId(itemId), subType(subType), buyPrice(buyPrice), sellPrice(sellPrice), realName(realName) {} -}; - -struct MarketOffer { - uint32_t price; - uint32_t timestamp; - uint16_t amount; - uint16_t counter; - uint16_t itemId; - std::string playerName; -}; - -struct MarketOfferEx { - MarketOfferEx() = default; - MarketOfferEx(MarketOfferEx&& other) : - id(other.id), playerId(other.playerId), timestamp(other.timestamp), price(other.price), - amount(other.amount), counter(other.counter), itemId(other.itemId), type(other.type), - playerName(std::move(other.playerName)) {} - - uint32_t id; - uint32_t playerId; - uint32_t timestamp; - uint32_t price; - uint16_t amount; - uint16_t counter; - uint16_t itemId; - MarketAction_t type; - std::string playerName; -}; - -struct HistoryMarketOffer { - uint32_t timestamp; - uint32_t price; - uint16_t itemId; - uint16_t amount; - MarketOfferState_t state; -}; - -struct MarketStatistics { - MarketStatistics() { - numTransactions = 0; - highestPrice = 0; - totalPrice = 0; - lowestPrice = 0; - } - - uint32_t numTransactions; - uint32_t highestPrice; - uint64_t totalPrice; - uint32_t lowestPrice; -}; - -struct ModalWindow -{ - std::list> buttons, choices; - std::string title, message; - uint32_t id; - uint8_t defaultEnterButton, defaultEscapeButton; - bool priority; - - ModalWindow(uint32_t id, std::string title, std::string message) - : title(title), message(message), id(id), defaultEnterButton(0xFF), defaultEscapeButton(0xFF), priority(false) {} -}; - -enum CombatOrigin -{ - ORIGIN_NONE, - ORIGIN_CONDITION, - ORIGIN_SPELL, - ORIGIN_MELEE, - ORIGIN_RANGED, -}; - -struct CombatDamage -{ - struct { - CombatType_t type; - int32_t value; - } primary, secondary; - - CombatOrigin origin; - CombatDamage() - { - origin = ORIGIN_NONE; - primary.type = secondary.type = COMBAT_NONE; - primary.value = secondary.value = 0; - } -}; - -typedef std::list MarketOfferList; -typedef std::list HistoryMarketOfferList; -typedef std::list ShopInfoList; - -#endif diff --git a/path_10_8/src/events.cpp b/path_10_8/src/events.cpp deleted file mode 100644 index 75925dca4..000000000 --- a/path_10_8/src/events.cpp +++ /dev/null @@ -1,819 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "events.h" -#include "tools.h" -#include "item.h" -#include "player.h" - -#include - -Events::Events() : - scriptInterface("Event Interface") -{ - clear(); - scriptInterface.initState(); -} - -void Events::clear() -{ - // Creature - creatureOnChangeOutfit = -1; - creatureOnAreaCombat = -1; - creatureOnTargetCombat = -1; - - // Party - partyOnJoin = -1; - partyOnLeave = -1; - partyOnDisband = -1; - - // Player - playerOnBrowseField = -1; - playerOnLook = -1; - playerOnLookInBattleList = -1; - playerOnLookInTrade = -1; - playerOnLookInShop = -1; - playerOnMoveItem = -1; - playerOnMoveCreature = -1; - playerOnTurn = -1; - playerOnTradeRequest = -1; - playerOnTradeAccept = -1; - playerOnGainExperience = -1; - playerOnLoseExperience = -1; - playerOnGainSkillTries = -1; - - // Custom - playerOnSave = -1; - monsterOnSpawn = -1; -} - -bool Events::load() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/events/events.xml"); - if (!result) { - printXMLError("Error - Events::load", "data/events/events.xml", result); - return false; - } - - clear(); - - std::set classes; - for (auto eventNode : doc.child("events").children()) { - if (!eventNode.attribute("enabled").as_bool()) { - continue; - } - - const std::string& className = eventNode.attribute("class").as_string(); - auto res = classes.insert(className); - if (res.second) { - const std::string& lowercase = asLowerCaseString(className); - if (scriptInterface.loadFile("data/events/scripts/" + lowercase + ".lua") != 0) { - std::cout << "[Warning - Events::load] Can not load script: " << lowercase << ".lua" << std::endl; - std::cout << scriptInterface.getLastLuaError() << std::endl; - } - } - - const std::string& methodName = eventNode.attribute("method").as_string(); - const int32_t event = scriptInterface.getMetaEvent(className, methodName); - if (className == "Creature") { - if (methodName == "onChangeOutfit") { - creatureOnChangeOutfit = event; - } else if (methodName == "onAreaCombat") { - creatureOnAreaCombat = event; - } else if (methodName == "onTargetCombat") { - creatureOnTargetCombat = event; - } else { - std::cout << "[Warning - Events::load] Unknown creature method: " << methodName << std::endl; - } - } else if (className == "Party") { - if (methodName == "onJoin") { - partyOnJoin = event; - } else if (methodName == "onLeave") { - partyOnLeave = event; - } else if (methodName == "onDisband") { - partyOnDisband = event; - } else { - std::cout << "[Warning - Events::load] Unknown party method: " << methodName << std::endl; - } - } else if (className == "Player") { - if (methodName == "onBrowseField") { - playerOnBrowseField = event; - } else if (methodName == "onLook") { - playerOnLook = event; - } else if (methodName == "onLookInBattleList") { - playerOnLookInBattleList = event; - } else if (methodName == "onLookInTrade") { - playerOnLookInTrade = event; - } else if (methodName == "onLookInShop") { - playerOnLookInShop = event; - } else if (methodName == "onTradeRequest") { - playerOnTradeRequest = event; - } else if (methodName == "onTradeAccept") { - playerOnTradeAccept = event; - } else if (methodName == "onMoveItem") { - playerOnMoveItem = event; - } else if (methodName == "onMoveCreature") { - playerOnMoveCreature = event; - } else if (methodName == "onTurn") { - playerOnTurn = event; - } else if (methodName == "onGainExperience") { - playerOnGainExperience = event; - } else if (methodName == "onLoseExperience") { - playerOnLoseExperience = event; - } else if (methodName == "onGainSkillTries") { - playerOnGainSkillTries = event; - } else if (methodName == "onSave") { - playerOnSave = event; - } else { - std::cout << "[Warning - Events::load] Unknown player method: " << methodName << std::endl; - } - } else if (className == "Monster") { - if (methodName == "onSpawn") { - monsterOnSpawn = event; - } else { - std::cout << "[Warning - Events::load] Unknown monster method: " << methodName << std::endl; - } - } else { - std::cout << "[Warning - Events::load] Unknown class: " << className << std::endl; - } - } - return true; -} - -// Creature -bool Events::eventCreatureOnChangeOutfit(Creature* creature, const Outfit_t& outfit) -{ - // Creature:onChangeOutfit(outfit) or Creature.onChangeOutfit(self, outfit) - if (creatureOnChangeOutfit == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventCreatureOnChangeOutfit] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(creatureOnChangeOutfit, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(creatureOnChangeOutfit); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushOutfit(L, outfit); - - return scriptInterface.callFunction(2); -} - -ReturnValue Events::eventCreatureOnAreaCombat(Creature* creature, Tile* tile, bool aggressive) -{ - // Creature:onAreaCombat(tile, aggressive) or Creature.onAreaCombat(self, tile, aggressive) - if (creatureOnAreaCombat == -1) { - return RETURNVALUE_NOERROR; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventCreatureOnAreaCombat] Call stack overflow" << std::endl; - return RETURNVALUE_NOTPOSSIBLE; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(creatureOnAreaCombat, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(creatureOnAreaCombat); - - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - - LuaScriptInterface::pushUserdata(L, tile); - LuaScriptInterface::setMetatable(L, -1, "Tile"); - - LuaScriptInterface::pushBoolean(L, aggressive); - - ReturnValue returnValue; - if (scriptInterface.protectedCall(L, 3, 1) != 0) { - returnValue = RETURNVALUE_NOTPOSSIBLE; - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - returnValue = LuaScriptInterface::getNumber(L, -1); - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); - return returnValue; -} - -ReturnValue Events::eventCreatureOnTargetCombat(Creature* creature, Creature* target) -{ - // Creature:onTargetCombat(target) or Creature.onTargetCombat(self, target) - if (creatureOnTargetCombat == -1) { - return RETURNVALUE_NOERROR; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventCreatureOnTargetCombat] Call stack overflow" << std::endl; - return RETURNVALUE_NOTPOSSIBLE; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(creatureOnTargetCombat, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(creatureOnTargetCombat); - - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setCreatureMetatable(L, -1, target); - - ReturnValue returnValue; - if (scriptInterface.protectedCall(L, 2, 1) != 0) { - returnValue = RETURNVALUE_NOTPOSSIBLE; - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - returnValue = LuaScriptInterface::getNumber(L, -1); - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); - return returnValue; -} - -// Party -bool Events::eventPartyOnJoin(Party* party, Player* player) -{ - // Party:onJoin(player) or Party.onJoin(self, player) - if (partyOnJoin == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPartyOnJoin] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(partyOnJoin, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(partyOnJoin); - - LuaScriptInterface::pushUserdata(L, party); - LuaScriptInterface::setMetatable(L, -1, "Party"); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface.callFunction(2); -} - -bool Events::eventPartyOnLeave(Party* party, Player* player) -{ - // Party:onLeave(player) or Party.onLeave(self, player) - if (partyOnLeave == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPartyOnLeave] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(partyOnLeave, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(partyOnLeave); - - LuaScriptInterface::pushUserdata(L, party); - LuaScriptInterface::setMetatable(L, -1, "Party"); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface.callFunction(2); -} - -bool Events::eventPartyOnDisband(Party* party) -{ - // Party:onDisband() or Party.onDisband(self) - if (partyOnDisband == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPartyOnDisband] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(partyOnDisband, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(partyOnDisband); - - LuaScriptInterface::pushUserdata(L, party); - LuaScriptInterface::setMetatable(L, -1, "Party"); - - return scriptInterface.callFunction(1); -} - -// Player -bool Events::eventPlayerOnBrowseField(Player* player, const Position& position) -{ - // Player:onBrowseField(position) or Player.onBrowseField(self, position) - if (playerOnBrowseField == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnBrowseField] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnBrowseField, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnBrowseField); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushPosition(L, position); - - return scriptInterface.callFunction(2); -} - -void Events::eventPlayerOnLook(Player* player, const Position& position, Thing* thing, uint8_t stackpos, int32_t lookDistance) -{ - // Player:onLook(thing, position, distance) or Player.onLook(self, thing, position, distance) - if (playerOnLook == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnLook] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnLook, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnLook); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - if (Creature* creature = thing->getCreature()) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else if (Item* item = thing->getItem()) { - LuaScriptInterface::pushUserdata(L, item); - LuaScriptInterface::setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - - LuaScriptInterface::pushPosition(L, position, stackpos); - lua_pushnumber(L, lookDistance); - - scriptInterface.callVoidFunction(4); -} - -void Events::eventPlayerOnLookInBattleList(Player* player, Creature* creature, int32_t lookDistance) -{ - // Player:onLookInBattleList(creature, position, distance) or Player.onLookInBattleList(self, creature, position, distance) - if (playerOnLookInBattleList == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnLookInBattleList] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnLookInBattleList, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnLookInBattleList); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - lua_pushnumber(L, lookDistance); - - scriptInterface.callVoidFunction(3); -} - -void Events::eventPlayerOnLookInTrade(Player* player, Player* partner, Item* item, int32_t lookDistance) -{ - // Player:onLookInTrade(partner, item, distance) or Player.onLookInTrade(self, partner, item, distance) - if (playerOnLookInTrade == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnLookInTrade] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnLookInTrade, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnLookInTrade); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, partner); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, item); - LuaScriptInterface::setItemMetatable(L, -1, item); - - lua_pushnumber(L, lookDistance); - - scriptInterface.callVoidFunction(4); -} - -bool Events::eventPlayerOnLookInShop(Player* player, const ItemType* itemType, uint8_t count) -{ - // Player:onLookInShop(itemType, count) or Player.onLookInShop(self, itemType, count) - if (playerOnLookInShop == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnLookInShop] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnLookInShop, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnLookInShop); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, itemType); - LuaScriptInterface::setMetatable(L, -1, "ItemType"); - - lua_pushnumber(L, count); - - return scriptInterface.callFunction(3); -} - -bool Events::eventPlayerOnMoveItem(Player* player, Item* item, uint16_t count, const Position& fromPosition, const Position& toPosition) -{ - // Player:onMoveItem(item, count, fromPosition, toPosition) or Player.onMoveItem(self, item, count, fromPosition, toPosition) - if (playerOnMoveItem == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnMoveItem] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnMoveItem, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnMoveItem); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, item); - LuaScriptInterface::setItemMetatable(L, -1, item); - - lua_pushnumber(L, count); - LuaScriptInterface::pushPosition(L, fromPosition); - LuaScriptInterface::pushPosition(L, toPosition); - - return scriptInterface.callFunction(5); -} - -bool Events::eventPlayerOnMoveCreature(Player* player, Creature* creature, const Position& fromPosition, const Position& toPosition) -{ - // Player:onMoveCreature(creature, fromPosition, toPosition) or Player.onMoveCreature(self, creature, fromPosition, toPosition) - if (playerOnMoveCreature == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnMoveCreature] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnMoveCreature, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnMoveCreature); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushPosition(L, fromPosition); - LuaScriptInterface::pushPosition(L, toPosition); - - return scriptInterface.callFunction(4); -} - -bool Events::eventPlayerOnTurn(Player* player, Direction direction) -{ - // Player:onTurn(direction) or Player.onTurn(self, direction) - if (playerOnTurn == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnTurn] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnTurn, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnTurn); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, direction); - - return scriptInterface.callFunction(2); -} - -bool Events::eventPlayerOnTradeRequest(Player* player, Player* target, Item* item) -{ - // Player:onTradeRequest(target, item) - if (playerOnTradeRequest == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnTradeRequest] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnTradeRequest, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnTradeRequest); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, item); - LuaScriptInterface::setItemMetatable(L, -1, item); - - return scriptInterface.callFunction(3); -} - -bool Events::eventPlayerOnTradeAccept(Player* player, Player* target, Item* item, Item* targetItem) -{ - // Player:onTradeAccept(target, item, targetItem) - if (playerOnTradeAccept == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnTradeAccept] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnTradeAccept, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnTradeAccept); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushUserdata(L, item); - LuaScriptInterface::setItemMetatable(L, -1, item); - - LuaScriptInterface::pushUserdata(L, targetItem); - LuaScriptInterface::setItemMetatable(L, -1, item); - - return scriptInterface.callFunction(4); -} - -void Events::eventPlayerOnGainExperience(Player* player, Creature* source, uint64_t& exp, uint64_t rawExp) -{ - // Player:onGainExperience(source, exp, rawExp) - // rawExp gives the original exp which is not multiplied - if (playerOnGainExperience == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnGainExperience] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnGainExperience, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnGainExperience); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - if (source) { - LuaScriptInterface::pushUserdata(L, source); - LuaScriptInterface::setCreatureMetatable(L, -1, source); - } else { - lua_pushnil(L); - } - - lua_pushnumber(L, exp); - lua_pushnumber(L, rawExp); - - if (scriptInterface.protectedCall(L, 4, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - exp = LuaScriptInterface::getNumber(L, -1); - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); -} - -void Events::eventPlayerOnLoseExperience(Player* player, uint64_t& exp) -{ - // Player:onLoseExperience(exp) - if (playerOnLoseExperience == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnLoseExperience] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnLoseExperience, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnLoseExperience); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, exp); - - if (scriptInterface.protectedCall(L, 2, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - exp = LuaScriptInterface::getNumber(L, -1); - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); -} - -void Events::eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries) -{ - // Player:onGainSkillTries(skill, tries) - if (playerOnGainSkillTries == -1) { - return; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnGainSkillTries] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnGainSkillTries, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnGainSkillTries); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, skill); - lua_pushnumber(L, tries); - - if (scriptInterface.protectedCall(L, 3, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(L)); - } else { - tries = LuaScriptInterface::getNumber(L, -1); - lua_pop(L, 1); - } - - scriptInterface.resetScriptEnv(); -} - -// Player Save -bool Events::eventPlayerOnSave(Player* player) -{ - // Player:OnSave(guid) - if (playerOnSave == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventPlayerOnSave] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(playerOnSave, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(playerOnSave); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, player->getGUID()); - - return scriptInterface.callFunction(2); -} - -// Monster -bool Events::eventMonsterOnSpawn(Monster* monster, const Position& position, bool isStartup) -{ - // Monster:onSpawn(position, isStartup) or Monster.onSpawn(self, position, isStartup) - if (monsterOnSpawn == -1) { - return true; - } - - if (!scriptInterface.reserveScriptEnv()) { - std::cout << "[Error - Events::eventMonsterOnSpawn] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface.getScriptEnv(); - env->setScriptId(monsterOnSpawn, &scriptInterface); - - lua_State* L = scriptInterface.getLuaState(); - scriptInterface.pushFunction(monsterOnSpawn); - - LuaScriptInterface::pushUserdata(L, monster); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - LuaScriptInterface::pushPosition(L, position); - - LuaScriptInterface::pushBoolean(L, isStartup); - - return scriptInterface.callFunction(3); -} \ No newline at end of file diff --git a/path_10_8/src/events.h b/path_10_8/src/events.h deleted file mode 100644 index 1bfc58bd0..000000000 --- a/path_10_8/src/events.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_EVENTS_H_BD444CC0EE167E5777E4C90C766B36DC -#define FS_EVENTS_H_BD444CC0EE167E5777E4C90C766B36DC - -#include "luascript.h" - -class Party; -class ItemType; -class Tile; - -class Events -{ - public: - Events(); - - void clear(); - bool load(); - - // Creature - bool eventCreatureOnChangeOutfit(Creature* creature, const Outfit_t& outfit); - ReturnValue eventCreatureOnAreaCombat(Creature* creature, Tile* tile, bool aggressive); - ReturnValue eventCreatureOnTargetCombat(Creature* creature, Creature* target); - - // Party - bool eventPartyOnJoin(Party* party, Player* player); - bool eventPartyOnLeave(Party* party, Player* player); - bool eventPartyOnDisband(Party* party); - - // Player - bool eventPlayerOnBrowseField(Player* player, const Position& position); - void eventPlayerOnLook(Player* player, const Position& position, Thing* thing, uint8_t stackpos, int32_t lookDistance); - void eventPlayerOnLookInBattleList(Player* player, Creature* creature, int32_t lookDistance); - void eventPlayerOnLookInTrade(Player* player, Player* partner, Item* item, int32_t lookDistance); - bool eventPlayerOnLookInShop(Player* player, const ItemType* itemType, uint8_t count); - bool eventPlayerOnMoveItem(Player* player, Item* item, uint16_t count, const Position& fromPosition, const Position& toPosition); - bool eventPlayerOnMoveCreature(Player* player, Creature* creature, const Position& fromPosition, const Position& toPosition); - bool eventPlayerOnTurn(Player* player, Direction direction); - bool eventPlayerOnTradeRequest(Player* player, Player* target, Item* item); - bool eventPlayerOnTradeAccept(Player* player, Player* target, Item* item, Item* targetItem); - void eventPlayerOnGainExperience(Player* player, Creature* source, uint64_t& exp, uint64_t rawExp); - void eventPlayerOnLoseExperience(Player* player, uint64_t& exp); - void eventPlayerOnGainSkillTries(Player* player, skills_t skill, uint64_t& tries); - - // Custom - bool eventPlayerOnSave(Player* player); - bool eventMonsterOnSpawn(Monster* monster, const Position& position, bool isStartup); - - private: - LuaScriptInterface scriptInterface; - - // Creature - int32_t creatureOnChangeOutfit; - int32_t creatureOnAreaCombat; - int32_t creatureOnTargetCombat; - - // Party - int32_t partyOnJoin; - int32_t partyOnLeave; - int32_t partyOnDisband; - - // Player - int32_t playerOnBrowseField; - int32_t playerOnLook; - int32_t playerOnLookInBattleList; - int32_t playerOnLookInTrade; - int32_t playerOnLookInShop; - int32_t playerOnMoveItem; - int32_t playerOnMoveCreature; - int32_t playerOnTurn; - int32_t playerOnTradeRequest; - int32_t playerOnTradeAccept; - int32_t playerOnGainExperience; - int32_t playerOnLoseExperience; - int32_t playerOnGainSkillTries; - - // Custom - int32_t playerOnSave; - int32_t monsterOnSpawn; -}; - -#endif diff --git a/path_10_8/src/ext/pugiconfig.hpp b/path_10_8/src/ext/pugiconfig.hpp deleted file mode 100644 index 29e2a0741..000000000 --- a/path_10_8/src/ext/pugiconfig.hpp +++ /dev/null @@ -1,71 +0,0 @@ -/** - * pugixml parser - version 1.6 - * -------------------------------------------------------- - * Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef HEADER_PUGICONFIG_HPP -#define HEADER_PUGICONFIG_HPP - -// Uncomment this to enable wchar_t mode -// #define PUGIXML_WCHAR_MODE - -// Uncomment this to disable XPath -#define PUGIXML_NO_XPATH - -// Uncomment this to disable STL -// #define PUGIXML_NO_STL - -// Uncomment this to disable exceptions -#define PUGIXML_NO_EXCEPTIONS - -// Set this to control attributes for public classes/functions, i.e.: -// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL -// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL -// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall -// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead - -// Tune these constants to adjust memory-related behavior -// #define PUGIXML_MEMORY_PAGE_SIZE 32768 -// #define PUGIXML_MEMORY_OUTPUT_STACK 10240 -// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 - -// Uncomment this to switch to header-only version -#define PUGIXML_HEADER_ONLY - -// Uncomment this to enable long long support -// #define PUGIXML_HAS_LONG_LONG - -#endif - -/** - * Copyright (c) 2006-2015 Arseny Kapoulkine - * - * 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/path_10_8/src/ext/pugixml.cpp b/path_10_8/src/ext/pugixml.cpp deleted file mode 100644 index 3182c370b..000000000 --- a/path_10_8/src/ext/pugixml.cpp +++ /dev/null @@ -1,6349 +0,0 @@ -/** - * pugixml parser - version 1.6 - * -------------------------------------------------------- - * Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef SOURCE_PUGIXML_CPP -#define SOURCE_PUGIXML_CPP - -#include "pugixml.hpp" - -#include -#include -#include -#include - -#ifdef PUGIXML_WCHAR_MODE -# include -#endif - -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// For placement new -#include - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant -# pragma warning(disable: 4324) // structure was padded due to __declspec(align()) -# pragma warning(disable: 4611) // interaction between '_setjmp' and C++ object destruction is non-portable -# pragma warning(disable: 4702) // unreachable code -# pragma warning(disable: 4996) // this function or variable may be unsafe -# pragma warning(disable: 4793) // function compiled as native: presence of '_setjmp' makes a function unmanaged -#endif - -#ifdef __INTEL_COMPILER -# pragma warning(disable: 177) // function was declared but never referenced -# pragma warning(disable: 279) // controlling expression is constant -# pragma warning(disable: 1478 1786) // function was declared "deprecated" -# pragma warning(disable: 1684) // conversion from pointer to same-sized integral type -#endif - -#if defined(__BORLANDC__) && defined(PUGIXML_HEADER_ONLY) -# pragma warn -8080 // symbol is declared but never used; disabling this inside push/pop bracket does not make the warning go away -#endif - -#ifdef __BORLANDC__ -# pragma option push -# pragma warn -8008 // condition is always false -# pragma warn -8066 // unreachable code -#endif - -#ifdef __SNC__ -// Using diag_push/diag_pop does not disable the warnings inside templates due to a compiler bug -# pragma diag_suppress=178 // function was declared but never referenced -# pragma diag_suppress=237 // controlling expression is constant -#endif - -// Inlining controls -#if defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGI__NO_INLINE __declspec(noinline) -#elif defined(__GNUC__) -# define PUGI__NO_INLINE __attribute__((noinline)) -#else -# define PUGI__NO_INLINE -#endif - -// Branch weight controls -#if defined(__GNUC__) -# define PUGI__UNLIKELY(cond) __builtin_expect(cond, 0) -#else -# define PUGI__UNLIKELY(cond) (cond) -#endif - -// Simple static assertion -#define PUGI__STATIC_ASSERT(cond) { static const char condition_failed[(cond) ? 1 : -1] = {0}; (void)condition_failed[0]; } - -// Digital Mars C++ bug workaround for passing char loaded from memory via stack -#ifdef __DMC__ -# define PUGI__DMC_VOLATILE volatile -#else -# define PUGI__DMC_VOLATILE -#endif - -// Borland C++ bug workaround for not defining ::memcpy depending on header include order (can't always use std::memcpy because some compilers don't have it at all) -#if defined(__BORLANDC__) && !defined(__MEM_H_USING_LIST) -using std::memcpy; -using std::memmove; -#endif - -// In some environments MSVC is a compiler but the CRT lacks certain MSVC-specific features -#if defined(_MSC_VER) && !defined(__S3E__) -# define PUGI__MSVC_CRT_VERSION _MSC_VER -#endif - -#ifdef PUGIXML_HEADER_ONLY -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } -# define PUGI__FN inline -# define PUGI__FN_NO_INLINE inline -#else -# if defined(_MSC_VER) && _MSC_VER < 1300 // MSVC6 seems to have an amusing bug with anonymous namespaces inside namespaces -# define PUGI__NS_BEGIN namespace pugi { namespace impl { -# define PUGI__NS_END } } -# else -# define PUGI__NS_BEGIN namespace pugi { namespace impl { namespace { -# define PUGI__NS_END } } } -# endif -# define PUGI__FN -# define PUGI__FN_NO_INLINE PUGI__NO_INLINE -#endif - -// uintptr_t -#if !defined(_MSC_VER) || _MSC_VER >= 1600 -# include -#else -# ifndef _UINTPTR_T_DEFINED -// No native uintptr_t in MSVC6 and in some WinCE versions -typedef size_t uintptr_t; -#define _UINTPTR_T_DEFINED -# endif -PUGI__NS_BEGIN - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -PUGI__NS_END -#endif - -// Memory allocation -PUGI__NS_BEGIN - PUGI__FN void* default_allocate(size_t size) - { - return malloc(size); - } - - PUGI__FN void default_deallocate(void* ptr) - { - free(ptr); - } - - template - struct xml_memory_management_function_storage - { - static allocation_function allocate; - static deallocation_function deallocate; - }; - - // Global allocation functions are stored in class statics so that in header mode linker deduplicates them - // Without a template<> we'll get multiple definitions of the same static - template allocation_function xml_memory_management_function_storage::allocate = default_allocate; - template deallocation_function xml_memory_management_function_storage::deallocate = default_deallocate; - - typedef xml_memory_management_function_storage xml_memory; -PUGI__NS_END - -// String utilities -PUGI__NS_BEGIN - // Get string length - PUGI__FN size_t strlength(const char_t* s) - { - assert(s); - - #ifdef PUGIXML_WCHAR_MODE - return wcslen(s); - #else - return strlen(s); - #endif - } - - // Compare two strings - PUGI__FN bool strequal(const char_t* src, const char_t* dst) - { - assert(src && dst); - - #ifdef PUGIXML_WCHAR_MODE - return wcscmp(src, dst) == 0; - #else - return strcmp(src, dst) == 0; - #endif - } - - // Compare lhs with [rhs_begin, rhs_end) - PUGI__FN bool strequalrange(const char_t* lhs, const char_t* rhs, size_t count) - { - for (size_t i = 0; i < count; ++i) - if (lhs[i] != rhs[i]) - return false; - - return lhs[count] == 0; - } - - // Get length of wide string, even if CRT lacks wide character support - PUGI__FN size_t strlength_wide(const wchar_t* s) - { - assert(s); - - #ifdef PUGIXML_WCHAR_MODE - return wcslen(s); - #else - const wchar_t* end = s; - while (*end) end++; - return static_cast(end - s); - #endif - } - -#ifdef PUGIXML_WCHAR_MODE - // Convert string to wide string, assuming all symbols are ASCII - PUGI__FN void widen_ascii(wchar_t* dest, const char* source) - { - for (const char* i = source; *i; ++i) *dest++ = *i; - *dest = 0; - } -#endif -PUGI__NS_END - -#if !defined(PUGIXML_NO_STL) || !defined(PUGIXML_NO_XPATH) -// auto_ptr-like buffer holder for exception recovery -PUGI__NS_BEGIN - struct buffer_holder - { - void* data; - void (*deleter)(void*); - - buffer_holder(void* data_, void (*deleter_)(void*)): data(data_), deleter(deleter_) - { - } - - ~buffer_holder() - { - if (data) deleter(data); - } - - void* release() - { - void* result = data; - data = 0; - return result; - } - }; -PUGI__NS_END -#endif - -PUGI__NS_BEGIN - static const size_t xml_memory_page_size = - #ifdef PUGIXML_MEMORY_PAGE_SIZE - PUGIXML_MEMORY_PAGE_SIZE - #else - 32768 - #endif - ; - - static const uintptr_t xml_memory_page_alignment = 64; - static const uintptr_t xml_memory_page_pointer_mask = ~(xml_memory_page_alignment - 1); - static const uintptr_t xml_memory_page_contents_shared_mask = 32; - static const uintptr_t xml_memory_page_name_allocated_mask = 16; - static const uintptr_t xml_memory_page_value_allocated_mask = 8; - static const uintptr_t xml_memory_page_type_mask = 7; - static const uintptr_t xml_memory_page_name_allocated_or_shared_mask = xml_memory_page_name_allocated_mask | xml_memory_page_contents_shared_mask; - static const uintptr_t xml_memory_page_value_allocated_or_shared_mask = xml_memory_page_value_allocated_mask | xml_memory_page_contents_shared_mask; - - #define PUGI__NODETYPE(n) static_cast(((n)->header & impl::xml_memory_page_type_mask) + 1) - - struct xml_allocator; - - struct xml_memory_page - { - static xml_memory_page* construct(void* memory) - { - xml_memory_page* result = static_cast(memory); - - result->allocator = 0; - result->prev = 0; - result->next = 0; - result->busy_size = 0; - result->freed_size = 0; - - return result; - } - - xml_allocator* allocator; - - xml_memory_page* prev; - xml_memory_page* next; - - size_t busy_size; - size_t freed_size; - }; - - struct xml_memory_string_header - { - uint16_t page_offset; // offset from page->data - uint16_t full_size; // 0 if string occupies whole page - }; - - struct xml_allocator - { - xml_allocator(xml_memory_page* root): _root(root), _busy_size(root->busy_size) - { - } - - xml_memory_page* allocate_page(size_t data_size) - { - size_t size = sizeof(xml_memory_page) + data_size; - - // allocate block with some alignment, leaving memory for worst-case padding - void* memory = xml_memory::allocate(size + xml_memory_page_alignment); - if (!memory) return 0; - - // align to next page boundary (note: this guarantees at least 1 usable byte before the page) - char* page_memory = reinterpret_cast((reinterpret_cast(memory) + xml_memory_page_alignment) & ~(xml_memory_page_alignment - 1)); - - // prepare page structure - xml_memory_page* page = xml_memory_page::construct(page_memory); - assert(page); - - page->allocator = _root->allocator; - - // record the offset for freeing the memory block - assert(page_memory > memory && page_memory - static_cast(memory) <= 127); - page_memory[-1] = static_cast(page_memory - static_cast(memory)); - - return page; - } - - static void deallocate_page(xml_memory_page* page) - { - char* page_memory = reinterpret_cast(page); - - xml_memory::deallocate(page_memory - page_memory[-1]); - } - - void* allocate_memory_oob(size_t size, xml_memory_page*& out_page); - - void* allocate_memory(size_t size, xml_memory_page*& out_page) - { - if (_busy_size + size > xml_memory_page_size) return allocate_memory_oob(size, out_page); - - void* buf = reinterpret_cast(_root) + sizeof(xml_memory_page) + _busy_size; - - _busy_size += size; - - out_page = _root; - - return buf; - } - - void deallocate_memory(void* ptr, size_t size, xml_memory_page* page) - { - if (page == _root) page->busy_size = _busy_size; - - assert(ptr >= reinterpret_cast(page) + sizeof(xml_memory_page) && ptr < reinterpret_cast(page) + sizeof(xml_memory_page) + page->busy_size); - (void)!ptr; - - page->freed_size += size; - assert(page->freed_size <= page->busy_size); - - if (page->freed_size == page->busy_size) - { - if (page->next == 0) - { - assert(_root == page); - - // top page freed, just reset sizes - page->busy_size = page->freed_size = 0; - _busy_size = 0; - } - else - { - assert(_root != page); - assert(page->prev); - - // remove from the list - page->prev->next = page->next; - page->next->prev = page->prev; - - // deallocate - deallocate_page(page); - } - } - } - - char_t* allocate_string(size_t length) - { - static const size_t max_encoded_offset = (1 << 16) * sizeof(void*); - - PUGI__STATIC_ASSERT(xml_memory_page_size <= max_encoded_offset); - - // allocate memory for string and header block - size_t size = sizeof(xml_memory_string_header) + length * sizeof(char_t); - - // round size up to pointer alignment boundary - size_t full_size = (size + (sizeof(void*) - 1)) & ~(sizeof(void*) - 1); - - xml_memory_page* page; - xml_memory_string_header* header = static_cast(allocate_memory(full_size, page)); - - if (!header) return 0; - - // setup header - ptrdiff_t page_offset = reinterpret_cast(header) - reinterpret_cast(page) - sizeof(xml_memory_page); - - assert(page_offset % sizeof(void*) == 0); - assert(page_offset >= 0 && static_cast(page_offset) < max_encoded_offset); - header->page_offset = static_cast(static_cast(page_offset) / sizeof(void*)); - - // full_size == 0 for large strings that occupy the whole page - assert(full_size % sizeof(void*) == 0); - assert(full_size < max_encoded_offset || (page->busy_size == full_size && page_offset == 0)); - header->full_size = static_cast(full_size < max_encoded_offset ? full_size / sizeof(void*) : 0); - - // round-trip through void* to avoid 'cast increases required alignment of target type' warning - // header is guaranteed a pointer-sized alignment, which should be enough for char_t - return static_cast(static_cast(header + 1)); - } - - void deallocate_string(char_t* string) - { - // this function casts pointers through void* to avoid 'cast increases required alignment of target type' warnings - // we're guaranteed the proper (pointer-sized) alignment on the input string if it was allocated via allocate_string - - // get header - xml_memory_string_header* header = static_cast(static_cast(string)) - 1; - assert(header); - - // deallocate - size_t page_offset = sizeof(xml_memory_page) + header->page_offset * sizeof(void*); - xml_memory_page* page = reinterpret_cast(static_cast(reinterpret_cast(header) - page_offset)); - - // if full_size == 0 then this string occupies the whole page - size_t full_size = header->full_size == 0 ? page->busy_size : header->full_size * sizeof(void*); - - deallocate_memory(header, full_size, page); - } - - xml_memory_page* _root; - size_t _busy_size; - }; - - PUGI__FN_NO_INLINE void* xml_allocator::allocate_memory_oob(size_t size, xml_memory_page*& out_page) - { - const size_t large_allocation_threshold = xml_memory_page_size / 4; - - xml_memory_page* page = allocate_page(size <= large_allocation_threshold ? xml_memory_page_size : size); - out_page = page; - - if (!page) return 0; - - if (size <= large_allocation_threshold) - { - _root->busy_size = _busy_size; - - // insert page at the end of linked list - page->prev = _root; - _root->next = page; - _root = page; - - _busy_size = size; - } - else - { - // insert page before the end of linked list, so that it is deleted as soon as possible - // the last page is not deleted even if it's empty (see deallocate_memory) - assert(_root->prev); - - page->prev = _root->prev; - page->next = _root; - - _root->prev->next = page; - _root->prev = page; - } - - // allocate inside page - page->busy_size = size; - - return reinterpret_cast(page) + sizeof(xml_memory_page); - } -PUGI__NS_END - -namespace pugi -{ - /// A 'name=value' XML attribute structure. - struct xml_attribute_struct - { - /// Default ctor - xml_attribute_struct(impl::xml_memory_page* page): header(reinterpret_cast(page)), name(0), value(0), prev_attribute_c(0), next_attribute(0) - { - } - - uintptr_t header; - - char_t* name; ///< Pointer to attribute name. - char_t* value; ///< Pointer to attribute value. - - xml_attribute_struct* prev_attribute_c; ///< Previous attribute (cyclic list) - xml_attribute_struct* next_attribute; ///< Next attribute - }; - - /// An XML document tree node. - struct xml_node_struct - { - /// Default ctor - /// \param type - node type - xml_node_struct(impl::xml_memory_page* page, xml_node_type type): header(reinterpret_cast(page) | (type - 1)), parent(0), name(0), value(0), first_child(0), prev_sibling_c(0), next_sibling(0), first_attribute(0) - { - } - - uintptr_t header; - - xml_node_struct* parent; ///< Pointer to parent - - char_t* name; ///< Pointer to element name. - char_t* value; ///< Pointer to any associated string data. - - xml_node_struct* first_child; ///< First child - - xml_node_struct* prev_sibling_c; ///< Left brother (cyclic list) - xml_node_struct* next_sibling; ///< Right brother - - xml_attribute_struct* first_attribute; ///< First attribute - }; -} - -PUGI__NS_BEGIN - struct xml_extra_buffer - { - char_t* buffer; - xml_extra_buffer* next; - }; - - struct xml_document_struct: public xml_node_struct, public xml_allocator - { - xml_document_struct(xml_memory_page* page): xml_node_struct(page, node_document), xml_allocator(page), buffer(0), extra_buffers(0) - { - } - - const char_t* buffer; - - xml_extra_buffer* extra_buffers; - }; - - inline xml_allocator& get_allocator(const xml_node_struct* node) - { - assert(node); - - return *reinterpret_cast(node->header & xml_memory_page_pointer_mask)->allocator; - } - - template inline xml_document_struct& get_document(const Object* object) - { - assert(object); - - return *static_cast(reinterpret_cast(object->header & xml_memory_page_pointer_mask)->allocator); - } -PUGI__NS_END - -// Low-level DOM operations -PUGI__NS_BEGIN - inline xml_attribute_struct* allocate_attribute(xml_allocator& alloc) - { - xml_memory_page* page; - void* memory = alloc.allocate_memory(sizeof(xml_attribute_struct), page); - - return new (memory) xml_attribute_struct(page); - } - - inline xml_node_struct* allocate_node(xml_allocator& alloc, xml_node_type type) - { - xml_memory_page* page; - void* memory = alloc.allocate_memory(sizeof(xml_node_struct), page); - - return new (memory) xml_node_struct(page, type); - } - - inline void destroy_attribute(xml_attribute_struct* a, xml_allocator& alloc) - { - uintptr_t header = a->header; - - if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(a->name); - if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(a->value); - - alloc.deallocate_memory(a, sizeof(xml_attribute_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); - } - - inline void destroy_node(xml_node_struct* n, xml_allocator& alloc) - { - uintptr_t header = n->header; - - if (header & impl::xml_memory_page_name_allocated_mask) alloc.deallocate_string(n->name); - if (header & impl::xml_memory_page_value_allocated_mask) alloc.deallocate_string(n->value); - - for (xml_attribute_struct* attr = n->first_attribute; attr; ) - { - xml_attribute_struct* next = attr->next_attribute; - - destroy_attribute(attr, alloc); - - attr = next; - } - - for (xml_node_struct* child = n->first_child; child; ) - { - xml_node_struct* next = child->next_sibling; - - destroy_node(child, alloc); - - child = next; - } - - alloc.deallocate_memory(n, sizeof(xml_node_struct), reinterpret_cast(header & xml_memory_page_pointer_mask)); - } - - inline void append_node(xml_node_struct* child, xml_node_struct* node) - { - child->parent = node; - - xml_node_struct* head = node->first_child; - - if (head) - { - xml_node_struct* tail = head->prev_sibling_c; - - tail->next_sibling = child; - child->prev_sibling_c = tail; - head->prev_sibling_c = child; - } - else - { - node->first_child = child; - child->prev_sibling_c = child; - } - } - - inline void prepend_node(xml_node_struct* child, xml_node_struct* node) - { - child->parent = node; - - xml_node_struct* head = node->first_child; - - if (head) - { - child->prev_sibling_c = head->prev_sibling_c; - head->prev_sibling_c = child; - } - else - child->prev_sibling_c = child; - - child->next_sibling = head; - node->first_child = child; - } - - inline void insert_node_after(xml_node_struct* child, xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - child->parent = parent; - - if (node->next_sibling) - node->next_sibling->prev_sibling_c = child; - else - parent->first_child->prev_sibling_c = child; - - child->next_sibling = node->next_sibling; - child->prev_sibling_c = node; - - node->next_sibling = child; - } - - inline void insert_node_before(xml_node_struct* child, xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - child->parent = parent; - - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = child; - else - parent->first_child = child; - - child->prev_sibling_c = node->prev_sibling_c; - child->next_sibling = node; - - node->prev_sibling_c = child; - } - - inline void remove_node(xml_node_struct* node) - { - xml_node_struct* parent = node->parent; - - if (node->next_sibling) - node->next_sibling->prev_sibling_c = node->prev_sibling_c; - else - parent->first_child->prev_sibling_c = node->prev_sibling_c; - - if (node->prev_sibling_c->next_sibling) - node->prev_sibling_c->next_sibling = node->next_sibling; - else - parent->first_child = node->next_sibling; - - node->parent = 0; - node->prev_sibling_c = 0; - node->next_sibling = 0; - } - - inline void append_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - xml_attribute_struct* head = node->first_attribute; - - if (head) - { - xml_attribute_struct* tail = head->prev_attribute_c; - - tail->next_attribute = attr; - attr->prev_attribute_c = tail; - head->prev_attribute_c = attr; - } - else - { - node->first_attribute = attr; - attr->prev_attribute_c = attr; - } - } - - inline void prepend_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - xml_attribute_struct* head = node->first_attribute; - - if (head) - { - attr->prev_attribute_c = head->prev_attribute_c; - head->prev_attribute_c = attr; - } - else - attr->prev_attribute_c = attr; - - attr->next_attribute = head; - node->first_attribute = attr; - } - - inline void insert_attribute_after(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) - { - if (place->next_attribute) - place->next_attribute->prev_attribute_c = attr; - else - node->first_attribute->prev_attribute_c = attr; - - attr->next_attribute = place->next_attribute; - attr->prev_attribute_c = place; - place->next_attribute = attr; - } - - inline void insert_attribute_before(xml_attribute_struct* attr, xml_attribute_struct* place, xml_node_struct* node) - { - if (place->prev_attribute_c->next_attribute) - place->prev_attribute_c->next_attribute = attr; - else - node->first_attribute = attr; - - attr->prev_attribute_c = place->prev_attribute_c; - attr->next_attribute = place; - place->prev_attribute_c = attr; - } - - inline void remove_attribute(xml_attribute_struct* attr, xml_node_struct* node) - { - if (attr->next_attribute) - attr->next_attribute->prev_attribute_c = attr->prev_attribute_c; - else - node->first_attribute->prev_attribute_c = attr->prev_attribute_c; - - if (attr->prev_attribute_c->next_attribute) - attr->prev_attribute_c->next_attribute = attr->next_attribute; - else - node->first_attribute = attr->next_attribute; - - attr->prev_attribute_c = 0; - attr->next_attribute = 0; - } - - PUGI__FN_NO_INLINE xml_node_struct* append_new_node(xml_node_struct* node, xml_allocator& alloc, xml_node_type type = node_element) - { - xml_node_struct* child = allocate_node(alloc, type); - if (!child) return 0; - - append_node(child, node); - - return child; - } - - PUGI__FN_NO_INLINE xml_attribute_struct* append_new_attribute(xml_node_struct* node, xml_allocator& alloc) - { - xml_attribute_struct* attr = allocate_attribute(alloc); - if (!attr) return 0; - - append_attribute(attr, node); - - return attr; - } -PUGI__NS_END - -// Helper classes for code generation -PUGI__NS_BEGIN - struct opt_false - { - enum { value = 0 }; - }; - - struct opt_true - { - enum { value = 1 }; - }; -PUGI__NS_END - -// Unicode utilities -PUGI__NS_BEGIN - inline uint16_t endian_swap(uint16_t value) - { - return static_cast(((value & 0xff) << 8) | (value >> 8)); - } - - inline uint32_t endian_swap(uint32_t value) - { - return ((value & 0xff) << 24) | ((value & 0xff00) << 8) | ((value & 0xff0000) >> 8) | (value >> 24); - } - - struct utf8_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) return result + 1; - // U+0080..U+07FF - else if (ch < 0x800) return result + 2; - // U+0800..U+FFFF - else return result + 3; - } - - static value_type high(value_type result, uint32_t) - { - // U+10000..U+10FFFF - return result + 4; - } - }; - - struct utf8_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - // U+0000..U+007F - if (ch < 0x80) - { - *result = static_cast(ch); - return result + 1; - } - // U+0080..U+07FF - else if (ch < 0x800) - { - result[0] = static_cast(0xC0 | (ch >> 6)); - result[1] = static_cast(0x80 | (ch & 0x3F)); - return result + 2; - } - // U+0800..U+FFFF - else - { - result[0] = static_cast(0xE0 | (ch >> 12)); - result[1] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[2] = static_cast(0x80 | (ch & 0x3F)); - return result + 3; - } - } - - static value_type high(value_type result, uint32_t ch) - { - // U+10000..U+10FFFF - result[0] = static_cast(0xF0 | (ch >> 18)); - result[1] = static_cast(0x80 | ((ch >> 12) & 0x3F)); - result[2] = static_cast(0x80 | ((ch >> 6) & 0x3F)); - result[3] = static_cast(0x80 | (ch & 0x3F)); - return result + 4; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf16_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 2; - } - }; - - struct utf16_writer - { - typedef uint16_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - uint32_t msh = static_cast(ch - 0x10000) >> 10; - uint32_t lsh = static_cast(ch - 0x10000) & 0x3ff; - - result[0] = static_cast(0xD800 + msh); - result[1] = static_cast(0xDC00 + lsh); - - return result + 2; - } - - static value_type any(value_type result, uint32_t ch) - { - return (ch < 0x10000) ? low(result, ch) : high(result, ch); - } - }; - - struct utf32_counter - { - typedef size_t value_type; - - static value_type low(value_type result, uint32_t) - { - return result + 1; - } - - static value_type high(value_type result, uint32_t) - { - return result + 1; - } - }; - - struct utf32_writer - { - typedef uint32_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - - static value_type any(value_type result, uint32_t ch) - { - *result = ch; - - return result + 1; - } - }; - - struct latin1_writer - { - typedef uint8_t* value_type; - - static value_type low(value_type result, uint32_t ch) - { - *result = static_cast(ch > 255 ? '?' : ch); - - return result + 1; - } - - static value_type high(value_type result, uint32_t ch) - { - (void)ch; - - *result = '?'; - - return result + 1; - } - }; - - template struct wchar_selector; - - template <> struct wchar_selector<2> - { - typedef uint16_t type; - typedef utf16_counter counter; - typedef utf16_writer writer; - }; - - template <> struct wchar_selector<4> - { - typedef uint32_t type; - typedef utf32_counter counter; - typedef utf32_writer writer; - }; - - typedef wchar_selector::counter wchar_counter; - typedef wchar_selector::writer wchar_writer; - - template struct utf_decoder - { - static inline typename Traits::value_type decode_utf8_block(const uint8_t* data, size_t size, typename Traits::value_type result) - { - const uint8_t utf8_byte_mask = 0x3f; - - while (size) - { - uint8_t lead = *data; - - // 0xxxxxxx -> U+0000..U+007F - if (lead < 0x80) - { - result = Traits::low(result, lead); - data += 1; - size -= 1; - - // process aligned single-byte (ascii) blocks - if ((reinterpret_cast(data) & 3) == 0) - { - // round-trip through void* to silence 'cast increases required alignment of target type' warnings - while (size >= 4 && (*static_cast(static_cast(data)) & 0x80808080) == 0) - { - result = Traits::low(result, data[0]); - result = Traits::low(result, data[1]); - result = Traits::low(result, data[2]); - result = Traits::low(result, data[3]); - data += 4; - size -= 4; - } - } - } - // 110xxxxx -> U+0080..U+07FF - else if (static_cast(lead - 0xC0) < 0x20 && size >= 2 && (data[1] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xC0) << 6) | (data[1] & utf8_byte_mask)); - data += 2; - size -= 2; - } - // 1110xxxx -> U+0800-U+FFFF - else if (static_cast(lead - 0xE0) < 0x10 && size >= 3 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80) - { - result = Traits::low(result, ((lead & ~0xE0) << 12) | ((data[1] & utf8_byte_mask) << 6) | (data[2] & utf8_byte_mask)); - data += 3; - size -= 3; - } - // 11110xxx -> U+10000..U+10FFFF - else if (static_cast(lead - 0xF0) < 0x08 && size >= 4 && (data[1] & 0xc0) == 0x80 && (data[2] & 0xc0) == 0x80 && (data[3] & 0xc0) == 0x80) - { - result = Traits::high(result, ((lead & ~0xF0) << 18) | ((data[1] & utf8_byte_mask) << 12) | ((data[2] & utf8_byte_mask) << 6) | (data[3] & utf8_byte_mask)); - data += 4; - size -= 4; - } - // 10xxxxxx or 11111xxx -> invalid - else - { - data += 1; - size -= 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_utf16_block(const uint16_t* data, size_t size, typename Traits::value_type result) - { - const uint16_t* end = data + size; - - while (data < end) - { - unsigned int lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+D7FF - if (lead < 0xD800) - { - result = Traits::low(result, lead); - data += 1; - } - // U+E000..U+FFFF - else if (static_cast(lead - 0xE000) < 0x2000) - { - result = Traits::low(result, lead); - data += 1; - } - // surrogate pair lead - else if (static_cast(lead - 0xD800) < 0x400 && data + 1 < end) - { - uint16_t next = opt_swap::value ? endian_swap(data[1]) : data[1]; - - if (static_cast(next - 0xDC00) < 0x400) - { - result = Traits::high(result, 0x10000 + ((lead & 0x3ff) << 10) + (next & 0x3ff)); - data += 2; - } - else - { - data += 1; - } - } - else - { - data += 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_utf32_block(const uint32_t* data, size_t size, typename Traits::value_type result) - { - const uint32_t* end = data + size; - - while (data < end) - { - uint32_t lead = opt_swap::value ? endian_swap(*data) : *data; - - // U+0000..U+FFFF - if (lead < 0x10000) - { - result = Traits::low(result, lead); - data += 1; - } - // U+10000..U+10FFFF - else - { - result = Traits::high(result, lead); - data += 1; - } - } - - return result; - } - - static inline typename Traits::value_type decode_latin1_block(const uint8_t* data, size_t size, typename Traits::value_type result) - { - for (size_t i = 0; i < size; ++i) - { - result = Traits::low(result, data[i]); - } - - return result; - } - - static inline typename Traits::value_type decode_wchar_block_impl(const uint16_t* data, size_t size, typename Traits::value_type result) - { - return decode_utf16_block(data, size, result); - } - - static inline typename Traits::value_type decode_wchar_block_impl(const uint32_t* data, size_t size, typename Traits::value_type result) - { - return decode_utf32_block(data, size, result); - } - - static inline typename Traits::value_type decode_wchar_block(const wchar_t* data, size_t size, typename Traits::value_type result) - { - return decode_wchar_block_impl(reinterpret_cast::type*>(data), size, result); - } - }; - - template PUGI__FN void convert_utf_endian_swap(T* result, const T* data, size_t length) - { - for (size_t i = 0; i < length; ++i) result[i] = endian_swap(data[i]); - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN void convert_wchar_endian_swap(wchar_t* result, const wchar_t* data, size_t length) - { - for (size_t i = 0; i < length; ++i) result[i] = static_cast(endian_swap(static_cast::type>(data[i]))); - } -#endif -PUGI__NS_END - -PUGI__NS_BEGIN - enum chartype_t - { - ct_parse_pcdata = 1, // \0, &, \r, < - ct_parse_attr = 2, // \0, &, \r, ', " - ct_parse_attr_ws = 4, // \0, &, \r, ', ", \n, tab - ct_space = 8, // \r, \n, space, tab - ct_parse_cdata = 16, // \0, ], >, \r - ct_parse_comment = 32, // \0, -, >, \r - ct_symbol = 64, // Any symbol > 127, a-z, A-Z, 0-9, _, :, -, . - ct_start_symbol = 128 // Any symbol > 127, a-z, A-Z, _, : - }; - - static const unsigned char chartype_table[256] = - { - 55, 0, 0, 0, 0, 0, 0, 0, 0, 12, 12, 0, 0, 63, 0, 0, // 0-15 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31 - 8, 0, 6, 0, 0, 0, 7, 6, 0, 0, 0, 0, 0, 96, 64, 0, // 32-47 - 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 192, 0, 1, 0, 48, 0, // 48-63 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 64-79 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 16, 0, 192, // 80-95 - 0, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 96-111 - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 0, 0, 0, 0, 0, // 112-127 - - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, // 128+ - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, - 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192 - }; - - enum chartypex_t - { - ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > - ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " - ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ - ctx_digit = 8, // 0-9 - ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . - }; - - static const unsigned char chartypex_table[256] = - { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 - 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 - - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 - 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 96-111 - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 0, // 112-127 - - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 128+ - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, - 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 - }; - -#ifdef PUGIXML_WCHAR_MODE - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) ((static_cast(c) < 128 ? table[static_cast(c)] : table[128]) & (ct)) -#else - #define PUGI__IS_CHARTYPE_IMPL(c, ct, table) (table[static_cast(c)] & (ct)) -#endif - - #define PUGI__IS_CHARTYPE(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartype_table) - #define PUGI__IS_CHARTYPEX(c, ct) PUGI__IS_CHARTYPE_IMPL(c, ct, chartypex_table) - - PUGI__FN bool is_little_endian() - { - unsigned int ui = 1; - - return *reinterpret_cast(&ui) == 1; - } - - PUGI__FN xml_encoding get_wchar_encoding() - { - PUGI__STATIC_ASSERT(sizeof(wchar_t) == 2 || sizeof(wchar_t) == 4); - - if (sizeof(wchar_t) == 2) - return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - else - return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - } - - PUGI__FN xml_encoding guess_buffer_encoding(uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3) - { - // look for BOM in first few bytes - if (d0 == 0 && d1 == 0 && d2 == 0xfe && d3 == 0xff) return encoding_utf32_be; - if (d0 == 0xff && d1 == 0xfe && d2 == 0 && d3 == 0) return encoding_utf32_le; - if (d0 == 0xfe && d1 == 0xff) return encoding_utf16_be; - if (d0 == 0xff && d1 == 0xfe) return encoding_utf16_le; - if (d0 == 0xef && d1 == 0xbb && d2 == 0xbf) return encoding_utf8; - - // look for <, (contents); - - PUGI__DMC_VOLATILE uint8_t d0 = data[0], d1 = data[1], d2 = data[2], d3 = data[3]; - - return guess_buffer_encoding(d0, d1, d2, d3); - } - - PUGI__FN bool get_mutable_buffer(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - size_t length = size / sizeof(char_t); - - if (is_mutable) - { - out_buffer = static_cast(const_cast(contents)); - out_length = length; - } - else - { - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - if (contents) - memcpy(buffer, contents, length * sizeof(char_t)); - else - assert(length == 0); - - buffer[length] = 0; - - out_buffer = buffer; - out_length = length + 1; - } - - return true; - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN bool need_endian_swap_utf(xml_encoding le, xml_encoding re) - { - return (le == encoding_utf16_be && re == encoding_utf16_le) || (le == encoding_utf16_le && re == encoding_utf16_be) || - (le == encoding_utf32_be && re == encoding_utf32_le) || (le == encoding_utf32_le && re == encoding_utf32_be); - } - - PUGI__FN bool convert_buffer_endian_swap(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const char_t* data = static_cast(contents); - size_t length = size / sizeof(char_t); - - if (is_mutable) - { - char_t* buffer = const_cast(data); - - convert_wchar_endian_swap(buffer, data, length); - - out_buffer = buffer; - out_length = length; - } - else - { - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - convert_wchar_endian_swap(buffer, data, length); - buffer[length] = 0; - - out_buffer = buffer; - out_length = length + 1; - } - - return true; - } - - PUGI__FN bool convert_buffer_utf8(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) - { - const uint8_t* data = static_cast(contents); - size_t data_length = size; - - // first pass: get length in wchar_t units - size_t length = utf_decoder::decode_utf8_block(data, data_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf8 input to wchar_t - wchar_writer::value_type obegin = reinterpret_cast(buffer); - wchar_writer::value_type oend = utf_decoder::decode_utf8_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint16_t* data = static_cast(contents); - size_t data_length = size / sizeof(uint16_t); - - // first pass: get length in wchar_t units - size_t length = utf_decoder::decode_utf16_block(data, data_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf16 input to wchar_t - wchar_writer::value_type obegin = reinterpret_cast(buffer); - wchar_writer::value_type oend = utf_decoder::decode_utf16_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint32_t* data = static_cast(contents); - size_t data_length = size / sizeof(uint32_t); - - // first pass: get length in wchar_t units - size_t length = utf_decoder::decode_utf32_block(data, data_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf32 input to wchar_t - wchar_writer::value_type obegin = reinterpret_cast(buffer); - wchar_writer::value_type oend = utf_decoder::decode_utf32_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size) - { - const uint8_t* data = static_cast(contents); - size_t data_length = size; - - // get length in wchar_t units - size_t length = data_length; - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // convert latin1 input to wchar_t - wchar_writer::value_type obegin = reinterpret_cast(buffer); - wchar_writer::value_type oend = utf_decoder::decode_latin1_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // get native encoding - xml_encoding wchar_encoding = get_wchar_encoding(); - - // fast path: no conversion required - if (encoding == wchar_encoding) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // only endian-swapping is required - if (need_endian_swap_utf(encoding, wchar_encoding)) return convert_buffer_endian_swap(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf8 - if (encoding == encoding_utf8) return convert_buffer_utf8(out_buffer, out_length, contents, size); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size); - - assert(!"Invalid encoding"); - return false; - } -#else - template PUGI__FN bool convert_buffer_utf16(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint16_t* data = static_cast(contents); - size_t data_length = size / sizeof(uint16_t); - - // first pass: get length in utf8 units - size_t length = utf_decoder::decode_utf16_block(data, data_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf16 input to utf8 - uint8_t* obegin = reinterpret_cast(buffer); - uint8_t* oend = utf_decoder::decode_utf16_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - template PUGI__FN bool convert_buffer_utf32(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, opt_swap) - { - const uint32_t* data = static_cast(contents); - size_t data_length = size / sizeof(uint32_t); - - // first pass: get length in utf8 units - size_t length = utf_decoder::decode_utf32_block(data, data_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert utf32 input to utf8 - uint8_t* obegin = reinterpret_cast(buffer); - uint8_t* oend = utf_decoder::decode_utf32_block(data, data_length, obegin); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN size_t get_latin1_7bit_prefix_length(const uint8_t* data, size_t size) - { - for (size_t i = 0; i < size; ++i) - if (data[i] > 127) - return i; - - return size; - } - - PUGI__FN bool convert_buffer_latin1(char_t*& out_buffer, size_t& out_length, const void* contents, size_t size, bool is_mutable) - { - const uint8_t* data = static_cast(contents); - size_t data_length = size; - - // get size of prefix that does not need utf8 conversion - size_t prefix_length = get_latin1_7bit_prefix_length(data, data_length); - assert(prefix_length <= data_length); - - const uint8_t* postfix = data + prefix_length; - size_t postfix_length = data_length - prefix_length; - - // if no conversion is needed, just return the original buffer - if (postfix_length == 0) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // first pass: get length in utf8 units - size_t length = prefix_length + utf_decoder::decode_latin1_block(postfix, postfix_length, 0); - - // allocate buffer of suitable length - char_t* buffer = static_cast(xml_memory::allocate((length + 1) * sizeof(char_t))); - if (!buffer) return false; - - // second pass: convert latin1 input to utf8 - memcpy(buffer, data, prefix_length); - - uint8_t* obegin = reinterpret_cast(buffer); - uint8_t* oend = utf_decoder::decode_latin1_block(postfix, postfix_length, obegin + prefix_length); - - assert(oend == obegin + length); - *oend = 0; - - out_buffer = buffer; - out_length = length + 1; - - return true; - } - - PUGI__FN bool convert_buffer(char_t*& out_buffer, size_t& out_length, xml_encoding encoding, const void* contents, size_t size, bool is_mutable) - { - // fast path: no conversion required - if (encoding == encoding_utf8) return get_mutable_buffer(out_buffer, out_length, contents, size, is_mutable); - - // source encoding is utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - return (native_encoding == encoding) ? - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf16(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - return (native_encoding == encoding) ? - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_false()) : - convert_buffer_utf32(out_buffer, out_length, contents, size, opt_true()); - } - - // source encoding is latin1 - if (encoding == encoding_latin1) return convert_buffer_latin1(out_buffer, out_length, contents, size, is_mutable); - - assert(!"Invalid encoding"); - return false; - } -#endif - - PUGI__FN size_t as_utf8_begin(const wchar_t* str, size_t length) - { - // get length in utf8 characters - return utf_decoder::decode_wchar_block(str, length, 0); - } - - PUGI__FN void as_utf8_end(char* buffer, size_t size, const wchar_t* str, size_t length) - { - // convert to utf8 - uint8_t* begin = reinterpret_cast(buffer); - uint8_t* end = utf_decoder::decode_wchar_block(str, length, begin); - - assert(begin + size == end); - (void)!end; - - // zero-terminate - buffer[size] = 0; - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string as_utf8_impl(const wchar_t* str, size_t length) - { - // first pass: get length in utf8 characters - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - std::string result; - result.resize(size); - - // second pass: convert to utf8 - if (size > 0) as_utf8_end(&result[0], size, str, length); - - return result; - } - - PUGI__FN std::basic_string as_wide_impl(const char* str, size_t size) - { - const uint8_t* data = reinterpret_cast(str); - - // first pass: get length in wchar_t units - size_t length = utf_decoder::decode_utf8_block(data, size, 0); - - // allocate resulting string - std::basic_string result; - result.resize(length); - - // second pass: convert to wchar_t - if (length > 0) - { - wchar_writer::value_type begin = reinterpret_cast(&result[0]); - wchar_writer::value_type end = utf_decoder::decode_utf8_block(data, size, begin); - - assert(begin + length == end); - (void)!end; - } - - return result; - } -#endif - - inline bool strcpy_insitu_allow(size_t length, uintptr_t header, uintptr_t header_mask, char_t* target) - { - // never reuse shared memory - if (header & xml_memory_page_contents_shared_mask) return false; - - size_t target_length = strlength(target); - - // always reuse document buffer memory if possible - if ((header & header_mask) == 0) return target_length >= length; - - // reuse heap memory if waste is not too great - const size_t reuse_threshold = 32; - - return target_length >= length && (target_length < reuse_threshold || target_length - length < target_length / 2); - } - - PUGI__FN bool strcpy_insitu(char_t*& dest, uintptr_t& header, uintptr_t header_mask, const char_t* source) - { - assert(header); - - size_t source_length = strlength(source); - - if (source_length == 0) - { - // empty string and null pointer are equivalent, so just deallocate old memory - xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; - - if (header & header_mask) alloc->deallocate_string(dest); - - // mark the string as not allocated - dest = 0; - header &= ~header_mask; - - return true; - } - else if (dest && strcpy_insitu_allow(source_length, header, header_mask, dest)) - { - // we can reuse old buffer, so just copy the new data (including zero terminator) - memcpy(dest, source, (source_length + 1) * sizeof(char_t)); - - return true; - } - else - { - xml_allocator* alloc = reinterpret_cast(header & xml_memory_page_pointer_mask)->allocator; - - // allocate new buffer - char_t* buf = alloc->allocate_string(source_length + 1); - if (!buf) return false; - - // copy the string (including zero terminator) - memcpy(buf, source, (source_length + 1) * sizeof(char_t)); - - // deallocate old buffer (*after* the above to protect against overlapping memory and/or allocation failures) - if (header & header_mask) alloc->deallocate_string(dest); - - // the string is now allocated, so set the flag - dest = buf; - header |= header_mask; - - return true; - } - } - - struct gap - { - char_t* end; - size_t size; - - gap(): end(0), size(0) - { - } - - // Push new gap, move s count bytes further (skipping the gap). - // Collapse previous gap. - void push(char_t*& s, size_t count) - { - if (end) // there was a gap already; collapse it - { - // Move [old_gap_end, new_gap_start) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - } - - s += count; // end of current gap - - // "merge" two gaps - end = s; - size += count; - } - - // Collapse all gaps, return past-the-end pointer - char_t* flush(char_t* s) - { - if (end) - { - // Move [old_gap_end, current_pos) to [old_gap_start, ...) - assert(s >= end); - memmove(end - size, end, reinterpret_cast(s) - reinterpret_cast(end)); - - return s - size; - } - else return s; - } - }; - - PUGI__FN char_t* strconv_escape(char_t* s, gap& g) - { - char_t* stre = s + 1; - - switch (*stre) - { - case '#': // &#... - { - unsigned int ucsc = 0; - - if (stre[1] == 'x') // &#x... (hex code) - { - stre += 2; - - char_t ch = *stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(ch - '0') <= 9) - ucsc = 16 * ucsc + (ch - '0'); - else if (static_cast((ch | ' ') - 'a') <= 5) - ucsc = 16 * ucsc + ((ch | ' ') - 'a' + 10); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - else // &#... (dec code) - { - char_t ch = *++stre; - - if (ch == ';') return stre; - - for (;;) - { - if (static_cast(static_cast(ch) - '0') <= 9) - ucsc = 10 * ucsc + (ch - '0'); - else if (ch == ';') - break; - else // cancel - return stre; - - ch = *++stre; - } - - ++stre; - } - - #ifdef PUGIXML_WCHAR_MODE - s = reinterpret_cast(wchar_writer::any(reinterpret_cast(s), ucsc)); - #else - s = reinterpret_cast(utf8_writer::any(reinterpret_cast(s), ucsc)); - #endif - - g.push(s, stre - s); - return stre; - } - - case 'a': // &a - { - ++stre; - - if (*stre == 'm') // &am - { - if (*++stre == 'p' && *++stre == ';') // & - { - *s++ = '&'; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - else if (*stre == 'p') // &ap - { - if (*++stre == 'o' && *++stre == 's' && *++stre == ';') // ' - { - *s++ = '\''; - ++stre; - - g.push(s, stre - s); - return stre; - } - } - break; - } - - case 'g': // &g - { - if (*++stre == 't' && *++stre == ';') // > - { - *s++ = '>'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'l': // &l - { - if (*++stre == 't' && *++stre == ';') // < - { - *s++ = '<'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - case 'q': // &q - { - if (*++stre == 'u' && *++stre == 'o' && *++stre == 't' && *++stre == ';') // " - { - *s++ = '"'; - ++stre; - - g.push(s, stre - s); - return stre; - } - break; - } - - default: - break; - } - - return stre; - } - - // Parser utilities - #define PUGI__ENDSWITH(c, e) ((c) == (e) || ((c) == 0 && endch == (e))) - #define PUGI__SKIPWS() { while (PUGI__IS_CHARTYPE(*s, ct_space)) ++s; } - #define PUGI__OPTSET(OPT) ( optmsk & (OPT) ) - #define PUGI__PUSHNODE(TYPE) { cursor = append_new_node(cursor, alloc, TYPE); if (!cursor) PUGI__THROW_ERROR(status_out_of_memory, s); } - #define PUGI__POPNODE() { cursor = cursor->parent; } - #define PUGI__SCANFOR(X) { while (*s != 0 && !(X)) ++s; } - #define PUGI__SCANWHILE(X) { while (X) ++s; } - #define PUGI__SCANWHILE_UNROLL(X) { for (;;) { char_t ss = s[0]; if (PUGI__UNLIKELY(!(X))) { break; } ss = s[1]; if (PUGI__UNLIKELY(!(X))) { s += 1; break; } ss = s[2]; if (PUGI__UNLIKELY(!(X))) { s += 2; break; } ss = s[3]; if (PUGI__UNLIKELY(!(X))) { s += 3; break; } s += 4; } } - #define PUGI__ENDSEG() { ch = *s; *s = 0; ++s; } - #define PUGI__THROW_ERROR(err, m) return error_offset = m, error_status = err, static_cast(0) - #define PUGI__CHECK_ERROR(err, m) { if (*s == 0) PUGI__THROW_ERROR(err, m); } - - PUGI__FN char_t* strconv_comment(char_t* s, char_t endch) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_comment)); - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')) // comment ends here - { - *g.flush(s) = 0; - - return s + (s[2] == '>' ? 3 : 2); - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - PUGI__FN char_t* strconv_cdata(char_t* s, char_t endch) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_cdata)); - - if (*s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')) // CDATA ends here - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == 0) - { - return 0; - } - else ++s; - } - } - - typedef char_t* (*strconv_pcdata_t)(char_t*); - - template struct strconv_pcdata_impl - { - static char_t* parse(char_t* s) - { - gap g; - - char_t* begin = s; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_pcdata)); - - if (*s == '<') // PCDATA ends here - { - char_t* end = g.flush(s); - - if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) - --end; - - *end = 0; - - return s + 1; - } - else if (opt_eol::value && *s == '\r') // Either a single 0x0d or 0x0d 0x0a pair - { - *s++ = '\n'; // replace first one with 0x0a - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (*s == 0) - { - char_t* end = g.flush(s); - - if (opt_trim::value) - while (end > begin && PUGI__IS_CHARTYPE(end[-1], ct_space)) - --end; - - *end = 0; - - return s; - } - else ++s; - } - } - }; - - PUGI__FN strconv_pcdata_t get_strconv_pcdata(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); - - switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim) - { - case 0: return strconv_pcdata_impl::parse; - case 1: return strconv_pcdata_impl::parse; - case 2: return strconv_pcdata_impl::parse; - case 3: return strconv_pcdata_impl::parse; - case 4: return strconv_pcdata_impl::parse; - case 5: return strconv_pcdata_impl::parse; - case 6: return strconv_pcdata_impl::parse; - case 7: return strconv_pcdata_impl::parse; - default: assert(false); return 0; // should not get here - } - } - - typedef char_t* (*strconv_attribute_t)(char_t*, char_t); - - template struct strconv_attribute_impl - { - static char_t* parse_wnorm(char_t* s, char_t end_quote) - { - gap g; - - // trim leading whitespaces - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s; - - do ++str; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - g.push(s, str - s); - } - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws | ct_space)); - - if (*s == end_quote) - { - char_t* str = g.flush(s); - - do *str-- = 0; - while (PUGI__IS_CHARTYPE(*str, ct_space)); - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - *s++ = ' '; - - if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - char_t* str = s + 1; - while (PUGI__IS_CHARTYPE(*str, ct_space)) ++str; - - g.push(s, str - s); - } - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_wconv(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr_ws)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (PUGI__IS_CHARTYPE(*s, ct_space)) - { - if (*s == '\r') - { - *s++ = ' '; - - if (*s == '\n') g.push(s, 1); - } - else *s++ = ' '; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_eol(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (*s == '\r') - { - *s++ = '\n'; - - if (*s == '\n') g.push(s, 1); - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - - static char_t* parse_simple(char_t* s, char_t end_quote) - { - gap g; - - while (true) - { - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPE(ss, ct_parse_attr)); - - if (*s == end_quote) - { - *g.flush(s) = 0; - - return s + 1; - } - else if (opt_escape::value && *s == '&') - { - s = strconv_escape(s, g); - } - else if (!*s) - { - return 0; - } - else ++s; - } - } - }; - - PUGI__FN strconv_attribute_t get_strconv_attribute(unsigned int optmask) - { - PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); - - switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) - { - case 0: return strconv_attribute_impl::parse_simple; - case 1: return strconv_attribute_impl::parse_simple; - case 2: return strconv_attribute_impl::parse_eol; - case 3: return strconv_attribute_impl::parse_eol; - case 4: return strconv_attribute_impl::parse_wconv; - case 5: return strconv_attribute_impl::parse_wconv; - case 6: return strconv_attribute_impl::parse_wconv; - case 7: return strconv_attribute_impl::parse_wconv; - case 8: return strconv_attribute_impl::parse_wnorm; - case 9: return strconv_attribute_impl::parse_wnorm; - case 10: return strconv_attribute_impl::parse_wnorm; - case 11: return strconv_attribute_impl::parse_wnorm; - case 12: return strconv_attribute_impl::parse_wnorm; - case 13: return strconv_attribute_impl::parse_wnorm; - case 14: return strconv_attribute_impl::parse_wnorm; - case 15: return strconv_attribute_impl::parse_wnorm; - default: assert(false); return 0; // should not get here - } - } - - inline xml_parse_result make_parse_result(xml_parse_status status, ptrdiff_t offset = 0) - { - xml_parse_result result; - result.status = status; - result.offset = offset; - - return result; - } - - struct xml_parser - { - xml_allocator alloc; - char_t* error_offset; - xml_parse_status error_status; - - xml_parser(const xml_allocator& alloc_): alloc(alloc_), error_offset(0), error_status(status_ok) - { - } - - // DOCTYPE consists of nested sections of the following possible types: - // , , "...", '...' - // - // - // First group can not contain nested groups - // Second group can contain nested groups of the same type - // Third group can contain all other groups - char_t* parse_doctype_primitive(char_t* s) - { - if (*s == '"' || *s == '\'') - { - // quoted string - char_t ch = *s++; - PUGI__SCANFOR(*s == ch); - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s++; - } - else if (s[0] == '<' && s[1] == '?') - { - // - s += 2; - PUGI__SCANFOR(s[0] == '?' && s[1] == '>'); // no need for ENDSWITH because ?> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 2; - } - else if (s[0] == '<' && s[1] == '!' && s[2] == '-' && s[3] == '-') - { - s += 4; - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && s[2] == '>'); // no need for ENDSWITH because --> can't terminate proper doctype - if (!*s) PUGI__THROW_ERROR(status_bad_doctype, s); - - s += 3; - } - else PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_doctype_ignore(char_t* s) - { - size_t depth = 0; - - assert(s[0] == '<' && s[1] == '!' && s[2] == '['); - s += 3; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] == '[') - { - // nested ignore section - s += 3; - depth++; - } - else if (s[0] == ']' && s[1] == ']' && s[2] == '>') - { - // ignore section end - s += 3; - - if (depth == 0) - return s; - - depth--; - } - else s++; - } - - PUGI__THROW_ERROR(status_bad_doctype, s); - } - - char_t* parse_doctype_group(char_t* s, char_t endch) - { - size_t depth = 0; - - assert((s[0] == '<' || s[0] == 0) && s[1] == '!'); - s += 2; - - while (*s) - { - if (s[0] == '<' && s[1] == '!' && s[2] != '-') - { - if (s[2] == '[') - { - // ignore - s = parse_doctype_ignore(s); - if (!s) return s; - } - else - { - // some control group - s += 2; - depth++; - } - } - else if (s[0] == '<' || s[0] == '"' || s[0] == '\'') - { - // unknown tag (forbidden), or some primitive group - s = parse_doctype_primitive(s); - if (!s) return s; - } - else if (*s == '>') - { - if (depth == 0) - return s; - - depth--; - s++; - } - else s++; - } - - if (depth != 0 || endch != '>') PUGI__THROW_ERROR(status_bad_doctype, s); - - return s; - } - - char_t* parse_exclamation(char_t* s, xml_node_struct* cursor, unsigned int optmsk, char_t endch) - { - // parse node contents, starting with exclamation mark - ++s; - - if (*s == '-') // 'value = s; // Save the offset. - } - - if (PUGI__OPTSET(parse_eol) && PUGI__OPTSET(parse_comments)) - { - s = strconv_comment(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_comment, cursor->value); - } - else - { - // Scan for terminating '-->'. - PUGI__SCANFOR(s[0] == '-' && s[1] == '-' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_comment, s); - - if (PUGI__OPTSET(parse_comments)) - *s = 0; // Zero-terminate this segment at the first terminating '-'. - - s += (s[2] == '>' ? 3 : 2); // Step over the '\0->'. - } - } - else PUGI__THROW_ERROR(status_bad_comment, s); - } - else if (*s == '[') - { - // 'value = s; // Save the offset. - - if (PUGI__OPTSET(parse_eol)) - { - s = strconv_cdata(s, endch); - - if (!s) PUGI__THROW_ERROR(status_bad_cdata, cursor->value); - } - else - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - *s++ = 0; // Zero-terminate this segment. - } - } - else // Flagged for discard, but we still have to scan for the terminator. - { - // Scan for terminating ']]>'. - PUGI__SCANFOR(s[0] == ']' && s[1] == ']' && PUGI__ENDSWITH(s[2], '>')); - PUGI__CHECK_ERROR(status_bad_cdata, s); - - ++s; - } - - s += (s[1] == '>' ? 2 : 1); // Step over the last ']>'. - } - else PUGI__THROW_ERROR(status_bad_cdata, s); - } - else if (s[0] == 'D' && s[1] == 'O' && s[2] == 'C' && s[3] == 'T' && s[4] == 'Y' && s[5] == 'P' && PUGI__ENDSWITH(s[6], 'E')) - { - s -= 2; - - if (cursor->parent) PUGI__THROW_ERROR(status_bad_doctype, s); - - char_t* mark = s + 9; - - s = parse_doctype_group(s, endch); - if (!s) return s; - - assert((*s == 0 && endch == '>') || *s == '>'); - if (*s) *s++ = 0; - - if (PUGI__OPTSET(parse_doctype)) - { - while (PUGI__IS_CHARTYPE(*mark, ct_space)) ++mark; - - PUGI__PUSHNODE(node_doctype); - - cursor->value = mark; - } - } - else if (*s == 0 && endch == '-') PUGI__THROW_ERROR(status_bad_comment, s); - else if (*s == 0 && endch == '[') PUGI__THROW_ERROR(status_bad_cdata, s); - else PUGI__THROW_ERROR(status_unrecognized_tag, s); - - return s; - } - - char_t* parse_question(char_t* s, xml_node_struct*& ref_cursor, unsigned int optmsk, char_t endch) - { - // load into registers - xml_node_struct* cursor = ref_cursor; - char_t ch = 0; - - // parse node contents, starting with question mark - ++s; - - // read PI target - char_t* target = s; - - if (!PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__SCANWHILE(PUGI__IS_CHARTYPE(*s, ct_symbol)); - PUGI__CHECK_ERROR(status_bad_pi, s); - - // determine node type; stricmp / strcasecmp is not portable - bool declaration = (target[0] | ' ') == 'x' && (target[1] | ' ') == 'm' && (target[2] | ' ') == 'l' && target + 3 == s; - - if (declaration ? PUGI__OPTSET(parse_declaration) : PUGI__OPTSET(parse_pi)) - { - if (declaration) - { - // disallow non top-level declarations - if (cursor->parent) PUGI__THROW_ERROR(status_bad_pi, s); - - PUGI__PUSHNODE(node_declaration); - } - else - { - PUGI__PUSHNODE(node_pi); - } - - cursor->name = target; - - PUGI__ENDSEG(); - - // parse value/attributes - if (ch == '?') - { - // empty node - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_pi, s); - s += (*s == '>'); - - PUGI__POPNODE(); - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); - - // scan for tag end - char_t* value = s; - - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - if (declaration) - { - // replace ending ? with / so that 'element' terminates properly - *s = '/'; - - // we exit from this function with cursor at node_declaration, which is a signal to parse() to go to LOC_ATTRIBUTES - s = value; - } - else - { - // store value and step over > - cursor->value = value; - PUGI__POPNODE(); - - PUGI__ENDSEG(); - - s += (*s == '>'); - } - } - else PUGI__THROW_ERROR(status_bad_pi, s); - } - else - { - // scan for tag end - PUGI__SCANFOR(s[0] == '?' && PUGI__ENDSWITH(s[1], '>')); - PUGI__CHECK_ERROR(status_bad_pi, s); - - s += (s[1] == '>' ? 2 : 1); - } - - // store from registers - ref_cursor = cursor; - - return s; - } - - char_t* parse_tree(char_t* s, xml_node_struct* root, unsigned int optmsk, char_t endch) - { - strconv_attribute_t strconv_attribute = get_strconv_attribute(optmsk); - strconv_pcdata_t strconv_pcdata = get_strconv_pcdata(optmsk); - - char_t ch = 0; - xml_node_struct* cursor = root; - char_t* mark = s; - - while (*s != 0) - { - if (*s == '<') - { - ++s; - - LOC_TAG: - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // '<#...' - { - PUGI__PUSHNODE(node_element); // Append a new node to the tree. - - cursor->name = s; - - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - - if (ch == '>') - { - // end of tag - } - else if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - LOC_ATTRIBUTES: - while (true) - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) // <... #... - { - xml_attribute_struct* a = append_new_attribute(cursor, alloc); // Make space for this attribute. - if (!a) PUGI__THROW_ERROR(status_out_of_memory, s); - - a->name = s; // Save the offset. - - PUGI__SCANWHILE_UNROLL(PUGI__IS_CHARTYPE(ss, ct_symbol)); // Scan for a terminator. - PUGI__ENDSEG(); // Save char in 'ch', terminate & step over. - - if (PUGI__IS_CHARTYPE(ch, ct_space)) - { - PUGI__SKIPWS(); // Eat any whitespace. - - ch = *s; - ++s; - } - - if (ch == '=') // '<... #=...' - { - PUGI__SKIPWS(); // Eat any whitespace. - - if (*s == '"' || *s == '\'') // '<... #="...' - { - ch = *s; // Save quote char to avoid breaking on "''" -or- '""'. - ++s; // Step over the quote. - a->value = s; // Save the offset. - - s = strconv_attribute(s, ch); - - if (!s) PUGI__THROW_ERROR(status_bad_attribute, a->value); - - // After this line the loop continues from the start; - // Whitespaces, / and > are ok, symbols and EOF are wrong, - // everything else will be detected - if (PUGI__IS_CHARTYPE(*s, ct_start_symbol)) PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else PUGI__THROW_ERROR(status_bad_attribute, s); - } - else if (*s == '/') - { - ++s; - - if (*s == '>') - { - PUGI__POPNODE(); - s++; - break; - } - else if (*s == 0 && endch == '>') - { - PUGI__POPNODE(); - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '>') - { - ++s; - - break; - } - else if (*s == 0 && endch == '>') - { - break; - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - - // !!! - } - else if (ch == '/') // '<#.../' - { - if (!PUGI__ENDSWITH(*s, '>')) PUGI__THROW_ERROR(status_bad_start_element, s); - - PUGI__POPNODE(); // Pop. - - s += (*s == '>'); - } - else if (ch == 0) - { - // we stepped over null terminator, backtrack & handle closing tag - --s; - - if (endch != '>') PUGI__THROW_ERROR(status_bad_start_element, s); - } - else PUGI__THROW_ERROR(status_bad_start_element, s); - } - else if (*s == '/') - { - ++s; - - char_t* name = cursor->name; - if (!name) PUGI__THROW_ERROR(status_end_element_mismatch, s); - - while (PUGI__IS_CHARTYPE(*s, ct_symbol)) - { - if (*s++ != *name++) PUGI__THROW_ERROR(status_end_element_mismatch, s); - } - - if (*name) - { - if (*s == 0 && name[0] == endch && name[1] == 0) PUGI__THROW_ERROR(status_bad_end_element, s); - else PUGI__THROW_ERROR(status_end_element_mismatch, s); - } - - PUGI__POPNODE(); // Pop. - - PUGI__SKIPWS(); - - if (*s == 0) - { - if (endch != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - } - else - { - if (*s != '>') PUGI__THROW_ERROR(status_bad_end_element, s); - ++s; - } - } - else if (*s == '?') // 'first_child) continue; - } - } - - if (!PUGI__OPTSET(parse_trim_pcdata)) - s = mark; - - if (cursor->parent || PUGI__OPTSET(parse_fragment)) - { - PUGI__PUSHNODE(node_pcdata); // Append a new node on the tree. - cursor->value = s; // Save the offset. - - s = strconv_pcdata(s); - - PUGI__POPNODE(); // Pop since this is a standalone. - - if (!*s) break; - } - else - { - PUGI__SCANFOR(*s == '<'); // '...<' - if (!*s) break; - - ++s; - } - - // We're after '<' - goto LOC_TAG; - } - } - - // check that last tag is closed - if (cursor != root) PUGI__THROW_ERROR(status_end_element_mismatch, s); - - return s; - } - - #ifdef PUGIXML_WCHAR_MODE - static char_t* parse_skip_bom(char_t* s) - { - unsigned int bom = 0xfeff; - return (s[0] == static_cast(bom)) ? s + 1 : s; - } - #else - static char_t* parse_skip_bom(char_t* s) - { - return (s[0] == '\xef' && s[1] == '\xbb' && s[2] == '\xbf') ? s + 3 : s; - } - #endif - - static bool has_element_node_siblings(xml_node_struct* node) - { - while (node) - { - if (PUGI__NODETYPE(node) == node_element) return true; - - node = node->next_sibling; - } - - return false; - } - - static xml_parse_result parse(char_t* buffer, size_t length, xml_document_struct* xmldoc, xml_node_struct* root, unsigned int optmsk) - { - // allocator object is a part of document object - xml_allocator& alloc_ = *static_cast(xmldoc); - - // early-out for empty documents - if (length == 0) - return make_parse_result(PUGI__OPTSET(parse_fragment) ? status_ok : status_no_document_element); - - // get last child of the root before parsing - xml_node_struct* last_root_child = root->first_child ? root->first_child->prev_sibling_c : 0; - - // create parser on stack - xml_parser parser(alloc_); - - // save last character and make buffer zero-terminated (speeds up parsing) - char_t endch = buffer[length - 1]; - buffer[length - 1] = 0; - - // skip BOM to make sure it does not end up as part of parse output - char_t* buffer_data = parse_skip_bom(buffer); - - // perform actual parsing - parser.parse_tree(buffer_data, root, optmsk, endch); - - // update allocator state - alloc_ = parser.alloc; - - xml_parse_result result = make_parse_result(parser.error_status, parser.error_offset ? parser.error_offset - buffer : 0); - assert(result.offset >= 0 && static_cast(result.offset) <= length); - - if (result) - { - // since we removed last character, we have to handle the only possible false positive (stray <) - if (endch == '<') - return make_parse_result(status_unrecognized_tag, length - 1); - - // check if there are any element nodes parsed - xml_node_struct* first_root_child_parsed = last_root_child ? last_root_child->next_sibling : root->first_child; - - if (!PUGI__OPTSET(parse_fragment) && !has_element_node_siblings(first_root_child_parsed)) - return make_parse_result(status_no_document_element, length - 1); - } - else - { - // roll back offset if it occurs on a null terminator in the source buffer - if (result.offset > 0 && static_cast(result.offset) == length - 1 && endch == 0) - result.offset--; - } - - return result; - } - }; - - // Output facilities - PUGI__FN xml_encoding get_write_native_encoding() - { - #ifdef PUGIXML_WCHAR_MODE - return get_wchar_encoding(); - #else - return encoding_utf8; - #endif - } - - PUGI__FN xml_encoding get_write_encoding(xml_encoding encoding) - { - // replace wchar encoding with utf implementation - if (encoding == encoding_wchar) return get_wchar_encoding(); - - // replace utf16 encoding with utf16 with specific endianness - if (encoding == encoding_utf16) return is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - // replace utf32 encoding with utf32 with specific endianness - if (encoding == encoding_utf32) return is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - // only do autodetection if no explicit encoding is requested - if (encoding != encoding_auto) return encoding; - - // assume utf8 encoding - return encoding_utf8; - } - -#ifdef PUGIXML_WCHAR_MODE - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - if (length < 1) return 0; - - // discard last character if it's the lead of a surrogate pair - return (sizeof(wchar_t) == 2 && static_cast(static_cast(data[length - 1]) - 0xD800) < 0x400) ? length - 1 : length; - } - - PUGI__FN size_t convert_buffer_output(char_t* r_char, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - // only endian-swapping is required - if (need_endian_swap_utf(encoding, get_wchar_encoding())) - { - convert_wchar_endian_swap(r_char, data, length); - - return length * sizeof(char_t); - } - - // convert to utf8 - if (encoding == encoding_utf8) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - return static_cast(end - dest); - } - - // convert to utf16 - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - uint16_t* dest = r_u16; - - // convert to native utf16 - uint16_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint16_t); - } - - // convert to utf32 - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - uint32_t* dest = r_u32; - - // convert to native utf32 - uint32_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint32_t); - } - - // convert to latin1 - if (encoding == encoding_latin1) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_wchar_block(data, length, dest); - - return static_cast(end - dest); - } - - assert(!"Invalid encoding"); - return 0; - } -#else - PUGI__FN size_t get_valid_length(const char_t* data, size_t length) - { - if (length < 5) return 0; - - for (size_t i = 1; i <= 4; ++i) - { - uint8_t ch = static_cast(data[length - i]); - - // either a standalone character or a leading one - if ((ch & 0xc0) != 0x80) return length - i; - } - - // there are four non-leading characters at the end, sequence tail is broken so might as well process the whole chunk - return length; - } - - PUGI__FN size_t convert_buffer_output(char_t* /* r_char */, uint8_t* r_u8, uint16_t* r_u16, uint32_t* r_u32, const char_t* data, size_t length, xml_encoding encoding) - { - if (encoding == encoding_utf16_be || encoding == encoding_utf16_le) - { - uint16_t* dest = r_u16; - - // convert to native utf16 - uint16_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf16_le : encoding_utf16_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint16_t); - } - - if (encoding == encoding_utf32_be || encoding == encoding_utf32_le) - { - uint32_t* dest = r_u32; - - // convert to native utf32 - uint32_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - // swap if necessary - xml_encoding native_encoding = is_little_endian() ? encoding_utf32_le : encoding_utf32_be; - - if (native_encoding != encoding) convert_utf_endian_swap(dest, dest, static_cast(end - dest)); - - return static_cast(end - dest) * sizeof(uint32_t); - } - - if (encoding == encoding_latin1) - { - uint8_t* dest = r_u8; - uint8_t* end = utf_decoder::decode_utf8_block(reinterpret_cast(data), length, dest); - - return static_cast(end - dest); - } - - assert(!"Invalid encoding"); - return 0; - } -#endif - - class xml_buffered_writer - { - xml_buffered_writer(const xml_buffered_writer&); - xml_buffered_writer& operator=(const xml_buffered_writer&); - - public: - xml_buffered_writer(xml_writer& writer_, xml_encoding user_encoding): writer(writer_), bufsize(0), encoding(get_write_encoding(user_encoding)) - { - PUGI__STATIC_ASSERT(bufcapacity >= 8); - } - - ~xml_buffered_writer() - { - flush(); - } - - size_t flush() - { - flush(buffer, bufsize); - bufsize = 0; - return 0; - } - - void flush(const char_t* data, size_t size) - { - if (size == 0) return; - - // fast path, just write data - if (encoding == get_write_native_encoding()) - writer.write(data, size * sizeof(char_t)); - else - { - // convert chunk - size_t result = convert_buffer_output(scratch.data_char, scratch.data_u8, scratch.data_u16, scratch.data_u32, data, size, encoding); - assert(result <= sizeof(scratch)); - - // write data - writer.write(scratch.data_u8, result); - } - } - - void write_direct(const char_t* data, size_t length) - { - // flush the remaining buffer contents - flush(); - - // handle large chunks - if (length > bufcapacity) - { - if (encoding == get_write_native_encoding()) - { - // fast path, can just write data chunk - writer.write(data, length * sizeof(char_t)); - return; - } - - // need to convert in suitable chunks - while (length > bufcapacity) - { - // get chunk size by selecting such number of characters that are guaranteed to fit into scratch buffer - // and form a complete codepoint sequence (i.e. discard start of last codepoint if necessary) - size_t chunk_size = get_valid_length(data, bufcapacity); - assert(chunk_size); - - // convert chunk and write - flush(data, chunk_size); - - // iterate - data += chunk_size; - length -= chunk_size; - } - - // small tail is copied below - bufsize = 0; - } - - memcpy(buffer + bufsize, data, length * sizeof(char_t)); - bufsize += length; - } - - void write_buffer(const char_t* data, size_t length) - { - size_t offset = bufsize; - - if (offset + length <= bufcapacity) - { - memcpy(buffer + offset, data, length * sizeof(char_t)); - bufsize = offset + length; - } - else - { - write_direct(data, length); - } - } - - void write_string(const char_t* data) - { - // write the part of the string that fits in the buffer - size_t offset = bufsize; - - while (*data && offset < bufcapacity) - buffer[offset++] = *data++; - - // write the rest - if (offset < bufcapacity) - { - bufsize = offset; - } - else - { - // backtrack a bit if we have split the codepoint - size_t length = offset - bufsize; - size_t extra = length - get_valid_length(data - length, length); - - bufsize = offset - extra; - - write_direct(data - extra, strlength(data) + extra); - } - } - - void write(char_t d0) - { - size_t offset = bufsize; - if (offset > bufcapacity - 1) offset = flush(); - - buffer[offset + 0] = d0; - bufsize = offset + 1; - } - - void write(char_t d0, char_t d1) - { - size_t offset = bufsize; - if (offset > bufcapacity - 2) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - bufsize = offset + 2; - } - - void write(char_t d0, char_t d1, char_t d2) - { - size_t offset = bufsize; - if (offset > bufcapacity - 3) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - bufsize = offset + 3; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3) - { - size_t offset = bufsize; - if (offset > bufcapacity - 4) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - bufsize = offset + 4; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4) - { - size_t offset = bufsize; - if (offset > bufcapacity - 5) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - buffer[offset + 4] = d4; - bufsize = offset + 5; - } - - void write(char_t d0, char_t d1, char_t d2, char_t d3, char_t d4, char_t d5) - { - size_t offset = bufsize; - if (offset > bufcapacity - 6) offset = flush(); - - buffer[offset + 0] = d0; - buffer[offset + 1] = d1; - buffer[offset + 2] = d2; - buffer[offset + 3] = d3; - buffer[offset + 4] = d4; - buffer[offset + 5] = d5; - bufsize = offset + 6; - } - - // utf8 maximum expansion: x4 (-> utf32) - // utf16 maximum expansion: x2 (-> utf32) - // utf32 maximum expansion: x1 - enum - { - bufcapacitybytes = - #ifdef PUGIXML_MEMORY_OUTPUT_STACK - PUGIXML_MEMORY_OUTPUT_STACK - #else - 10240 - #endif - , - bufcapacity = bufcapacitybytes / (sizeof(char_t) + 4) - }; - - char_t buffer[bufcapacity]; - - union - { - uint8_t data_u8[4 * bufcapacity]; - uint16_t data_u16[2 * bufcapacity]; - uint32_t data_u32[bufcapacity]; - char_t data_char[bufcapacity]; - } scratch; - - xml_writer& writer; - size_t bufsize; - xml_encoding encoding; - }; - - PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) - { - while (*s) - { - const char_t* prev = s; - - // While *s is a usual symbol - PUGI__SCANWHILE_UNROLL(!PUGI__IS_CHARTYPEX(ss, type)); - - writer.write_buffer(prev, static_cast(s - prev)); - - switch (*s) - { - case 0: break; - case '&': - writer.write('&', 'a', 'm', 'p', ';'); - ++s; - break; - case '<': - writer.write('&', 'l', 't', ';'); - ++s; - break; - case '>': - writer.write('&', 'g', 't', ';'); - ++s; - break; - case '"': - writer.write('&', 'q', 'u', 'o', 't', ';'); - ++s; - break; - default: // s is not a usual symbol - { - unsigned int ch = static_cast(*s++); - assert(ch < 32); - - writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); - } - } - } - } - - PUGI__FN void text_output(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) - { - if (flags & format_no_escapes) - writer.write_string(s); - else - text_output_escaped(writer, s, type); - } - - PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) - { - do - { - writer.write('<', '!', '[', 'C', 'D'); - writer.write('A', 'T', 'A', '['); - - const char_t* prev = s; - - // look for ]]> sequence - we can't output it as is since it terminates CDATA - while (*s && !(s[0] == ']' && s[1] == ']' && s[2] == '>')) ++s; - - // skip ]] if we stopped at ]]>, > will go to the next CDATA section - if (*s) s += 2; - - writer.write_buffer(prev, static_cast(s - prev)); - - writer.write(']', ']', '>'); - } - while (*s); - } - - PUGI__FN void text_output_indent(xml_buffered_writer& writer, const char_t* indent, size_t indent_length, unsigned int depth) - { - switch (indent_length) - { - case 1: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0]); - break; - } - - case 2: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1]); - break; - } - - case 3: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1], indent[2]); - break; - } - - case 4: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write(indent[0], indent[1], indent[2], indent[3]); - break; - } - - default: - { - for (unsigned int i = 0; i < depth; ++i) - writer.write_buffer(indent, indent_length); - } - } - } - - PUGI__FN void node_output_comment(xml_buffered_writer& writer, const char_t* s) - { - writer.write('<', '!', '-', '-'); - - while (*s) - { - const char_t* prev = s; - - // look for -\0 or -- sequence - we can't output it since -- is illegal in comment body - while (*s && !(s[0] == '-' && (s[1] == '-' || s[1] == 0))) ++s; - - writer.write_buffer(prev, static_cast(s - prev)); - - if (*s) - { - assert(*s == '-'); - - writer.write('-', ' '); - ++s; - } - } - - writer.write('-', '-', '>'); - } - - PUGI__FN void node_output_pi_value(xml_buffered_writer& writer, const char_t* s) - { - while (*s) - { - const char_t* prev = s; - - // look for ?> sequence - we can't output it since ?> terminates PI - while (*s && !(s[0] == '?' && s[1] == '>')) ++s; - - writer.write_buffer(prev, static_cast(s - prev)); - - if (*s) - { - assert(s[0] == '?' && s[1] == '>'); - - writer.write('?', ' ', '>'); - s += 2; - } - } - } - - PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) - { - writer.write(' '); - writer.write_string(a->name ? a->name : default_name); - writer.write('=', '"'); - - if (a->value) - text_output(writer, a->value, ctx_special_attr, flags); - - writer.write('"'); - } - } - - PUGI__FN bool node_output_start(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - const char_t* name = node->name ? node->name : default_name; - - writer.write('<'); - writer.write_string(name); - - if (node->first_attribute) - node_output_attributes(writer, node, flags); - - if (!node->first_child) - { - writer.write(' ', '/', '>'); - - return false; - } - else - { - writer.write('>'); - - return true; - } - } - - PUGI__FN void node_output_end(xml_buffered_writer& writer, xml_node_struct* node) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - const char_t* name = node->name ? node->name : default_name; - - writer.write('<', '/'); - writer.write_string(name); - writer.write('>'); - } - - PUGI__FN void node_output_simple(xml_buffered_writer& writer, xml_node_struct* node, unsigned int flags) - { - const char_t* default_name = PUGIXML_TEXT(":anonymous"); - - switch (PUGI__NODETYPE(node)) - { - case node_pcdata: - text_output(writer, node->value ? node->value : PUGIXML_TEXT(""), ctx_special_pcdata, flags); - break; - - case node_cdata: - text_output_cdata(writer, node->value ? node->value : PUGIXML_TEXT("")); - break; - - case node_comment: - node_output_comment(writer, node->value ? node->value : PUGIXML_TEXT("")); - break; - - case node_pi: - writer.write('<', '?'); - writer.write_string(node->name ? node->name : default_name); - - if (node->value) - { - writer.write(' '); - node_output_pi_value(writer, node->value); - } - - writer.write('?', '>'); - break; - - case node_declaration: - writer.write('<', '?'); - writer.write_string(node->name ? node->name : default_name); - node_output_attributes(writer, node, flags); - writer.write('?', '>'); - break; - - case node_doctype: - writer.write('<', '!', 'D', 'O', 'C'); - writer.write('T', 'Y', 'P', 'E'); - - if (node->value) - { - writer.write(' '); - writer.write_string(node->value); - } - - writer.write('>'); - break; - - default: - assert(!"Invalid node type"); - } - } - - enum indent_flags_t - { - indent_newline = 1, - indent_indent = 2 - }; - - PUGI__FN void node_output(xml_buffered_writer& writer, xml_node_struct* root, const char_t* indent, unsigned int flags, unsigned int depth) - { - size_t indent_length = ((flags & (format_indent | format_raw)) == format_indent) ? strlength(indent) : 0; - unsigned int indent_flags = indent_indent; - - xml_node_struct* node = root; - - do - { - assert(node); - - // begin writing current node - if (PUGI__NODETYPE(node) == node_pcdata || PUGI__NODETYPE(node) == node_cdata) - { - node_output_simple(writer, node, flags); - - indent_flags = 0; - } - else - { - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - - if ((indent_flags & indent_indent) && indent_length) - text_output_indent(writer, indent, indent_length, depth); - - if (PUGI__NODETYPE(node) == node_element) - { - indent_flags = indent_newline | indent_indent; - - if (node_output_start(writer, node, flags)) - { - node = node->first_child; - depth++; - continue; - } - } - else if (PUGI__NODETYPE(node) == node_document) - { - indent_flags = indent_indent; - - if (node->first_child) - { - node = node->first_child; - continue; - } - } - else - { - node_output_simple(writer, node, flags); - - indent_flags = indent_newline | indent_indent; - } - } - - // continue to the next node - while (node != root) - { - if (node->next_sibling) - { - node = node->next_sibling; - break; - } - - node = node->parent; - - // write closing node - if (PUGI__NODETYPE(node) == node_element) - { - depth--; - - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - - if ((indent_flags & indent_indent) && indent_length) - text_output_indent(writer, indent, indent_length, depth); - - node_output_end(writer, node); - - indent_flags = indent_newline | indent_indent; - } - } - } - while (node != root); - - if ((indent_flags & indent_newline) && (flags & format_raw) == 0) - writer.write('\n'); - } - - PUGI__FN bool has_declaration(xml_node_struct* node) - { - for (xml_node_struct* child = node->first_child; child; child = child->next_sibling) - { - xml_node_type type = PUGI__NODETYPE(child); - - if (type == node_declaration) return true; - if (type == node_element) return false; - } - - return false; - } - - PUGI__FN bool is_attribute_of(xml_attribute_struct* attr, xml_node_struct* node) - { - for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) - if (a == attr) - return true; - - return false; - } - - PUGI__FN bool allow_insert_attribute(xml_node_type parent) - { - return parent == node_element || parent == node_declaration; - } - - PUGI__FN bool allow_insert_child(xml_node_type parent, xml_node_type child) - { - if (parent != node_document && parent != node_element) return false; - if (child == node_document || child == node_null) return false; - if (parent != node_document && (child == node_declaration || child == node_doctype)) return false; - - return true; - } - - PUGI__FN bool allow_move(xml_node parent, xml_node child) - { - // check that child can be a child of parent - if (!allow_insert_child(parent.type(), child.type())) - return false; - - // check that node is not moved between documents - if (parent.root() != child.root()) - return false; - - // check that new parent is not in the child subtree - xml_node cur = parent; - - while (cur) - { - if (cur == child) - return false; - - cur = cur.parent(); - } - - return true; - } - - PUGI__FN void node_copy_string(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char_t* source, uintptr_t& source_header, xml_allocator* alloc) - { - assert(!dest && (header & header_mask) == 0); - - if (source) - { - if (alloc && (source_header & header_mask) == 0) - { - dest = source; - - // since strcpy_insitu can reuse document buffer memory we need to mark both source and dest as shared - header |= xml_memory_page_contents_shared_mask; - source_header |= xml_memory_page_contents_shared_mask; - } - else - strcpy_insitu(dest, header, header_mask, source); - } - } - - PUGI__FN void node_copy_contents(xml_node_struct* dn, xml_node_struct* sn, xml_allocator* shared_alloc) - { - node_copy_string(dn->name, dn->header, xml_memory_page_name_allocated_mask, sn->name, sn->header, shared_alloc); - node_copy_string(dn->value, dn->header, xml_memory_page_value_allocated_mask, sn->value, sn->header, shared_alloc); - - for (xml_attribute_struct* sa = sn->first_attribute; sa; sa = sa->next_attribute) - { - xml_attribute_struct* da = append_new_attribute(dn, get_allocator(dn)); - - if (da) - { - node_copy_string(da->name, da->header, xml_memory_page_name_allocated_mask, sa->name, sa->header, shared_alloc); - node_copy_string(da->value, da->header, xml_memory_page_value_allocated_mask, sa->value, sa->header, shared_alloc); - } - } - } - - PUGI__FN void node_copy_tree(xml_node_struct* dn, xml_node_struct* sn) - { - xml_allocator& alloc = get_allocator(dn); - xml_allocator* shared_alloc = (&alloc == &get_allocator(sn)) ? &alloc : 0; - - node_copy_contents(dn, sn, shared_alloc); - - xml_node_struct* dit = dn; - xml_node_struct* sit = sn->first_child; - - while (sit && sit != sn) - { - if (sit != dn) - { - xml_node_struct* copy = append_new_node(dit, alloc, PUGI__NODETYPE(sit)); - - if (copy) - { - node_copy_contents(copy, sit, shared_alloc); - - if (sit->first_child) - { - dit = copy; - sit = sit->first_child; - continue; - } - } - } - - // continue to the next node - do - { - if (sit->next_sibling) - { - sit = sit->next_sibling; - break; - } - - sit = sit->parent; - dit = dit->parent; - } - while (sit != sn); - } - } - - inline bool is_text_node(xml_node_struct* node) - { - xml_node_type type = PUGI__NODETYPE(node); - - return type == node_pcdata || type == node_cdata; - } - - // get value with conversion functions - PUGI__FN int get_integer_base(const char_t* value) - { - const char_t* s = value; - - while (PUGI__IS_CHARTYPE(*s, ct_space)) - s++; - - if (*s == '-') - s++; - - return (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) ? 16 : 10; - } - - PUGI__FN int get_value_int(const char_t* value, int def) - { - if (!value) return def; - - int base = get_integer_base(value); - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstol(value, 0, base)); - #else - return static_cast(strtol(value, 0, base)); - #endif - } - - PUGI__FN unsigned int get_value_uint(const char_t* value, unsigned int def) - { - if (!value) return def; - - int base = get_integer_base(value); - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstoul(value, 0, base)); - #else - return static_cast(strtoul(value, 0, base)); - #endif - } - - PUGI__FN double get_value_double(const char_t* value, double def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return wcstod(value, 0); - #else - return strtod(value, 0); - #endif - } - - PUGI__FN float get_value_float(const char_t* value, float def) - { - if (!value) return def; - - #ifdef PUGIXML_WCHAR_MODE - return static_cast(wcstod(value, 0)); - #else - return static_cast(strtod(value, 0)); - #endif - } - - PUGI__FN bool get_value_bool(const char_t* value, bool def) - { - if (!value) return def; - - // only look at first char - char_t first = *value; - - // 1*, t* (true), T* (True), y* (yes), Y* (YES) - return (first == '1' || first == 't' || first == 'T' || first == 'y' || first == 'Y'); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long get_value_llong(const char_t* value, long long def) - { - if (!value) return def; - - int base = get_integer_base(value); - - #ifdef PUGIXML_WCHAR_MODE - #ifdef PUGI__MSVC_CRT_VERSION - return _wcstoi64(value, 0, base); - #else - return wcstoll(value, 0, base); - #endif - #else - #ifdef PUGI__MSVC_CRT_VERSION - return _strtoi64(value, 0, base); - #else - return strtoll(value, 0, base); - #endif - #endif - } - - PUGI__FN unsigned long long get_value_ullong(const char_t* value, unsigned long long def) - { - if (!value) return def; - - int base = get_integer_base(value); - - #ifdef PUGIXML_WCHAR_MODE - #ifdef PUGI__MSVC_CRT_VERSION - return _wcstoui64(value, 0, base); - #else - return wcstoull(value, 0, base); - #endif - #else - #ifdef PUGI__MSVC_CRT_VERSION - return _strtoui64(value, 0, base); - #else - return strtoull(value, 0, base); - #endif - #endif - } -#endif - - // set value with conversion functions - PUGI__FN bool set_value_buffer(char_t*& dest, uintptr_t& header, uintptr_t header_mask, char (&buf)[128]) - { - #ifdef PUGIXML_WCHAR_MODE - char_t wbuf[128]; - impl::widen_ascii(wbuf, buf); - - return strcpy_insitu(dest, header, header_mask, wbuf); - #else - return strcpy_insitu(dest, header, header_mask, buf); - #endif - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, int value) - { - char buf[128]; - sprintf(buf, "%d", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned int value) - { - char buf[128]; - sprintf(buf, "%u", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, float value) - { - char buf[128]; - sprintf(buf, "%.9g", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, double value) - { - char buf[128]; - sprintf(buf, "%.17g", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, bool value) - { - return strcpy_insitu(dest, header, header_mask, value ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, long long value) - { - char buf[128]; - sprintf(buf, "%lld", value); - - return set_value_buffer(dest, header, header_mask, buf); - } - - PUGI__FN bool set_value_convert(char_t*& dest, uintptr_t& header, uintptr_t header_mask, unsigned long long value) - { - char buf[128]; - sprintf(buf, "%llu", value); - - return set_value_buffer(dest, header, header_mask, buf); - } -#endif - - // we need to get length of entire file to load it in memory; the only (relatively) sane way to do it is via seek/tell trick - PUGI__FN xml_parse_status get_file_size(FILE* file, size_t& out_result) - { - #if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 && !defined(_WIN32_WCE) - // there are 64-bit versions of fseek/ftell, let's use them - typedef __int64 length_type; - - _fseeki64(file, 0, SEEK_END); - length_type length = _ftelli64(file); - _fseeki64(file, 0, SEEK_SET); - #elif defined(__MINGW32__) && !defined(__NO_MINGW_LFS) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR)) - // there are 64-bit versions of fseek/ftell, let's use them - typedef off64_t length_type; - - fseeko64(file, 0, SEEK_END); - length_type length = ftello64(file); - fseeko64(file, 0, SEEK_SET); - #else - // if this is a 32-bit OS, long is enough; if this is a unix system, long is 64-bit, which is enough; otherwise we can't do anything anyway. - typedef long length_type; - - fseek(file, 0, SEEK_END); - length_type length = ftell(file); - fseek(file, 0, SEEK_SET); - #endif - - // check for I/O errors - if (length < 0) return status_io_error; - - // check for overflow - size_t result = static_cast(length); - - if (static_cast(result) != length) return status_out_of_memory; - - // finalize - out_result = result; - - return status_ok; - } - - PUGI__FN size_t zero_terminate_buffer(void* buffer, size_t size, xml_encoding encoding) - { - // We only need to zero-terminate if encoding conversion does not do it for us - #ifdef PUGIXML_WCHAR_MODE - xml_encoding wchar_encoding = get_wchar_encoding(); - - if (encoding == wchar_encoding || need_endian_swap_utf(encoding, wchar_encoding)) - { - size_t length = size / sizeof(char_t); - - static_cast(buffer)[length] = 0; - return (length + 1) * sizeof(char_t); - } - #else - if (encoding == encoding_utf8) - { - static_cast(buffer)[size] = 0; - return size + 1; - } - #endif - - return size; - } - - PUGI__FN xml_parse_result load_file_impl(xml_document& doc, FILE* file, unsigned int options, xml_encoding encoding) - { - if (!file) return make_parse_result(status_file_not_found); - - // get file size (can result in I/O errors) - size_t size = 0; - xml_parse_status size_status = get_file_size(file, size); - - if (size_status != status_ok) - { - fclose(file); - return make_parse_result(size_status); - } - - size_t max_suffix_size = sizeof(char_t); - - // allocate buffer for the whole file - char* contents = static_cast(xml_memory::allocate(size + max_suffix_size)); - - if (!contents) - { - fclose(file); - return make_parse_result(status_out_of_memory); - } - - // read file in memory - size_t read_size = fread(contents, 1, size, file); - fclose(file); - - if (read_size != size) - { - xml_memory::deallocate(contents); - return make_parse_result(status_io_error); - } - - xml_encoding real_encoding = get_buffer_encoding(encoding, contents, size); - - return doc.load_buffer_inplace_own(contents, zero_terminate_buffer(contents, size, real_encoding), options, real_encoding); - } - -#ifndef PUGIXML_NO_STL - template struct xml_stream_chunk - { - static xml_stream_chunk* create() - { - void* memory = xml_memory::allocate(sizeof(xml_stream_chunk)); - - return new (memory) xml_stream_chunk(); - } - - static void destroy(void* ptr) - { - xml_stream_chunk* chunk = static_cast(ptr); - - // free chunk chain - while (chunk) - { - xml_stream_chunk* next_ = chunk->next; - - xml_memory::deallocate(chunk); - - chunk = next_; - } - } - - xml_stream_chunk(): next(0), size(0) - { - } - - xml_stream_chunk* next; - size_t size; - - T data[xml_memory_page_size / sizeof(T)]; - }; - - template PUGI__FN xml_parse_status load_stream_data_noseek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - buffer_holder chunks(0, xml_stream_chunk::destroy); - - // read file to a chunk list - size_t total = 0; - xml_stream_chunk* last = 0; - - while (!stream.eof()) - { - // allocate new chunk - xml_stream_chunk* chunk = xml_stream_chunk::create(); - if (!chunk) return status_out_of_memory; - - // append chunk to list - if (last) last = last->next = chunk; - else chunks.data = last = chunk; - - // read data to chunk - stream.read(chunk->data, static_cast(sizeof(chunk->data) / sizeof(T))); - chunk->size = static_cast(stream.gcount()) * sizeof(T); - - // read may set failbit | eofbit in case gcount() is less than read length, so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // guard against huge files (chunk size is small enough to make this overflow check work) - if (total + chunk->size < total) return status_out_of_memory; - total += chunk->size; - } - - size_t max_suffix_size = sizeof(char_t); - - // copy chunk list to a contiguous buffer - char* buffer = static_cast(xml_memory::allocate(total + max_suffix_size)); - if (!buffer) return status_out_of_memory; - - char* write = buffer; - - for (xml_stream_chunk* chunk = static_cast*>(chunks.data); chunk; chunk = chunk->next) - { - assert(write + chunk->size <= buffer + total); - memcpy(write, chunk->data, chunk->size); - write += chunk->size; - } - - assert(write == buffer + total); - - // return buffer - *out_buffer = buffer; - *out_size = total; - - return status_ok; - } - - template PUGI__FN xml_parse_status load_stream_data_seek(std::basic_istream& stream, void** out_buffer, size_t* out_size) - { - // get length of remaining data in stream - typename std::basic_istream::pos_type pos = stream.tellg(); - stream.seekg(0, std::ios::end); - std::streamoff length = stream.tellg() - pos; - stream.seekg(pos); - - if (stream.fail() || pos < 0) return status_io_error; - - // guard against huge files - size_t read_length = static_cast(length); - - if (static_cast(read_length) != length || length < 0) return status_out_of_memory; - - size_t max_suffix_size = sizeof(char_t); - - // read stream data into memory (guard against stream exceptions with buffer holder) - buffer_holder buffer(xml_memory::allocate(read_length * sizeof(T) + max_suffix_size), xml_memory::deallocate); - if (!buffer.data) return status_out_of_memory; - - stream.read(static_cast(buffer.data), static_cast(read_length)); - - // read may set failbit | eofbit in case gcount() is less than read_length (i.e. line ending conversion), so check for other I/O errors - if (stream.bad() || (!stream.eof() && stream.fail())) return status_io_error; - - // return buffer - size_t actual_length = static_cast(stream.gcount()); - assert(actual_length <= read_length); - - *out_buffer = buffer.release(); - *out_size = actual_length * sizeof(T); - - return status_ok; - } - - template PUGI__FN xml_parse_result load_stream_impl(xml_document& doc, std::basic_istream& stream, unsigned int options, xml_encoding encoding) - { - void* buffer = 0; - size_t size = 0; - xml_parse_status status = status_ok; - - // if stream has an error bit set, bail out (otherwise tellg() can fail and we'll clear error bits) - if (stream.fail()) return make_parse_result(status_io_error); - - // load stream to memory (using seek-based implementation if possible, since it's faster and takes less memory) - if (stream.tellg() < 0) - { - stream.clear(); // clear error flags that could be set by a failing tellg - status = load_stream_data_noseek(stream, &buffer, &size); - } - else - status = load_stream_data_seek(stream, &buffer, &size); - - if (status != status_ok) return make_parse_result(status); - - xml_encoding real_encoding = get_buffer_encoding(encoding, buffer, size); - - return doc.load_buffer_inplace_own(buffer, zero_terminate_buffer(buffer, size, real_encoding), options, real_encoding); - } -#endif - -#if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - return _wfopen(path, mode); - } -#else - PUGI__FN char* convert_path_heap(const wchar_t* str) - { - assert(str); - - // first pass: get length in utf8 characters - size_t length = strlength_wide(str); - size_t size = as_utf8_begin(str, length); - - // allocate resulting string - char* result = static_cast(xml_memory::allocate(size + 1)); - if (!result) return 0; - - // second pass: convert to utf8 - as_utf8_end(result, size, str, length); - - return result; - } - - PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) - { - // there is no standard function to open wide paths, so our best bet is to try utf8 path - char* path_utf8 = convert_path_heap(path); - if (!path_utf8) return 0; - - // convert mode to ASCII (we mirror _wfopen interface) - char mode_ascii[4] = {0}; - for (size_t i = 0; mode[i]; ++i) mode_ascii[i] = static_cast(mode[i]); - - // try to open the utf8 path - FILE* result = fopen(path_utf8, mode_ascii); - - // free dummy buffer - xml_memory::deallocate(path_utf8); - - return result; - } -#endif - - PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) - { - if (!file) return false; - - xml_writer_file writer(file); - doc.save(writer, indent, flags, encoding); - - int result = ferror(file); - - fclose(file); - - return result == 0; - } - - PUGI__FN xml_parse_result load_buffer_impl(xml_document_struct* doc, xml_node_struct* root, void* contents, size_t size, unsigned int options, xml_encoding encoding, bool is_mutable, bool own, char_t** out_buffer) - { - // check input buffer - if (!contents && size) return make_parse_result(status_io_error); - - // get actual encoding - xml_encoding buffer_encoding = impl::get_buffer_encoding(encoding, contents, size); - - // get private buffer - char_t* buffer = 0; - size_t length = 0; - - if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); - - // delete original buffer if we performed a conversion - if (own && buffer != contents && contents) impl::xml_memory::deallocate(contents); - - // store buffer for offset_debug - doc->buffer = buffer; - - // parse - xml_parse_result res = impl::xml_parser::parse(buffer, length, doc, root, options); - - // remember encoding - res.encoding = buffer_encoding; - - // grab onto buffer if it's our buffer, user is responsible for deallocating contents himself - if (own || buffer != contents) *out_buffer = buffer; - - return res; - } -PUGI__NS_END - -namespace pugi -{ - PUGI__FN xml_writer_file::xml_writer_file(void* file_): file(file_) - { - } - - PUGI__FN void xml_writer_file::write(const void* data, size_t size) - { - size_t result = fwrite(data, 1, size, static_cast(file)); - (void)!result; // unfortunately we can't do proper error handling here - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(&stream), wide_stream(0) - { - } - - PUGI__FN xml_writer_stream::xml_writer_stream(std::basic_ostream >& stream): narrow_stream(0), wide_stream(&stream) - { - } - - PUGI__FN void xml_writer_stream::write(const void* data, size_t size) - { - if (narrow_stream) - { - assert(!wide_stream); - narrow_stream->write(reinterpret_cast(data), static_cast(size)); - } - else - { - assert(wide_stream); - assert(size % sizeof(wchar_t) == 0); - - wide_stream->write(reinterpret_cast(data), static_cast(size / sizeof(wchar_t))); - } - } -#endif - - PUGI__FN xml_tree_walker::xml_tree_walker(): _depth(0) - { - } - - PUGI__FN xml_tree_walker::~xml_tree_walker() - { - } - - PUGI__FN int xml_tree_walker::depth() const - { - return _depth; - } - - PUGI__FN bool xml_tree_walker::begin(xml_node&) - { - return true; - } - - PUGI__FN bool xml_tree_walker::end(xml_node&) - { - return true; - } - - PUGI__FN xml_attribute::xml_attribute(): _attr(0) - { - } - - PUGI__FN xml_attribute::xml_attribute(xml_attribute_struct* attr): _attr(attr) - { - } - - PUGI__FN static void unspecified_bool_xml_attribute(xml_attribute***) - { - } - - PUGI__FN xml_attribute::operator xml_attribute::unspecified_bool_type() const - { - return _attr ? unspecified_bool_xml_attribute : 0; - } - - PUGI__FN bool xml_attribute::operator!() const - { - return !_attr; - } - - PUGI__FN bool xml_attribute::operator==(const xml_attribute& r) const - { - return (_attr == r._attr); - } - - PUGI__FN bool xml_attribute::operator!=(const xml_attribute& r) const - { - return (_attr != r._attr); - } - - PUGI__FN bool xml_attribute::operator<(const xml_attribute& r) const - { - return (_attr < r._attr); - } - - PUGI__FN bool xml_attribute::operator>(const xml_attribute& r) const - { - return (_attr > r._attr); - } - - PUGI__FN bool xml_attribute::operator<=(const xml_attribute& r) const - { - return (_attr <= r._attr); - } - - PUGI__FN bool xml_attribute::operator>=(const xml_attribute& r) const - { - return (_attr >= r._attr); - } - - PUGI__FN xml_attribute xml_attribute::next_attribute() const - { - return _attr ? xml_attribute(_attr->next_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_attribute::previous_attribute() const - { - return _attr && _attr->prev_attribute_c->next_attribute ? xml_attribute(_attr->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN const char_t* xml_attribute::as_string(const char_t* def) const - { - return (_attr && _attr->value) ? _attr->value : def; - } - - PUGI__FN int xml_attribute::as_int(int def) const - { - return impl::get_value_int(_attr ? _attr->value : 0, def); - } - - PUGI__FN unsigned int xml_attribute::as_uint(unsigned int def) const - { - return impl::get_value_uint(_attr ? _attr->value : 0, def); - } - - PUGI__FN double xml_attribute::as_double(double def) const - { - return impl::get_value_double(_attr ? _attr->value : 0, def); - } - - PUGI__FN float xml_attribute::as_float(float def) const - { - return impl::get_value_float(_attr ? _attr->value : 0, def); - } - - PUGI__FN bool xml_attribute::as_bool(bool def) const - { - return impl::get_value_bool(_attr ? _attr->value : 0, def); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_attribute::as_llong(long long def) const - { - return impl::get_value_llong(_attr ? _attr->value : 0, def); - } - - PUGI__FN unsigned long long xml_attribute::as_ullong(unsigned long long def) const - { - return impl::get_value_ullong(_attr ? _attr->value : 0, def); - } -#endif - - PUGI__FN bool xml_attribute::empty() const - { - return !_attr; - } - - PUGI__FN const char_t* xml_attribute::name() const - { - return (_attr && _attr->name) ? _attr->name : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_attribute::value() const - { - return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT(""); - } - - PUGI__FN size_t xml_attribute::hash_value() const - { - return static_cast(reinterpret_cast(_attr) / sizeof(xml_attribute_struct)); - } - - PUGI__FN xml_attribute_struct* xml_attribute::internal_object() const - { - return _attr; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(const char_t* rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned int rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(double rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(float rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(bool rhs) - { - set_value(rhs); - return *this; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_attribute& xml_attribute::operator=(long long rhs) - { - set_value(rhs); - return *this; - } - - PUGI__FN xml_attribute& xml_attribute::operator=(unsigned long long rhs) - { - set_value(rhs); - return *this; - } -#endif - - PUGI__FN bool xml_attribute::set_name(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->name, _attr->header, impl::xml_memory_page_name_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(const char_t* rhs) - { - if (!_attr) return false; - - return impl::strcpy_insitu(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(int rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(unsigned int rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(double rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(float rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(bool rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_attribute::set_value(long long rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } - - PUGI__FN bool xml_attribute::set_value(unsigned long long rhs) - { - if (!_attr) return false; - - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); - } -#endif - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_attribute& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node::xml_node(): _root(0) - { - } - - PUGI__FN xml_node::xml_node(xml_node_struct* p): _root(p) - { - } - - PUGI__FN static void unspecified_bool_xml_node(xml_node***) - { - } - - PUGI__FN xml_node::operator xml_node::unspecified_bool_type() const - { - return _root ? unspecified_bool_xml_node : 0; - } - - PUGI__FN bool xml_node::operator!() const - { - return !_root; - } - - PUGI__FN xml_node::iterator xml_node::begin() const - { - return iterator(_root ? _root->first_child : 0, _root); - } - - PUGI__FN xml_node::iterator xml_node::end() const - { - return iterator(0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_begin() const - { - return attribute_iterator(_root ? _root->first_attribute : 0, _root); - } - - PUGI__FN xml_node::attribute_iterator xml_node::attributes_end() const - { - return attribute_iterator(0, _root); - } - - PUGI__FN xml_object_range xml_node::children() const - { - return xml_object_range(begin(), end()); - } - - PUGI__FN xml_object_range xml_node::children(const char_t* name_) const - { - return xml_object_range(xml_named_node_iterator(child(name_)._root, _root, name_), xml_named_node_iterator(0, _root, name_)); - } - - PUGI__FN xml_object_range xml_node::attributes() const - { - return xml_object_range(attributes_begin(), attributes_end()); - } - - PUGI__FN bool xml_node::operator==(const xml_node& r) const - { - return (_root == r._root); - } - - PUGI__FN bool xml_node::operator!=(const xml_node& r) const - { - return (_root != r._root); - } - - PUGI__FN bool xml_node::operator<(const xml_node& r) const - { - return (_root < r._root); - } - - PUGI__FN bool xml_node::operator>(const xml_node& r) const - { - return (_root > r._root); - } - - PUGI__FN bool xml_node::operator<=(const xml_node& r) const - { - return (_root <= r._root); - } - - PUGI__FN bool xml_node::operator>=(const xml_node& r) const - { - return (_root >= r._root); - } - - PUGI__FN bool xml_node::empty() const - { - return !_root; - } - - PUGI__FN const char_t* xml_node::name() const - { - return (_root && _root->name) ? _root->name : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node_type xml_node::type() const - { - return _root ? PUGI__NODETYPE(_root) : node_null; - } - - PUGI__FN const char_t* xml_node::value() const - { - return (_root && _root->value) ? _root->value : PUGIXML_TEXT(""); - } - - PUGI__FN xml_node xml_node::child(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_attribute xml_node::attribute(const char_t* name_) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute_struct* i = _root->first_attribute; i; i = i->next_attribute) - if (i->name && impl::strequal(name_, i->name)) - return xml_attribute(i); - - return xml_attribute(); - } - - PUGI__FN xml_node xml_node::next_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->next_sibling; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_node xml_node::next_sibling() const - { - return _root ? xml_node(_root->next_sibling) : xml_node(); - } - - PUGI__FN xml_node xml_node::previous_sibling(const char_t* name_) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->prev_sibling_c; i->next_sibling; i = i->prev_sibling_c) - if (i->name && impl::strequal(name_, i->name)) return xml_node(i); - - return xml_node(); - } - - PUGI__FN xml_node xml_node::previous_sibling() const - { - if (!_root) return xml_node(); - - if (_root->prev_sibling_c->next_sibling) return xml_node(_root->prev_sibling_c); - else return xml_node(); - } - - PUGI__FN xml_node xml_node::parent() const - { - return _root ? xml_node(_root->parent) : xml_node(); - } - - PUGI__FN xml_node xml_node::root() const - { - return _root ? xml_node(&impl::get_document(_root)) : xml_node(); - } - - PUGI__FN xml_text xml_node::text() const - { - return xml_text(_root); - } - - PUGI__FN const char_t* xml_node::child_value() const - { - if (!_root) return PUGIXML_TEXT(""); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->value && impl::is_text_node(i)) - return i->value; - - return PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_node::child_value(const char_t* name_) const - { - return child(name_).child_value(); - } - - PUGI__FN xml_attribute xml_node::first_attribute() const - { - return _root ? xml_attribute(_root->first_attribute) : xml_attribute(); - } - - PUGI__FN xml_attribute xml_node::last_attribute() const - { - return _root && _root->first_attribute ? xml_attribute(_root->first_attribute->prev_attribute_c) : xml_attribute(); - } - - PUGI__FN xml_node xml_node::first_child() const - { - return _root ? xml_node(_root->first_child) : xml_node(); - } - - PUGI__FN xml_node xml_node::last_child() const - { - return _root && _root->first_child ? xml_node(_root->first_child->prev_sibling_c) : xml_node(); - } - - PUGI__FN bool xml_node::set_name(const char_t* rhs) - { - switch (type()) - { - case node_pi: - case node_declaration: - case node_element: - return impl::strcpy_insitu(_root->name, _root->header, impl::xml_memory_page_name_allocated_mask, rhs); - - default: - return false; - } - } - - PUGI__FN bool xml_node::set_value(const char_t* rhs) - { - switch (type()) - { - case node_pi: - case node_cdata: - case node_pcdata: - case node_comment: - case node_doctype: - return impl::strcpy_insitu(_root->value, _root->header, impl::xml_memory_page_value_allocated_mask, rhs); - - default: - return false; - } - } - - PUGI__FN xml_attribute xml_node::append_attribute(const char_t* name_) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - impl::append_attribute(a._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::prepend_attribute(const char_t* name_) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - impl::prepend_attribute(a._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_after(const char_t* name_, const xml_attribute& attr) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - impl::insert_attribute_after(a._attr, attr._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::insert_attribute_before(const char_t* name_, const xml_attribute& attr) - { - if (!impl::allow_insert_attribute(type())) return xml_attribute(); - if (!attr || !impl::is_attribute_of(attr._attr, _root)) return xml_attribute(); - - xml_attribute a(impl::allocate_attribute(impl::get_allocator(_root))); - if (!a) return xml_attribute(); - - impl::insert_attribute_before(a._attr, attr._attr, _root); - - a.set_name(name_); - - return a; - } - - PUGI__FN xml_attribute xml_node::append_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - - xml_attribute result = append_attribute(proto.name()); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::prepend_copy(const xml_attribute& proto) - { - if (!proto) return xml_attribute(); - - xml_attribute result = prepend_attribute(proto.name()); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::insert_copy_after(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - - xml_attribute result = insert_attribute_after(proto.name(), attr); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_attribute xml_node::insert_copy_before(const xml_attribute& proto, const xml_attribute& attr) - { - if (!proto) return xml_attribute(); - - xml_attribute result = insert_attribute_before(proto.name(), attr); - result.set_value(proto.value()); - - return result; - } - - PUGI__FN xml_node xml_node::append_child(xml_node_type type_) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::append_node(n._root, _root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::prepend_child(xml_node_type type_) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::prepend_node(n._root, _root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_before(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::insert_node_before(n._root, node._root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::insert_child_after(xml_node_type type_, const xml_node& node) - { - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::insert_node_after(n._root, node._root); - - if (type_ == node_declaration) n.set_name(PUGIXML_TEXT("xml")); - - return n; - } - - PUGI__FN xml_node xml_node::append_child(const char_t* name_) - { - xml_node result = append_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::prepend_child(const char_t* name_) - { - xml_node result = prepend_child(node_element); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_after(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_after(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::insert_child_before(const char_t* name_, const xml_node& node) - { - xml_node result = insert_child_before(node_element, node); - - result.set_name(name_); - - return result; - } - - PUGI__FN xml_node xml_node::append_copy(const xml_node& proto) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::append_node(n._root, _root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::prepend_copy(const xml_node& proto) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::prepend_node(n._root, _root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::insert_copy_after(const xml_node& proto, const xml_node& node) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::insert_node_after(n._root, node._root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::insert_copy_before(const xml_node& proto, const xml_node& node) - { - xml_node_type type_ = proto.type(); - if (!impl::allow_insert_child(type(), type_)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - - xml_node n(impl::allocate_node(impl::get_allocator(_root), type_)); - if (!n) return xml_node(); - - impl::insert_node_before(n._root, node._root); - impl::node_copy_tree(n._root, proto._root); - - return n; - } - - PUGI__FN xml_node xml_node::append_move(const xml_node& moved) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::append_node(moved._root, _root); - - return moved; - } - - PUGI__FN xml_node xml_node::prepend_move(const xml_node& moved) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::prepend_node(moved._root, _root); - - return moved; - } - - PUGI__FN xml_node xml_node::insert_move_after(const xml_node& moved, const xml_node& node) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - if (moved._root == node._root) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::insert_node_after(moved._root, node._root); - - return moved; - } - - PUGI__FN xml_node xml_node::insert_move_before(const xml_node& moved, const xml_node& node) - { - if (!impl::allow_move(*this, moved)) return xml_node(); - if (!node._root || node._root->parent != _root) return xml_node(); - if (moved._root == node._root) return xml_node(); - - // disable document_buffer_order optimization since moving nodes around changes document order without changing buffer pointers - impl::get_document(_root).header |= impl::xml_memory_page_contents_shared_mask; - - impl::remove_node(moved._root); - impl::insert_node_before(moved._root, node._root); - - return moved; - } - - PUGI__FN bool xml_node::remove_attribute(const char_t* name_) - { - return remove_attribute(attribute(name_)); - } - - PUGI__FN bool xml_node::remove_attribute(const xml_attribute& a) - { - if (!_root || !a._attr) return false; - if (!impl::is_attribute_of(a._attr, _root)) return false; - - impl::remove_attribute(a._attr, _root); - impl::destroy_attribute(a._attr, impl::get_allocator(_root)); - - return true; - } - - PUGI__FN bool xml_node::remove_child(const char_t* name_) - { - return remove_child(child(name_)); - } - - PUGI__FN bool xml_node::remove_child(const xml_node& n) - { - if (!_root || !n._root || n._root->parent != _root) return false; - - impl::remove_node(n._root); - impl::destroy_node(n._root, impl::get_allocator(_root)); - - return true; - } - - PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - // append_buffer is only valid for elements/documents - if (!impl::allow_insert_child(type(), node_element)) return impl::make_parse_result(status_append_invalid_root); - - // get document node - impl::xml_document_struct* doc = &impl::get_document(_root); - - // disable document_buffer_order optimization since in a document with multiple buffers comparing buffer pointers does not make sense - doc->header |= impl::xml_memory_page_contents_shared_mask; - - // get extra buffer element (we'll store the document fragment buffer there so that we can deallocate it later) - impl::xml_memory_page* page = 0; - impl::xml_extra_buffer* extra = static_cast(doc->allocate_memory(sizeof(impl::xml_extra_buffer), page)); - (void)page; - - if (!extra) return impl::make_parse_result(status_out_of_memory); - - // save name; name of the root has to be NULL before parsing - otherwise closing node mismatches will not be detected at the top level - char_t* rootname = _root->name; - _root->name = 0; - - // parse - char_t* buffer = 0; - xml_parse_result res = impl::load_buffer_impl(doc, _root, const_cast(contents), size, options, encoding, false, false, &buffer); - - // restore name - _root->name = rootname; - - // add extra buffer to the list - extra->buffer = buffer; - extra->next = doc->extra_buffers; - doc->extra_buffers = extra; - - return res; - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (i->name && impl::strequal(name_, i->name)) - { - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value : PUGIXML_TEXT(""))) - return xml_node(i); - } - - return xml_node(); - } - - PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const - { - if (!_root) return xml_node(); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - for (xml_attribute_struct* a = i->first_attribute; a; a = a->next_attribute) - if (a->name && impl::strequal(attr_name, a->name) && impl::strequal(attr_value, a->value ? a->value : PUGIXML_TEXT(""))) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN string_t xml_node::path(char_t delimiter) const - { - xml_node cursor = *this; // Make a copy. - - string_t result = cursor.name(); - - while (cursor.parent()) - { - cursor = cursor.parent(); - - string_t temp = cursor.name(); - temp += delimiter; - temp += result; - result.swap(temp); - } - - return result; - } -#endif - - PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const - { - xml_node found = *this; // Current search context. - - if (!_root || !path_ || !path_[0]) return found; - - if (path_[0] == delimiter) - { - // Absolute path; e.g. '/foo/bar' - found = found.root(); - ++path_; - } - - const char_t* path_segment = path_; - - while (*path_segment == delimiter) ++path_segment; - - const char_t* path_segment_end = path_segment; - - while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; - - if (path_segment == path_segment_end) return found; - - const char_t* next_segment = path_segment_end; - - while (*next_segment == delimiter) ++next_segment; - - if (*path_segment == '.' && path_segment + 1 == path_segment_end) - return found.first_element_by_path(next_segment, delimiter); - else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) - return found.parent().first_element_by_path(next_segment, delimiter); - else - { - for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) - { - if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) - { - xml_node subsearch = xml_node(j).first_element_by_path(next_segment, delimiter); - - if (subsearch) return subsearch; - } - } - - return xml_node(); - } - } - - PUGI__FN bool xml_node::traverse(xml_tree_walker& walker) - { - walker._depth = -1; - - xml_node arg_begin = *this; - if (!walker.begin(arg_begin)) return false; - - xml_node cur = first_child(); - - if (cur) - { - ++walker._depth; - - do - { - xml_node arg_for_each = cur; - if (!walker.for_each(arg_for_each)) - return false; - - if (cur.first_child()) - { - ++walker._depth; - cur = cur.first_child(); - } - else if (cur.next_sibling()) - cur = cur.next_sibling(); - else - { - // Borland C++ workaround - while (!cur.next_sibling() && cur != *this && !cur.parent().empty()) - { - --walker._depth; - cur = cur.parent(); - } - - if (cur != *this) - cur = cur.next_sibling(); - } - } - while (cur && cur != *this); - } - - assert(walker._depth == -1); - - xml_node arg_end = *this; - return walker.end(arg_end); - } - - PUGI__FN size_t xml_node::hash_value() const - { - return static_cast(reinterpret_cast(_root) / sizeof(xml_node_struct)); - } - - PUGI__FN xml_node_struct* xml_node::internal_object() const - { - return _root; - } - - PUGI__FN void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - if (!_root) return; - - impl::xml_buffered_writer buffered_writer(writer, encoding); - - impl::node_output(buffered_writer, _root, indent, flags, depth); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding, depth); - } - - PUGI__FN void xml_node::print(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, unsigned int depth) const - { - xml_writer_stream writer(stream); - - print(writer, indent, flags, encoding_wchar, depth); - } -#endif - - PUGI__FN ptrdiff_t xml_node::offset_debug() const - { - if (!_root) return -1; - - impl::xml_document_struct& doc = impl::get_document(_root); - - // we can determine the offset reliably only if there is exactly once parse buffer - if (!doc.buffer || doc.extra_buffers) return -1; - - switch (type()) - { - case node_document: - return 0; - - case node_element: - case node_declaration: - case node_pi: - return _root->name && (_root->header & impl::xml_memory_page_name_allocated_or_shared_mask) == 0 ? _root->name - doc.buffer : -1; - - case node_pcdata: - case node_cdata: - case node_comment: - case node_doctype: - return _root->value && (_root->header & impl::xml_memory_page_value_allocated_or_shared_mask) == 0 ? _root->value - doc.buffer : -1; - - default: - return -1; - } - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_node& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_node& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_text::xml_text(xml_node_struct* root): _root(root) - { - } - - PUGI__FN xml_node_struct* xml_text::_data() const - { - if (!_root || impl::is_text_node(_root)) return _root; - - for (xml_node_struct* node = _root->first_child; node; node = node->next_sibling) - if (impl::is_text_node(node)) - return node; - - return 0; - } - - PUGI__FN xml_node_struct* xml_text::_data_new() - { - xml_node_struct* d = _data(); - if (d) return d; - - return xml_node(_root).append_child(node_pcdata).internal_object(); - } - - PUGI__FN xml_text::xml_text(): _root(0) - { - } - - PUGI__FN static void unspecified_bool_xml_text(xml_text***) - { - } - - PUGI__FN xml_text::operator xml_text::unspecified_bool_type() const - { - return _data() ? unspecified_bool_xml_text : 0; - } - - PUGI__FN bool xml_text::operator!() const - { - return !_data(); - } - - PUGI__FN bool xml_text::empty() const - { - return _data() == 0; - } - - PUGI__FN const char_t* xml_text::get() const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value : PUGIXML_TEXT(""); - } - - PUGI__FN const char_t* xml_text::as_string(const char_t* def) const - { - xml_node_struct* d = _data(); - - return (d && d->value) ? d->value : def; - } - - PUGI__FN int xml_text::as_int(int def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_int(d ? d->value : 0, def); - } - - PUGI__FN unsigned int xml_text::as_uint(unsigned int def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_uint(d ? d->value : 0, def); - } - - PUGI__FN double xml_text::as_double(double def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_double(d ? d->value : 0, def); - } - - PUGI__FN float xml_text::as_float(float def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_float(d ? d->value : 0, def); - } - - PUGI__FN bool xml_text::as_bool(bool def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_bool(d ? d->value : 0, def); - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN long long xml_text::as_llong(long long def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_llong(d ? d->value : 0, def); - } - - PUGI__FN unsigned long long xml_text::as_ullong(unsigned long long def) const - { - xml_node_struct* d = _data(); - - return impl::get_value_ullong(d ? d->value : 0, def); - } -#endif - - PUGI__FN bool xml_text::set(const char_t* rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::strcpy_insitu(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(unsigned int rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(float rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(double rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(bool rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN bool xml_text::set(long long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } - - PUGI__FN bool xml_text::set(unsigned long long rhs) - { - xml_node_struct* dn = _data_new(); - - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; - } -#endif - - PUGI__FN xml_text& xml_text::operator=(const char_t* rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned int rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(double rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(float rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(bool rhs) - { - set(rhs); - return *this; - } - -#ifdef PUGIXML_HAS_LONG_LONG - PUGI__FN xml_text& xml_text::operator=(long long rhs) - { - set(rhs); - return *this; - } - - PUGI__FN xml_text& xml_text::operator=(unsigned long long rhs) - { - set(rhs); - return *this; - } -#endif - - PUGI__FN xml_node xml_text::data() const - { - return xml_node(_data()); - } - -#ifdef __BORLANDC__ - PUGI__FN bool operator&&(const xml_text& lhs, bool rhs) - { - return (bool)lhs && rhs; - } - - PUGI__FN bool operator||(const xml_text& lhs, bool rhs) - { - return (bool)lhs || rhs; - } -#endif - - PUGI__FN xml_node_iterator::xml_node_iterator() - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(const xml_node& node): _wrap(node), _parent(node.parent()) - { - } - - PUGI__FN xml_node_iterator::xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_node_iterator::operator==(const xml_node_iterator& rhs) const - { - return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_node_iterator::operator!=(const xml_node_iterator& rhs) const - { - return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_node& xml_node_iterator::operator*() const - { - assert(_wrap._root); - return _wrap; - } - - PUGI__FN xml_node* xml_node_iterator::operator->() const - { - assert(_wrap._root); - return const_cast(&_wrap); // BCC32 workaround - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator++() - { - assert(_wrap._root); - _wrap._root = _wrap._root->next_sibling; - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator++(int) - { - xml_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_node_iterator& xml_node_iterator::operator--() - { - _wrap = _wrap._root ? _wrap.previous_sibling() : _parent.last_child(); - return *this; - } - - PUGI__FN xml_node_iterator xml_node_iterator::operator--(int) - { - xml_node_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator() - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent): _wrap(attr), _parent(parent) - { - } - - PUGI__FN xml_attribute_iterator::xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent): _wrap(ref), _parent(parent) - { - } - - PUGI__FN bool xml_attribute_iterator::operator==(const xml_attribute_iterator& rhs) const - { - return _wrap._attr == rhs._wrap._attr && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_attribute_iterator::operator!=(const xml_attribute_iterator& rhs) const - { - return _wrap._attr != rhs._wrap._attr || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_attribute& xml_attribute_iterator::operator*() const - { - assert(_wrap._attr); - return _wrap; - } - - PUGI__FN xml_attribute* xml_attribute_iterator::operator->() const - { - assert(_wrap._attr); - return const_cast(&_wrap); // BCC32 workaround - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator++() - { - assert(_wrap._attr); - _wrap._attr = _wrap._attr->next_attribute; - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator++(int) - { - xml_attribute_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_attribute_iterator& xml_attribute_iterator::operator--() - { - _wrap = _wrap._attr ? _wrap.previous_attribute() : _parent.last_attribute(); - return *this; - } - - PUGI__FN xml_attribute_iterator xml_attribute_iterator::operator--(int) - { - xml_attribute_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(): _name(0) - { - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(const xml_node& node, const char_t* name): _wrap(node), _parent(node.parent()), _name(name) - { - } - - PUGI__FN xml_named_node_iterator::xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name): _wrap(ref), _parent(parent), _name(name) - { - } - - PUGI__FN bool xml_named_node_iterator::operator==(const xml_named_node_iterator& rhs) const - { - return _wrap._root == rhs._wrap._root && _parent._root == rhs._parent._root; - } - - PUGI__FN bool xml_named_node_iterator::operator!=(const xml_named_node_iterator& rhs) const - { - return _wrap._root != rhs._wrap._root || _parent._root != rhs._parent._root; - } - - PUGI__FN xml_node& xml_named_node_iterator::operator*() const - { - assert(_wrap._root); - return _wrap; - } - - PUGI__FN xml_node* xml_named_node_iterator::operator->() const - { - assert(_wrap._root); - return const_cast(&_wrap); // BCC32 workaround - } - - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator++() - { - assert(_wrap._root); - _wrap = _wrap.next_sibling(_name); - return *this; - } - - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator++(int) - { - xml_named_node_iterator temp = *this; - ++*this; - return temp; - } - - PUGI__FN const xml_named_node_iterator& xml_named_node_iterator::operator--() - { - if (_wrap._root) - _wrap = _wrap.previous_sibling(_name); - else - { - _wrap = _parent.last_child(); - - if (!impl::strequal(_wrap.name(), _name)) - _wrap = _wrap.previous_sibling(_name); - } - - return *this; - } - - PUGI__FN xml_named_node_iterator xml_named_node_iterator::operator--(int) - { - xml_named_node_iterator temp = *this; - --*this; - return temp; - } - - PUGI__FN xml_parse_result::xml_parse_result(): status(status_internal_error), offset(0), encoding(encoding_auto) - { - } - - PUGI__FN xml_parse_result::operator bool() const - { - return status == status_ok; - } - - PUGI__FN const char* xml_parse_result::description() const - { - switch (status) - { - case status_ok: return "No error"; - - case status_file_not_found: return "File was not found"; - case status_io_error: return "Error reading from file/stream"; - case status_out_of_memory: return "Could not allocate memory"; - case status_internal_error: return "Internal error occurred"; - - case status_unrecognized_tag: return "Could not determine tag type"; - - case status_bad_pi: return "Error parsing document declaration/processing instruction"; - case status_bad_comment: return "Error parsing comment"; - case status_bad_cdata: return "Error parsing CDATA section"; - case status_bad_doctype: return "Error parsing document type declaration"; - case status_bad_pcdata: return "Error parsing PCDATA section"; - case status_bad_start_element: return "Error parsing start element tag"; - case status_bad_attribute: return "Error parsing element attribute"; - case status_bad_end_element: return "Error parsing end element tag"; - case status_end_element_mismatch: return "Start-end tags mismatch"; - - case status_append_invalid_root: return "Unable to append nodes: root is not an element or document"; - - case status_no_document_element: return "No document element found"; - - default: return "Unknown error"; - } - } - - PUGI__FN xml_document::xml_document(): _buffer(0) - { - create(); - } - - PUGI__FN xml_document::~xml_document() - { - destroy(); - } - - PUGI__FN void xml_document::reset() - { - destroy(); - create(); - } - - PUGI__FN void xml_document::reset(const xml_document& proto) - { - reset(); - - for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) - append_copy(cur); - } - - PUGI__FN void xml_document::create() - { - assert(!_root); - - // initialize sentinel page - PUGI__STATIC_ASSERT(sizeof(impl::xml_memory_page) + sizeof(impl::xml_document_struct) + impl::xml_memory_page_alignment - sizeof(void*) <= sizeof(_memory)); - - // align upwards to page boundary - void* page_memory = reinterpret_cast((reinterpret_cast(_memory) + (impl::xml_memory_page_alignment - 1)) & ~(impl::xml_memory_page_alignment - 1)); - - // prepare page structure - impl::xml_memory_page* page = impl::xml_memory_page::construct(page_memory); - assert(page); - - page->busy_size = impl::xml_memory_page_size; - - // allocate new root - _root = new (reinterpret_cast(page) + sizeof(impl::xml_memory_page)) impl::xml_document_struct(page); - _root->prev_sibling_c = _root; - - // setup sentinel page - page->allocator = static_cast(_root); - - // verify the document allocation - assert(reinterpret_cast(_root) + sizeof(impl::xml_document_struct) <= _memory + sizeof(_memory)); - } - - PUGI__FN void xml_document::destroy() - { - assert(_root); - - // destroy static storage - if (_buffer) - { - impl::xml_memory::deallocate(_buffer); - _buffer = 0; - } - - // destroy extra buffers (note: no need to destroy linked list nodes, they're allocated using document allocator) - for (impl::xml_extra_buffer* extra = static_cast(_root)->extra_buffers; extra; extra = extra->next) - { - if (extra->buffer) impl::xml_memory::deallocate(extra->buffer); - } - - // destroy dynamic storage, leave sentinel page (it's in static memory) - impl::xml_memory_page* root_page = reinterpret_cast(_root->header & impl::xml_memory_page_pointer_mask); - assert(root_page && !root_page->prev); - assert(reinterpret_cast(root_page) >= _memory && reinterpret_cast(root_page) < _memory + sizeof(_memory)); - - for (impl::xml_memory_page* page = root_page->next; page; ) - { - impl::xml_memory_page* next = page->next; - - impl::xml_allocator::deallocate_page(page); - - page = next; - } - - _root = 0; - } - -#ifndef PUGIXML_NO_STL - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_stream_impl(*this, stream, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load(std::basic_istream >& stream, unsigned int options) - { - reset(); - - return impl::load_stream_impl(*this, stream, options, encoding_wchar); - } -#endif - - PUGI__FN xml_parse_result xml_document::load_string(const char_t* contents, unsigned int options) - { - // Force native encoding (skip autodetection) - #ifdef PUGIXML_WCHAR_MODE - xml_encoding encoding = encoding_wchar; - #else - xml_encoding encoding = encoding_utf8; - #endif - - return load_buffer(contents, impl::strlength(contents) * sizeof(char_t), options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load(const char_t* contents, unsigned int options) - { - return load_string(contents, options); - } - - PUGI__FN xml_parse_result xml_document::load_file(const char* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - FILE* file = fopen(path_, "rb"); - - return impl::load_file_impl(*this, file, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load_file(const wchar_t* path_, unsigned int options, xml_encoding encoding) - { - reset(); - - FILE* file = impl::open_file_wide(path_, L"rb"); - - return impl::load_file_impl(*this, file, options, encoding); - } - - PUGI__FN xml_parse_result xml_document::load_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, const_cast(contents), size, options, encoding, false, false, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, false, &_buffer); - } - - PUGI__FN xml_parse_result xml_document::load_buffer_inplace_own(void* contents, size_t size, unsigned int options, xml_encoding encoding) - { - reset(); - - return impl::load_buffer_impl(static_cast(_root), _root, contents, size, options, encoding, true, true, &_buffer); - } - - PUGI__FN void xml_document::save(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - impl::xml_buffered_writer buffered_writer(writer, encoding); - - if ((flags & format_write_bom) && encoding != encoding_latin1) - { - // BOM always represents the codepoint U+FEFF, so just write it in native encoding - #ifdef PUGIXML_WCHAR_MODE - unsigned int bom = 0xfeff; - buffered_writer.write(static_cast(bom)); - #else - buffered_writer.write('\xef', '\xbb', '\xbf'); - #endif - } - - if (!(flags & format_no_declaration) && !impl::has_declaration(_root)) - { - buffered_writer.write_string(PUGIXML_TEXT("'); - if (!(flags & format_raw)) buffered_writer.write('\n'); - } - - impl::node_output(buffered_writer, _root, indent, flags, 0); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding); - } - - PUGI__FN void xml_document::save(std::basic_ostream >& stream, const char_t* indent, unsigned int flags) const - { - xml_writer_stream writer(stream); - - save(writer, indent, flags, encoding_wchar); - } -#endif - - PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - FILE* file = fopen(path_, (flags & format_save_file_text) ? "w" : "wb"); - return impl::save_file_impl(*this, file, indent, flags, encoding); - } - - PUGI__FN bool xml_document::save_file(const wchar_t* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const - { - FILE* file = impl::open_file_wide(path_, (flags & format_save_file_text) ? L"w" : L"wb"); - return impl::save_file_impl(*this, file, indent, flags, encoding); - } - - PUGI__FN xml_node xml_document::document_element() const - { - assert(_root); - - for (xml_node_struct* i = _root->first_child; i; i = i->next_sibling) - if (PUGI__NODETYPE(i) == node_element) - return xml_node(i); - - return xml_node(); - } - -#ifndef PUGIXML_NO_STL - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const wchar_t* str) - { - assert(str); - - return impl::as_utf8_impl(str, impl::strlength_wide(str)); - } - - PUGI__FN std::string PUGIXML_FUNCTION as_utf8(const std::basic_string& str) - { - return impl::as_utf8_impl(str.c_str(), str.size()); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const char* str) - { - assert(str); - - return impl::as_wide_impl(str, strlen(str)); - } - - PUGI__FN std::basic_string PUGIXML_FUNCTION as_wide(const std::string& str) - { - return impl::as_wide_impl(str.c_str(), str.size()); - } -#endif - - PUGI__FN void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate) - { - impl::xml_memory::allocate = allocate; - impl::xml_memory::deallocate = deallocate; - } - - PUGI__FN allocation_function PUGIXML_FUNCTION get_memory_allocation_function() - { - return impl::xml_memory::allocate; - } - - PUGI__FN deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function() - { - return impl::xml_memory::deallocate; - } -} - -#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag _Iter_cat(const pugi::xml_named_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_attribute_iterator&) - { - return std::bidirectional_iterator_tag(); - } - - PUGI__FN std::bidirectional_iterator_tag __iterator_category(const pugi::xml_named_node_iterator&) - { - return std::bidirectional_iterator_tag(); - } -} -#endif - -#ifdef __BORLANDC__ -# pragma option pop -#endif - -// Intel C++ does not properly keep warning state for function templates, -// so popping warning state at the end of translation unit leads to warnings in the middle. -#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) -# pragma warning(pop) -#endif - -// Undefine all local macros (makes sure we're not leaking macros in header-only mode) -#undef PUGI__NO_INLINE -#undef PUGI__UNLIKELY -#undef PUGI__STATIC_ASSERT -#undef PUGI__DMC_VOLATILE -#undef PUGI__MSVC_CRT_VERSION -#undef PUGI__NS_BEGIN -#undef PUGI__NS_END -#undef PUGI__FN -#undef PUGI__FN_NO_INLINE -#undef PUGI__NODETYPE -#undef PUGI__IS_CHARTYPE_IMPL -#undef PUGI__IS_CHARTYPE -#undef PUGI__IS_CHARTYPEX -#undef PUGI__ENDSWITH -#undef PUGI__SKIPWS -#undef PUGI__OPTSET -#undef PUGI__PUSHNODE -#undef PUGI__POPNODE -#undef PUGI__SCANFOR -#undef PUGI__SCANWHILE -#undef PUGI__SCANWHILE_UNROLL -#undef PUGI__ENDSEG -#undef PUGI__THROW_ERROR -#undef PUGI__CHECK_ERROR - -#endif - -/** - * Copyright (c) 2006-2015 Arseny Kapoulkine - * - * 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/path_10_8/src/ext/pugixml.hpp b/path_10_8/src/ext/pugixml.hpp deleted file mode 100644 index ff35adf51..000000000 --- a/path_10_8/src/ext/pugixml.hpp +++ /dev/null @@ -1,1053 +0,0 @@ -/** - * pugixml parser - version 1.6 - * -------------------------------------------------------- - * Copyright (C) 2006-2015, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ - * - * This library is distributed under the MIT License. See notice at the end - * of this file. - * - * This work is based on the pugxml parser, which is: - * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) - */ - -#ifndef PUGIXML_VERSION -// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -# define PUGIXML_VERSION 160 -#endif - -// Include user configuration file (this can define various configuration macros) -#include "pugiconfig.hpp" - -#ifndef HEADER_PUGIXML_HPP -#define HEADER_PUGIXML_HPP - -// Include stddef.h for size_t and ptrdiff_t -#include - -// Include STL headers -#ifndef PUGIXML_NO_STL -# include -# include -# include -#endif - -// Macro for deprecated features -#ifndef PUGIXML_DEPRECATED -# if defined(__GNUC__) -# define PUGIXML_DEPRECATED __attribute__((deprecated)) -# elif defined(_MSC_VER) && _MSC_VER >= 1300 -# define PUGIXML_DEPRECATED __declspec(deprecated) -# else -# define PUGIXML_DEPRECATED -# endif -#endif - -// If no API is defined, assume default -#ifndef PUGIXML_API -# define PUGIXML_API -#endif - -// If no API for classes is defined, assume default -#ifndef PUGIXML_CLASS -# define PUGIXML_CLASS PUGIXML_API -#endif - -// If no API for functions is defined, assume default -#ifndef PUGIXML_FUNCTION -# define PUGIXML_FUNCTION PUGIXML_API -#endif - -// If the platform is known to have long long support, enable long long functions -#ifndef PUGIXML_HAS_LONG_LONG -# if defined(__cplusplus) && __cplusplus >= 201103 -# define PUGIXML_HAS_LONG_LONG -# elif defined(_MSC_VER) && _MSC_VER >= 1400 -# define PUGIXML_HAS_LONG_LONG -# endif -#endif - -// Character interface macros -#ifdef PUGIXML_WCHAR_MODE -# define PUGIXML_TEXT(t) L ## t -# define PUGIXML_CHAR wchar_t -#else -# define PUGIXML_TEXT(t) t -# define PUGIXML_CHAR char -#endif - -namespace pugi -{ - // Character type used for all internal storage and operations; depends on PUGIXML_WCHAR_MODE - typedef PUGIXML_CHAR char_t; - -#ifndef PUGIXML_NO_STL - // String type used for operations that work with STL string; depends on PUGIXML_WCHAR_MODE - typedef std::basic_string, std::allocator > string_t; -#endif -} - -// The PugiXML namespace -namespace pugi -{ - // Tree node types - enum xml_node_type - { - node_null, // Empty (null) node handle - node_document, // A document tree's absolute root - node_element, // Element tag, i.e. '' - node_pcdata, // Plain character data, i.e. 'text' - node_cdata, // Character data, i.e. '' - node_comment, // Comment tag, i.e. '' - node_pi, // Processing instruction, i.e. '' - node_declaration, // Document declaration, i.e. '' - node_doctype // Document type declaration, i.e. '' - }; - - // Parsing options - - // Minimal parsing mode (equivalent to turning all other flags off). - // Only elements and PCDATA sections are added to the DOM tree, no text conversions are performed. - const unsigned int parse_minimal = 0x0000; - - // This flag determines if processing instructions (node_pi) are added to the DOM tree. This flag is off by default. - const unsigned int parse_pi = 0x0001; - - // This flag determines if comments (node_comment) are added to the DOM tree. This flag is off by default. - const unsigned int parse_comments = 0x0002; - - // This flag determines if CDATA sections (node_cdata) are added to the DOM tree. This flag is on by default. - const unsigned int parse_cdata = 0x0004; - - // This flag determines if plain character data (node_pcdata) that consist only of whitespace are added to the DOM tree. - // This flag is off by default; turning it on usually results in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata = 0x0008; - - // This flag determines if character and entity references are expanded during parsing. This flag is on by default. - const unsigned int parse_escapes = 0x0010; - - // This flag determines if EOL characters are normalized (converted to #xA) during parsing. This flag is on by default. - const unsigned int parse_eol = 0x0020; - - // This flag determines if attribute values are normalized using CDATA normalization rules during parsing. This flag is on by default. - const unsigned int parse_wconv_attribute = 0x0040; - - // This flag determines if attribute values are normalized using NMTOKENS normalization rules during parsing. This flag is off by default. - const unsigned int parse_wnorm_attribute = 0x0080; - - // This flag determines if document declaration (node_declaration) is added to the DOM tree. This flag is off by default. - const unsigned int parse_declaration = 0x0100; - - // This flag determines if document type declaration (node_doctype) is added to the DOM tree. This flag is off by default. - const unsigned int parse_doctype = 0x0200; - - // This flag determines if plain character data (node_pcdata) that is the only child of the parent node and that consists only - // of whitespace is added to the DOM tree. - // This flag is off by default; turning it on may result in slower parsing and more memory consumption. - const unsigned int parse_ws_pcdata_single = 0x0400; - - // This flag determines if leading and trailing whitespace is to be removed from plain character data. This flag is off by default. - const unsigned int parse_trim_pcdata = 0x0800; - - // This flag determines if plain character data that does not have a parent node is added to the DOM tree, and if an empty document - // is a valid document. This flag is off by default. - const unsigned int parse_fragment = 0x1000; - - // The default parsing mode. - // Elements, PCDATA and CDATA sections are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_default = parse_cdata | parse_escapes | parse_wconv_attribute | parse_eol; - - // The full parsing mode. - // Nodes of all types are added to the DOM tree, character/reference entities are expanded, - // End-of-Line characters are normalized, attribute values are normalized using CDATA normalization rules. - const unsigned int parse_full = parse_default | parse_pi | parse_comments | parse_declaration | parse_doctype; - - // These flags determine the encoding of input data for XML document - enum xml_encoding - { - encoding_auto, // Auto-detect input encoding using BOM or < / class xml_object_range - { - public: - typedef It const_iterator; - typedef It iterator; - - xml_object_range(It b, It e): _begin(b), _end(e) - { - } - - It begin() const { return _begin; } - It end() const { return _end; } - - private: - It _begin, _end; - }; - - // Writer interface for node printing (see xml_node::print) - class PUGIXML_CLASS xml_writer - { - public: - virtual ~xml_writer() {} - - // Write memory chunk into stream/file/whatever - virtual void write(const void* data, size_t size) = 0; - }; - - // xml_writer implementation for FILE* - class PUGIXML_CLASS xml_writer_file: public xml_writer - { - public: - // Construct writer from a FILE* object; void* is used to avoid header dependencies on stdio - xml_writer_file(void* file); - - virtual void write(const void* data, size_t size); - - private: - void* file; - }; - - #ifndef PUGIXML_NO_STL - // xml_writer implementation for streams - class PUGIXML_CLASS xml_writer_stream: public xml_writer - { - public: - // Construct writer from an output stream object - xml_writer_stream(std::basic_ostream >& stream); - xml_writer_stream(std::basic_ostream >& stream); - - virtual void write(const void* data, size_t size); - - private: - std::basic_ostream >* narrow_stream; - std::basic_ostream >* wide_stream; - }; - #endif - - // A light-weight handle for manipulating attributes in DOM tree - class PUGIXML_CLASS xml_attribute - { - friend class xml_attribute_iterator; - friend class xml_node; - - private: - xml_attribute_struct* _attr; - - typedef void (*unspecified_bool_type)(xml_attribute***); - - public: - // Default constructor. Constructs an empty attribute. - xml_attribute(); - - // Constructs attribute from internal pointer - explicit xml_attribute(xml_attribute_struct* attr); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped attribute pointers) - bool operator==(const xml_attribute& r) const; - bool operator!=(const xml_attribute& r) const; - bool operator<(const xml_attribute& r) const; - bool operator>(const xml_attribute& r) const; - bool operator<=(const xml_attribute& r) const; - bool operator>=(const xml_attribute& r) const; - - // Check if attribute is empty - bool empty() const; - - // Get attribute name/value, or "" if attribute is empty - const char_t* name() const; - const char_t* value() const; - - // Get attribute value, or the default value if attribute is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get attribute value as a number, or the default value if conversion did not succeed or attribute is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get attribute value as bool (returns true if first character is in '1tTyY' set), or the default value if attribute is empty - bool as_bool(bool def = false) const; - - // Set attribute name/value (returns false if attribute is empty or there is not enough memory) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Set attribute value with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set_value(int rhs); - bool set_value(unsigned int rhs); - bool set_value(double rhs); - bool set_value(float rhs); - bool set_value(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set_value(long long rhs); - bool set_value(unsigned long long rhs); - #endif - - // Set attribute value (equivalent to set_value without error checking) - xml_attribute& operator=(const char_t* rhs); - xml_attribute& operator=(int rhs); - xml_attribute& operator=(unsigned int rhs); - xml_attribute& operator=(double rhs); - xml_attribute& operator=(float rhs); - xml_attribute& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_attribute& operator=(long long rhs); - xml_attribute& operator=(unsigned long long rhs); - #endif - - // Get next/previous attribute in the attribute list of the parent node - xml_attribute next_attribute() const; - xml_attribute previous_attribute() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_attribute_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_attribute& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_attribute& lhs, bool rhs); -#endif - - // A light-weight handle for manipulating nodes in DOM tree - class PUGIXML_CLASS xml_node - { - friend class xml_attribute_iterator; - friend class xml_node_iterator; - friend class xml_named_node_iterator; - - protected: - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_node***); - - public: - // Default constructor. Constructs an empty node. - xml_node(); - - // Constructs node from internal pointer - explicit xml_node(xml_node_struct* p); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Comparison operators (compares wrapped node pointers) - bool operator==(const xml_node& r) const; - bool operator!=(const xml_node& r) const; - bool operator<(const xml_node& r) const; - bool operator>(const xml_node& r) const; - bool operator<=(const xml_node& r) const; - bool operator>=(const xml_node& r) const; - - // Check if node is empty. - bool empty() const; - - // Get node type - xml_node_type type() const; - - // Get node name, or "" if node is empty or it has no name - const char_t* name() const; - - // Get node value, or "" if node is empty or it has no value - // Note: For text node.value() does not return "text"! Use child_value() or text() methods to access text inside nodes. - const char_t* value() const; - - // Get attribute list - xml_attribute first_attribute() const; - xml_attribute last_attribute() const; - - // Get children list - xml_node first_child() const; - xml_node last_child() const; - - // Get next/previous sibling in the children list of the parent node - xml_node next_sibling() const; - xml_node previous_sibling() const; - - // Get parent node - xml_node parent() const; - - // Get root of DOM tree this node belongs to - xml_node root() const; - - // Get text object for the current node - xml_text text() const; - - // Get child, attribute or next/previous sibling with the specified name - xml_node child(const char_t* name) const; - xml_attribute attribute(const char_t* name) const; - xml_node next_sibling(const char_t* name) const; - xml_node previous_sibling(const char_t* name) const; - - // Get child value of current node; that is, value of the first child node of type PCDATA/CDATA - const char_t* child_value() const; - - // Get child value of child with specified name. Equivalent to child(name).child_value(). - const char_t* child_value(const char_t* name) const; - - // Set node name/value (returns false if node is empty, there is not enough memory, or node can not have name/value) - bool set_name(const char_t* rhs); - bool set_value(const char_t* rhs); - - // Add attribute with specified name. Returns added attribute, or empty attribute on errors. - xml_attribute append_attribute(const char_t* name); - xml_attribute prepend_attribute(const char_t* name); - xml_attribute insert_attribute_after(const char_t* name, const xml_attribute& attr); - xml_attribute insert_attribute_before(const char_t* name, const xml_attribute& attr); - - // Add a copy of the specified attribute. Returns added attribute, or empty attribute on errors. - xml_attribute append_copy(const xml_attribute& proto); - xml_attribute prepend_copy(const xml_attribute& proto); - xml_attribute insert_copy_after(const xml_attribute& proto, const xml_attribute& attr); - xml_attribute insert_copy_before(const xml_attribute& proto, const xml_attribute& attr); - - // Add child node with specified type. Returns added node, or empty node on errors. - xml_node append_child(xml_node_type type = node_element); - xml_node prepend_child(xml_node_type type = node_element); - xml_node insert_child_after(xml_node_type type, const xml_node& node); - xml_node insert_child_before(xml_node_type type, const xml_node& node); - - // Add child element with specified name. Returns added node, or empty node on errors. - xml_node append_child(const char_t* name); - xml_node prepend_child(const char_t* name); - xml_node insert_child_after(const char_t* name, const xml_node& node); - xml_node insert_child_before(const char_t* name, const xml_node& node); - - // Add a copy of the specified node as a child. Returns added node, or empty node on errors. - xml_node append_copy(const xml_node& proto); - xml_node prepend_copy(const xml_node& proto); - xml_node insert_copy_after(const xml_node& proto, const xml_node& node); - xml_node insert_copy_before(const xml_node& proto, const xml_node& node); - - // Move the specified node to become a child of this node. Returns moved node, or empty node on errors. - xml_node append_move(const xml_node& moved); - xml_node prepend_move(const xml_node& moved); - xml_node insert_move_after(const xml_node& moved, const xml_node& node); - xml_node insert_move_before(const xml_node& moved, const xml_node& node); - - // Remove specified attribute - bool remove_attribute(const xml_attribute& a); - bool remove_attribute(const char_t* name); - - // Remove specified child - bool remove_child(const xml_node& n); - bool remove_child(const char_t* name); - - // Parses buffer as an XML document fragment and appends all nodes as children of the current node. - // Copies/converts the buffer, so it may be deleted or changed after the function returns. - // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. - xml_parse_result append_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Find attribute using predicate. Returns first attribute for which predicate returned true. - template xml_attribute find_attribute(Predicate pred) const - { - if (!_root) return xml_attribute(); - - for (xml_attribute attrib = first_attribute(); attrib; attrib = attrib.next_attribute()) - if (pred(attrib)) - return attrib; - - return xml_attribute(); - } - - // Find child node using predicate. Returns first child for which predicate returned true. - template xml_node find_child(Predicate pred) const - { - if (!_root) return xml_node(); - - for (xml_node node = first_child(); node; node = node.next_sibling()) - if (pred(node)) - return node; - - return xml_node(); - } - - // Find node from subtree using predicate. Returns first node from subtree (depth-first), for which predicate returned true. - template xml_node find_node(Predicate pred) const - { - if (!_root) return xml_node(); - - xml_node cur = first_child(); - - while (cur._root && cur._root != _root) - { - if (pred(cur)) return cur; - - if (cur.first_child()) cur = cur.first_child(); - else if (cur.next_sibling()) cur = cur.next_sibling(); - else - { - while (!cur.next_sibling() && cur._root != _root) cur = cur.parent(); - - if (cur._root != _root) cur = cur.next_sibling(); - } - } - - return xml_node(); - } - - // Find child node by attribute name/value - xml_node find_child_by_attribute(const char_t* name, const char_t* attr_name, const char_t* attr_value) const; - xml_node find_child_by_attribute(const char_t* attr_name, const char_t* attr_value) const; - - #ifndef PUGIXML_NO_STL - // Get the absolute node path from root as a text string. - string_t path(char_t delimiter = '/') const; - #endif - - // Search for a node by path consisting of node names and . or .. elements. - xml_node first_element_by_path(const char_t* path, char_t delimiter = '/') const; - - // Recursively traverse subtree with xml_tree_walker - bool traverse(xml_tree_walker& walker); - - // Print subtree using a writer object - void print(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - - #ifndef PUGIXML_NO_STL - // Print subtree to stream - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto, unsigned int depth = 0) const; - void print(std::basic_ostream >& os, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, unsigned int depth = 0) const; - #endif - - // Child nodes iterators - typedef xml_node_iterator iterator; - - iterator begin() const; - iterator end() const; - - // Attribute iterators - typedef xml_attribute_iterator attribute_iterator; - - attribute_iterator attributes_begin() const; - attribute_iterator attributes_end() const; - - // Range-based for support - xml_object_range children() const; - xml_object_range children(const char_t* name) const; - xml_object_range attributes() const; - - // Get node offset in parsed file/string (in char_t units) for debugging purposes - ptrdiff_t offset_debug() const; - - // Get hash value (unique for handles to the same object) - size_t hash_value() const; - - // Get internal pointer - xml_node_struct* internal_object() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_node& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_node& lhs, bool rhs); -#endif - - // A helper for working with text inside PCDATA nodes - class PUGIXML_CLASS xml_text - { - friend class xml_node; - - xml_node_struct* _root; - - typedef void (*unspecified_bool_type)(xml_text***); - - explicit xml_text(xml_node_struct* root); - - xml_node_struct* _data_new(); - xml_node_struct* _data() const; - - public: - // Default constructor. Constructs an empty object. - xml_text(); - - // Safe bool conversion operator - operator unspecified_bool_type() const; - - // Borland C++ workaround - bool operator!() const; - - // Check if text object is empty - bool empty() const; - - // Get text, or "" if object is empty - const char_t* get() const; - - // Get text, or the default value if object is empty - const char_t* as_string(const char_t* def = PUGIXML_TEXT("")) const; - - // Get text as a number, or the default value if conversion did not succeed or object is empty - int as_int(int def = 0) const; - unsigned int as_uint(unsigned int def = 0) const; - double as_double(double def = 0) const; - float as_float(float def = 0) const; - - #ifdef PUGIXML_HAS_LONG_LONG - long long as_llong(long long def = 0) const; - unsigned long long as_ullong(unsigned long long def = 0) const; - #endif - - // Get text as bool (returns true if first character is in '1tTyY' set), or the default value if object is empty - bool as_bool(bool def = false) const; - - // Set text (returns false if object is empty or there is not enough memory) - bool set(const char_t* rhs); - - // Set text with type conversion (numbers are converted to strings, boolean is converted to "true"/"false") - bool set(int rhs); - bool set(unsigned int rhs); - bool set(double rhs); - bool set(float rhs); - bool set(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - bool set(long long rhs); - bool set(unsigned long long rhs); - #endif - - // Set text (equivalent to set without error checking) - xml_text& operator=(const char_t* rhs); - xml_text& operator=(int rhs); - xml_text& operator=(unsigned int rhs); - xml_text& operator=(double rhs); - xml_text& operator=(float rhs); - xml_text& operator=(bool rhs); - - #ifdef PUGIXML_HAS_LONG_LONG - xml_text& operator=(long long rhs); - xml_text& operator=(unsigned long long rhs); - #endif - - // Get the data node (node_pcdata or node_cdata) for this object - xml_node data() const; - }; - -#ifdef __BORLANDC__ - // Borland C++ workaround - bool PUGIXML_FUNCTION operator&&(const xml_text& lhs, bool rhs); - bool PUGIXML_FUNCTION operator||(const xml_text& lhs, bool rhs); -#endif - - // Child node iterator (a bidirectional iterator over a collection of xml_node) - class PUGIXML_CLASS xml_node_iterator - { - friend class xml_node; - - private: - mutable xml_node _wrap; - xml_node _parent; - - xml_node_iterator(xml_node_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_node_iterator(); - - // Construct an iterator which points to the specified node - xml_node_iterator(const xml_node& node); - - // Iterator operators - bool operator==(const xml_node_iterator& rhs) const; - bool operator!=(const xml_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_node_iterator& operator++(); - xml_node_iterator operator++(int); - - const xml_node_iterator& operator--(); - xml_node_iterator operator--(int); - }; - - // Attribute iterator (a bidirectional iterator over a collection of xml_attribute) - class PUGIXML_CLASS xml_attribute_iterator - { - friend class xml_node; - - private: - mutable xml_attribute _wrap; - xml_node _parent; - - xml_attribute_iterator(xml_attribute_struct* ref, xml_node_struct* parent); - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_attribute value_type; - typedef xml_attribute* pointer; - typedef xml_attribute& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_attribute_iterator(); - - // Construct an iterator which points to the specified attribute - xml_attribute_iterator(const xml_attribute& attr, const xml_node& parent); - - // Iterator operators - bool operator==(const xml_attribute_iterator& rhs) const; - bool operator!=(const xml_attribute_iterator& rhs) const; - - xml_attribute& operator*() const; - xml_attribute* operator->() const; - - const xml_attribute_iterator& operator++(); - xml_attribute_iterator operator++(int); - - const xml_attribute_iterator& operator--(); - xml_attribute_iterator operator--(int); - }; - - // Named node range helper - class PUGIXML_CLASS xml_named_node_iterator - { - friend class xml_node; - - public: - // Iterator traits - typedef ptrdiff_t difference_type; - typedef xml_node value_type; - typedef xml_node* pointer; - typedef xml_node& reference; - - #ifndef PUGIXML_NO_STL - typedef std::bidirectional_iterator_tag iterator_category; - #endif - - // Default constructor - xml_named_node_iterator(); - - // Construct an iterator which points to the specified node - xml_named_node_iterator(const xml_node& node, const char_t* name); - - // Iterator operators - bool operator==(const xml_named_node_iterator& rhs) const; - bool operator!=(const xml_named_node_iterator& rhs) const; - - xml_node& operator*() const; - xml_node* operator->() const; - - const xml_named_node_iterator& operator++(); - xml_named_node_iterator operator++(int); - - const xml_named_node_iterator& operator--(); - xml_named_node_iterator operator--(int); - - private: - mutable xml_node _wrap; - xml_node _parent; - const char_t* _name; - - xml_named_node_iterator(xml_node_struct* ref, xml_node_struct* parent, const char_t* name); - }; - - // Abstract tree walker class (see xml_node::traverse) - class PUGIXML_CLASS xml_tree_walker - { - friend class xml_node; - - private: - int _depth; - - protected: - // Get current traversal depth - int depth() const; - - public: - xml_tree_walker(); - virtual ~xml_tree_walker(); - - // Callback that is called when traversal begins - virtual bool begin(xml_node& node); - - // Callback that is called for each node traversed - virtual bool for_each(xml_node& node) = 0; - - // Callback that is called when traversal ends - virtual bool end(xml_node& node); - }; - - // Parsing status, returned as part of xml_parse_result object - enum xml_parse_status - { - status_ok = 0, // No error - - status_file_not_found, // File was not found during load_file() - status_io_error, // Error reading from file/stream - status_out_of_memory, // Could not allocate memory - status_internal_error, // Internal error occurred - - status_unrecognized_tag, // Parser could not determine tag type - - status_bad_pi, // Parsing error occurred while parsing document declaration/processing instruction - status_bad_comment, // Parsing error occurred while parsing comment - status_bad_cdata, // Parsing error occurred while parsing CDATA section - status_bad_doctype, // Parsing error occurred while parsing document type declaration - status_bad_pcdata, // Parsing error occurred while parsing PCDATA section - status_bad_start_element, // Parsing error occurred while parsing start element tag - status_bad_attribute, // Parsing error occurred while parsing element attribute - status_bad_end_element, // Parsing error occurred while parsing end element tag - status_end_element_mismatch,// There was a mismatch of start-end tags (closing tag had incorrect name, some tag was not closed or there was an excessive closing tag) - - status_append_invalid_root, // Unable to append nodes since root type is not node_element or node_document (exclusive to xml_node::append_buffer) - - status_no_document_element // Parsing resulted in a document without element nodes - }; - - // Parsing result - struct PUGIXML_CLASS xml_parse_result - { - // Parsing status (see xml_parse_status) - xml_parse_status status; - - // Last parsed offset (in char_t units from start of input data) - ptrdiff_t offset; - - // Source document encoding - xml_encoding encoding; - - // Default constructor, initializes object to failed state - xml_parse_result(); - - // Cast to bool operator - operator bool() const; - - // Get error description - const char* description() const; - }; - - // Document class (DOM tree root) - class PUGIXML_CLASS xml_document: public xml_node - { - private: - char_t* _buffer; - - char _memory[192]; - - // Non-copyable semantics - xml_document(const xml_document&); - const xml_document& operator=(const xml_document&); - - void create(); - void destroy(); - - public: - // Default constructor, makes empty document - xml_document(); - - // Destructor, invalidates all node/attribute handles to this document - ~xml_document(); - - // Removes all nodes, leaving the empty document - void reset(); - - // Removes all nodes, then copies the entire contents of the specified document - void reset(const xml_document& proto); - - #ifndef PUGIXML_NO_STL - // Load document from stream. - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load(std::basic_istream >& stream, unsigned int options = parse_default); - #endif - - // (deprecated: use load_string instead) Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load(const char_t* contents, unsigned int options = parse_default); - - // Load document from zero-terminated string. No encoding conversions are applied. - xml_parse_result load_string(const char_t* contents, unsigned int options = parse_default); - - // Load document from file - xml_parse_result load_file(const char* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - xml_parse_result load_file(const wchar_t* path, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer. Copies/converts the buffer, so it may be deleted or changed after the function returns. - xml_parse_result load_buffer(const void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should ensure that buffer data will persist throughout the document's lifetime, and free the buffer memory manually once document is destroyed. - xml_parse_result load_buffer_inplace(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Load document from buffer, using the buffer for in-place parsing (the buffer is modified and used for storage of document data). - // You should allocate the buffer with pugixml allocation function; document will free the buffer when it is no longer needed (you can't use it anymore). - xml_parse_result load_buffer_inplace_own(void* contents, size_t size, unsigned int options = parse_default, xml_encoding encoding = encoding_auto); - - // Save XML document to writer (semantics is slightly different from xml_node::print, see documentation for details). - void save(xml_writer& writer, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - #ifndef PUGIXML_NO_STL - // Save XML document to stream (semantics is slightly different from xml_node::print, see documentation for details). - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - void save(std::basic_ostream >& stream, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default) const; - #endif - - // Save XML to file - bool save_file(const char* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - bool save_file(const wchar_t* path, const char_t* indent = PUGIXML_TEXT("\t"), unsigned int flags = format_default, xml_encoding encoding = encoding_auto) const; - - // Get document element - xml_node document_element() const; - }; - -#ifndef PUGIXML_NO_STL - // Convert wide string to UTF8 - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const wchar_t* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_utf8(const std::basic_string, std::allocator >& str); - - // Convert UTF8 to wide string - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const char* str); - std::basic_string, std::allocator > PUGIXML_FUNCTION as_wide(const std::basic_string, std::allocator >& str); -#endif - - // Memory allocation function interface; returns pointer to allocated memory or NULL on failure - typedef void* (*allocation_function)(size_t size); - - // Memory deallocation function interface - typedef void (*deallocation_function)(void* ptr); - - // Override default memory management functions. All subsequent allocations/deallocations will be performed via supplied functions. - void PUGIXML_FUNCTION set_memory_management_functions(allocation_function allocate, deallocation_function deallocate); - - // Get current memory management functions - allocation_function PUGIXML_FUNCTION get_memory_allocation_function(); - deallocation_function PUGIXML_FUNCTION get_memory_deallocation_function(); -} - -#if !defined(PUGIXML_NO_STL) && (defined(_MSC_VER) || defined(__ICC)) -namespace std -{ - // Workarounds for (non-standard) iterator category detection for older versions (MSVC7/IC8 and earlier) - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION _Iter_cat(const pugi::xml_named_node_iterator&); -} -#endif - -#if !defined(PUGIXML_NO_STL) && defined(__SUNPRO_CC) -namespace std -{ - // Workarounds for (non-standard) iterator category detection - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_node_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_attribute_iterator&); - std::bidirectional_iterator_tag PUGIXML_FUNCTION __iterator_category(const pugi::xml_named_node_iterator&); -} -#endif - -#endif - -// Make sure implementation is included in header-only mode -// Use macro expansion in #include to work around QMake (QTBUG-11923) -#if defined(PUGIXML_HEADER_ONLY) && !defined(PUGIXML_SOURCE) -# define PUGIXML_SOURCE "pugixml.cpp" -# include PUGIXML_SOURCE -#endif - -/** - * Copyright (c) 2006-2015 Arseny Kapoulkine - * - * 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/path_10_8/src/fileloader.cpp b/path_10_8/src/fileloader.cpp deleted file mode 100644 index 593cda338..000000000 --- a/path_10_8/src/fileloader.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "fileloader.h" - -FileLoader::FileLoader() : m_cached_data() -{ - m_file = nullptr; - m_root = nullptr; - m_buffer = new uint8_t[1024]; - m_buffer_size = 1024; - m_lastError = ERROR_NONE; - - //cache - m_cache_size = 0; - m_cache_index = NO_VALID_CACHE; - m_cache_offset = NO_VALID_CACHE; -} - -FileLoader::~FileLoader() -{ - if (m_file) { - fclose(m_file); - m_file = nullptr; - } - - NodeStruct::clearNet(m_root); - delete[] m_buffer; - - for (int32_t i = 0; i < CACHE_BLOCKS; i++) { - delete[] m_cached_data[i].data; - } -} - -bool FileLoader::openFile(const char* filename, const char* accept_identifier) -{ - m_file = fopen(filename, "rb"); - if (!m_file) { - m_lastError = ERROR_CAN_NOT_OPEN; - return false; - } - - char identifier[4]; - if (fread(identifier, 1, 4, m_file) < 4) { - fclose(m_file); - m_file = nullptr; - m_lastError = ERROR_EOF; - return false; - } - - // The first four bytes must either match the accept identifier or be 0x00000000 (wildcard) - if (memcmp(identifier, accept_identifier, 4) != 0 && memcmp(identifier, "\0\0\0\0", 4) != 0) { - fclose(m_file); - m_file = nullptr; - m_lastError = ERROR_INVALID_FILE_VERSION; - return false; - } - - fseek(m_file, 0, SEEK_END); - int32_t file_size = ftell(m_file); - m_cache_size = std::min(32768, std::max(file_size / 20, 8192)) & ~0x1FFF; - - if (!safeSeek(4)) { - m_lastError = ERROR_INVALID_FORMAT; - return false; - } - - delete m_root; - m_root = new NodeStruct(); - m_root->start = 4; - - int32_t byte; - if (safeSeek(4) && readByte(byte) && byte == NODE_START) { - return parseNode(m_root); - } - - return false; -} - -bool FileLoader::parseNode(NODE node) -{ - int32_t byte, pos; - NODE currentNode = node; - - while (readByte(byte)) { - currentNode->type = byte; - bool setPropsSize = false; - - while (true) { - if (!readByte(byte)) { - return false; - } - - bool skipNode = false; - - switch (byte) { - case NODE_START: { - //child node start - if (!safeTell(pos)) { - return false; - } - - NODE childNode = new NodeStruct(); - childNode->start = pos; - currentNode->propsSize = pos - currentNode->start - 2; - currentNode->child = childNode; - - setPropsSize = true; - - if (!parseNode(childNode)) { - return false; - } - - break; - } - - case NODE_END: { - //current node end - if (!setPropsSize) { - if (!safeTell(pos)) { - return false; - } - - currentNode->propsSize = pos - currentNode->start - 2; - } - - if (!readByte(byte)) { - return true; - } - - switch (byte) { - case NODE_START: { - //starts next node - if (!safeTell(pos)) { - return false; - } - - skipNode = true; - NODE nextNode = new NodeStruct(); - nextNode->start = pos; - currentNode->next = nextNode; - currentNode = nextNode; - break; - } - - case NODE_END: - return safeTell(pos) && safeSeek(pos); - - default: - m_lastError = ERROR_INVALID_FORMAT; - return false; - } - - break; - } - - case ESCAPE_CHAR: { - if (!readByte(byte)) { - return false; - } - - break; - } - - default: - break; - } - - if (skipNode) { - break; - } - } - } - return false; -} - -const uint8_t* FileLoader::getProps(const NODE node, size_t& size) -{ - if (!node) { - return nullptr; - } - - if (node->propsSize >= m_buffer_size) { - delete[] m_buffer; - - while (node->propsSize >= m_buffer_size) { - m_buffer_size *= 2; - } - - m_buffer = new uint8_t[m_buffer_size]; - } - - //get buffer - if (!readBytes(m_buffer, node->propsSize, node->start + 2)) { - return nullptr; - } - - //unscape buffer - size_t j = 0; - bool escaped = false; - for (uint32_t i = 0; i < node->propsSize; ++i, ++j) { - if (m_buffer[i] == ESCAPE_CHAR) { - //escape char found, skip it and write next - m_buffer[j] = m_buffer[++i]; - //is neede a displacement for next bytes - escaped = true; - } else if (escaped) { - //perform that displacement - m_buffer[j] = m_buffer[i]; - } - } - - size = j; - return m_buffer; -} - -bool FileLoader::getProps(const NODE node, PropStream& props) -{ - size_t size; - if (const uint8_t* a = getProps(node, size)) { - props.init(reinterpret_cast(a), size); // does not break strict aliasing - return true; - } - - props.init(nullptr, 0); - return false; -} - -NODE FileLoader::getChildNode(const NODE parent, uint32_t& type) -{ - if (parent) { - NODE child = parent->child; - if (child) { - type = child->type; - } - - return child; - } - - type = m_root->type; - return m_root; -} - -NODE FileLoader::getNextNode(const NODE prev, uint32_t& type) -{ - if (!prev) { - return NO_NODE; - } - - NODE next = prev->next; - if (next) { - type = next->type; - } - return next; -} - -inline bool FileLoader::readByte(int32_t& value) -{ - if (m_cache_index == NO_VALID_CACHE) { - m_lastError = ERROR_CACHE_ERROR; - return false; - } - - if (m_cache_offset >= m_cached_data[m_cache_index].size) { - int32_t pos = m_cache_offset + m_cached_data[m_cache_index].base; - int32_t tmp = getCacheBlock(pos); - if (tmp < 0) { - return false; - } - - m_cache_index = tmp; - m_cache_offset = pos - m_cached_data[m_cache_index].base; - if (m_cache_offset >= m_cached_data[m_cache_index].size) { - return false; - } - } - - value = m_cached_data[m_cache_index].data[m_cache_offset++]; - return true; -} - -inline bool FileLoader::readBytes(uint8_t* buffer, uint32_t size, int32_t pos) -{ - //seek at pos - uint32_t remain = size, bufferPos = 0; - do { - //prepare cache - uint32_t i = getCacheBlock(pos); - if (i == NO_VALID_CACHE) { - return false; - } - - m_cache_index = i; - m_cache_offset = pos - m_cached_data[i].base; - - //get maximum read block size and calculate remaining bytes - uint32_t reading = std::min(remain, m_cached_data[i].size - m_cache_offset); - remain -= reading; - - //read it - memcpy(buffer + bufferPos, m_cached_data[m_cache_index].data + m_cache_offset, reading); - - //update variables - m_cache_offset += reading; - bufferPos += reading; - pos += reading; - } while (remain > 0); - return true; -} - -inline bool FileLoader::safeSeek(uint32_t pos) -{ - uint32_t i = getCacheBlock(pos); - if (i == NO_VALID_CACHE) { - return false; - } - - m_cache_index = i; - m_cache_offset = pos - m_cached_data[i].base; - return true; -} - -inline bool FileLoader::safeTell(int32_t& pos) -{ - if (m_cache_index == NO_VALID_CACHE) { - m_lastError = ERROR_CACHE_ERROR; - return false; - } - - pos = m_cached_data[m_cache_index].base + m_cache_offset - 1; - return true; -} - -inline uint32_t FileLoader::getCacheBlock(uint32_t pos) -{ - bool found = false; - uint32_t i, base_pos = pos & ~(m_cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (m_cached_data[i].loaded) { - if (m_cached_data[i].base == base_pos) { - found = true; - break; - } - } - } - - if (!found) { - i = loadCacheBlock(pos); - } - - return i; -} - -int32_t FileLoader::loadCacheBlock(uint32_t pos) -{ - int32_t i, loading_cache = -1, base_pos = pos & ~(m_cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (!m_cached_data[i].loaded) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - for (i = 0; i < CACHE_BLOCKS; i++) { - if (std::abs(static_cast(m_cached_data[i].base) - base_pos) > static_cast(2 * m_cache_size)) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - loading_cache = 0; - } - } - - if (m_cached_data[loading_cache].data == nullptr) { - m_cached_data[loading_cache].data = new uint8_t[m_cache_size]; - } - - m_cached_data[loading_cache].base = base_pos; - - if (fseek(m_file, m_cached_data[loading_cache].base, SEEK_SET) != 0) { - m_lastError = ERROR_SEEK_ERROR; - return -1; - } - - uint32_t size = fread(m_cached_data[loading_cache].data, 1, m_cache_size, m_file); - m_cached_data[loading_cache].size = size; - - if (size < (pos - m_cached_data[loading_cache].base)) { - m_lastError = ERROR_SEEK_ERROR; - return -1; - } - - m_cached_data[loading_cache].loaded = 1; - return loading_cache; -} diff --git a/path_10_8/src/fileloader.h b/path_10_8/src/fileloader.h deleted file mode 100644 index 7fea6db28..000000000 --- a/path_10_8/src/fileloader.h +++ /dev/null @@ -1,285 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_FILELOADER_H_9B663D19E58D42E6BFACFE5B09D7A05E -#define FS_FILELOADER_H_9B663D19E58D42E6BFACFE5B09D7A05E - -struct NodeStruct; - -typedef NodeStruct* NODE; - -struct NodeStruct { - NodeStruct() : start(0), propsSize(0), type(0), next(nullptr), child(nullptr) {} - - uint32_t start; - uint32_t propsSize; - uint32_t type; - NodeStruct* next; - NodeStruct* child; - - static void clearNet(NodeStruct* root) { - if (root) { - clearChild(root); - } - } - - private: - static void clearNext(NodeStruct* node) { - NodeStruct* deleteNode = node; - NodeStruct* nextNode; - - while (deleteNode) { - if (deleteNode->child) { - clearChild(deleteNode->child); - } - - nextNode = deleteNode->next; - delete deleteNode; - deleteNode = nextNode; - } - } - - static void clearChild(NodeStruct* node) { - if (node->child) { - clearChild(node->child); - } - - if (node->next) { - clearNext(node->next); - } - - delete node; - } -}; - -#define NO_NODE 0 - -enum FILELOADER_ERRORS { - ERROR_NONE, - ERROR_INVALID_FILE_VERSION, - ERROR_CAN_NOT_OPEN, - ERROR_CAN_NOT_CREATE, - ERROR_EOF, - ERROR_SEEK_ERROR, - ERROR_NOT_OPEN, - ERROR_INVALID_NODE, - ERROR_INVALID_FORMAT, - ERROR_TELL_ERROR, - ERROR_COULDNOTWRITE, - ERROR_CACHE_ERROR, -}; - -class PropStream; - -class FileLoader -{ - public: - FileLoader(); - ~FileLoader(); - - // non-copyable - FileLoader(const FileLoader&) = delete; - FileLoader& operator=(const FileLoader&) = delete; - - bool openFile(const char* filename, const char* identifier); - const uint8_t* getProps(const NODE, size_t& size); - bool getProps(const NODE, PropStream& props); - NODE getChildNode(const NODE parent, uint32_t& type); - NODE getNextNode(const NODE prev, uint32_t& type); - - FILELOADER_ERRORS getError() const { - return m_lastError; - } - - protected: - enum SPECIAL_BYTES { - ESCAPE_CHAR = 0xFD, - NODE_START = 0xFE, - NODE_END = 0xFF, - }; - - bool parseNode(NODE node); - - inline bool readByte(int32_t& value); - inline bool readBytes(uint8_t* buffer, uint32_t size, int32_t pos); - inline bool safeSeek(uint32_t pos); - inline bool safeTell(int32_t& pos); - - protected: - struct _cache { - uint8_t* data; - uint32_t loaded; - uint32_t base; - uint32_t size; - }; - -#define CACHE_BLOCKS 3 - _cache m_cached_data[CACHE_BLOCKS]; - - uint8_t* m_buffer; - NODE m_root; - FILE* m_file; - - FILELOADER_ERRORS m_lastError; - uint32_t m_buffer_size; - - uint32_t m_cache_size; -#define NO_VALID_CACHE 0xFFFFFFFF - uint32_t m_cache_index; - uint32_t m_cache_offset; - - inline uint32_t getCacheBlock(uint32_t pos); - int32_t loadCacheBlock(uint32_t pos); -}; - -class PropStream -{ - public: - PropStream() { - end = nullptr; - p = nullptr; - } - - void init(const char* a, size_t size) { - p = a; - end = a + size; - } - - size_t size() const { - return end - p; - } - - template - inline bool read(T& ret) { - if (size() < sizeof(T)) { - return false; - } - - memcpy(&ret, p, sizeof(T)); - p += sizeof(T); - return true; - } - - inline bool readString(std::string& ret) { - uint16_t strLen; - if (!read(strLen)) { - return false; - } - - if (size() < strLen) { - return false; - } - - char* str = new char[strLen + 1]; - memcpy(str, p, strLen); - str[strLen] = 0; - ret.assign(str, strLen); - delete[] str; - p += strLen; - return true; - } - - inline bool skip(size_t n) { - if (size() < n) { - return false; - } - - p += n; - return true; - } - - protected: - const char* p; - const char* end; -}; - -class PropWriteStream -{ - public: - PropWriteStream() { - buffer_size = 32; - buffer = static_cast(malloc(buffer_size)); - if (!buffer) { - throw std::bad_alloc(); - } - - size = 0; - } - - ~PropWriteStream() { - free(buffer); - } - - // non-copyable - PropWriteStream(const PropWriteStream&) = delete; - PropWriteStream& operator=(const PropWriteStream&) = delete; - - const char* getStream(size_t& _size) const { - _size = size; - return buffer; - } - - inline void clear() { - size = 0; - } - - template - inline void write(T add) { - reserve(sizeof(T)); - memcpy(buffer + size, &add, sizeof(T)); - size += sizeof(T); - } - - inline void writeString(const std::string& str) { - size_t strLength = str.size(); - if (strLength > std::numeric_limits::max()) { - write(0); - return; - } - - write(strLength); - reserve(strLength); - memcpy(buffer + size, str.c_str(), strLength); - size += strLength; - } - - protected: - void reserve(size_t length) { - if ((buffer_size - size) >= length) { - return; - } - - do { - buffer_size <<= 1; - } while ((buffer_size - size) < length); - - void* newBuffer = realloc(buffer, buffer_size); - if (!newBuffer) { - throw std::bad_alloc(); - } - - buffer = static_cast(newBuffer); - } - - char* buffer; - size_t buffer_size; - size_t size; -}; - -#endif diff --git a/path_10_8/src/game.cpp b/path_10_8/src/game.cpp deleted file mode 100644 index d44f6e2eb..000000000 --- a/path_10_8/src/game.cpp +++ /dev/null @@ -1,5567 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "pugicast.h" - -#include "items.h" -#include "commands.h" -#include "creature.h" -#include "monster.h" -#include "game.h" -#include "tile.h" -#include "house.h" -#include "actions.h" -#include "combat.h" -#include "iologindata.h" -#include "iomarket.h" -#include "chat.h" -#include "talkaction.h" -#include "spells.h" -#include "configmanager.h" -#include "ban.h" -#include "raids.h" -#include "database.h" -#include "server.h" -#include "ioguild.h" -#include "quests.h" -#include "globalevent.h" -#include "mounts.h" -#include "bed.h" -#include "scheduler.h" -#include "monster.h" -#include "spawn.h" -#include "connection.h" -#include "events.h" -#include "databasetasks.h" - -extern ConfigManager g_config; -extern Actions* g_actions; -extern Chat* g_chat; -extern TalkActions* g_talkActions; -extern Spells* g_spells; -extern Vocations g_vocations; -extern GlobalEvents* g_globalEvents; -extern Events* g_events; - -Game::Game() : - wildcardTree(false), - offlineTrainingWindow(std::numeric_limits::max(), "Choose a Skill", "Please choose a skill:") -{ - gameState = GAME_STATE_NORMAL; - worldType = WORLD_TYPE_PVP; - - serviceManager = nullptr; - lastStageLevel = 0; - playersRecord = 0; - motdNum = 0; - useLastStageLevel = false; - stagesEnabled = false; - - lastBucket = 0; - - //(1440 minutes/day)/(3600 seconds/day)*10 seconds event interval - int32_t dayCycle = 3600; - lightHourDelta = 1440 * 10 / dayCycle; - lightHour = SUNRISE + (SUNSET - SUNRISE) / 2; - lightLevel = LIGHT_LEVEL_DAY; - lightState = LIGHT_STATE_DAY; - - offlineTrainingWindow.choices.emplace_back("Sword Fighting and Shielding", SKILL_SWORD); - offlineTrainingWindow.choices.emplace_back("Axe Fighting and Shielding", SKILL_AXE); - offlineTrainingWindow.choices.emplace_back("Club Fighting and Shielding", SKILL_CLUB); - offlineTrainingWindow.choices.emplace_back("Distance Fighting and Shielding", SKILL_DISTANCE); - offlineTrainingWindow.choices.emplace_back("Magic Level and Shielding", SKILL_MAGLEVEL); - offlineTrainingWindow.buttons.emplace_back("Okay", 1); - offlineTrainingWindow.buttons.emplace_back("Cancel", 0); - offlineTrainingWindow.defaultEnterButton = 1; - offlineTrainingWindow.defaultEscapeButton = 0; - offlineTrainingWindow.priority = true; -} - -Game::~Game() -{ - for (const auto& it : guilds) { - delete it.second; - } -} - -void Game::start(ServiceManager* manager) -{ - serviceManager = manager; - - g_scheduler.addEvent(createSchedulerTask(EVENT_LIGHTINTERVAL, std::bind(&Game::checkLight, this))); - g_scheduler.addEvent(createSchedulerTask(EVENT_CREATURE_THINK_INTERVAL, std::bind(&Game::checkCreatures, this, 0))); - g_scheduler.addEvent(createSchedulerTask(EVENT_DECAYINTERVAL, std::bind(&Game::checkDecay, this))); -} - -GameState_t Game::getGameState() const -{ - return gameState; -} - -void Game::setWorldType(WorldType_t type) -{ - worldType = type; -} - -void Game::setGameState(GameState_t newState) -{ - if (gameState == GAME_STATE_SHUTDOWN) { - return; //this cannot be stopped - } - - if (gameState == newState) { - return; - } - - gameState = newState; - switch (newState) { - case GAME_STATE_INIT: { - commands.loadFromXml(); - - loadExperienceStages(); - - groups.load(); - g_chat->load(); - - map.spawns.startup(); - - raids.loadFromXml(); - raids.startup(); - - quests.loadFromXml(); - mounts.loadFromXml(); - - loadMotdNum(); - loadPlayersRecord(); - - g_globalEvents->startup(); - break; - } - - case GAME_STATE_SHUTDOWN: { - g_globalEvents->execute(GLOBALEVENT_SHUTDOWN); - - //kick all players that are still online - auto it = players.begin(); - while (it != players.end()) { - it->second->kickPlayer(true); - it = players.begin(); - } - - saveMotdNum(); - saveGameState(); - - g_dispatcher.addTask( - createTask(std::bind(&Game::shutdown, this))); - - g_scheduler.stop(); - g_databaseTasks.stop(); - g_dispatcher.stop(); - break; - } - - case GAME_STATE_CLOSED: { - /* kick all players without the CanAlwaysLogin flag */ - auto it = players.begin(); - while (it != players.end()) { - if (!it->second->hasFlag(PlayerFlag_CanAlwaysLogin)) { - it->second->kickPlayer(true); - it = players.begin(); - } else { - ++it; - } - } - - saveGameState(); - break; - } - - default: - break; - } -} - -void Game::saveGameState() -{ - if (gameState == GAME_STATE_NORMAL) { - setGameState(GAME_STATE_MAINTAIN); - } - - std::cout << "Saving server..." << std::endl; - - for (const auto& it : players) { - it.second->loginPosition = it.second->getPosition(); - IOLoginData::savePlayer(it.second); - } - - Map::save(); - - if (gameState == GAME_STATE_MAINTAIN) { - setGameState(GAME_STATE_NORMAL); - } -} - -bool Game::loadMainMap(const std::string& filename) -{ - Monster::despawnRange = g_config.getNumber(ConfigManager::DEFAULT_DESPAWNRANGE); - Monster::despawnRadius = g_config.getNumber(ConfigManager::DEFAULT_DESPAWNRADIUS); - return map.loadMap("data/world/" + filename + ".otbm", true); -} - -void Game::loadMap(const std::string& path) -{ - map.loadMap(path, false); -} - -Cylinder* Game::internalGetCylinder(Player* player, const Position& pos) const -{ - if (pos.x != 0xFFFF) { - return map.getTile(pos); - } - - //container - if (pos.y & 0x40) { - uint8_t from_cid = pos.y & 0x0F; - return player->getContainerByID(from_cid); - } - - //inventory - return player; -} - -Thing* Game::internalGetThing(Player* player, const Position& pos, int32_t index, uint32_t spriteId, stackPosType_t type) const -{ - if (pos.x != 0xFFFF) { - Tile* tile = map.getTile(pos); - if (!tile) { - return nullptr; - } - - Thing* thing; - switch (type) { - case STACKPOS_LOOK: { - return tile->getTopVisibleThing(player); - } - - case STACKPOS_MOVE: { - Item* item = tile->getTopDownItem(); - if (item && item->isMoveable()) { - thing = item; - } else { - thing = tile->getTopVisibleCreature(player); - } - break; - } - - case STACKPOS_USEITEM: { - thing = tile->getUseItem(); - break; - } - - case STACKPOS_TOPDOWN_ITEM: { - thing = tile->getTopDownItem(); - break; - } - - case STACKPOS_USETARGET: { - thing = tile->getTopVisibleCreature(player); - if (!thing) { - thing = tile->getUseItem(); - } - break; - } - - default: { - thing = nullptr; - break; - } - } - - if (player && tile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { - //do extra checks here if the thing is accessable - if (thing && thing->getItem()) { - if (tile->hasProperty(CONST_PROP_ISVERTICAL)) { - if (player->getPosition().x + 1 == tile->getPosition().x) { - thing = nullptr; - } - } else { // horizontal - if (player->getPosition().y + 1 == tile->getPosition().y) { - thing = nullptr; - } - } - } - } - return thing; - } - - //container - if (pos.y & 0x40) { - uint8_t fromCid = pos.y & 0x0F; - - Container* parentContainer = player->getContainerByID(fromCid); - if (!parentContainer) { - return nullptr; - } - - if (parentContainer->getID() == ITEM_BROWSEFIELD) { - Tile* tile = parentContainer->getTile(); - if (tile && tile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { - if (tile->hasProperty(CONST_PROP_ISVERTICAL)) { - if (player->getPosition().x + 1 == tile->getPosition().x) { - return nullptr; - } - } else { // horizontal - if (player->getPosition().y + 1 == tile->getPosition().y) { - return nullptr; - } - } - } - } - - uint8_t slot = pos.z; - return parentContainer->getItemByIndex(player->getContainerIndex(fromCid) + slot); - } else if (pos.y == 0 && pos.z == 0) { - const ItemType& it = Item::items.getItemIdByClientId(spriteId); - if (it.id == 0) { - return nullptr; - } - - int32_t subType; - if (it.isFluidContainer() && index < static_cast(sizeof(reverseFluidMap) / sizeof(uint8_t))) { - subType = reverseFluidMap[index]; - } else { - subType = -1; - } - - return findItemOfType(player, it.id, true, subType); - } - - //inventory - slots_t slot = static_cast(pos.y); - return player->getInventoryItem(slot); -} - -void Game::internalGetPosition(Item* item, Position& pos, uint8_t& stackpos) -{ - pos.x = 0; - pos.y = 0; - pos.z = 0; - stackpos = 0; - - Cylinder* topParent = item->getTopParent(); - if (topParent) { - if (Player* player = dynamic_cast(topParent)) { - pos.x = 0xFFFF; - - Container* container = dynamic_cast(item->getParent()); - if (container) { - pos.y = static_cast(0x40) | static_cast(player->getContainerID(container)); - pos.z = container->getThingIndex(item); - stackpos = pos.z; - } else { - pos.y = player->getThingIndex(item); - stackpos = pos.y; - } - } else if (Tile* tile = topParent->getTile()) { - pos = tile->getPosition(); - stackpos = tile->getThingIndex(item); - } - } -} - -Creature* Game::getCreatureByID(uint32_t id) -{ - if (id <= Player::playerAutoID) { - return getPlayerByID(id); - } else if (id <= Monster::monsterAutoID) { - return getMonsterByID(id); - } else if (id <= Npc::npcAutoID) { - return getNpcByID(id); - } - return nullptr; -} - -Monster* Game::getMonsterByID(uint32_t id) -{ - if (id == 0) { - return nullptr; - } - - auto it = monsters.find(id); - if (it == monsters.end()) { - return nullptr; - } - return it->second; -} - -Npc* Game::getNpcByID(uint32_t id) -{ - if (id == 0) { - return nullptr; - } - - auto it = npcs.find(id); - if (it == npcs.end()) { - return nullptr; - } - return it->second; -} - -Player* Game::getPlayerByID(uint32_t id) -{ - if (id == 0) { - return nullptr; - } - - auto it = players.find(id); - if (it == players.end()) { - return nullptr; - } - return it->second; -} - -Creature* Game::getCreatureByName(const std::string& s) -{ - if (s.empty()) { - return nullptr; - } - - const std::string& lowerCaseName = asLowerCaseString(s); - - auto m_it = mappedPlayerNames.find(lowerCaseName); - if (m_it != mappedPlayerNames.end()) { - return m_it->second; - } - - for (const auto& it : npcs) { - if (lowerCaseName == asLowerCaseString(it.second->getName())) { - return it.second; - } - } - - for (const auto& it : monsters) { - if (lowerCaseName == asLowerCaseString(it.second->getName())) { - return it.second; - } - } - return nullptr; -} - -Npc* Game::getNpcByName(const std::string& s) -{ - if (s.empty()) { - return nullptr; - } - - const char* npcName = s.c_str(); - for (const auto& it : npcs) { - if (strcasecmp(npcName, it.second->getName().c_str()) == 0) { - return it.second; - } - } - return nullptr; -} - -Player* Game::getPlayerByName(const std::string& s) -{ - if (s.empty()) { - return nullptr; - } - - auto it = mappedPlayerNames.find(asLowerCaseString(s)); - if (it == mappedPlayerNames.end()) { - return nullptr; - } - return it->second; -} - -Player* Game::getPlayerByGUID(const uint32_t& guid) -{ - if (guid == 0) { - return nullptr; - } - - for (const auto& it : players) { - if (guid == it.second->getGUID()) { - return it.second; - } - } - return nullptr; -} - -ReturnValue Game::getPlayerByNameWildcard(const std::string& s, Player*& player) -{ - size_t strlen = s.length(); - if (strlen == 0 || strlen > 20) { - return RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE; - } - - if (s.back() == '~') { - const std::string& query = asLowerCaseString(s.substr(0, strlen - 1)); - std::string result; - ReturnValue ret = wildcardTree.findOne(query, result); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - player = getPlayerByName(result); - } else { - player = getPlayerByName(s); - } - - if (!player) { - return RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE; - } - - return RETURNVALUE_NOERROR; -} - -Player* Game::getPlayerByAccount(uint32_t acc) -{ - for (const auto& it : players) { - if (it.second->getAccount() == acc) { - return it.second; - } - } - return nullptr; -} - -bool Game::internalPlaceCreature(Creature* creature, const Position& pos, bool extendedPos /*=false*/, bool forced /*= false*/) -{ - if (creature->getParent() != nullptr) { - return false; - } - - if (!map.placeCreature(pos, creature, extendedPos, forced)) { - return false; - } - - creature->incrementReferenceCounter(); - creature->setID(); - creature->addList(); - return true; -} - -bool Game::placeCreature(Creature* creature, const Position& pos, bool extendedPos /*=false*/, bool forced /*= false*/) -{ - if (!internalPlaceCreature(creature, pos, extendedPos, forced)) { - return false; - } - - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true); - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendCreatureAppear(creature, creature->getPosition(), true); - } - } - - for (Creature* spectator : list) { - spectator->onCreatureAppear(creature, true); - } - - creature->getParent()->postAddNotification(creature, nullptr, 0); - - addCreatureCheck(creature); - creature->onPlacedCreature(); - return true; -} - -bool Game::removeCreature(Creature* creature, bool isLogout/* = true*/) -{ - if (creature->isRemoved()) { - return false; - } - - Tile* tile = creature->getTile(); - - std::vector oldStackPosVector; - - SpectatorVec list; - map.getSpectators(list, tile->getPosition(), true); - for (Creature* spectator : list) { - if (Player* player = spectator->getPlayer()) { - oldStackPosVector.push_back(player->canSeeCreature(creature) ? tile->getStackposOfCreature(player, creature) : -1); - } - } - - tile->removeCreature(creature); - - const Position& tilePosition = tile->getPosition(); - - //send to client - size_t i = 0; - for (Creature* spectator : list) { - if (Player* player = spectator->getPlayer()) { - player->sendRemoveTileThing(tilePosition, oldStackPosVector[i++]); - } - } - - //event method - for (Creature* spectator : list) { - spectator->onRemoveCreature(creature, isLogout); - } - - creature->getParent()->postRemoveNotification(creature, nullptr, 0); - - creature->removeList(); - creature->setRemoved(); - ReleaseCreature(creature); - - removeCreatureCheck(creature); - - for (Creature* summon : creature->summons) { - summon->setLossSkill(false); - removeCreature(summon); - } - return true; -} - -void Game::playerMoveThing(uint32_t playerId, const Position& fromPos, - uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - uint8_t fromIndex = 0; - if (fromPos.x == 0xFFFF) { - if (fromPos.y & 0x40) { - fromIndex = fromPos.z; - } else { - fromIndex = static_cast(fromPos.y); - } - } else { - fromIndex = fromStackPos; - } - - Thing* thing = internalGetThing(player, fromPos, fromIndex, 0, STACKPOS_MOVE); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - if (Creature* movingCreature = thing->getCreature()) { - Tile* tile = map.getTile(toPos); - if (!tile) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - if (Position::areInRange<1, 1, 0>(movingCreature->getPosition(), player->getPosition())) { - SchedulerTask* task = createSchedulerTask(1000, - std::bind(&Game::playerMoveCreatureByID, this, player->getID(), - movingCreature->getID(), movingCreature->getPosition(), tile->getPosition())); - player->setNextActionTask(task); - } else { - playerMoveCreature(player, movingCreature, movingCreature->getPosition(), tile); - } - } else if (thing->getItem()) { - Cylinder* toCylinder = internalGetCylinder(player, toPos); - if (!toCylinder) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - playerMoveItem(player, fromPos, spriteId, fromStackPos, toPos, count, thing->getItem(), toCylinder); - } -} - -void Game::playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, const Position& movingCreatureOrigPos, const Position& toPos) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Creature* movingCreature = getCreatureByID(movingCreatureId); - if (!movingCreature) { - return; - } - - Tile* toTile = map.getTile(toPos); - if (!toTile) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - playerMoveCreature(player, movingCreature, movingCreatureOrigPos, toTile); -} - -void Game::playerMoveCreature(Player* player, Creature* movingCreature, const Position& movingCreatureOrigPos, Tile* toTile) -{ - if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerMoveCreatureByID, - this, player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition())); - player->setNextActionTask(task); - return; - } - - player->setNextActionTask(nullptr); - - if (!Position::areInRange<1, 1, 0>(movingCreatureOrigPos, player->getPosition())) { - //need to walk to the creature first before moving it - std::forward_list listDir; - if (player->getPathTo(movingCreatureOrigPos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - SchedulerTask* task = createSchedulerTask(1500, std::bind(&Game::playerMoveCreatureByID, this, - player->getID(), movingCreature->getID(), movingCreatureOrigPos, toTile->getPosition())); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - if ((!movingCreature->isPushable() && !player->hasFlag(PlayerFlag_CanPushAllCreatures)) || - (movingCreature->isInGhostMode() && !player->isAccessPlayer())) { - player->sendCancelMessage(RETURNVALUE_NOTMOVEABLE); - return; - } - - //check throw distance - const Position& movingCreaturePos = movingCreature->getPosition(); - const Position& toPos = toTile->getPosition(); - if ((Position::getDistanceX(movingCreaturePos, toPos) > movingCreature->getThrowRange()) || (Position::getDistanceY(movingCreaturePos, toPos) > movingCreature->getThrowRange()) || (Position::getDistanceZ(movingCreaturePos, toPos) * 4 > movingCreature->getThrowRange())) { - player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH); - return; - } - - if (player != movingCreature) { - if (toTile->hasProperty(CONST_PROP_BLOCKPATH)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - return; - } else if ((movingCreature->getZone() == ZONE_PROTECTION && !toTile->hasFlag(TILESTATE_PROTECTIONZONE)) || (movingCreature->getZone() == ZONE_NOPVP && !toTile->hasFlag(TILESTATE_NOPVPZONE))) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } else { - if (CreatureVector* tileCreatures = toTile->getCreatures()) { - for (Creature* tileCreature : *tileCreatures) { - if (!tileCreature->isInGhostMode()) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - return; - } - } - } - - Npc* movingNpc = movingCreature->getNpc(); - if (movingNpc && !Spawns::isInZone(movingNpc->getMasterPos(), movingNpc->getMasterRadius(), toPos)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - return; - } - } - } - - if (!g_events->eventPlayerOnMoveCreature(player, movingCreature, movingCreaturePos, toPos)) { - return; - } - - ReturnValue ret = internalMoveCreature(*movingCreature, *toTile); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - } -} - -ReturnValue Game::internalMoveCreature(Creature* creature, Direction direction, uint32_t flags /*= 0*/) -{ - creature->setLastPosition(creature->getPosition()); - const Position& currentPos = creature->getPosition(); - Position destPos = getNextPosition(direction, currentPos); - - bool diagonalMovement = (direction & DIRECTION_DIAGONAL_MASK) != 0; - if (creature->getPlayer() && !diagonalMovement) { - //try go up - if (currentPos.z != 8 && creature->getTile()->hasHeight(3)) { - Tile* tmpTile = map.getTile(currentPos.x, currentPos.y, currentPos.getZ() - 1); - if (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasProperty(CONST_PROP_BLOCKSOLID))) { - tmpTile = map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasProperty(CONST_PROP_BLOCKSOLID)) { - flags = flags | FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE; - - if (!tmpTile->floorChange()) { - destPos.z--; - } - } - } - } else { - //try go down - Tile* tmpTile = map.getTile(destPos.x, destPos.y, destPos.z); - if (currentPos.z != 7 && (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasProperty(CONST_PROP_BLOCKSOLID)))) { - tmpTile = map.getTile(destPos.x, destPos.y, destPos.z + 1); - if (tmpTile && tmpTile->hasHeight(3)) { - flags |= FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE; - destPos.z++; - } - } - } - } - - Tile* toTile = map.getTile(destPos); - if (!toTile) { - return RETURNVALUE_NOTPOSSIBLE; - } - return internalMoveCreature(*creature, *toTile, flags); -} - -ReturnValue Game::internalMoveCreature(Creature& creature, Tile& toTile, uint32_t flags /*= 0*/) -{ - //check if we can move the creature to the destination - ReturnValue ret = toTile.queryAdd(0, creature, 1, flags); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - map.moveCreature(creature, toTile); - if (creature.getParent() != &toTile) { - return RETURNVALUE_NOERROR; - } - - int32_t index = 0; - Item* toItem = nullptr; - Tile* subCylinder = nullptr; - Tile* toCylinder = &toTile; - Tile* fromCylinder = nullptr; - uint32_t n = 0; - - while ((subCylinder = toCylinder->queryDestination(index, creature, &toItem, flags)) != toCylinder) { - map.moveCreature(creature, *subCylinder); - - if (creature.getParent() != subCylinder) { - //could happen if a script move the creature - fromCylinder = nullptr; - break; - } - - fromCylinder = toCylinder; - toCylinder = subCylinder; - flags = 0; - - //to prevent infinite loop - if (++n >= MAP_MAX_LAYERS) { - break; - } - } - - if (fromCylinder) { - const Position& fromPosition = fromCylinder->getPosition(); - const Position& toPosition = toCylinder->getPosition(); - if (fromPosition.z != toPosition.z && (fromPosition.x != toPosition.x || fromPosition.y != toPosition.y)) { - Direction dir = getDirectionTo(fromPosition, toPosition); - if ((dir & DIRECTION_DIAGONAL_MASK) == 0) { - internalCreatureTurn(&creature, dir); - } - } - } - - return RETURNVALUE_NOERROR; -} - -void Game::playerMoveItemByPlayerID(uint32_t playerId, const Position& fromPos, uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - playerMoveItem(player, fromPos, spriteId, fromStackPos, toPos, count, nullptr, nullptr); -} - -void Game::playerMoveItem(Player* player, const Position& fromPos, - uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count, Item* item, Cylinder* toCylinder) -{ - if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerMoveItemByPlayerID, this, - player->getID(), fromPos, spriteId, fromStackPos, toPos, count)); - player->setNextActionTask(task); - return; - } - - player->setNextActionTask(nullptr); - - if (item == nullptr) { - uint8_t fromIndex = 0; - if (fromPos.x == 0xFFFF) { - if (fromPos.y & 0x40) { - fromIndex = fromPos.z; - } else { - fromIndex = static_cast(fromPos.y); - } - } else { - fromIndex = fromStackPos; - } - - Thing* thing = internalGetThing(player, fromPos, fromIndex, 0, STACKPOS_MOVE); - if (!thing || !thing->getItem()) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - item = thing->getItem(); - } - - if (item->getClientID() != spriteId) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Cylinder* fromCylinder = internalGetCylinder(player, fromPos); - if (fromCylinder == nullptr) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - if (toCylinder == nullptr) { - toCylinder = internalGetCylinder(player, toPos); - if (toCylinder == nullptr) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - } - - if (!item->isPushable() || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - player->sendCancelMessage(RETURNVALUE_NOTMOVEABLE); - return; - } - - const Position& playerPos = player->getPosition(); - const Position& mapFromPos = fromCylinder->getTile()->getPosition(); - if (playerPos.z != mapFromPos.z) { - player->sendCancelMessage(playerPos.z > mapFromPos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS); - return; - } - - if (!Position::areInRange<1, 1>(playerPos, mapFromPos)) { - //need to walk to the item first before using it - std::forward_list listDir; - if (player->getPathTo(item->getPosition(), listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, - player->getID(), fromPos, spriteId, fromStackPos, toPos, count)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - const Tile* toCylinderTile = toCylinder->getTile(); - const Position& mapToPos = toCylinderTile->getPosition(); - - //hangable item specific code - if (item->isHangable() && toCylinderTile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { - //destination supports hangable objects so need to move there first - bool vertical = toCylinderTile->hasProperty(CONST_PROP_ISVERTICAL); - if (vertical) { - if (playerPos.x + 1 == mapToPos.x) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - } else { // horizontal - if (playerPos.y + 1 == mapToPos.y) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - } - - if (!Position::areInRange<1, 1, 0>(playerPos, mapToPos)) { - Position walkPos = mapToPos; - if (vertical) { - walkPos.x++; - } else { - walkPos.y++; - } - - Position itemPos = fromPos; - uint8_t itemStackPos = fromStackPos; - - if (fromPos.x != 0xFFFF && Position::areInRange<1, 1>(mapFromPos, playerPos) - && !Position::areInRange<1, 1, 0>(mapFromPos, walkPos)) { - //need to pickup the item first - Item* moveItem = nullptr; - - ReturnValue ret = internalMoveItem(fromCylinder, player, INDEX_WHEREEVER, item, count, &moveItem); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - return; - } - - //changing the position since its now in the inventory of the player - internalGetPosition(moveItem, itemPos, itemStackPos); - } - - std::forward_list listDir; - if (player->getPathTo(walkPos, listDir, 0, 0, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerMoveItemByPlayerID, this, - player->getID(), itemPos, spriteId, itemStackPos, toPos, count)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - } - - if ((Position::getDistanceX(playerPos, mapToPos) > item->getThrowRange()) || - (Position::getDistanceY(playerPos, mapToPos) > item->getThrowRange()) || - (Position::getDistanceZ(mapFromPos, mapToPos) * 4 > item->getThrowRange())) { - player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH); - return; - } - - if (!canThrowObjectTo(mapFromPos, mapToPos)) { - player->sendCancelMessage(RETURNVALUE_CANNOTTHROW); - return; - } - - if (!g_events->eventPlayerOnMoveItem(player, item, count, fromPos, toPos)) { - return; - } - - uint8_t toIndex = 0; - if (toPos.x == 0xFFFF) { - if (toPos.y & 0x40) { - toIndex = toPos.z; - } else { - toIndex = static_cast(toPos.y); - } - } - - ReturnValue ret = internalMoveItem(fromCylinder, toCylinder, toIndex, item, count, nullptr, 0, player); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - } -} - -ReturnValue Game::internalMoveItem(Cylinder* fromCylinder, Cylinder* toCylinder, int32_t index, - Item* item, uint32_t count, Item** _moveItem, uint32_t flags /*= 0*/, Creature* actor/* = nullptr*/, Item* tradeItem/* = nullptr*/) -{ - Tile* fromTile = fromCylinder->getTile(); - if (fromTile) { - auto it = browseFields.find(fromTile); - if (it != browseFields.end() && it->second == fromCylinder) { - fromCylinder = fromTile; - } - } - - Item* toItem = nullptr; - - Cylinder* subCylinder; - int floorN = 0; - - while ((subCylinder = toCylinder->queryDestination(index, *item, &toItem, flags)) != toCylinder) { - toCylinder = subCylinder; - flags = 0; - - //to prevent infinite loop - if (++floorN >= MAP_MAX_LAYERS) { - break; - } - } - - //destination is the same as the source? - if (item == toItem) { - return RETURNVALUE_NOERROR; //silently ignore move - } - - //check if we can add this item - ReturnValue ret = toCylinder->queryAdd(index, *item, count, flags, actor); - if (ret == RETURNVALUE_NEEDEXCHANGE) { - //check if we can add it to source cylinder - ret = fromCylinder->queryAdd(fromCylinder->getThingIndex(item), *toItem, toItem->getItemCount(), 0); - if (ret == RETURNVALUE_NOERROR) { - //check how much we can move - uint32_t maxExchangeQueryCount = 0; - ReturnValue retExchangeMaxCount = fromCylinder->queryMaxCount(INDEX_WHEREEVER, *toItem, toItem->getItemCount(), maxExchangeQueryCount, 0); - - if (retExchangeMaxCount != RETURNVALUE_NOERROR && maxExchangeQueryCount == 0) { - return retExchangeMaxCount; - } - - if (toCylinder->queryRemove(*toItem, toItem->getItemCount(), flags) == RETURNVALUE_NOERROR) { - int32_t oldToItemIndex = toCylinder->getThingIndex(toItem); - toCylinder->removeThing(toItem, toItem->getItemCount()); - fromCylinder->addThing(toItem); - - if (oldToItemIndex != -1) { - toCylinder->postRemoveNotification(toItem, fromCylinder, oldToItemIndex); - } - - int32_t newToItemIndex = fromCylinder->getThingIndex(toItem); - if (newToItemIndex != -1) { - fromCylinder->postAddNotification(toItem, toCylinder, newToItemIndex); - } - - ret = toCylinder->queryAdd(index, *item, count, flags); - toItem = nullptr; - } - } - } - - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - //check how much we can move - uint32_t maxQueryCount = 0; - ReturnValue retMaxCount = toCylinder->queryMaxCount(index, *item, count, maxQueryCount, flags); - if (retMaxCount != RETURNVALUE_NOERROR && maxQueryCount == 0) { - return retMaxCount; - } - - uint32_t m; - if (item->isStackable()) { - m = std::min(count, maxQueryCount); - } else { - m = maxQueryCount; - } - - Item* moveItem = item; - - //check if we can remove this item - ret = fromCylinder->queryRemove(*item, m, flags); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - if (tradeItem) { - if (toCylinder->getItem() == tradeItem) { - return RETURNVALUE_NOTENOUGHROOM; - } - - Cylinder* tmpCylinder = toCylinder->getParent(); - while (tmpCylinder) { - if (tmpCylinder->getItem() == tradeItem) { - return RETURNVALUE_NOTENOUGHROOM; - } - - tmpCylinder = tmpCylinder->getParent(); - } - } - - //remove the item - int32_t itemIndex = fromCylinder->getThingIndex(item); - Item* updateItem = nullptr; - fromCylinder->removeThing(item, m); - - //update item(s) - if (item->isStackable()) { - uint32_t n; - - if (item->equals(toItem)) { - n = std::min(100 - toItem->getItemCount(), m); - toCylinder->updateThing(toItem, toItem->getID(), toItem->getItemCount() + n); - updateItem = toItem; - } else { - n = 0; - } - - int32_t newCount = m - n; - if (newCount > 0) { - moveItem = item->clone(); - moveItem->setItemCount(newCount); - } else { - moveItem = nullptr; - } - - if (item->isRemoved()) { - ReleaseItem(item); - } - } - - //add item - if (moveItem /*m - n > 0*/) { - toCylinder->addThing(index, moveItem); - } - - if (itemIndex != -1) { - fromCylinder->postRemoveNotification(item, toCylinder, itemIndex); - } - - if (moveItem) { - int32_t moveItemIndex = toCylinder->getThingIndex(moveItem); - if (moveItemIndex != -1) { - toCylinder->postAddNotification(moveItem, fromCylinder, moveItemIndex); - } - } - - if (updateItem) { - int32_t updateItemIndex = toCylinder->getThingIndex(updateItem); - if (updateItemIndex != -1) { - toCylinder->postAddNotification(updateItem, fromCylinder, updateItemIndex); - } - } - - if (_moveItem) { - if (moveItem) { - *_moveItem = moveItem; - } else { - *_moveItem = item; - } - } - - //we could not move all, inform the player - if (item->isStackable() && maxQueryCount < count) { - return retMaxCount; - } - - return ret; -} - -ReturnValue Game::internalAddItem(Cylinder* toCylinder, Item* item, int32_t index /*= INDEX_WHEREEVER*/, - uint32_t flags/* = 0*/, bool test/* = false*/) -{ - uint32_t remainderCount = 0; - return internalAddItem(toCylinder, item, index, flags, test, remainderCount); -} - -ReturnValue Game::internalAddItem(Cylinder* toCylinder, Item* item, int32_t index, - uint32_t flags, bool test, uint32_t& remainderCount) -{ - if (toCylinder == nullptr || item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - Cylinder* destCylinder = toCylinder; - Item* toItem = nullptr; - toCylinder = toCylinder->queryDestination(index, *item, &toItem, flags); - - //check if we can add this item - ReturnValue ret = toCylinder->queryAdd(index, *item, item->getItemCount(), flags); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - /* - Check if we can move add the whole amount, we do this by checking against the original cylinder, - since the queryDestination can return a cylinder that might only hold a part of the full amount. - */ - uint32_t maxQueryCount = 0; - ret = destCylinder->queryMaxCount(INDEX_WHEREEVER, *item, item->getItemCount(), maxQueryCount, flags); - - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - if (test) { - return RETURNVALUE_NOERROR; - } - - if (item->isStackable() && item->equals(toItem)) { - uint32_t m = std::min(item->getItemCount(), maxQueryCount); - uint32_t n = std::min(100 - toItem->getItemCount(), m); - - toCylinder->updateThing(toItem, toItem->getID(), toItem->getItemCount() + n); - - int32_t count = m - n; - if (count > 0) { - if (item->getItemCount() != count) { - Item* remainderItem = item->clone(); - remainderItem->setItemCount(count); - if (internalAddItem(destCylinder, remainderItem, INDEX_WHEREEVER, flags, false) != RETURNVALUE_NOERROR) { - ReleaseItem(remainderItem); - remainderCount = count; - } - } else { - toCylinder->addThing(index, item); - - int32_t itemIndex = toCylinder->getThingIndex(item); - if (itemIndex != -1) { - toCylinder->postAddNotification(item, nullptr, itemIndex); - } - } - } else { - //fully merged with toItem, item will be destroyed - item->onRemoved(); - ReleaseItem(item); - - int32_t itemIndex = toCylinder->getThingIndex(toItem); - if (itemIndex != -1) { - toCylinder->postAddNotification(toItem, nullptr, itemIndex); - } - } - } else { - toCylinder->addThing(index, item); - - int32_t itemIndex = toCylinder->getThingIndex(item); - if (itemIndex != -1) { - toCylinder->postAddNotification(item, nullptr, itemIndex); - } - } - - return RETURNVALUE_NOERROR; -} - -ReturnValue Game::internalRemoveItem(Item* item, int32_t count /*= -1*/, bool test /*= false*/, uint32_t flags /*= 0*/) -{ - Cylinder* cylinder = item->getParent(); - if (cylinder == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - Tile* fromTile = cylinder->getTile(); - if (fromTile) { - auto it = browseFields.find(fromTile); - if (it != browseFields.end() && it->second == cylinder) { - cylinder = fromTile; - } - } - - if (count == -1) { - count = item->getItemCount(); - } - - //check if we can remove this item - ReturnValue ret = cylinder->queryRemove(*item, count, flags | FLAG_IGNORENOTMOVEABLE); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - if (!item->canRemove()) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (!test) { - int32_t index = cylinder->getThingIndex(item); - - //remove the item - cylinder->removeThing(item, count); - - if (item->isRemoved()) { - ReleaseItem(item); - } - - cylinder->postRemoveNotification(item, nullptr, index); - } - - item->onRemoved(); - return RETURNVALUE_NOERROR; -} - -ReturnValue Game::internalPlayerAddItem(Player* player, Item* item, bool dropOnMap /*= true*/, slots_t slot /*= CONST_SLOT_WHEREEVER*/) -{ - uint32_t remainderCount = 0; - ReturnValue ret = internalAddItem(player, item, static_cast(slot), 0, false, remainderCount); - if (remainderCount != 0) { - Item* remainderItem = Item::CreateItem(item->getID(), remainderCount); - ReturnValue remaindRet = internalAddItem(player->getTile(), remainderItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - if (remaindRet != RETURNVALUE_NOERROR) { - ReleaseItem(remainderItem); - } - } - - if (ret != RETURNVALUE_NOERROR && dropOnMap) { - ret = internalAddItem(player->getTile(), item, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - - return ret; -} - -Item* Game::findItemOfType(Cylinder* cylinder, uint16_t itemId, - bool depthSearch /*= true*/, int32_t subType /*= -1*/) const -{ - if (cylinder == nullptr) { - return nullptr; - } - - std::vector containers; - for (size_t i = cylinder->getFirstIndex(), j = cylinder->getLastIndex(); i < j; ++i) { - Thing* thing = cylinder->getThing(i); - if (!thing) { - continue; - } - - Item* item = thing->getItem(); - if (!item) { - continue; - } - - if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { - return item; - } - - if (depthSearch) { - Container* container = item->getContainer(); - if (container) { - containers.push_back(container); - } - } - } - - size_t i = 0; - while (i < containers.size()) { - Container* container = containers[i++]; - for (Item* item : container->getItemList()) { - if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { - return item; - } - - Container* tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); - } - } - } - return nullptr; -} - -bool Game::removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) -{ - if (cylinder == nullptr) { - return false; - } - - if (money <= 0) { - return true; - } - - std::vector containers; - - std::multimap moneyMap; - uint64_t moneyCount = 0; - - for (size_t i = cylinder->getFirstIndex(), j = cylinder->getLastIndex(); i < j; ++i) { - Thing* thing = cylinder->getThing(i); - if (!thing) { - continue; - } - - Item* item = thing->getItem(); - if (!item) { - continue; - } - - Container* container = item->getContainer(); - if (container) { - containers.push_back(container); - } else { - int32_t worth = item->getWorth(); - if (worth != 0) { - moneyCount += worth; - moneyMap.emplace(worth, item); - } - } - } - - size_t i = 0; - while (i < containers.size()) { - Container* container = containers[i++]; - for (Item* item : container->getItemList()) { - Container* tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); - } else { - int32_t worth = item->getWorth(); - if (worth != 0) { - moneyCount += worth; - moneyMap.emplace(worth, item); - } - } - } - } - - if (moneyCount < money) { - return false; - } - - for (const auto& moneyEntry : moneyMap) { - Item* item = moneyEntry.second; - if (moneyEntry.first > money) { - uint32_t worth = moneyEntry.first / item->getItemCount(); - uint32_t removeCount = (money / worth) + 1; - - addMoney(cylinder, (worth * removeCount) - money, flags); - internalRemoveItem(item, removeCount); - money = 0; - } else { - internalRemoveItem(item); - money -= moneyEntry.first; - } - - if (money == 0) { - return true; - } - } - return false; -} - -void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) -{ - uint32_t crys = money / 10000; - money -= crys * 10000; - while (crys > 0) { - Item* remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, std::min(100, crys)); - - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - - crys -= std::min(100, crys); - } - - uint16_t plat = money / 100; - if (plat != 0) { - Item* remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, plat); - - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - - money -= plat * 100; - } - - if (money != 0) { - Item* remaindItem = Item::CreateItem(ITEM_GOLD_COIN, money); - - ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); - if (ret != RETURNVALUE_NOERROR) { - internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - } -} - -Item* Game::transformItem(Item* item, uint16_t newId, int32_t newCount /*= -1*/) -{ - if (item->getID() == newId && (newCount == -1 || (newCount == item->getSubType() && newCount != 0))) { //chargeless item placed on map = infinite - return item; - } - - Cylinder* cylinder = item->getParent(); - if (cylinder == nullptr) { - return nullptr; - } - - Tile* fromTile = cylinder->getTile(); - if (fromTile) { - auto it = browseFields.find(fromTile); - if (it != browseFields.end() && it->second == cylinder) { - cylinder = fromTile; - } - } - - int32_t itemIndex = cylinder->getThingIndex(item); - if (itemIndex == -1) { - return item; - } - - if (!item->canTransform()) { - return item; - } - - const ItemType& newType = Item::items[newId]; - if (newType.id == 0) { - return item; - } - - const ItemType& curType = Item::items[item->getID()]; - if (curType.alwaysOnTop != newType.alwaysOnTop) { - //This only occurs when you transform items on tiles from a downItem to a topItem (or vice versa) - //Remove the old, and add the new - cylinder->removeThing(item, item->getItemCount()); - cylinder->postRemoveNotification(item, cylinder, itemIndex); - - item->setID(newId); - if (newCount != -1) { - item->setSubType(newCount); - } - cylinder->addThing(item); - - Cylinder* newParent = item->getParent(); - if (newParent == nullptr) { - ReleaseItem(item); - return nullptr; - } - - newParent->postAddNotification(item, cylinder, newParent->getThingIndex(item)); - return item; - } - - if (curType.type == newType.type) { - //Both items has the same type so we can safely change id/subtype - if (newCount == 0 && (item->isStackable() || item->hasAttribute(ITEM_ATTRIBUTE_CHARGES))) { - if (item->isStackable()) { - internalRemoveItem(item); - return nullptr; - } else { - int32_t newItemId = newId; - - if (curType.id == newType.id) { - newItemId = curType.decayTo; - } - - if (newItemId < 0) { - internalRemoveItem(item); - return nullptr; - } else if (newItemId != newId) { - //Replacing the the old item with the new while maintaining the old position - Item* newItem = Item::CreateItem(newItemId, 1); - if (newItem == nullptr) { - return nullptr; - } - - cylinder->replaceThing(itemIndex, newItem); - cylinder->postAddNotification(newItem, cylinder, itemIndex); - - item->setParent(nullptr); - cylinder->postRemoveNotification(item, cylinder, itemIndex); - ReleaseItem(item); - return newItem; - } else { - return transformItem(item, newItemId); - } - } - } else { - cylinder->postRemoveNotification(item, cylinder, itemIndex); - uint16_t itemId = item->getID(); - int32_t count = item->getSubType(); - - if (curType.id != newType.id) { - if (newType.group != curType.group) { - item->setDefaultSubtype(); - } - - itemId = newId; - } - - if (newCount != -1 && newType.hasSubType()) { - count = newCount; - } - - cylinder->updateThing(item, itemId, count); - cylinder->postAddNotification(item, cylinder, itemIndex); - return item; - } - } - - //Replacing the the old item with the new while maintaining the old position - Item* newItem; - if (newCount == -1) { - newItem = Item::CreateItem(newId); - } else { - newItem = Item::CreateItem(newId, newCount); - } - - if (newItem == nullptr) { - return nullptr; - } - - cylinder->replaceThing(itemIndex, newItem); - cylinder->postAddNotification(newItem, cylinder, itemIndex); - - item->setParent(nullptr); - cylinder->postRemoveNotification(item, cylinder, itemIndex); - ReleaseItem(item); - - return newItem; -} - -ReturnValue Game::internalTeleport(Thing* thing, const Position& newPos, bool pushMove/* = true*/, uint32_t flags /*= 0*/) -{ - if (newPos == thing->getPosition()) { - return RETURNVALUE_NOERROR; - } else if (thing->isRemoved()) { - return RETURNVALUE_NOTPOSSIBLE; - } - - Tile* toTile = map.getTile(newPos); - if (!toTile) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (Creature* creature = thing->getCreature()) { - ReturnValue ret = toTile->queryAdd(0, *creature, 1, FLAG_NOLIMIT); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - map.moveCreature(*creature, *toTile, !pushMove); - return RETURNVALUE_NOERROR; - } else if (Item* item = thing->getItem()) { - return internalMoveItem(item->getParent(), toTile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr, flags); - } - return RETURNVALUE_NOTPOSSIBLE; -} - -//Implementation of player invoked events -void Game::playerMove(uint32_t playerId, Direction direction) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->resetIdleTime(); - player->setNextWalkActionTask(nullptr); - - player->startAutoWalk(std::forward_list { direction }); -} - -bool Game::playerBroadcastMessage(Player* player, const std::string& text) const -{ - if (!player->hasFlag(PlayerFlag_CanBroadcast)) { - return false; - } - - std::cout << "> " << player->getName() << " broadcasted: \"" << text << "\"." << std::endl; - - for (const auto& it : players) { - it.second->sendPrivateMessage(player, TALKTYPE_BROADCAST, text); - } - - return true; -} - -void Game::playerCreatePrivateChannel(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player || !player->isPremium()) { - return; - } - - ChatChannel* channel = g_chat->createChannel(*player, CHANNEL_PRIVATE); - if (!channel || !channel->addUser(*player)) { - return; - } - - player->sendCreatePrivateChannel(channel->getId(), channel->getName()); -} - -void Game::playerChannelInvite(uint32_t playerId, const std::string& name) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - PrivateChatChannel* channel = g_chat->getPrivateChannel(*player); - if (!channel) { - return; - } - - Player* invitePlayer = getPlayerByName(name); - if (!invitePlayer) { - return; - } - - if (player == invitePlayer) { - return; - } - - channel->invitePlayer(*player, *invitePlayer); -} - -void Game::playerChannelExclude(uint32_t playerId, const std::string& name) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - PrivateChatChannel* channel = g_chat->getPrivateChannel(*player); - if (!channel) { - return; - } - - Player* excludePlayer = getPlayerByName(name); - if (!excludePlayer) { - return; - } - - if (player == excludePlayer) { - return; - } - - channel->excludePlayer(*player, *excludePlayer); -} - -void Game::playerRequestChannels(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->sendChannelsDialog(); -} - -void Game::playerOpenChannel(uint32_t playerId, uint16_t channelId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - ChatChannel* channel = g_chat->addUserToChannel(*player, channelId); - if (!channel) { - return; - } - - const InvitedMap* invitedUsers = channel->getInvitedUsersPtr(); - const UsersMap* users; - if (!channel->isPublicChannel()) { - users = &channel->getUsers(); - } else { - users = nullptr; - } - - player->sendChannel(channel->getId(), channel->getName(), users, invitedUsers); -} - -void Game::playerCloseChannel(uint32_t playerId, uint16_t channelId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - g_chat->removeUserFromChannel(*player, channelId); -} - -void Game::playerOpenPrivateChannel(uint32_t playerId, std::string& receiver) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!IOLoginData::formatPlayerName(receiver)) { - player->sendCancelMessage("A player with this name does not exist."); - return; - } - - player->sendOpenPrivateChannel(receiver); -} - -void Game::playerCloseNpcChannel(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - SpectatorVec list; - map.getSpectators(list, player->getPosition()); - for (Creature* spectator : list) { - if (Npc* npc = spectator->getNpc()) { - npc->onPlayerCloseChannel(player); - } - } -} - -void Game::playerReceivePing(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->receivePing(); -} - -void Game::playerReceivePingBack(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->sendPingBack(); -} - -void Game::playerAutoWalk(uint32_t playerId, const std::forward_list& listDir) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->resetIdleTime(); - player->setNextWalkTask(nullptr); - player->startAutoWalk(listDir); -} - -void Game::playerStopAutoWalk(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->stopWalk(); -} - -void Game::playerUseItemEx(uint32_t playerId, const Position& fromPos, uint8_t fromStackPos, uint16_t fromSpriteId, - const Position& toPos, uint8_t toStackPos, uint16_t toSpriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - bool isHotkey = (fromPos.x == 0xFFFF && fromPos.y == 0 && fromPos.z == 0); - if (isHotkey && !g_config.getBoolean(ConfigManager::AIMBOT_HOTKEY_ENABLED)) { - return; - } - - Thing* thing = internalGetThing(player, fromPos, fromStackPos, fromSpriteId, STACKPOS_USEITEM); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Item* item = thing->getItem(); - if (!item || !item->isUseable() || item->getClientID() != fromSpriteId) { - player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); - return; - } - - Position walkToPos = fromPos; - ReturnValue ret = g_actions->canUse(player, fromPos); - if (ret == RETURNVALUE_NOERROR) { - ret = g_actions->canUse(player, toPos, item); - if (ret == RETURNVALUE_TOOFARAWAY) { - walkToPos = toPos; - } - } - - if (ret != RETURNVALUE_NOERROR) { - if (ret == RETURNVALUE_TOOFARAWAY) { - Position itemPos = fromPos; - uint8_t itemStackPos = fromStackPos; - - if (fromPos.x != 0xFFFF && toPos.x != 0xFFFF && Position::areInRange<1, 1, 0>(fromPos, player->getPosition()) && - !Position::areInRange<1, 1, 0>(fromPos, toPos)) { - Item* moveItem = nullptr; - - ret = internalMoveItem(item->getParent(), player, INDEX_WHEREEVER, item, item->getItemCount(), &moveItem); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - return; - } - - //changing the position since its now in the inventory of the player - internalGetPosition(moveItem, itemPos, itemStackPos); - } - - std::forward_list listDir; - if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerUseItemEx, this, - playerId, itemPos, itemStackPos, fromSpriteId, toPos, toStackPos, toSpriteId)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - player->sendCancelMessage(ret); - return; - } - - if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerUseItemEx, this, - playerId, fromPos, fromStackPos, fromSpriteId, toPos, toStackPos, toSpriteId)); - player->setNextActionTask(task); - return; - } - - player->resetIdleTime(); - player->setNextActionTask(nullptr); - - g_actions->useItemEx(player, fromPos, toPos, toStackPos, item, isHotkey); -} - -void Game::playerUseItem(uint32_t playerId, const Position& pos, uint8_t stackPos, - uint8_t index, uint16_t spriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - bool isHotkey = (pos.x == 0xFFFF && pos.y == 0 && pos.z == 0); - if (isHotkey && !g_config.getBoolean(ConfigManager::AIMBOT_HOTKEY_ENABLED)) { - return; - } - - Thing* thing = internalGetThing(player, pos, stackPos, spriteId, STACKPOS_USEITEM); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Item* item = thing->getItem(); - if (!item || item->isUseable() || item->getClientID() != spriteId) { - player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); - return; - } - - ReturnValue ret = g_actions->canUse(player, pos); - if (ret != RETURNVALUE_NOERROR) { - if (ret == RETURNVALUE_TOOFARAWAY) { - std::forward_list listDir; - if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerUseItem, this, - playerId, pos, stackPos, index, spriteId)); - player->setNextWalkActionTask(task); - return; - } - - ret = RETURNVALUE_THEREISNOWAY; - } - - player->sendCancelMessage(ret); - return; - } - - if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerUseItem, this, - playerId, pos, stackPos, index, spriteId)); - player->setNextActionTask(task); - return; - } - - player->resetIdleTime(); - player->setNextActionTask(nullptr); - - g_actions->useItem(player, pos, index, item, isHotkey); -} - -void Game::playerUseWithCreature(uint32_t playerId, const Position& fromPos, uint8_t fromStackPos, uint32_t creatureId, uint16_t spriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Creature* creature = getCreatureByID(creatureId); - if (!creature) { - return; - } - - if (!Position::areInRange<7, 5, 0>(creature->getPosition(), player->getPosition())) { - return; - } - - bool isHotkey = (fromPos.x == 0xFFFF && fromPos.y == 0 && fromPos.z == 0); - if (!g_config.getBoolean(ConfigManager::AIMBOT_HOTKEY_ENABLED)) { - if (creature->getPlayer() || isHotkey) { - player->sendCancelMessage(RETURNVALUE_DIRECTPLAYERSHOOT); - return; - } - } - - Thing* thing = internalGetThing(player, fromPos, fromStackPos, spriteId, STACKPOS_USEITEM); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Item* item = thing->getItem(); - if (!item || !item->isUseable() || item->getClientID() != spriteId) { - player->sendCancelMessage(RETURNVALUE_CANNOTUSETHISOBJECT); - return; - } - - Position toPos = creature->getPosition(); - Position walkToPos = fromPos; - ReturnValue ret = g_actions->canUse(player, fromPos); - if (ret == RETURNVALUE_NOERROR) { - ret = g_actions->canUse(player, toPos, item); - if (ret == RETURNVALUE_TOOFARAWAY) { - walkToPos = toPos; - } - } - - if (ret != RETURNVALUE_NOERROR) { - if (ret == RETURNVALUE_TOOFARAWAY) { - Position itemPos = fromPos; - uint8_t itemStackPos = fromStackPos; - - if (fromPos.x != 0xFFFF && Position::areInRange<1, 1, 0>(fromPos, player->getPosition()) && !Position::areInRange<1, 1, 0>(fromPos, toPos)) { - Item* moveItem = nullptr; - ret = internalMoveItem(item->getParent(), player, INDEX_WHEREEVER, item, item->getItemCount(), &moveItem); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - return; - } - - //changing the position since its now in the inventory of the player - internalGetPosition(moveItem, itemPos, itemStackPos); - } - - std::forward_list listDir; - if (player->getPathTo(walkToPos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerUseWithCreature, this, - playerId, itemPos, itemStackPos, creatureId, spriteId)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - player->sendCancelMessage(ret); - return; - } - - if (!player->canDoAction()) { - uint32_t delay = player->getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::playerUseWithCreature, this, - playerId, fromPos, fromStackPos, creatureId, spriteId)); - player->setNextActionTask(task); - return; - } - - player->resetIdleTime(); - player->setNextActionTask(nullptr); - - g_actions->useItemEx(player, fromPos, creature->getPosition(), creature->getParent()->getThingIndex(creature), item, isHotkey, creature); -} - -void Game::playerCloseContainer(uint32_t playerId, uint8_t cid) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->closeContainer(cid); - player->sendCloseContainer(cid); -} - -void Game::playerMoveUpContainer(uint32_t playerId, uint8_t cid) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Container* container = player->getContainerByID(cid); - if (!container) { - return; - } - - Container* parentContainer = dynamic_cast(container->getRealParent()); - if (!parentContainer) { - Tile* tile = container->getTile(); - if (!tile) { - return; - } - - auto it = browseFields.find(tile); - if (it == browseFields.end()) { - parentContainer = new Container(tile); - parentContainer->incrementReferenceCounter(); - browseFields[tile] = parentContainer; - g_scheduler.addEvent(createSchedulerTask(30000, std::bind(&Game::decreaseBrowseFieldRef, this, tile->getPosition()))); - } else { - parentContainer = it->second; - } - } - - player->addContainer(cid, parentContainer); - player->sendContainer(cid, parentContainer, parentContainer->hasParent(), player->getContainerIndex(cid)); -} - -void Game::playerUpdateContainer(uint32_t playerId, uint8_t cid) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Container* container = player->getContainerByID(cid); - if (!container) { - return; - } - - player->sendContainer(cid, container, container->hasParent(), player->getContainerIndex(cid)); -} - -void Game::playerRotateItem(uint32_t playerId, const Position& pos, uint8_t stackPos, const uint16_t spriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Thing* thing = internalGetThing(player, pos, stackPos, 0, STACKPOS_TOPDOWN_ITEM); - if (!thing) { - return; - } - - Item* item = thing->getItem(); - if (!item || item->getClientID() != spriteId || !item->isRotatable() || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - if (pos.x != 0xFFFF && !Position::areInRange<1, 1, 0>(pos, player->getPosition())) { - std::forward_list listDir; - if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerRotateItem, this, - playerId, pos, stackPos, spriteId)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - uint16_t newId = Item::items[item->getID()].rotateTo; - if (newId != 0) { - transformItem(item, newId); - } -} - -void Game::playerWriteItem(uint32_t playerId, uint32_t windowTextId, const std::string& text) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - uint16_t maxTextLength = 0; - uint32_t internalWindowTextId = 0; - - Item* writeItem = player->getWriteItem(internalWindowTextId, maxTextLength); - if (text.length() > maxTextLength || windowTextId != internalWindowTextId) { - return; - } - - if (!writeItem || writeItem->isRemoved()) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Cylinder* topParent = writeItem->getTopParent(); - - Player* owner = dynamic_cast(topParent); - if (owner && owner != player) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - if (!Position::areInRange<1, 1, 0>(writeItem->getPosition(), player->getPosition())) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - for (auto creatureEvent : player->getCreatureEvents(CREATURE_EVENT_TEXTEDIT)) { - if (!creatureEvent->executeTextEdit(player, writeItem, text)) { - player->setWriteItem(nullptr); - return; - } - } - - if (!text.empty()) { - if (writeItem->getText() != text) { - writeItem->setText(text); - writeItem->setWriter(player->getName()); - writeItem->setDate(time(nullptr)); - } - } else { - writeItem->resetText(); - writeItem->resetWriter(); - writeItem->resetDate(); - } - - uint16_t newId = Item::items[writeItem->getID()].writeOnceItemId; - if (newId != 0) { - transformItem(writeItem, newId); - } - - player->setWriteItem(nullptr); -} - -void Game::playerBrowseField(uint32_t playerId, const Position& pos) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - const Position& playerPos = player->getPosition(); - if (playerPos.z != pos.z) { - player->sendCancelMessage(playerPos.z > pos.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS); - return; - } - - if (!Position::areInRange<1, 1>(playerPos, pos)) { - std::forward_list listDir; - if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - SchedulerTask* task = createSchedulerTask(400, std::bind( - &Game::playerBrowseField, this, playerId, pos - )); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - Tile* tile = map.getTile(pos); - if (!tile) { - return; - } - - if (!g_events->eventPlayerOnBrowseField(player, pos)) { - return; - } - - Container* container; - - auto it = browseFields.find(tile); - if (it == browseFields.end()) { - container = new Container(tile); - container->incrementReferenceCounter(); - browseFields[tile] = container; - g_scheduler.addEvent(createSchedulerTask(30000, std::bind(&Game::decreaseBrowseFieldRef, this, tile->getPosition()))); - } else { - container = it->second; - } - - uint8_t dummyContainerId = 0xF - ((pos.x % 3) * 3 + (pos.y % 3)); - Container* openContainer = player->getContainerByID(dummyContainerId); - if (openContainer) { - player->onCloseContainer(openContainer); - player->closeContainer(dummyContainerId); - } else { - player->addContainer(dummyContainerId, container); - player->sendContainer(dummyContainerId, container, false, 0); - } -} - -void Game::playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_t index) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Container* container = player->getContainerByID(containerId); - if (!container || !container->hasPagination()) { - return; - } - - if ((index % container->capacity()) != 0 || index >= container->size()) { - return; - } - - player->setContainerIndex(containerId, index); - player->sendContainer(containerId, container, false, index); -} - -void Game::playerUpdateHouseWindow(uint32_t playerId, uint8_t listId, uint32_t windowTextId, const std::string& text) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - uint32_t internalWindowTextId; - uint32_t internalListId; - - House* house = player->getEditHouse(internalWindowTextId, internalListId); - if (house && internalWindowTextId == windowTextId && listId == 0) { - house->setAccessList(internalListId, text); - player->setEditHouse(nullptr); - } -} - -void Game::playerRequestTrade(uint32_t playerId, const Position& pos, uint8_t stackPos, - uint32_t tradePlayerId, uint16_t spriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Player* tradePartner = getPlayerByID(tradePlayerId); - if (!tradePartner || tradePartner == player) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "Sorry, not possible."); - return; - } - - if (!Position::areInRange<2, 2, 0>(tradePartner->getPosition(), player->getPosition())) { - std::ostringstream ss; - ss << tradePartner->getName() << " tells you to move closer."; - player->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - return; - } - - if (!canThrowObjectTo(tradePartner->getPosition(), player->getPosition())) { - player->sendCancelMessage(RETURNVALUE_CREATUREISNOTREACHABLE); - return; - } - - Thing* tradeThing = internalGetThing(player, pos, stackPos, 0, STACKPOS_TOPDOWN_ITEM); - if (!tradeThing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Item* tradeItem = tradeThing->getItem(); - if (tradeItem->getClientID() != spriteId || !tradeItem->isPickupable() || tradeItem->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - const Position& playerPosition = player->getPosition(); - const Position& tradeItemPosition = tradeItem->getPosition(); - if (playerPosition.z != tradeItemPosition.z) { - player->sendCancelMessage(playerPosition.z > tradeItemPosition.z ? RETURNVALUE_FIRSTGOUPSTAIRS : RETURNVALUE_FIRSTGODOWNSTAIRS); - return; - } - - if (!Position::areInRange<1, 1>(tradeItemPosition, playerPosition)) { - std::forward_list listDir; - if (player->getPathTo(pos, listDir, 0, 1, true, true)) { - g_dispatcher.addTask(createTask(std::bind(&Game::playerAutoWalk, - this, player->getID(), listDir))); - - SchedulerTask* task = createSchedulerTask(400, std::bind(&Game::playerRequestTrade, this, - playerId, pos, stackPos, tradePlayerId, spriteId)); - player->setNextWalkActionTask(task); - } else { - player->sendCancelMessage(RETURNVALUE_THEREISNOWAY); - } - return; - } - - Container* tradeItemContainer = tradeItem->getContainer(); - if (tradeItemContainer) { - for (const auto& it : tradeItems) { - Item* item = it.first; - if (tradeItem == item) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "This item is already being traded."); - return; - } - - if (tradeItemContainer->isHoldingItem(item)) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "This item is already being traded."); - return; - } - - Container* container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "This item is already being traded."); - return; - } - } - } else { - for (const auto& it : tradeItems) { - Item* item = it.first; - if (tradeItem == item) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "This item is already being traded."); - return; - } - - Container* container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "This item is already being traded."); - return; - } - } - } - - Container* tradeContainer = tradeItem->getContainer(); - if (tradeContainer && tradeContainer->getItemHoldingCount() + 1 > 100) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "You can not trade more than 100 items."); - return; - } - - if (!g_events->eventPlayerOnTradeRequest(player, tradePartner, tradeItem)) { - return; - } - - internalStartTrade(player, tradePartner, tradeItem); -} - -bool Game::internalStartTrade(Player* player, Player* tradePartner, Item* tradeItem) -{ - if (player->tradeState != TRADE_NONE && !(player->tradeState == TRADE_ACKNOWLEDGE && player->tradePartner == tradePartner)) { - player->sendCancelMessage(RETURNVALUE_YOUAREALREADYTRADING); - return false; - } else if (tradePartner->tradeState != TRADE_NONE && tradePartner->tradePartner != player) { - player->sendCancelMessage(RETURNVALUE_THISPLAYERISALREADYTRADING); - return false; - } - - player->tradePartner = tradePartner; - player->tradeItem = tradeItem; - player->tradeState = TRADE_INITIATED; - tradeItem->incrementReferenceCounter(); - tradeItems[tradeItem] = player->getID(); - - player->sendTradeItemRequest(player->getName(), tradeItem, true); - - if (tradePartner->tradeState == TRADE_NONE) { - std::ostringstream ss; - ss << player->getName() << " wants to trade with you."; - tradePartner->sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - tradePartner->tradeState = TRADE_ACKNOWLEDGE; - tradePartner->tradePartner = player; - } else { - Item* counterOfferItem = tradePartner->tradeItem; - player->sendTradeItemRequest(tradePartner->getName(), counterOfferItem, false); - tradePartner->sendTradeItemRequest(player->getName(), tradeItem, false); - } - - return true; -} - -void Game::playerAcceptTrade(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!(player->getTradeState() == TRADE_ACKNOWLEDGE || player->getTradeState() == TRADE_INITIATED)) { - return; - } - - Player* tradePartner = player->tradePartner; - if (!tradePartner) { - return; - } - - if (!canThrowObjectTo(tradePartner->getPosition(), player->getPosition())) { - player->sendCancelMessage(RETURNVALUE_CREATUREISNOTREACHABLE); - return; - } - - player->setTradeState(TRADE_ACCEPT); - - if (tradePartner->getTradeState() == TRADE_ACCEPT) { - Item* tradeItem1 = player->tradeItem; - Item* tradeItem2 = tradePartner->tradeItem; - - if (!g_events->eventPlayerOnTradeAccept(player, tradePartner, tradeItem1, tradeItem2)) { - internalCloseTrade(player); - return; - } - - player->setTradeState(TRADE_TRANSFER); - tradePartner->setTradeState(TRADE_TRANSFER); - - std::map::iterator it = tradeItems.find(tradeItem1); - if (it != tradeItems.end()) { - ReleaseItem(it->first); - tradeItems.erase(it); - } - - it = tradeItems.find(tradeItem2); - if (it != tradeItems.end()) { - ReleaseItem(it->first); - tradeItems.erase(it); - } - - bool isSuccess = false; - - ReturnValue ret1 = internalAddItem(tradePartner, tradeItem1, INDEX_WHEREEVER, 0, true); - ReturnValue ret2 = internalAddItem(player, tradeItem2, INDEX_WHEREEVER, 0, true); - if (ret1 == RETURNVALUE_NOERROR && ret2 == RETURNVALUE_NOERROR) { - ret1 = internalRemoveItem(tradeItem1, tradeItem1->getItemCount(), true); - ret2 = internalRemoveItem(tradeItem2, tradeItem2->getItemCount(), true); - if (ret1 == RETURNVALUE_NOERROR && ret2 == RETURNVALUE_NOERROR) { - Cylinder* cylinder1 = tradeItem1->getParent(); - Cylinder* cylinder2 = tradeItem2->getParent(); - - uint32_t count1 = tradeItem1->getItemCount(); - uint32_t count2 = tradeItem2->getItemCount(); - - ret1 = internalMoveItem(cylinder1, tradePartner, INDEX_WHEREEVER, tradeItem1, count1, nullptr, FLAG_IGNOREAUTOSTACK, nullptr, tradeItem2); - if (ret1 == RETURNVALUE_NOERROR) { - internalMoveItem(cylinder2, player, INDEX_WHEREEVER, tradeItem2, count2, nullptr, FLAG_IGNOREAUTOSTACK); - - tradeItem1->onTradeEvent(ON_TRADE_TRANSFER, tradePartner); - tradeItem2->onTradeEvent(ON_TRADE_TRANSFER, player); - - isSuccess = true; - } - } - } - - if (!isSuccess) { - std::string errorDescription; - - if (tradePartner->tradeItem) { - errorDescription = getTradeErrorDescription(ret1, tradeItem1); - tradePartner->sendTextMessage(MESSAGE_EVENT_ADVANCE, errorDescription); - tradePartner->tradeItem->onTradeEvent(ON_TRADE_CANCEL, tradePartner); - } - - if (player->tradeItem) { - errorDescription = getTradeErrorDescription(ret2, tradeItem2); - player->sendTextMessage(MESSAGE_EVENT_ADVANCE, errorDescription); - player->tradeItem->onTradeEvent(ON_TRADE_CANCEL, player); - } - } - - player->setTradeState(TRADE_NONE); - player->tradeItem = nullptr; - player->tradePartner = nullptr; - player->sendTradeClose(); - - tradePartner->setTradeState(TRADE_NONE); - tradePartner->tradeItem = nullptr; - tradePartner->tradePartner = nullptr; - tradePartner->sendTradeClose(); - } -} - -std::string Game::getTradeErrorDescription(ReturnValue ret, Item* item) -{ - if (item) { - if (ret == RETURNVALUE_NOTENOUGHCAPACITY) { - std::ostringstream ss; - ss << "You do not have enough capacity to carry"; - - if (item->isStackable() && item->getItemCount() > 1) { - ss << " these objects."; - } else { - ss << " this object."; - } - - ss << std::endl << ' ' << item->getWeightDescription(); - return ss.str(); - } else if (ret == RETURNVALUE_NOTENOUGHROOM || ret == RETURNVALUE_CONTAINERNOTENOUGHROOM) { - std::ostringstream ss; - ss << "You do not have enough room to carry"; - - if (item->isStackable() && item->getItemCount() > 1) { - ss << " these objects."; - } else { - ss << " this object."; - } - - return ss.str(); - } - } - return "Trade could not be completed."; -} - -void Game::playerLookInTrade(uint32_t playerId, bool lookAtCounterOffer, uint8_t index) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Player* tradePartner = player->tradePartner; - if (!tradePartner) { - return; - } - - Item* tradeItem; - if (lookAtCounterOffer) { - tradeItem = tradePartner->getTradeItem(); - } else { - tradeItem = player->getTradeItem(); - } - - if (!tradeItem) { - return; - } - - const Position& playerPosition = player->getPosition(); - const Position& tradeItemPosition = tradeItem->getPosition(); - - int32_t lookDistance = std::max(Position::getDistanceX(playerPosition, tradeItemPosition), - Position::getDistanceY(playerPosition, tradeItemPosition)); - if (index == 0) { - g_events->eventPlayerOnLookInTrade(player, tradePartner, tradeItem, lookDistance); - return; - } - - Container* tradeContainer = tradeItem->getContainer(); - if (!tradeContainer) { - return; - } - - std::vector containers {tradeContainer}; - size_t i = 0; - while (i < containers.size()) { - const Container* container = containers[i++]; - for (Item* item : container->getItemList()) { - Container* tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); - } - - if (--index == 0) { - g_events->eventPlayerOnLookInTrade(player, tradePartner, item, lookDistance); - return; - } - } - } -} - -void Game::playerCloseTrade(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - internalCloseTrade(player); -} - -void Game::internalCloseTrade(Player* player) -{ - Player* tradePartner = player->tradePartner; - if ((tradePartner && tradePartner->getTradeState() == TRADE_TRANSFER) || player->getTradeState() == TRADE_TRANSFER) { - return; - } - - if (player->getTradeItem()) { - std::map::iterator it = tradeItems.find(player->getTradeItem()); - if (it != tradeItems.end()) { - ReleaseItem(it->first); - tradeItems.erase(it); - } - - player->tradeItem->onTradeEvent(ON_TRADE_CANCEL, player); - player->tradeItem = nullptr; - } - - player->setTradeState(TRADE_NONE); - player->tradePartner = nullptr; - - player->sendTextMessage(MESSAGE_STATUS_SMALL, "Trade cancelled."); - player->sendTradeClose(); - - if (tradePartner) { - if (tradePartner->getTradeItem()) { - std::map::iterator it = tradeItems.find(tradePartner->getTradeItem()); - if (it != tradeItems.end()) { - ReleaseItem(it->first); - tradeItems.erase(it); - } - - tradePartner->tradeItem->onTradeEvent(ON_TRADE_CANCEL, tradePartner); - tradePartner->tradeItem = nullptr; - } - - tradePartner->setTradeState(TRADE_NONE); - tradePartner->tradePartner = nullptr; - - tradePartner->sendTextMessage(MESSAGE_STATUS_SMALL, "Trade cancelled."); - tradePartner->sendTradeClose(); - } -} - -void Game::playerPurchaseItem(uint32_t playerId, uint16_t spriteId, uint8_t count, uint8_t amount, - bool ignoreCap/* = false*/, bool inBackpacks/* = false*/) -{ - if (amount == 0 || amount > 100) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - int32_t onBuy, onSell; - - Npc* merchant = player->getShopOwner(onBuy, onSell); - if (!merchant) { - return; - } - - const ItemType& it = Item::items.getItemIdByClientId(spriteId); - if (it.id == 0) { - return; - } - - uint8_t subType; - if (it.isSplash() || it.isFluidContainer()) { - subType = clientFluidToServer(count); - } else { - subType = count; - } - - if (!player->hasShopItemForSale(it.id, subType)) { - return; - } - - merchant->onPlayerTrade(player, onBuy, it.id, subType, amount, ignoreCap, inBackpacks); -} - -void Game::playerSellItem(uint32_t playerId, uint16_t spriteId, uint8_t count, uint8_t amount, bool ignoreEquipped) -{ - if (amount == 0 || amount > 100) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - int32_t onBuy, onSell; - - Npc* merchant = player->getShopOwner(onBuy, onSell); - if (!merchant) { - return; - } - - const ItemType& it = Item::items.getItemIdByClientId(spriteId); - if (it.id == 0) { - return; - } - - uint8_t subType; - if (it.isSplash() || it.isFluidContainer()) { - subType = clientFluidToServer(count); - } else { - subType = count; - } - - merchant->onPlayerTrade(player, onSell, it.id, subType, amount, ignoreEquipped); -} - -void Game::playerCloseShop(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->closeShopWindow(); -} - -void Game::playerLookInShop(uint32_t playerId, uint16_t spriteId, uint8_t count) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - int32_t onBuy, onSell; - - Npc* merchant = player->getShopOwner(onBuy, onSell); - if (!merchant) { - return; - } - - const ItemType& it = Item::items.getItemIdByClientId(spriteId); - if (it.id == 0) { - return; - } - - int32_t subType; - if (it.isFluidContainer() || it.isSplash()) { - subType = clientFluidToServer(count); - } else { - subType = count; - } - - if (!player->hasShopItemForSale(it.id, subType)) { - return; - } - - if (!g_events->eventPlayerOnLookInShop(player, &it, subType)) { - return; - } - - std::ostringstream ss; - ss << "You see " << Item::getDescription(it, 1, nullptr, subType); - player->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); -} - -void Game::playerLookAt(uint32_t playerId, const Position& pos, uint8_t stackPos) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Thing* thing = internalGetThing(player, pos, stackPos, 0, STACKPOS_LOOK); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Position thingPos = thing->getPosition(); - if (!player->canSee(thingPos)) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return; - } - - Position playerPos = player->getPosition(); - - int32_t lookDistance; - if (thing != player) { - lookDistance = std::max(Position::getDistanceX(playerPos, thingPos), Position::getDistanceY(playerPos, thingPos)); - if (playerPos.z != thingPos.z) { - lookDistance += 15; - } - } else { - lookDistance = -1; - } - - g_events->eventPlayerOnLook(player, pos, thing, stackPos, lookDistance); -} - -void Game::playerLookInBattleList(uint32_t playerId, uint32_t creatureId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Creature* creature = getCreatureByID(creatureId); - if (!creature) { - return; - } - - if (!player->canSeeCreature(creature)) { - return; - } - - const Position& creaturePos = creature->getPosition(); - if (!player->canSee(creaturePos)) { - return; - } - - int32_t lookDistance; - if (creature != player) { - const Position& playerPos = player->getPosition(); - lookDistance = std::max(Position::getDistanceX(playerPos, creaturePos), Position::getDistanceY(playerPos, creaturePos)); - if (playerPos.z != creaturePos.z) { - lookDistance += 15; - } - } else { - lookDistance = -1; - } - - g_events->eventPlayerOnLookInBattleList(player, creature, lookDistance); -} - -void Game::playerCancelAttackAndFollow(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - playerSetAttackedCreature(playerId, 0); - playerFollowCreature(playerId, 0); - player->stopWalk(); -} - -void Game::playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (player->getAttackedCreature() && creatureId == 0) { - player->setAttackedCreature(nullptr); - player->sendCancelTarget(); - return; - } - - Creature* attackCreature = getCreatureByID(creatureId); - if (!attackCreature) { - player->setAttackedCreature(nullptr); - player->sendCancelTarget(); - return; - } - - ReturnValue ret = Combat::canTargetCreature(player, attackCreature); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - player->sendCancelTarget(); - player->setAttackedCreature(nullptr); - return; - } - - player->setAttackedCreature(attackCreature); - g_dispatcher.addTask(createTask(std::bind(&Game::updateCreatureWalk, this, player->getID()))); -} - -void Game::playerFollowCreature(uint32_t playerId, uint32_t creatureId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->setAttackedCreature(nullptr); - g_dispatcher.addTask(createTask(std::bind(&Game::updateCreatureWalk, this, player->getID()))); - player->setFollowCreature(getCreatureByID(creatureId)); -} - -void Game::playerSetFightModes(uint32_t playerId, fightMode_t fightMode, chaseMode_t chaseMode, bool secureMode) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->setFightMode(fightMode); - player->setChaseMode(chaseMode); - player->setSecureMode(secureMode); -} - -void Game::playerRequestAddVip(uint32_t playerId, const std::string& name) -{ - if (name.length() > 20) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Player* vipPlayer = getPlayerByName(name); - if (!vipPlayer) { - uint32_t guid; - bool specialVip; - std::string formattedName = name; - if (!IOLoginData::getGuidByNameEx(guid, specialVip, formattedName)) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "A player with this name does not exist."); - return; - } - - if (specialVip && !player->hasFlag(PlayerFlag_SpecialVIP)) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "You can not add this player."); - return; - } - - player->addVIP(guid, formattedName, VIPSTATUS_OFFLINE); - } else { - if (vipPlayer->hasFlag(PlayerFlag_SpecialVIP) && !player->hasFlag(PlayerFlag_SpecialVIP)) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "You can not add this player."); - return; - } - - if (!vipPlayer->isInGhostMode() || player->isAccessPlayer()) { - player->addVIP(vipPlayer->getGUID(), vipPlayer->getName(), VIPSTATUS_ONLINE); - } else { - player->addVIP(vipPlayer->getGUID(), vipPlayer->getName(), VIPSTATUS_OFFLINE); - } - } -} - -void Game::playerRequestRemoveVip(uint32_t playerId, uint32_t guid) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->removeVIP(guid); -} - -void Game::playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::string& description, uint32_t icon, bool notify) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->editVIP(guid, description, icon, notify); -} - -void Game::playerTurn(uint32_t playerId, Direction dir) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!g_events->eventPlayerOnTurn(player, dir)) { - return; - } - - player->resetIdleTime(); - internalCreatureTurn(player, dir); -} - -void Game::playerRequestOutfit(uint32_t playerId) -{ - if (!g_config.getBoolean(ConfigManager::ALLOW_CHANGEOUTFIT)) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->sendOutfitWindow(); -} - -void Game::playerToggleMount(uint32_t playerId, bool mount) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->toggleMount(mount); -} - -void Game::playerChangeOutfit(uint32_t playerId, Outfit_t outfit) -{ - if (!g_config.getBoolean(ConfigManager::ALLOW_CHANGEOUTFIT)) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (outfit.lookMount != 0) { - Mount* mount = mounts.getMountByClientID(outfit.lookMount); - if (!mount) { - return; - } - - if (!player->hasMount(mount)) { - return; - } - - if (player->isMounted()) { - Mount* prevMount = mounts.getMountByID(player->getCurrentMount()); - if (prevMount) { - changeSpeed(player, mount->speed - prevMount->speed); - } - - player->setCurrentMount(mount->id); - } else { - player->setCurrentMount(mount->id); - outfit.lookMount = 0; - } - } else if (player->isMounted()) { - player->dismount(); - } - - if (player->canWear(outfit.lookType, outfit.lookAddons)) { - player->defaultOutfit = outfit; - - if (player->hasCondition(CONDITION_OUTFIT)) { - return; - } - - internalCreatureChangeOutfit(player, outfit); - } -} - -void Game::playerShowQuestLog(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->sendQuestLog(); -} - -void Game::playerShowQuestLine(uint32_t playerId, uint16_t questId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Quest* quest = quests.getQuestByID(questId); - if (!quest) { - return; - } - - player->sendQuestLine(quest); -} - -void Game::playerSay(uint32_t playerId, uint16_t channelId, SpeakClasses type, - const std::string& receiver, const std::string& text) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->resetIdleTime(); - - uint32_t muteTime = player->isMuted(); - if (muteTime > 0) { - std::ostringstream ss; - ss << "You are still muted for " << muteTime << " seconds."; - player->sendTextMessage(MESSAGE_STATUS_SMALL, ss.str()); - return; - } - - if (playerSayCommand(player, text)) { - return; - } - - if (playerSaySpell(player, type, text)) { - return; - } - - if (!text.empty() && text.front() == '/' && player->isAccessPlayer()) { - return; - } - - if (type != TALKTYPE_PRIVATE_PN) { - player->removeMessageBuffer(); - } - - switch (type) { - case TALKTYPE_SAY: - internalCreatureSay(player, TALKTYPE_SAY, text, false); - break; - - case TALKTYPE_WHISPER: - playerWhisper(player, text); - break; - - case TALKTYPE_YELL: - playerYell(player, text); - break; - - case TALKTYPE_PRIVATE_TO: - case TALKTYPE_PRIVATE_RED_TO: - playerSpeakTo(player, type, receiver, text); - break; - - case TALKTYPE_CHANNEL_O: - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - g_chat->talkToChannel(*player, type, text, channelId); - break; - - case TALKTYPE_PRIVATE_PN: - playerSpeakToNpc(player, text); - break; - - case TALKTYPE_BROADCAST: - playerBroadcastMessage(player, text); - break; - - default: - break; - } -} - -bool Game::playerSayCommand(Player* player, const std::string& text) -{ - if (text.empty()) { - return false; - } - - char firstCharacter = text.front(); - for (char commandTag : commandTags) { - if (commandTag == firstCharacter) { - if (commands.exeCommand(*player, text)) { - return true; - } - } - } - return false; -} - -bool Game::playerSaySpell(Player* player, SpeakClasses type, const std::string& text) -{ - std::string words = text; - - TalkActionResult_t result = g_talkActions->playerSaySpell(player, type, words); - if (result == TALKACTION_BREAK) { - return true; - } - - result = g_spells->playerSaySpell(player, words); - if (result == TALKACTION_BREAK) { - if (!g_config.getBoolean(ConfigManager::EMOTE_SPELLS)) { - return internalCreatureSay(player, TALKTYPE_SAY, words, false); - } else { - return internalCreatureSay(player, TALKTYPE_MONSTER_SAY, words, false); - } - - } else if (result == TALKACTION_FAILED) { - return true; - } - - return false; -} - -void Game::playerWhisper(Player* player, const std::string& text) -{ - SpectatorVec list; - map.getSpectators(list, player->getPosition(), false, false, - Map::maxClientViewportX, Map::maxClientViewportX, - Map::maxClientViewportY, Map::maxClientViewportY); - - //send to client - for (Creature* spectator : list) { - if (Player* spectatorPlayer = spectator->getPlayer()) { - if (!Position::areInRange<1, 1>(player->getPosition(), spectatorPlayer->getPosition())) { - spectatorPlayer->sendCreatureSay(player, TALKTYPE_WHISPER, "pspsps"); - } else { - spectatorPlayer->sendCreatureSay(player, TALKTYPE_WHISPER, text); - } - } - } - - //event method - for (Creature* spectator : list) { - spectator->onCreatureSay(player, TALKTYPE_WHISPER, text); - } -} - -bool Game::playerYell(Player* player, const std::string& text) -{ - if (player->getLevel() == 1) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "You may not yell as long as you are on level 1."); - return false; - } - - if (player->hasCondition(CONDITION_YELLTICKS)) { - player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); - return false; - } - - if (player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_YELLTICKS, 30000, 0); - player->addCondition(condition); - } - - internalCreatureSay(player, TALKTYPE_YELL, asUpperCaseString(text), false); - return true; -} - -bool Game::playerSpeakTo(Player* player, SpeakClasses type, const std::string& receiver, - const std::string& text) -{ - Player* toPlayer = getPlayerByName(receiver); - if (!toPlayer) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "A player with this name is not online."); - return false; - } - - if (type == TALKTYPE_PRIVATE_RED_TO && (player->hasFlag(PlayerFlag_CanTalkRedPrivate) || player->getAccountType() >= ACCOUNT_TYPE_GAMEMASTER)) { - type = TALKTYPE_PRIVATE_RED_FROM; - } else { - type = TALKTYPE_PRIVATE_FROM; - } - - toPlayer->sendPrivateMessage(player, type, text); - toPlayer->onCreatureSay(player, type, text); - - if (toPlayer->isInGhostMode() && !player->isAccessPlayer()) { - player->sendTextMessage(MESSAGE_STATUS_SMALL, "A player with this name is not online."); - } else { - std::ostringstream ss; - ss << "Message sent to " << toPlayer->getName() << '.'; - player->sendTextMessage(MESSAGE_STATUS_SMALL, ss.str()); - } - return true; -} - -void Game::playerSpeakToNpc(Player* player, const std::string& text) -{ - SpectatorVec list; - map.getSpectators(list, player->getPosition()); - for (Creature* spectator : list) { - if (spectator->getNpc()) { - spectator->onCreatureSay(player, TALKTYPE_PRIVATE_PN, text); - } - } -} - -//-- -bool Game::canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight /*= true*/, - int32_t rangex /*= Map::maxClientViewportX*/, int32_t rangey /*= Map::maxClientViewportY*/) const -{ - return map.canThrowObjectTo(fromPos, toPos, checkLineOfSight, rangex, rangey); -} - -bool Game::isSightClear(const Position& fromPos, const Position& toPos, bool floorCheck) const -{ - return map.isSightClear(fromPos, toPos, floorCheck); -} - -bool Game::internalCreatureTurn(Creature* creature, Direction dir) -{ - if (creature->getDirection() == dir) { - return false; - } - - creature->setDirection(dir); - - //send to client - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureTurn(creature); - } - return true; -} - -bool Game::internalCreatureSay(Creature* creature, SpeakClasses type, const std::string& text, - bool ghostMode, SpectatorVec* listPtr/* = nullptr*/, const Position* pos/* = nullptr*/) -{ - if (text.empty()) { - return false; - } - - if (!pos) { - pos = &creature->getPosition(); - } - - SpectatorVec list; - - if (!listPtr || listPtr->empty()) { - // This somewhat complex construct ensures that the cached SpectatorVec - // is used if available and if it can be used, else a local vector is - // used (hopefully the compiler will optimize away the construction of - // the temporary when it's not used). - if (type != TALKTYPE_YELL && type != TALKTYPE_MONSTER_YELL) { - map.getSpectators(list, *pos, false, false, - Map::maxClientViewportX, Map::maxClientViewportX, - Map::maxClientViewportY, Map::maxClientViewportY); - } else { - map.getSpectators(list, *pos, true, false, 18, 18, 14, 14); - } - } else { - list = (*listPtr); - } - - //send to client - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - if (!ghostMode || tmpPlayer->canSeeCreature(creature)) { - tmpPlayer->sendCreatureSay(creature, type, text, pos); - } - } - } - - //event method - for (Creature* spectator : list) { - spectator->onCreatureSay(creature, type, text); - } - return true; -} - -void Game::checkCreatureWalk(uint32_t creatureId) -{ - Creature* creature = getCreatureByID(creatureId); - if (creature && creature->getHealth() > 0) { - creature->onWalk(); - cleanup(); - } -} - -void Game::updateCreatureWalk(uint32_t creatureId) -{ - Creature* creature = getCreatureByID(creatureId); - if (creature && creature->getHealth() > 0) { - creature->goToFollowCreature(); - } -} - -void Game::checkCreatureAttack(uint32_t creatureId) -{ - Creature* creature = getCreatureByID(creatureId); - if (creature && creature->getHealth() > 0) { - creature->onAttacking(0); - } -} - -void Game::addCreatureCheck(Creature* creature) -{ - creature->creatureCheck = true; - - if (creature->inCheckCreaturesVector) { - // already in a vector - return; - } - - creature->inCheckCreaturesVector = true; - checkCreatureLists[uniform_random(0, EVENT_CREATURECOUNT - 1)].push_back(creature); - creature->incrementReferenceCounter(); -} - -void Game::removeCreatureCheck(Creature* creature) -{ - if (creature->inCheckCreaturesVector) { - creature->creatureCheck = false; - } -} - -void Game::checkCreatures(size_t index) -{ - g_scheduler.addEvent(createSchedulerTask(EVENT_CHECK_CREATURE_INTERVAL, std::bind(&Game::checkCreatures, this, (index + 1) % EVENT_CREATURECOUNT))); - - auto& checkCreatureList = checkCreatureLists[index]; - auto it = checkCreatureList.begin(), end = checkCreatureList.end(); - while (it != end) { - Creature* creature = *it; - if (creature->creatureCheck) { - if (creature->getHealth() > 0) { - creature->onThink(EVENT_CREATURE_THINK_INTERVAL); - creature->onAttacking(EVENT_CREATURE_THINK_INTERVAL); - creature->executeConditions(EVENT_CREATURE_THINK_INTERVAL); - } else { - creature->onDeath(); - } - ++it; - } else { - creature->inCheckCreaturesVector = false; - it = checkCreatureList.erase(it); - ReleaseCreature(creature); - } - } - - cleanup(); -} - -void Game::changeSpeed(Creature* creature, int32_t varSpeedDelta) -{ - int32_t varSpeed = creature->getSpeed() - creature->getBaseSpeed(); - varSpeed += varSpeedDelta; - - creature->setSpeed(varSpeed); - - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), false, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendChangeSpeed(creature, creature->getStepSpeed()); - } -} - -void Game::internalCreatureChangeOutfit(Creature* creature, const Outfit_t& outfit) -{ - if (!g_events->eventCreatureOnChangeOutfit(creature, outfit)) { - return; - } - - creature->setCurrentOutfit(outfit); - - if (creature->isInvisible()) { - return; - } - - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureChangeOutfit(creature, outfit); - } -} - -void Game::internalCreatureChangeVisible(Creature* creature, bool visible) -{ - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureChangeVisible(creature, visible); - } -} - -void Game::changeLight(const Creature* creature) -{ - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureLight(creature); - } -} - -bool Game::combatBlockHit(CombatDamage& damage, Creature* attacker, Creature* target, bool checkDefense, bool checkArmor, bool field) -{ - if (damage.primary.type == COMBAT_NONE && damage.secondary.type == COMBAT_NONE) { - return true; - } - - if (target->getPlayer() && target->isInGhostMode()) { - return true; - } - - if (damage.primary.value > 0) { - return false; - } - - static const auto sendBlockEffect = [this](BlockType_t blockType, CombatType_t combatType, const Position& targetPos) { - if (blockType == BLOCK_DEFENSE) { - addMagicEffect(targetPos, CONST_ME_POFF); - } else if (blockType == BLOCK_ARMOR) { - addMagicEffect(targetPos, CONST_ME_BLOCKHIT); - } else if (blockType == BLOCK_IMMUNITY) { - uint8_t hitEffect = 0; - switch (combatType) { - case COMBAT_UNDEFINEDDAMAGE: { - return; - } - case COMBAT_ENERGYDAMAGE: - case COMBAT_FIREDAMAGE: - case COMBAT_PHYSICALDAMAGE: - case COMBAT_ICEDAMAGE: - case COMBAT_DEATHDAMAGE: { - hitEffect = CONST_ME_BLOCKHIT; - break; - } - case COMBAT_EARTHDAMAGE: { - hitEffect = CONST_ME_GREEN_RINGS; - break; - } - case COMBAT_HOLYDAMAGE: { - hitEffect = CONST_ME_HOLYDAMAGE; - break; - } - default: { - hitEffect = CONST_ME_POFF; - break; - } - } - addMagicEffect(targetPos, hitEffect); - } - }; - - BlockType_t primaryBlockType, secondaryBlockType; - if (damage.primary.type != COMBAT_NONE) { - damage.primary.value = -damage.primary.value; - primaryBlockType = target->blockHit(attacker, damage.primary.type, damage.primary.value, checkDefense, checkArmor, field); - - damage.primary.value = -damage.primary.value; - sendBlockEffect(primaryBlockType, damage.primary.type, target->getPosition()); - } else { - primaryBlockType = BLOCK_NONE; - } - - if (damage.secondary.type != COMBAT_NONE) { - damage.secondary.value = -damage.secondary.value; - secondaryBlockType = target->blockHit(attacker, damage.secondary.type, damage.secondary.value, false, false, field); - - damage.secondary.value = -damage.secondary.value; - sendBlockEffect(secondaryBlockType, damage.secondary.type, target->getPosition()); - } else { - secondaryBlockType = BLOCK_NONE; - } - return (primaryBlockType != BLOCK_NONE) && (secondaryBlockType != BLOCK_NONE); -} - -void Game::combatGetTypeInfo(CombatType_t combatType, Creature* target, TextColor_t& color, uint8_t& effect) -{ - switch (combatType) { - case COMBAT_PHYSICALDAMAGE: { - Item* splash = nullptr; - switch (target->getRace()) { - case RACE_VENOM: - color = TEXTCOLOR_LIGHTGREEN; - effect = CONST_ME_HITBYPOISON; - splash = Item::CreateItem(ITEM_SMALLSPLASH, FLUID_GREEN); - break; - case RACE_BLOOD: - color = TEXTCOLOR_RED; - effect = CONST_ME_DRAWBLOOD; - splash = Item::CreateItem(ITEM_SMALLSPLASH, FLUID_BLOOD); - break; - case RACE_UNDEAD: - color = TEXTCOLOR_LIGHTGREY; - effect = CONST_ME_HITAREA; - break; - case RACE_FIRE: - color = TEXTCOLOR_ORANGE; - effect = CONST_ME_DRAWBLOOD; - break; - case RACE_ENERGY: - color = TEXTCOLOR_PURPLE; - effect = CONST_ME_ENERGYHIT; - break; - default: - color = TEXTCOLOR_NONE; - effect = CONST_ME_NONE; - break; - } - - if (splash) { - internalAddItem(target->getTile(), splash, INDEX_WHEREEVER, FLAG_NOLIMIT); - startDecay(splash); - } - - break; - } - - case COMBAT_ENERGYDAMAGE: { - color = TEXTCOLOR_PURPLE; - effect = CONST_ME_ENERGYHIT; - break; - } - - case COMBAT_EARTHDAMAGE: { - color = TEXTCOLOR_LIGHTGREEN; - effect = CONST_ME_GREEN_RINGS; - break; - } - - case COMBAT_DROWNDAMAGE: { - color = TEXTCOLOR_LIGHTBLUE; - effect = CONST_ME_LOSEENERGY; - break; - } - case COMBAT_FIREDAMAGE: { - color = TEXTCOLOR_ORANGE; - effect = CONST_ME_HITBYFIRE; - break; - } - case COMBAT_ICEDAMAGE: { - color = TEXTCOLOR_SKYBLUE; - effect = CONST_ME_ICEATTACK; - break; - } - case COMBAT_HOLYDAMAGE: { - color = TEXTCOLOR_YELLOW; - effect = CONST_ME_HOLYDAMAGE; - break; - } - case COMBAT_DEATHDAMAGE: { - color = TEXTCOLOR_DARKRED; - effect = CONST_ME_SMALLCLOUDS; - break; - } - case COMBAT_LIFEDRAIN: { - color = TEXTCOLOR_RED; - effect = CONST_ME_MAGIC_RED; - break; - } - default: { - color = TEXTCOLOR_NONE; - effect = CONST_ME_NONE; - break; - } - } -} - -bool Game::combatChangeHealth(Creature* attacker, Creature* target, CombatDamage& damage) -{ - const Position& targetPos = target->getPosition(); - if (damage.primary.value > 0) { - if (target->getHealth() <= 0) { - return false; - } - - Player* attackerPlayer; - if (attacker) { - attackerPlayer = attacker->getPlayer(); - } else { - attackerPlayer = nullptr; - } - - Player* targetPlayer = target->getPlayer(); - if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) { - return false; - } - - if (damage.origin != ORIGIN_NONE) { - const auto& events = target->getCreatureEvents(CREATURE_EVENT_HEALTHCHANGE); - if (!events.empty()) { - for (CreatureEvent* creatureEvent : events) { - creatureEvent->executeHealthChange(target, attacker, damage); - } - damage.origin = ORIGIN_NONE; - return combatChangeHealth(attacker, target, damage); - } - } - - int32_t realHealthChange = target->getHealth(); - target->gainHealth(attacker, damage.primary.value); - realHealthChange = target->getHealth() - realHealthChange; - - if (realHealthChange > 0 && !target->isInGhostMode()) { - std::string damageString = std::to_string(realHealthChange) + (realHealthChange != 1 ? " hitpoints." : " hitpoint."); - - std::string spectatorMessage; - if (!attacker) { - spectatorMessage += ucfirst(target->getNameDescription()); - spectatorMessage += " was healed for " + damageString; - } else { - spectatorMessage += ucfirst(attacker->getNameDescription()); - spectatorMessage += " healed "; - if (attacker == target) { - spectatorMessage += (targetPlayer ? (targetPlayer->getSex() == PLAYERSEX_FEMALE ? "herself" : "himself") : "itself"); - } else { - spectatorMessage += target->getNameDescription(); - } - spectatorMessage += " for " + damageString; - } - - TextMessage message; - message.position = targetPos; - message.primary.value = realHealthChange; - message.primary.color = TEXTCOLOR_MAYABLUE; - - SpectatorVec list; - map.getSpectators(list, targetPos, false, true); - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - if (tmpPlayer == attackerPlayer && attackerPlayer != targetPlayer) { - message.type = MESSAGE_HEALED; - message.text = "You heal " + target->getNameDescription() + " for " + damageString; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_HEALED; - if (!attacker) { - message.text = "You were healed for " + damageString; - } else if (targetPlayer == attackerPlayer) { - message.text = "You heal yourself for " + damageString; - } else { - message.text = "You were healed by " + attacker->getNameDescription() + " for " + damageString; - } - } else { - message.type = MESSAGE_HEALED_OTHERS; - message.text = spectatorMessage; - } - tmpPlayer->sendTextMessage(message); - } - } - } else { - if (!target->isAttackable()) { - if (!target->isInGhostMode()) { - addMagicEffect(targetPos, CONST_ME_POFF); - } - return true; - } - - Player* attackerPlayer; - if (attacker) { - attackerPlayer = attacker->getPlayer(); - } else { - attackerPlayer = nullptr; - } - - Player* targetPlayer = target->getPlayer(); - if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) { - return false; - } - - damage.primary.value = std::abs(damage.primary.value); - damage.secondary.value = std::abs(damage.secondary.value); - - int32_t healthChange = damage.primary.value + damage.secondary.value; - if (healthChange == 0) { - return true; - } - - TextMessage message; - message.position = targetPos; - - SpectatorVec list; - if (target->hasCondition(CONDITION_MANASHIELD) && damage.primary.type != COMBAT_UNDEFINEDDAMAGE) { - int32_t manaDamage = std::min(target->getMana(), healthChange); - if (manaDamage != 0) { - if (damage.origin != ORIGIN_NONE) { - const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE); - if (!events.empty()) { - for (CreatureEvent* creatureEvent : events) { - creatureEvent->executeManaChange(target, attacker, healthChange, damage.origin); - } - if (healthChange == 0) { - return true; - } - manaDamage = std::min(target->getMana(), healthChange); - } - } - - target->drainMana(attacker, manaDamage); - map.getSpectators(list, targetPos, true, true); - addMagicEffect(list, targetPos, CONST_ME_LOSEENERGY); - - std::string damageString = std::to_string(manaDamage); - std::string spectatorMessage = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana"; - if (attacker) { - spectatorMessage += " due to "; - if (attacker == target) { - spectatorMessage += (targetPlayer ? (targetPlayer->getSex() == PLAYERSEX_FEMALE ? "her own attack" : "his own attack") : "its own attack"); - } else { - spectatorMessage += "an attack by " + attacker->getNameDescription(); - } - } - spectatorMessage += '.'; - - message.primary.value = manaDamage; - message.primary.color = TEXTCOLOR_BLUE; - - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - if (tmpPlayer->getPosition().z != targetPos.z) { - continue; - } - - if (tmpPlayer == attackerPlayer && attackerPlayer != targetPlayer) { - message.type = MESSAGE_DAMAGE_DEALT; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_DAMAGE_RECEIVED; - if (!attacker) { - message.text = "You lose " + damageString + " mana."; - } else if (targetPlayer == attackerPlayer) { - message.text = "You lose " + damageString + " mana due to your own attack."; - } else { - message.text = "You lose " + damageString + " mana due to an attack by " + attacker->getNameDescription() + '.'; - } - } else { - message.type = MESSAGE_DAMAGE_OTHERS; - message.text = spectatorMessage; - } - tmpPlayer->sendTextMessage(message); - } - - damage.primary.value -= manaDamage; - if (damage.primary.value < 0) { - damage.secondary.value = std::max(0, damage.secondary.value + damage.primary.value); - damage.primary.value = 0; - } - } - } - - int32_t realDamage = damage.primary.value + damage.secondary.value; - if (realDamage == 0) { - return true; - } - - if (damage.origin != ORIGIN_NONE) { - const auto& events = target->getCreatureEvents(CREATURE_EVENT_HEALTHCHANGE); - if (!events.empty()) { - for (CreatureEvent* creatureEvent : events) { - creatureEvent->executeHealthChange(target, attacker, damage); - } - damage.origin = ORIGIN_NONE; - return combatChangeHealth(attacker, target, damage); - } - } - - int32_t targetHealth = target->getHealth(); - if (damage.primary.value >= targetHealth) { - damage.primary.value = targetHealth; - damage.secondary.value = 0; - } else if (damage.secondary.value) { - damage.secondary.value = std::min(damage.secondary.value, targetHealth - damage.primary.value); - } - - realDamage = damage.primary.value + damage.secondary.value; - if (realDamage == 0) { - return true; - } else if (realDamage >= targetHealth) { - for (CreatureEvent* creatureEvent : target->getCreatureEvents(CREATURE_EVENT_PREPAREDEATH)) { - if (!creatureEvent->executeOnPrepareDeath(target, attacker)) { - return false; - } - } - } - - target->drainHealth(attacker, realDamage); - if (list.empty()) { - map.getSpectators(list, targetPos, true, true); - } - addCreatureHealth(list, target); - - message.primary.value = damage.primary.value; - message.secondary.value = damage.secondary.value; - - uint8_t hitEffect; - if (message.primary.value) { - combatGetTypeInfo(damage.primary.type, target, message.primary.color, hitEffect); - if (hitEffect != CONST_ME_NONE) { - addMagicEffect(list, targetPos, hitEffect); - } - } - - if (message.secondary.value) { - combatGetTypeInfo(damage.secondary.type, target, message.secondary.color, hitEffect); - if (hitEffect != CONST_ME_NONE) { - addMagicEffect(list, targetPos, hitEffect); - } - } - - if (message.primary.color != TEXTCOLOR_NONE || message.secondary.color != TEXTCOLOR_NONE) { - std::string damageString = std::to_string(realDamage) + (realDamage != 1 ? " hitpoints" : " hitpoint"); - std::string spectatorMessage = ucfirst(target->getNameDescription()) + " loses " + damageString; - if (attacker) { - spectatorMessage += " due to "; - if (attacker == target) { - spectatorMessage += (targetPlayer ? (targetPlayer->getSex() == PLAYERSEX_FEMALE ? "her own attack" : "his own attack") : "its own attack"); - } else { - spectatorMessage += "an attack by " + attacker->getNameDescription(); - } - } - spectatorMessage += '.'; - - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - if (tmpPlayer->getPosition().z != targetPos.z) { - continue; - } - - if (tmpPlayer == attackerPlayer && attackerPlayer != targetPlayer) { - message.type = MESSAGE_DAMAGE_DEALT; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_DAMAGE_RECEIVED; - if (!attacker) { - message.text = "You lose " + damageString + '.'; - } else if (targetPlayer == attackerPlayer) { - message.text = "You lose " + damageString + " due to your own attack."; - } else { - message.text = "You lose " + damageString + " due to an attack by " + attacker->getNameDescription() + '.'; - } - } else { - message.type = MESSAGE_DAMAGE_OTHERS; - // TODO: Avoid copying spectatorMessage everytime we send to a spectator - message.text = spectatorMessage; - } - tmpPlayer->sendTextMessage(message); - } - } - } - - return true; -} - -bool Game::combatChangeMana(Creature* attacker, Creature* target, int32_t manaChange, CombatOrigin origin) -{ - if (manaChange > 0) { - if (attacker) { - const Player* attackerPlayer = attacker->getPlayer(); - if (attackerPlayer && attackerPlayer->getSkull() == SKULL_BLACK && target->getPlayer() && attackerPlayer->getSkullClient(target) == SKULL_NONE) { - return false; - } - } - - if (origin != ORIGIN_NONE) { - const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE); - if (!events.empty()) { - for (CreatureEvent* creatureEvent : events) { - creatureEvent->executeManaChange(target, attacker, manaChange, origin); - } - return combatChangeMana(attacker, target, manaChange, ORIGIN_NONE); - } - } - - target->changeMana(manaChange); - } else { - const Position& targetPos = target->getPosition(); - if (!target->isAttackable()) { - if (!target->isInGhostMode()) { - addMagicEffect(targetPos, CONST_ME_POFF); - } - return false; - } - - Player* attackerPlayer; - if (attacker) { - attackerPlayer = attacker->getPlayer(); - } else { - attackerPlayer = nullptr; - } - - Player* targetPlayer = target->getPlayer(); - if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) { - return false; - } - - int32_t manaLoss = std::min(target->getMana(), -manaChange); - BlockType_t blockType = target->blockHit(attacker, COMBAT_MANADRAIN, manaLoss); - if (blockType != BLOCK_NONE) { - addMagicEffect(targetPos, CONST_ME_POFF); - return false; - } - - if (manaLoss <= 0) { - return true; - } - - if (origin != ORIGIN_NONE) { - const auto& events = target->getCreatureEvents(CREATURE_EVENT_MANACHANGE); - if (!events.empty()) { - for (CreatureEvent* creatureEvent : events) { - creatureEvent->executeManaChange(target, attacker, manaChange, origin); - } - return combatChangeMana(attacker, target, manaChange, ORIGIN_NONE); - } - } - - target->drainMana(attacker, manaLoss); - - std::string damageString = std::to_string(manaLoss); - std::string spectatorMessage = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana"; - if (attacker) { - spectatorMessage += " due to "; - if (attacker == target) { - spectatorMessage += (targetPlayer ? (targetPlayer->getSex() == PLAYERSEX_FEMALE ? "her own attack" : "his own attack") : "its own attack"); - } else { - spectatorMessage += "an attack by " + attacker->getNameDescription(); - } - } - spectatorMessage += '.'; - - TextMessage message; - message.position = targetPos; - message.primary.value = manaLoss; - message.primary.color = TEXTCOLOR_BLUE; - - SpectatorVec list; - map.getSpectators(list, targetPos, false, true); - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - if (tmpPlayer == attackerPlayer && attackerPlayer != targetPlayer) { - message.type = MESSAGE_DAMAGE_DEALT; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_DAMAGE_RECEIVED; - if (!attacker) { - message.text = "You lose " + damageString + " mana."; - } else if (targetPlayer == attackerPlayer) { - message.text = "You lose " + damageString + " mana due to your own attack."; - } else { - message.text = "You lose " + damageString + " mana due to an attack by " + attacker->getNameDescription() + '.'; - } - } else { - message.type = MESSAGE_DAMAGE_OTHERS; - message.text = spectatorMessage; - } - tmpPlayer->sendTextMessage(message); - } - } - - return true; -} - -void Game::addCreatureHealth(const Creature* target) -{ - SpectatorVec list; - map.getSpectators(list, target->getPosition(), true, true); - addCreatureHealth(list, target); -} - -void Game::addCreatureHealth(const SpectatorVec& list, const Creature* target) -{ - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendCreatureHealth(target); - } - } -} - -void Game::addMagicEffect(const Position& pos, uint8_t effect) -{ - SpectatorVec list; - map.getSpectators(list, pos, true, true); - addMagicEffect(list, pos, effect); -} - -void Game::addMagicEffect(const SpectatorVec& list, const Position& pos, uint8_t effect) -{ - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendMagicEffect(pos, effect); - } - } -} - -void Game::addDistanceEffect(const Position& fromPos, const Position& toPos, uint8_t effect) -{ - SpectatorVec list; - map.getSpectators(list, fromPos, false, true); - map.getSpectators(list, toPos, false, true); - addDistanceEffect(list, fromPos, toPos, effect); -} - -void Game::addDistanceEffect(const SpectatorVec& list, const Position& fromPos, const Position& toPos, uint8_t effect) -{ - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendDistanceShoot(fromPos, toPos, effect); - } - } -} - -void Game::startDecay(Item* item) -{ - if (!item || !item->canDecay()) { - return; - } - - ItemDecayState_t decayState = item->getDecaying(); - if (decayState == DECAYING_TRUE) { - return; - } - - if (item->getDuration() > 0) { - item->incrementReferenceCounter(); - item->setDecaying(DECAYING_TRUE); - toDecayItems.push_front(item); - } else { - internalDecayItem(item); - } -} - -void Game::internalDecayItem(Item* item) -{ - const ItemType& it = Item::items[item->getID()]; - if (it.decayTo != 0) { - Item* newItem = transformItem(item, it.decayTo); - startDecay(newItem); - } else { - ReturnValue ret = internalRemoveItem(item); - if (ret != RETURNVALUE_NOERROR) { - std::cout << "[Debug - Game::internalDecayItem] internalDecayItem failed, error code: " << static_cast(ret) << ", item id: " << item->getID() << std::endl; - } - } -} - -void Game::checkDecay() -{ - g_scheduler.addEvent(createSchedulerTask(EVENT_DECAYINTERVAL, std::bind(&Game::checkDecay, this))); - - size_t bucket = (lastBucket + 1) % EVENT_DECAY_BUCKETS; - - auto it = decayItems[bucket].begin(), end = decayItems[bucket].end(); - while (it != end) { - Item* item = *it; - if (!item->canDecay()) { - item->setDecaying(DECAYING_FALSE); - ReleaseItem(item); - it = decayItems[bucket].erase(it); - continue; - } - - int32_t duration = item->getDuration(); - int32_t decreaseTime = std::min(EVENT_DECAYINTERVAL * EVENT_DECAY_BUCKETS, duration); - - duration -= decreaseTime; - item->decreaseDuration(decreaseTime); - - if (duration <= 0) { - it = decayItems[bucket].erase(it); - internalDecayItem(item); - ReleaseItem(item); - } else if (duration < EVENT_DECAYINTERVAL * EVENT_DECAY_BUCKETS) { - it = decayItems[bucket].erase(it); - size_t newBucket = (bucket + ((duration + EVENT_DECAYINTERVAL / 2) / 1000)) % EVENT_DECAY_BUCKETS; - if (newBucket == bucket) { - internalDecayItem(item); - ReleaseItem(item); - } else { - decayItems[newBucket].push_back(item); - } - } else { - ++it; - } - } - - lastBucket = bucket; - cleanup(); -} - -void Game::checkLight() -{ - g_scheduler.addEvent(createSchedulerTask(EVENT_LIGHTINTERVAL, std::bind(&Game::checkLight, this))); - - lightHour += lightHourDelta; - - if (lightHour > 1440) { - lightHour -= 1440; - } - - if (std::abs(lightHour - SUNRISE) < 2 * lightHourDelta) { - lightState = LIGHT_STATE_SUNRISE; - } else if (std::abs(lightHour - SUNSET) < 2 * lightHourDelta) { - lightState = LIGHT_STATE_SUNSET; - } - - int32_t newLightLevel = lightLevel; - bool lightChange = false; - - switch (lightState) { - case LIGHT_STATE_SUNRISE: { - newLightLevel += (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT) / 30; - lightChange = true; - break; - } - case LIGHT_STATE_SUNSET: { - newLightLevel -= (LIGHT_LEVEL_DAY - LIGHT_LEVEL_NIGHT) / 30; - lightChange = true; - break; - } - default: - break; - } - - if (newLightLevel <= LIGHT_LEVEL_NIGHT) { - lightLevel = LIGHT_LEVEL_NIGHT; - lightState = LIGHT_STATE_NIGHT; - } else if (newLightLevel >= LIGHT_LEVEL_DAY) { - lightLevel = LIGHT_LEVEL_DAY; - lightState = LIGHT_STATE_DAY; - } else { - lightLevel = newLightLevel; - } - - if (lightChange) { - LightInfo lightInfo; - getWorldLightInfo(lightInfo); - - for (const auto& it : players) { - it.second->sendWorldLight(lightInfo); - } - } -} - -void Game::getWorldLightInfo(LightInfo& lightInfo) const -{ - lightInfo.level = lightLevel; - lightInfo.color = 0xD7; -} - -void Game::addCommandTag(char tag) -{ - for (char commandTag : commandTags) { - if (commandTag == tag) { - return; - } - } - commandTags.push_back(tag); -} - -void Game::resetCommandTag() -{ - commandTags.clear(); -} - -void Game::shutdown() -{ - std::cout << "Shutting down..." << std::flush; - - g_scheduler.shutdown(); - g_databaseTasks.shutdown(); - g_dispatcher.shutdown(); - map.spawns.clear(); - raids.clear(); - - cleanup(); - - if (serviceManager) { - serviceManager->stop(); - } - - ConnectionManager::getInstance().closeAll(); - - std::cout << " done!" << std::endl; -} - -void Game::cleanup() -{ - //free memory - for (auto creature : ToReleaseCreatures) { - creature->decrementReferenceCounter(); - } - ToReleaseCreatures.clear(); - - for (auto item : ToReleaseItems) { - item->decrementReferenceCounter(); - } - ToReleaseItems.clear(); - - for (Item* item : toDecayItems) { - const uint32_t dur = item->getDuration(); - if (dur >= EVENT_DECAYINTERVAL * EVENT_DECAY_BUCKETS) { - decayItems[lastBucket].push_back(item); - } else { - decayItems[(lastBucket + 1 + dur / 1000) % EVENT_DECAY_BUCKETS].push_back(item); - } - } - toDecayItems.clear(); -} - -void Game::ReleaseCreature(Creature* creature) -{ - ToReleaseCreatures.push_back(creature); -} - -void Game::ReleaseItem(Item* item) -{ - ToReleaseItems.push_back(item); -} - -void Game::broadcastMessage(const std::string& text, MessageClasses type) const -{ - std::cout << "> Broadcasted message: \"" << text << "\"." << std::endl; - for (const auto& it : players) { - it.second->sendTextMessage(type, text); - } -} - -void Game::updateCreatureWalkthrough(const Creature* creature) -{ - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - tmpPlayer->sendCreatureWalkthrough(creature, tmpPlayer->canWalkthroughEx(creature)); - } -} - -void Game::updateCreatureSkull(const Creature* creature) -{ - if (getWorldType() != WORLD_TYPE_PVP) { - return; - } - - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureSkull(creature); - } -} - -void Game::updatePlayerShield(Player* player) -{ - SpectatorVec list; - map.getSpectators(list, player->getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureShield(player); - } -} - -void Game::updatePlayerHelpers(const Player& player) -{ - uint32_t creatureId = player.getID(); - uint16_t helpers = player.getHelpers(); - - SpectatorVec list; - map.getSpectators(list, player.getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureHelpers(creatureId, helpers); - } -} - -void Game::updateCreatureType(Creature* creature) -{ - const Player* masterPlayer = nullptr; - - uint32_t creatureId = creature->getID(); - CreatureType_t creatureType = creature->getType(); - if (creatureType == CREATURETYPE_MONSTER) { - const Creature* master = creature->getMaster(); - if (master) { - masterPlayer = master->getPlayer(); - if (masterPlayer) { - creatureType = CREATURETYPE_SUMMON_OTHERS; - } - } - } - - //send to clients - SpectatorVec list; - map.getSpectators(list, creature->getPosition(), true, true); - - if (creatureType == CREATURETYPE_SUMMON_OTHERS) { - for (Creature* spectator : list) { - Player* player = spectator->getPlayer(); - if (masterPlayer == player) { - player->sendCreatureType(creatureId, CREATURETYPE_SUMMON_OWN); - } else { - player->sendCreatureType(creatureId, creatureType); - } - } - } else { - for (Creature* spectator : list) { - spectator->getPlayer()->sendCreatureType(creatureId, creatureType); - } - } -} - -void Game::updatePremium(Account& account) -{ - bool save = false; - time_t timeNow = time(nullptr); - - if (account.premiumDays != 0 && account.premiumDays != std::numeric_limits::max()) { - if (account.lastDay == 0) { - account.lastDay = timeNow; - save = true; - } else { - uint32_t days = (timeNow - account.lastDay) / 86400; - if (days > 0) { - if (days >= account.premiumDays) { - account.premiumDays = 0; - account.lastDay = 0; - } else { - account.premiumDays -= days; - time_t remainder = (timeNow - account.lastDay) % 86400; - account.lastDay = timeNow - remainder; - } - - save = true; - } - } - } else if (account.lastDay != 0) { - account.lastDay = 0; - save = true; - } - - if (save && !IOLoginData::saveAccount(account)) { - std::cout << "> ERROR: Failed to save account: " << account.name << "!" << std::endl; - } -} - -void Game::loadMotdNum() -{ - Database* db = Database::getInstance(); - - DBResult_ptr result = db->storeQuery("SELECT `value` FROM `server_config` WHERE `config` = 'motd_num'"); - if (result) { - motdNum = result->getNumber("value"); - } else { - db->executeQuery("INSERT INTO `server_config` (`config`, `value`) VALUES ('motd_num', '0')"); - } - - result = db->storeQuery("SELECT `value` FROM `server_config` WHERE `config` = 'motd_hash'"); - if (result) { - motdHash = result->getString("value"); - if (motdHash != transformToSHA1(g_config.getString(ConfigManager::MOTD))) { - ++motdNum; - } - } else { - db->executeQuery("INSERT INTO `server_config` (`config`, `value`) VALUES ('motd_hash', '')"); - } -} - -void Game::saveMotdNum() const -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "UPDATE `server_config` SET `value` = '" << motdNum << "' WHERE `config` = 'motd_num'"; - db->executeQuery(query.str()); - - query.str(std::string()); - query << "UPDATE `server_config` SET `value` = '" << transformToSHA1(g_config.getString(ConfigManager::MOTD)) << "' WHERE `config` = 'motd_hash'"; - db->executeQuery(query.str()); -} - -void Game::checkPlayersRecord() -{ - const size_t playersOnline = getPlayersOnline(); - if (playersOnline > playersRecord) { - uint32_t previousRecord = playersRecord; - playersRecord = playersOnline; - - for (const auto& it : g_globalEvents->getEventMap(GLOBALEVENT_RECORD)) { - it.second->executeRecord(playersRecord, previousRecord); - } - updatePlayersRecord(); - } -} - -void Game::updatePlayersRecord() const -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "UPDATE `server_config` SET `value` = '" << playersRecord << "' WHERE `config` = 'players_record'"; - db->executeQuery(query.str()); -} - -void Game::loadPlayersRecord() -{ - Database* db = Database::getInstance(); - - DBResult_ptr result = db->storeQuery("SELECT `value` FROM `server_config` WHERE `config` = 'players_record'"); - if (result) { - playersRecord = result->getNumber("value"); - } else { - db->executeQuery("INSERT INTO `server_config` (`config`, `value`) VALUES ('players_record', '0')"); - } -} - -uint64_t Game::getExperienceStage(uint32_t level) -{ - if (!stagesEnabled) { - return g_config.getNumber(ConfigManager::RATE_EXPERIENCE); - } - - if (useLastStageLevel && level >= lastStageLevel) { - return stages[lastStageLevel]; - } - - return stages[level]; -} - -bool Game::loadExperienceStages() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/stages.xml"); - if (!result) { - printXMLError("Error - Game::loadExperienceStages", "data/XML/stages.xml", result); - return false; - } - - for (auto stageNode : doc.child("stages").children()) { - if (strcasecmp(stageNode.name(), "config") == 0) { - stagesEnabled = stageNode.attribute("enabled").as_bool(); - } else { - uint32_t minLevel, maxLevel, multiplier; - - pugi::xml_attribute minLevelAttribute = stageNode.attribute("minlevel"); - if (minLevelAttribute) { - minLevel = pugi::cast(minLevelAttribute.value()); - } else { - minLevel = 1; - } - - pugi::xml_attribute maxLevelAttribute = stageNode.attribute("maxlevel"); - if (maxLevelAttribute) { - maxLevel = pugi::cast(maxLevelAttribute.value()); - } else { - maxLevel = 0; - lastStageLevel = minLevel; - useLastStageLevel = true; - } - - pugi::xml_attribute multiplierAttribute = stageNode.attribute("multiplier"); - if (multiplierAttribute) { - multiplier = pugi::cast(multiplierAttribute.value()); - } else { - multiplier = 1; - } - - if (useLastStageLevel) { - stages[lastStageLevel] = multiplier; - } else { - for (uint32_t i = minLevel; i <= maxLevel; ++i) { - stages[i] = multiplier; - } - } - } - } - return true; -} - -void Game::playerInviteToParty(uint32_t playerId, uint32_t invitedId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Player* invitedPlayer = getPlayerByID(invitedId); - if (!invitedPlayer || invitedPlayer->isInviting(player)) { - return; - } - - if (invitedPlayer->getParty()) { - std::ostringstream ss; - ss << invitedPlayer->getName() << " is already in a party."; - player->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - return; - } - - Party* party = player->getParty(); - if (!party) { - party = new Party(player); - } else if (party->getLeader() != player) { - return; - } - - party->invitePlayer(*invitedPlayer); -} - -void Game::playerJoinParty(uint32_t playerId, uint32_t leaderId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Player* leader = getPlayerByID(leaderId); - if (!leader || !leader->isInviting(player)) { - return; - } - - Party* party = leader->getParty(); - if (!party || party->getLeader() != leader) { - return; - } - - if (player->getParty()) { - player->sendTextMessage(MESSAGE_INFO_DESCR, "You are already in a party."); - return; - } - - party->joinParty(*player); -} - -void Game::playerRevokePartyInvitation(uint32_t playerId, uint32_t invitedId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Party* party = player->getParty(); - if (!party || party->getLeader() != player) { - return; - } - - Player* invitedPlayer = getPlayerByID(invitedId); - if (!invitedPlayer || !player->isInviting(invitedPlayer)) { - return; - } - - party->revokeInvitation(*invitedPlayer); -} - -void Game::playerPassPartyLeadership(uint32_t playerId, uint32_t newLeaderId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Party* party = player->getParty(); - if (!party || party->getLeader() != player) { - return; - } - - Player* newLeader = getPlayerByID(newLeaderId); - if (!newLeader || !player->isPartner(newLeader)) { - return; - } - - party->passPartyLeadership(newLeader); -} - -void Game::playerLeaveParty(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Party* party = player->getParty(); - if (!party || player->hasCondition(CONDITION_INFIGHT)) { - return; - } - - party->leaveParty(player); -} - -void Game::playerEnableSharedPartyExperience(uint32_t playerId, bool sharedExpActive) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Party* party = player->getParty(); - if (!party || player->hasCondition(CONDITION_INFIGHT)) { - return; - } - - party->setSharedExperience(player, sharedExpActive); -} - -void Game::sendGuildMotd(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - Guild* guild = player->getGuild(); - if (guild) { - player->sendChannelMessage("Message of the Day", guild->getMotd(), TALKTYPE_CHANNEL_R1, CHANNEL_GUILD); - } -} - -void Game::kickPlayer(uint32_t playerId, bool displayEffect) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->kickPlayer(displayEffect); -} - -void Game::playerReportBug(uint32_t playerId, const std::string& message, const Position& position, uint8_t category) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (player->getAccountType() == ACCOUNT_TYPE_NORMAL) { - return; - } - - std::string fileName = "data/reports/" + player->getName() + " report.txt"; - FILE* file = fopen(fileName.c_str(), "a"); - if (!file) { - player->sendTextMessage(MESSAGE_EVENT_DEFAULT, "There was an error when processing your report, please contact a gamemaster."); - return; - } - - const Position& playerPosition = player->getPosition(); - if (category == BUG_CATEGORY_MAP) { - fprintf(file, "------------------------------\nName: %s [Map Position: %u, %u, %u] [Player Position: %u, %u, %u]\nComment: %s\n", player->getName().c_str(), position.x, position.y, position.z, playerPosition.x, playerPosition.y, playerPosition.z, message.c_str()); - } else { - fprintf(file, "------------------------------\nName: %s [Player Position: %u, %u, %u]\nComment: %s\n", player->getName().c_str(), playerPosition.x, playerPosition.y, playerPosition.z, message.c_str()); - } - fclose(file); - - player->sendTextMessage(MESSAGE_EVENT_DEFAULT, "Your report has been sent to " + g_config.getString(ConfigManager::SERVER_NAME) + "."); -} - -void Game::playerDebugAssert(uint32_t playerId, const std::string& assertLine, const std::string& date, const std::string& description, const std::string& comment) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - // TODO: move debug assertions to database - FILE* file = fopen("client_assertions.txt", "a"); - if (file) { - fprintf(file, "----- %s - %s (%s) -----\n", formatDate(time(nullptr)).c_str(), player->getName().c_str(), convertIPToString(player->getIP()).c_str()); - fprintf(file, "%s\n%s\n%s\n%s\n", assertLine.c_str(), date.c_str(), description.c_str(), comment.c_str()); - fclose(file); - } -} - -void Game::playerLeaveMarket(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->setInMarket(false); -} - -void Game::playerBrowseMarket(uint32_t playerId, uint16_t spriteId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - const ItemType& it = Item::items.getItemIdByClientId(spriteId); - if (it.id == 0) { - return; - } - - if (it.wareId == 0) { - return; - } - - const MarketOfferList& buyOffers = IOMarket::getActiveOffers(MARKETACTION_BUY, it.id); - const MarketOfferList& sellOffers = IOMarket::getActiveOffers(MARKETACTION_SELL, it.id); - player->sendMarketBrowseItem(it.id, buyOffers, sellOffers); - player->sendMarketDetail(it.id); -} - -void Game::playerBrowseMarketOwnOffers(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - const MarketOfferList& buyOffers = IOMarket::getOwnOffers(MARKETACTION_BUY, player->getGUID()); - const MarketOfferList& sellOffers = IOMarket::getOwnOffers(MARKETACTION_SELL, player->getGUID()); - player->sendMarketBrowseOwnOffers(buyOffers, sellOffers); -} - -void Game::playerBrowseMarketOwnHistory(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - const HistoryMarketOfferList& buyOffers = IOMarket::getOwnHistory(MARKETACTION_BUY, player->getGUID()); - const HistoryMarketOfferList& sellOffers = IOMarket::getOwnHistory(MARKETACTION_SELL, player->getGUID()); - player->sendMarketBrowseOwnHistory(buyOffers, sellOffers); -} - -void Game::playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t spriteId, uint16_t amount, uint32_t price, bool anonymous) -{ - if (amount == 0 || amount > 64000) { - return; - } - - if (price == 0 || price > 999999999) { - return; - } - - if (type != MARKETACTION_BUY && type != MARKETACTION_SELL) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - if (g_config.getBoolean(ConfigManager::MARKET_PREMIUM) && !player->isPremium()) { - player->sendMarketLeave(); - return; - } - - const ItemType& itt = Item::items.getItemIdByClientId(spriteId); - if (itt.id == 0 || itt.wareId == 0) { - return; - } - - const ItemType& it = Item::items.getItemIdByClientId(itt.wareId); - if (it.id == 0 || it.wareId == 0) { - return; - } - - if (!it.stackable && amount > 2000) { - return; - } - - const uint32_t maxOfferCount = g_config.getNumber(ConfigManager::MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER); - if (maxOfferCount != 0 && IOMarket::getPlayerOfferCount(player->getGUID()) >= maxOfferCount) { - return; - } - - uint64_t fee = (price / 100.) * amount; - if (fee < 20) { - fee = 20; - } else if (fee > 1000) { - fee = 1000; - } - - if (type == MARKETACTION_SELL) { - if (fee > player->bankBalance) { - return; - } - - DepotChest* depotChest = player->getDepotChest(player->getLastDepotId(), false); - if (!depotChest) { - return; - } - - std::forward_list itemList = getMarketItemList(it.wareId, amount, depotChest, player->getInbox()); - if (itemList.empty()) { - return; - } - - if (it.stackable) { - uint16_t tmpAmount = amount; - for (Item* item : itemList) { - uint16_t removeCount = std::min(tmpAmount, item->getItemCount()); - tmpAmount -= removeCount; - internalRemoveItem(item, removeCount); - - if (tmpAmount == 0) { - break; - } - } - } else { - for (Item* item : itemList) { - internalRemoveItem(item); - } - } - - player->bankBalance -= fee; - } else { - uint64_t totalPrice = static_cast(price) * amount; - totalPrice += fee; - if (totalPrice > player->bankBalance) { - return; - } - - player->bankBalance -= totalPrice; - } - - IOMarket::createOffer(player->getGUID(), static_cast(type), it.id, amount, price, anonymous); - - player->sendMarketEnter(player->getLastDepotId()); - const MarketOfferList& buyOffers = IOMarket::getActiveOffers(MARKETACTION_BUY, it.id); - const MarketOfferList& sellOffers = IOMarket::getActiveOffers(MARKETACTION_SELL, it.id); - player->sendMarketBrowseItem(it.id, buyOffers, sellOffers); -} - -void Game::playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - MarketOfferEx offer = IOMarket::getOfferByCounter(timestamp, counter); - if (offer.id == 0 || offer.playerId != player->getGUID()) { - return; - } - - if (offer.type == MARKETACTION_BUY) { - player->bankBalance += static_cast(offer.price) * offer.amount; - player->sendMarketEnter(player->getLastDepotId()); - } else { - const ItemType& it = Item::items[offer.itemId]; - if (it.id == 0) { - return; - } - - if (it.stackable) { - uint16_t tmpAmount = offer.amount; - while (tmpAmount > 0) { - int32_t stackCount = std::min(100, tmpAmount); - Item* item = Item::CreateItem(it.id, stackCount); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - - tmpAmount -= stackCount; - } - } else { - int32_t subType; - if (it.charges != 0) { - subType = it.charges; - } else { - subType = -1; - } - - for (uint16_t i = 0; i < offer.amount; ++i) { - Item* item = Item::CreateItem(it.id, subType); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - } - } - } - - IOMarket::moveOfferToHistory(offer.id, OFFERSTATE_CANCELLED); - offer.amount = 0; - offer.timestamp += g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - player->sendMarketCancelOffer(offer); -} - -void Game::playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter, uint16_t amount) -{ - if (amount == 0 || amount > 64000) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->isInMarket()) { - return; - } - - MarketOfferEx offer = IOMarket::getOfferByCounter(timestamp, counter); - if (offer.id == 0) { - return; - } - - if (amount > offer.amount) { - return; - } - - const ItemType& it = Item::items[offer.itemId]; - if (it.id == 0) { - return; - } - - uint64_t totalPrice = static_cast(offer.price) * amount; - - if (offer.type == MARKETACTION_BUY) { - DepotChest* depotChest = player->getDepotChest(player->getLastDepotId(), false); - if (!depotChest) { - return; - } - - std::forward_list itemList = getMarketItemList(it.wareId, amount, depotChest, player->getInbox()); - if (itemList.empty()) { - return; - } - - Player* buyerPlayer = getPlayerByGUID(offer.playerId); - if (!buyerPlayer) { - buyerPlayer = new Player(nullptr); - if (!IOLoginData::loadPlayerById(buyerPlayer, offer.playerId)) { - delete buyerPlayer; - return; - } - } - - if (it.stackable) { - uint16_t tmpAmount = amount; - for (Item* item : itemList) { - uint16_t removeCount = std::min(tmpAmount, item->getItemCount()); - tmpAmount -= removeCount; - internalRemoveItem(item, removeCount); - - if (tmpAmount == 0) { - break; - } - } - } else { - for (Item* item : itemList) { - internalRemoveItem(item); - } - } - - player->bankBalance += totalPrice; - - if (it.stackable) { - uint16_t tmpAmount = amount; - while (tmpAmount > 0) { - uint16_t stackCount = std::min(100, tmpAmount); - Item* item = Item::CreateItem(it.id, stackCount); - if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - - tmpAmount -= stackCount; - } - } else { - int32_t subType; - if (it.charges != 0) { - subType = it.charges; - } else { - subType = -1; - } - - for (uint16_t i = 0; i < amount; ++i) { - Item* item = Item::CreateItem(it.id, subType); - if (internalAddItem(buyerPlayer->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - } - } - - if (buyerPlayer->isOffline()) { - IOLoginData::savePlayer(buyerPlayer); - delete buyerPlayer; - } else { - buyerPlayer->onReceiveMail(); - } - } else { - if (totalPrice > player->bankBalance) { - return; - } - - player->bankBalance -= totalPrice; - - if (it.stackable) { - uint16_t tmpAmount = amount; - while (tmpAmount > 0) { - uint16_t stackCount = std::min(100, tmpAmount); - Item* item = Item::CreateItem(it.id, stackCount); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - - tmpAmount -= stackCount; - } - } else { - int32_t subType; - if (it.charges != 0) { - subType = it.charges; - } else { - subType = -1; - } - - for (uint16_t i = 0; i < amount; ++i) { - Item* item = Item::CreateItem(it.id, subType); - if (internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - } - } - - Player* sellerPlayer = getPlayerByGUID(offer.playerId); - if (sellerPlayer) { - sellerPlayer->bankBalance += totalPrice; - } else { - IOLoginData::increaseBankBalance(offer.playerId, totalPrice); - } - - player->onReceiveMail(); - } - - const int32_t marketOfferDuration = g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - IOMarket::appendHistory(player->getGUID(), (offer.type == MARKETACTION_BUY ? MARKETACTION_SELL : MARKETACTION_BUY), offer.itemId, amount, offer.price, offer.timestamp + marketOfferDuration, OFFERSTATE_ACCEPTEDEX); - - IOMarket::appendHistory(offer.playerId, offer.type, offer.itemId, amount, offer.price, offer.timestamp + marketOfferDuration, OFFERSTATE_ACCEPTED); - - offer.amount -= amount; - - if (offer.amount == 0) { - IOMarket::deleteOffer(offer.id); - } else { - IOMarket::acceptOffer(offer.id, amount); - } - - player->sendMarketEnter(player->getLastDepotId()); - offer.timestamp += marketOfferDuration; - player->sendMarketAcceptOffer(offer); -} - -void Game::parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - for (CreatureEvent* creatureEvent : player->getCreatureEvents(CREATURE_EVENT_EXTENDED_OPCODE)) { - creatureEvent->executeExtendedOpcode(player, opcode, buffer); - } -} - -std::forward_list Game::getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotChest* depotChest, Inbox* inbox) -{ - std::forward_list itemList; - uint16_t count = 0; - - std::list containers { depotChest, inbox }; - do { - Container* container = containers.front(); - containers.pop_front(); - - for (Item* item : container->getItemList()) { - Container* c = item->getContainer(); - if (c && !c->empty()) { - containers.push_back(c); - continue; - } - - const ItemType& itemType = Item::items[item->getID()]; - if (itemType.wareId != wareId) { - continue; - } - - if (c && (!itemType.isContainer() || c->capacity() != itemType.maxItems)) { - continue; - } - - if (!item->hasMarketAttributes()) { - continue; - } - - itemList.push_front(item); - - count += Item::countByType(item, -1); - if (count >= sufficientCount) { - return itemList; - } - } - } while (!containers.empty()); - return std::forward_list(); -} - -void Game::forceAddCondition(uint32_t creatureId, Condition* condition) -{ - Creature* creature = getCreatureByID(creatureId); - if (!creature) { - delete condition; - return; - } - - creature->addCondition(condition, true); -} - -void Game::forceRemoveCondition(uint32_t creatureId, ConditionType_t type) -{ - Creature* creature = getCreatureByID(creatureId); - if (!creature) { - return; - } - - creature->removeCondition(type, true); -} - -void Game::sendOfflineTrainingDialog(Player* player) -{ - if (!player) { - return; - } - - if (!player->hasModalWindowOpen(offlineTrainingWindow.id)) { - player->sendModalWindow(offlineTrainingWindow); - } -} - -void Game::playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, uint8_t button, uint8_t choice) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - if (!player->hasModalWindowOpen(modalWindowId)) { - return; - } - - player->onModalWindowHandled(modalWindowId); - - // offline training, hardcoded - if (modalWindowId == std::numeric_limits::max()) { - if (button == 1) { - if (choice == SKILL_SWORD || choice == SKILL_AXE || choice == SKILL_CLUB || choice == SKILL_DISTANCE || choice == SKILL_MAGLEVEL) { - BedItem* bedItem = player->getBedItem(); - if (bedItem && bedItem->sleep(player)) { - player->setOfflineTrainingSkill(choice); - return; - } - } - } else { - player->sendTextMessage(MESSAGE_EVENT_ADVANCE, "Offline training aborted."); - } - - player->setBedItem(nullptr); - } else { - for (auto creatureEvent : player->getCreatureEvents(CREATURE_EVENT_MODALWINDOW)) { - creatureEvent->executeModalWindow(player, modalWindowId, button, choice); - } - } -} - -void Game::addPlayer(Player* player) -{ - const std::string& lowercase_name = asLowerCaseString(player->getName()); - mappedPlayerNames[lowercase_name] = player; - wildcardTree.insert(lowercase_name); - players[player->getID()] = player; -} - -void Game::removePlayer(Player* player) -{ - const std::string& lowercase_name = asLowerCaseString(player->getName()); - mappedPlayerNames.erase(lowercase_name); - wildcardTree.remove(lowercase_name); - players.erase(player->getID()); -} - -void Game::addNpc(Npc* npc) -{ - npcs[npc->getID()] = npc; -} - -void Game::removeNpc(Npc* npc) -{ - npcs.erase(npc->getID()); -} - -void Game::addMonster(Monster* monster) -{ - monsters[monster->getID()] = monster; -} - -void Game::removeMonster(Monster* monster) -{ - monsters.erase(monster->getID()); -} - -Guild* Game::getGuild(uint32_t id) const -{ - auto it = guilds.find(id); - if (it == guilds.end()) { - return nullptr; - } - return it->second; -} - -void Game::addGuild(Guild* guild) -{ - guilds[guild->getId()] = guild; -} - -void Game::removeGuild(uint32_t guildId) -{ - guilds.erase(guildId); -} - -void Game::decreaseBrowseFieldRef(const Position& pos) -{ - Tile* tile = map.getTile(pos.x, pos.y, pos.z); - if (!tile) { - return; - } - - auto it = browseFields.find(tile); - if (it != browseFields.end()) { - it->second->decrementReferenceCounter(); - } -} - -void Game::internalRemoveItems(std::vector itemList, uint32_t amount, bool stackable) -{ - if (stackable) { - for (Item* item : itemList) { - if (item->getItemCount() > amount) { - internalRemoveItem(item, amount); - break; - } else { - amount -= item->getItemCount(); - internalRemoveItem(item); - } - } - } else { - for (Item* item : itemList) { - internalRemoveItem(item); - } - } -} - -BedItem* Game::getBedBySleeper(uint32_t guid) const -{ - auto it = bedSleepersMap.find(guid); - if (it == bedSleepersMap.end()) { - return nullptr; - } - return it->second; -} - -void Game::setBedSleeper(BedItem* bed, uint32_t guid) -{ - bedSleepersMap[guid] = bed; -} - -void Game::removeBedSleeper(uint32_t guid) -{ - auto it = bedSleepersMap.find(guid); - if (it != bedSleepersMap.end()) { - bedSleepersMap.erase(it); - } -} - -Item* Game::getUniqueItem(uint16_t uniqueId) -{ - auto it = uniqueItems.find(uniqueId); - if (it == uniqueItems.end()) { - return nullptr; - } - return it->second; -} - -bool Game::addUniqueItem(uint16_t uniqueId, Item* item) -{ - auto result = uniqueItems.emplace(uniqueId, item); - if (!result.second) { - std::cout << "Duplicate unique id: " << uniqueId << std::endl; - } - return result.second; -} - -void Game::removeUniqueItem(uint16_t uniqueId) -{ - auto it = uniqueItems.find(uniqueId); - if (it != uniqueItems.end()) { - uniqueItems.erase(it); - } -} - -bool Game::hasEffect(uint8_t effectId) { - for (uint8_t i = CONST_ME_NONE; i <= CONST_ME_LAST; i++) { - MagicEffectClasses effect = static_cast(i); - if (effect == effectId) { - return true; - } - } - return false; -} - -bool Game::hasDistanceEffect(uint8_t effectId) { - for (uint8_t i = CONST_ANI_NONE; i <= CONST_ANI_LAST; i++) { - ShootType_t effect = static_cast(i); - if (effect == effectId) { - return true; - } - } - return false; -} diff --git a/path_10_8/src/game.h b/path_10_8/src/game.h deleted file mode 100644 index 7fe4b5da4..000000000 --- a/path_10_8/src/game.h +++ /dev/null @@ -1,578 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_GAME_H_3EC96D67DD024E6093B3BAC29B7A6D7F -#define FS_GAME_H_3EC96D67DD024E6093B3BAC29B7A6D7F - -#include "account.h" -#include "combat.h" -#include "commands.h" -#include "groups.h" -#include "map.h" -#include "position.h" -#include "item.h" -#include "container.h" -#include "player.h" -#include "raids.h" -#include "npc.h" -#include "wildcardtree.h" -#include "quests.h" - -class ServiceManager; -class Creature; -class Monster; -class Npc; -class CombatInfo; - -enum stackPosType_t { - STACKPOS_MOVE, - STACKPOS_LOOK, - STACKPOS_TOPDOWN_ITEM, - STACKPOS_USEITEM, - STACKPOS_USETARGET, -}; - -enum WorldType_t { - WORLD_TYPE_NO_PVP = 1, - WORLD_TYPE_PVP = 2, - WORLD_TYPE_PVP_ENFORCED = 3, -}; - -enum GameState_t { - GAME_STATE_STARTUP, - GAME_STATE_INIT, - GAME_STATE_NORMAL, - GAME_STATE_CLOSED, - GAME_STATE_SHUTDOWN, - GAME_STATE_CLOSING, - GAME_STATE_MAINTAIN, -}; - -enum LightState_t { - LIGHT_STATE_DAY, - LIGHT_STATE_NIGHT, - LIGHT_STATE_SUNSET, - LIGHT_STATE_SUNRISE, -}; - -#define EVENT_LIGHTINTERVAL 10000 -#define EVENT_DECAYINTERVAL 250 -#define EVENT_DECAY_BUCKETS 4 - -/** - * Main Game class. - * This class is responsible to control everything that happens - */ - -class Game -{ - public: - Game(); - ~Game(); - - // non-copyable - Game(const Game&) = delete; - Game& operator=(const Game&) = delete; - - void start(ServiceManager* manager); - - void forceAddCondition(uint32_t creatureId, Condition* condition); - void forceRemoveCondition(uint32_t creatureId, ConditionType_t type); - - bool loadMainMap(const std::string& filename); - void loadMap(const std::string& path); - - /** - * Get the map size - info purpose only - * \param width width of the map - * \param height height of the map - */ - void getMapDimensions(uint32_t& width, uint32_t& height) const { - width = map.width; - height = map.height; - } - - void setWorldType(WorldType_t type); - WorldType_t getWorldType() const { - return worldType; - } - - Cylinder* internalGetCylinder(Player* player, const Position& pos) const; - Thing* internalGetThing(Player* player, const Position& pos, int32_t index, - uint32_t spriteId, stackPosType_t type) const; - static void internalGetPosition(Item* item, Position& pos, uint8_t& stackpos); - - static std::string getTradeErrorDescription(ReturnValue ret, Item* item); - - /** - * Returns a creature based on the unique creature identifier - * \param id is the unique creature id to get a creature pointer to - * \returns A Creature pointer to the creature - */ - Creature* getCreatureByID(uint32_t id); - - /** - * Returns a monster based on the unique creature identifier - * \param id is the unique monster id to get a monster pointer to - * \returns A Monster pointer to the monster - */ - Monster* getMonsterByID(uint32_t id); - - /** - * Returns a npc based on the unique creature identifier - * \param id is the unique npc id to get a npc pointer to - * \returns A NPC pointer to the npc - */ - Npc* getNpcByID(uint32_t id); - - /** - * Returns a player based on the unique creature identifier - * \param id is the unique player id to get a player pointer to - * \returns A Pointer to the player - */ - Player* getPlayerByID(uint32_t id); - - /** - * Returns a creature based on a string name identifier - * \param s is the name identifier - * \returns A Pointer to the creature - */ - Creature* getCreatureByName(const std::string& s); - - /** - * Returns a npc based on a string name identifier - * \param s is the name identifier - * \returns A Pointer to the npc - */ - Npc* getNpcByName(const std::string& s); - - /** - * Returns a player based on a string name identifier - * \param s is the name identifier - * \returns A Pointer to the player - */ - Player* getPlayerByName(const std::string& s); - - /** - * Returns a player based on guid - * \returns A Pointer to the player - */ - Player* getPlayerByGUID(const uint32_t& guid); - - /** - * Returns a player based on a string name identifier, with support for the "~" wildcard. - * \param s is the name identifier, with or without wildcard - * \param player will point to the found player (if any) - * \return "RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE" or "RETURNVALUE_NAMEISTOOAMBIGIOUS" - */ - ReturnValue getPlayerByNameWildcard(const std::string& s, Player*& player); - - /** - * Returns a player based on an account number identifier - * \param acc is the account identifier - * \returns A Pointer to the player - */ - Player* getPlayerByAccount(uint32_t acc); - - /* Place Creature on the map without sending out events to the surrounding. - * \param creature Creature to place on the map - * \param pos The position to place the creature - * \param extendedPos If true, the creature will in first-hand be placed 2 tiles away - * \param forced If true, placing the creature will not fail because of obstacles (creatures/items) - */ - bool internalPlaceCreature(Creature* creature, const Position& pos, bool extendedPos = false, bool forced = false); - - /** - * Place Creature on the map. - * \param creature Creature to place on the map - * \param pos The position to place the creature - * \param extendedPos If true, the creature will in first-hand be placed 2 tiles away - * \param force If true, placing the creature will not fail because of obstacles (creatures/items) - */ - bool placeCreature(Creature* creature, const Position& pos, bool extendedPos = false, bool force = false); - - /** - * Remove Creature from the map. - * Removes the Creature the map - * \param c Creature to remove - */ - bool removeCreature(Creature* creature, bool isLogout = true); - - void addCreatureCheck(Creature* creature); - static void removeCreatureCheck(Creature* creature); - - size_t getPlayersOnline() const { - return players.size(); - } - size_t getMonstersOnline() const { - return monsters.size(); - } - size_t getNpcsOnline() const { - return npcs.size(); - } - uint32_t getPlayersRecord() const { - return playersRecord; - } - - void getWorldLightInfo(LightInfo& lightInfo) const; - - ReturnValue internalMoveCreature(Creature* creature, Direction direction, uint32_t flags = 0); - ReturnValue internalMoveCreature(Creature& creature, Tile& toTile, uint32_t flags = 0); - - ReturnValue internalMoveItem(Cylinder* fromCylinder, Cylinder* toCylinder, int32_t index, - Item* item, uint32_t count, Item** _moveItem, uint32_t flags = 0, Creature* actor = nullptr, Item* tradeItem = nullptr); - - ReturnValue internalAddItem(Cylinder* toCylinder, Item* item, int32_t index = INDEX_WHEREEVER, - uint32_t flags = 0, bool test = false); - ReturnValue internalAddItem(Cylinder* toCylinder, Item* item, int32_t index, - uint32_t flags, bool test, uint32_t& remainderCount); - ReturnValue internalRemoveItem(Item* item, int32_t count = -1, bool test = false, uint32_t flags = 0); - - ReturnValue internalPlayerAddItem(Player* player, Item* item, bool dropOnMap = true, slots_t slot = CONST_SLOT_WHEREEVER); - - /** - * Find an item of a certain type - * \param cylinder to search the item - * \param itemId is the item to remove - * \param subType is the extra type an item can have such as charges/fluidtype, default is -1 - * meaning it's not used - * \param depthSearch if true it will check child containers aswell - * \returns A pointer to the item to an item and nullptr if not found - */ - Item* findItemOfType(Cylinder* cylinder, uint16_t itemId, - bool depthSearch = true, int32_t subType = -1) const; - - /** - * Remove/Add item(s) with a monetary value - * \param cylinder to remove the money from - * \param money is the amount to remove - * \param flags optional flags to modifiy the default behaviour - * \returns true if the removal was successful - */ - bool removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags = 0); - - /** - * Add item(s) with monetary value - * \param cylinder which will receive money - * \param money the amount to give - * \param flags optional flags to modify default behavior - */ - void addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags = 0); - - /** - * Transform one item to another type/count - * \param item is the item to transform - * \param newId is the new itemid - * \param newCount is the new count value, use default value (-1) to not change it - * \returns true if the tranformation was successful - */ - Item* transformItem(Item* item, uint16_t newId, int32_t newCount = -1); - - /** - * Teleports an object to another position - * \param thing is the object to teleport - * \param newPos is the new position - * \param pushMove force teleport if false - * \param flags optional flags to modify default behavior - * \returns true if the teleportation was successful - */ - ReturnValue internalTeleport(Thing* thing, const Position& newPos, bool pushMove = true, uint32_t flags = 0); - - /** - * Turn a creature to a different direction. - * \param creature Creature to change the direction - * \param dir Direction to turn to - */ - bool internalCreatureTurn(Creature* creature, Direction dir); - - /** - * Creature wants to say something. - * \param creature Creature pointer - * \param type Type of message - * \param text The text to say - */ - bool internalCreatureSay(Creature* creature, SpeakClasses type, const std::string& text, - bool ghostMode, SpectatorVec* listPtr = nullptr, const Position* pos = nullptr); - - void loadPlayersRecord(); - void checkPlayersRecord(); - - void sendGuildMotd(uint32_t playerId); - void kickPlayer(uint32_t playerId, bool displayEffect); - void playerReportBug(uint32_t playerId, const std::string& message, const Position& position, uint8_t category); - void playerDebugAssert(uint32_t playerId, const std::string& assertLine, const std::string& date, const std::string& description, const std::string& comment); - void playerAnswerModalWindow(uint32_t playerId, uint32_t modalWindowId, uint8_t button, uint8_t choice); - - bool internalStartTrade(Player* player, Player* partner, Item* tradeItem); - void internalCloseTrade(Player* player); - bool playerBroadcastMessage(Player* player, const std::string& text) const; - void broadcastMessage(const std::string& text, MessageClasses type) const; - - //Implementation of player invoked events - void playerMoveThing(uint32_t playerId, const Position& fromPos, uint16_t spriteId, uint8_t fromStackPos, - const Position& toPos, uint8_t count); - void playerMoveCreatureByID(uint32_t playerId, uint32_t movingCreatureId, const Position& movingCreatureOrigPos, const Position& toPos); - void playerMoveCreature(Player* playerId, Creature* movingCreature, const Position& movingCreatureOrigPos, Tile* toTile); - void playerMoveItemByPlayerID(uint32_t playerId, const Position& fromPos, uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count); - void playerMoveItem(Player* player, const Position& fromPos, - uint16_t spriteId, uint8_t fromStackPos, const Position& toPos, uint8_t count, Item* item, Cylinder* toCylinder); - void playerMove(uint32_t playerId, Direction direction); - void playerCreatePrivateChannel(uint32_t playerId); - void playerChannelInvite(uint32_t playerId, const std::string& name); - void playerChannelExclude(uint32_t playerId, const std::string& name); - void playerRequestChannels(uint32_t playerId); - void playerOpenChannel(uint32_t playerId, uint16_t channelId); - void playerCloseChannel(uint32_t playerId, uint16_t channelId); - void playerOpenPrivateChannel(uint32_t playerId, std::string& receiver); - void playerCloseNpcChannel(uint32_t playerId); - void playerReceivePing(uint32_t playerId); - void playerReceivePingBack(uint32_t playerId); - void playerAutoWalk(uint32_t playerId, const std::forward_list& listDir); - void playerStopAutoWalk(uint32_t playerId); - void playerUseItemEx(uint32_t playerId, const Position& fromPos, uint8_t fromStackPos, - uint16_t fromSpriteId, const Position& toPos, uint8_t toStackPos, uint16_t toSpriteId); - void playerUseItem(uint32_t playerId, const Position& pos, uint8_t stackPos, uint8_t index, uint16_t spriteId); - void playerUseWithCreature(uint32_t playerId, const Position& fromPos, uint8_t fromStackPos, uint32_t creatureId, uint16_t spriteId); - void playerCloseContainer(uint32_t playerId, uint8_t cid); - void playerMoveUpContainer(uint32_t playerId, uint8_t cid); - void playerUpdateContainer(uint32_t playerId, uint8_t cid); - void playerRotateItem(uint32_t playerId, const Position& pos, uint8_t stackPos, const uint16_t spriteId); - void playerWriteItem(uint32_t playerId, uint32_t windowTextId, const std::string& text); - void playerBrowseField(uint32_t playerId, const Position& pos); - void playerSeekInContainer(uint32_t playerId, uint8_t containerId, uint16_t index); - void playerUpdateHouseWindow(uint32_t playerId, uint8_t listId, uint32_t windowTextId, const std::string& text); - void playerRequestTrade(uint32_t playerId, const Position& pos, uint8_t stackPos, - uint32_t tradePlayerId, uint16_t spriteId); - void playerAcceptTrade(uint32_t playerId); - void playerLookInTrade(uint32_t playerId, bool lookAtCounterOffer, uint8_t index); - void playerPurchaseItem(uint32_t playerId, uint16_t spriteId, uint8_t count, uint8_t amount, - bool ignoreCap = false, bool inBackpacks = false); - void playerSellItem(uint32_t playerId, uint16_t spriteId, uint8_t count, - uint8_t amount, bool ignoreEquipped = false); - void playerCloseShop(uint32_t playerId); - void playerLookInShop(uint32_t playerId, uint16_t spriteId, uint8_t count); - void playerCloseTrade(uint32_t playerId); - void playerSetAttackedCreature(uint32_t playerId, uint32_t creatureId); - void playerFollowCreature(uint32_t playerId, uint32_t creatureId); - void playerCancelAttackAndFollow(uint32_t playerId); - void playerSetFightModes(uint32_t playerId, fightMode_t fightMode, chaseMode_t chaseMode, bool secureMode); - void playerLookAt(uint32_t playerId, const Position& pos, uint8_t stackPos); - void playerLookInBattleList(uint32_t playerId, uint32_t creatureId); - void playerRequestAddVip(uint32_t playerId, const std::string& name); - void playerRequestRemoveVip(uint32_t playerId, uint32_t guid); - void playerRequestEditVip(uint32_t playerId, uint32_t guid, const std::string& description, uint32_t icon, bool notify); - void playerTurn(uint32_t playerId, Direction dir); - void playerRequestOutfit(uint32_t playerId); - void playerShowQuestLog(uint32_t playerId); - void playerShowQuestLine(uint32_t playerId, uint16_t questId); - void playerSay(uint32_t playerId, uint16_t channelId, SpeakClasses type, - const std::string& receiver, const std::string& text); - void playerChangeOutfit(uint32_t playerId, Outfit_t outfit); - void playerInviteToParty(uint32_t playerId, uint32_t invitedId); - void playerJoinParty(uint32_t playerId, uint32_t leaderId); - void playerRevokePartyInvitation(uint32_t playerId, uint32_t invitedId); - void playerPassPartyLeadership(uint32_t playerId, uint32_t newLeaderId); - void playerLeaveParty(uint32_t playerId); - void playerEnableSharedPartyExperience(uint32_t playerId, bool sharedExpActive); - void playerToggleMount(uint32_t playerId, bool mount); - void playerLeaveMarket(uint32_t playerId); - void playerBrowseMarket(uint32_t playerId, uint16_t spriteId); - void playerBrowseMarketOwnOffers(uint32_t playerId); - void playerBrowseMarketOwnHistory(uint32_t playerId); - void playerCreateMarketOffer(uint32_t playerId, uint8_t type, uint16_t spriteId, uint16_t amount, uint32_t price, bool anonymous); - void playerCancelMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter); - void playerAcceptMarketOffer(uint32_t playerId, uint32_t timestamp, uint16_t counter, uint16_t amount); - - void parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer); - - std::forward_list getMarketItemList(uint16_t wareId, uint16_t sufficientCount, DepotChest* depotChest, Inbox* inbox); - - static void updatePremium(Account& account); - - void cleanup(); - void shutdown(); - void ReleaseCreature(Creature* creature); - void ReleaseItem(Item* item); - - bool canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight = true, - int32_t rangex = Map::maxClientViewportX, int32_t rangey = Map::maxClientViewportY) const; - bool isSightClear(const Position& fromPos, const Position& toPos, bool sameFloor) const; - - void changeSpeed(Creature* creature, int32_t varSpeedDelta); - void internalCreatureChangeOutfit(Creature* creature, const Outfit_t& oufit); - void internalCreatureChangeVisible(Creature* creature, bool visible); - void changeLight(const Creature* creature); - void updateCreatureSkull(const Creature* player); - void updatePlayerShield(Player* player); - void updatePlayerHelpers(const Player& player); - void updateCreatureType(Creature* creature); - void updateCreatureWalkthrough(const Creature* creature); - - GameState_t getGameState() const; - void setGameState(GameState_t newState); - void saveGameState(); - - //Events - void checkCreatureWalk(uint32_t creatureId); - void updateCreatureWalk(uint32_t creatureId); - void checkCreatureAttack(uint32_t creatureId); - void checkCreatures(size_t index); - void checkLight(); - - bool combatBlockHit(CombatDamage& damage, Creature* attacker, Creature* target, bool checkDefense, bool checkArmor, bool field); - - void combatGetTypeInfo(CombatType_t combatType, Creature* target, TextColor_t& color, uint8_t& effect); - - bool combatChangeHealth(Creature* attacker, Creature* target, CombatDamage& damage); - bool combatChangeMana(Creature* attacker, Creature* target, int32_t manaChange, CombatOrigin origin); - - //animation help functions - void addCreatureHealth(const Creature* target); - static void addCreatureHealth(const SpectatorVec& list, const Creature* target); - void addMagicEffect(const Position& pos, uint8_t effect); - static void addMagicEffect(const SpectatorVec& list, const Position& pos, uint8_t effect); - void addDistanceEffect(const Position& fromPos, const Position& toPos, uint8_t effect); - static void addDistanceEffect(const SpectatorVec& list, const Position& fromPos, const Position& toPos, uint8_t effect); - - void addCommandTag(char tag); - void resetCommandTag(); - - void startDecay(Item* item); - int32_t getLightHour() const { - return lightHour; - } - - bool loadExperienceStages(); - uint64_t getExperienceStage(uint32_t level); - - void loadMotdNum(); - void saveMotdNum() const; - const std::string& getMotdHash() const { return motdHash; } - uint32_t getMotdNum() const { return motdNum; } - void incrementMotdNum() { motdNum++; } - - void sendOfflineTrainingDialog(Player* player); - - const std::unordered_map& getPlayers() const { return players; } - const std::map& getNpcs() const { return npcs; } - const std::map& getMonsters() const { return monsters; } - - void addPlayer(Player* player); - void removePlayer(Player* player); - - void addNpc(Npc* npc); - void removeNpc(Npc* npc); - - void addMonster(Monster* npc); - void removeMonster(Monster* npc); - - Guild* getGuild(uint32_t id) const; - void addGuild(Guild* guild); - void removeGuild(uint32_t guildId); - void decreaseBrowseFieldRef(const Position& pos); - - std::unordered_map browseFields; - - void internalRemoveItems(std::vector itemList, uint32_t amount, bool stackable); - - BedItem* getBedBySleeper(uint32_t guid) const; - void setBedSleeper(BedItem* bed, uint32_t guid); - void removeBedSleeper(uint32_t guid); - - Item* getUniqueItem(uint16_t uniqueId); - bool addUniqueItem(uint16_t uniqueId, Item* item); - void removeUniqueItem(uint16_t uniqueId); - - bool hasEffect(uint8_t effectId); - bool hasDistanceEffect(uint8_t effectId); - - Groups groups; - Map map; - Mounts mounts; - Raids raids; - Quests quests; - - protected: - bool playerSayCommand(Player* player, const std::string& text); - bool playerSaySpell(Player* player, SpeakClasses type, const std::string& text); - void playerWhisper(Player* player, const std::string& text); - bool playerYell(Player* player, const std::string& text); - bool playerSpeakTo(Player* player, SpeakClasses type, const std::string& receiver, const std::string& text); - void playerSpeakToNpc(Player* player, const std::string& text); - - void checkDecay(); - void internalDecayItem(Item* item); - - std::unordered_map players; - std::unordered_map mappedPlayerNames; - std::unordered_map guilds; - std::unordered_map uniqueItems; - std::map stages; - - std::list decayItems[EVENT_DECAY_BUCKETS]; - std::list checkCreatureLists[EVENT_CREATURECOUNT]; - - std::forward_list toDecayItems; - - std::vector ToReleaseCreatures; - std::vector ToReleaseItems; - std::vector commandTags; - - size_t lastBucket; - - WildcardTreeNode wildcardTree; - - std::map npcs; - std::map monsters; - - //list of items that are in trading state, mapped to the player - std::map tradeItems; - - std::map bedSleepersMap; - - ModalWindow offlineTrainingWindow; - Commands commands; - - static const int32_t LIGHT_LEVEL_DAY = 250; - static const int32_t LIGHT_LEVEL_NIGHT = 40; - static const int32_t SUNSET = 1305; - static const int32_t SUNRISE = 430; - - GameState_t gameState; - WorldType_t worldType; - - LightState_t lightState; - uint8_t lightLevel; - int32_t lightHour; - int32_t lightHourDelta; - - ServiceManager* serviceManager; - - void updatePlayersRecord() const; - uint32_t playersRecord; - - std::string motdHash; - uint32_t motdNum; - - uint32_t lastStageLevel; - bool stagesEnabled; - bool useLastStageLevel; -}; - -#endif diff --git a/path_10_8/src/globalevent.cpp b/path_10_8/src/globalevent.cpp deleted file mode 100644 index 13ff9f1e0..000000000 --- a/path_10_8/src/globalevent.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "globalevent.h" -#include "tools.h" -#include "scheduler.h" -#include "pugicast.h" - -extern ConfigManager g_config; - -GlobalEvents::GlobalEvents() : - m_scriptInterface("GlobalEvent Interface") -{ - m_scriptInterface.initState(); - thinkEventId = 0; - timerEventId = 0; -} - -GlobalEvents::~GlobalEvents() -{ - clear(); -} - -void GlobalEvents::clearMap(GlobalEventMap& map) -{ - for (const auto& it : map) { - delete it.second; - } - map.clear(); -} - -void GlobalEvents::clear() -{ - g_scheduler.stopEvent(thinkEventId); - thinkEventId = 0; - g_scheduler.stopEvent(timerEventId); - timerEventId = 0; - - clearMap(thinkMap); - clearMap(serverMap); - clearMap(timerMap); - - m_scriptInterface.reInitState(); -} - -Event* GlobalEvents::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "globalevent") != 0) { - return nullptr; - } - return new GlobalEvent(&m_scriptInterface); -} - -bool GlobalEvents::registerEvent(Event* event, const pugi::xml_node&) -{ - GlobalEvent* globalEvent = static_cast(event); //event is guaranteed to be a GlobalEvent - if (globalEvent->getEventType() == GLOBALEVENT_TIMER) { - auto result = timerMap.emplace(globalEvent->getName(), globalEvent); - if (result.second) { - if (timerEventId == 0) { - timerEventId = g_scheduler.addEvent(createSchedulerTask(SCHEDULER_MINTICKS, std::bind(&GlobalEvents::timer, this))); - } - return true; - } - } else if (globalEvent->getEventType() != GLOBALEVENT_NONE) { - auto result = serverMap.emplace(globalEvent->getName(), globalEvent); - if (result.second) { - return true; - } - } else { // think event - auto result = thinkMap.emplace(globalEvent->getName(), globalEvent); - if (result.second) { - if (thinkEventId == 0) { - thinkEventId = g_scheduler.addEvent(createSchedulerTask(SCHEDULER_MINTICKS, std::bind(&GlobalEvents::think, this))); - } - return true; - } - } - - std::cout << "[Warning - GlobalEvents::configureEvent] Duplicate registered globalevent with name: " << globalEvent->getName() << std::endl; - return false; -} - -void GlobalEvents::startup() const -{ - execute(GLOBALEVENT_STARTUP); -} - -void GlobalEvents::timer() -{ - time_t now = time(nullptr); - - int64_t nextScheduledTime = std::numeric_limits::max(); - - auto it = timerMap.begin(); - while (it != timerMap.end()) { - GlobalEvent* globalEvent = it->second; - - int64_t nextExecutionTime = globalEvent->getNextExecution() - now; - if (nextExecutionTime > 0) { - if (nextExecutionTime < nextScheduledTime) { - nextScheduledTime = nextExecutionTime; - } - - ++it; - continue; - } - - if (!globalEvent->executeEvent()) { - it = timerMap.erase(it); - continue; - } - - nextExecutionTime = 86400; - if (nextExecutionTime < nextScheduledTime) { - nextScheduledTime = nextExecutionTime; - } - - globalEvent->setNextExecution(globalEvent->getNextExecution() + nextExecutionTime); - - ++it; - } - - if (nextScheduledTime != std::numeric_limits::max()) { - timerEventId = g_scheduler.addEvent(createSchedulerTask(std::max(1000, nextScheduledTime * 1000), - std::bind(&GlobalEvents::timer, this))); - } -} - -void GlobalEvents::think() -{ - int64_t now = OTSYS_TIME(); - - int64_t nextScheduledTime = std::numeric_limits::max(); - for (const auto& it : thinkMap) { - GlobalEvent* globalEvent = it.second; - - int64_t nextExecutionTime = globalEvent->getNextExecution() - now; - if (nextExecutionTime > 0) { - if (nextExecutionTime < nextScheduledTime) { - nextScheduledTime = nextExecutionTime; - } - continue; - } - - if (!globalEvent->executeEvent()) { - std::cout << "[Error - GlobalEvents::think] Failed to execute event: " << globalEvent->getName() << std::endl; - } - - nextExecutionTime = globalEvent->getInterval(); - if (nextExecutionTime < nextScheduledTime) { - nextScheduledTime = nextExecutionTime; - } - - globalEvent->setNextExecution(globalEvent->getNextExecution() + nextExecutionTime); - } - - if (nextScheduledTime != std::numeric_limits::max()) { - thinkEventId = g_scheduler.addEvent(createSchedulerTask(nextScheduledTime, std::bind(&GlobalEvents::think, this))); - } -} - -void GlobalEvents::execute(GlobalEvent_t type) const -{ - for (const auto& it : serverMap) { - GlobalEvent* globalEvent = it.second; - if (globalEvent->getEventType() == type) { - globalEvent->executeEvent(); - } - } -} - -GlobalEventMap GlobalEvents::getEventMap(GlobalEvent_t type) -{ - switch (type) { - case GLOBALEVENT_NONE: return thinkMap; - case GLOBALEVENT_TIMER: return timerMap; - case GLOBALEVENT_STARTUP: - case GLOBALEVENT_SHUTDOWN: - case GLOBALEVENT_RECORD: { - GlobalEventMap retMap; - for (const auto& it : serverMap) { - if (it.second->getEventType() == type) { - retMap[it.first] = it.second; - } - } - return retMap; - } - default: return GlobalEventMap(); - } -} - -GlobalEvent::GlobalEvent(LuaScriptInterface* _interface): - Event(_interface) -{ - m_eventType = GLOBALEVENT_NONE; - m_nextExecution = 0; - m_interval = 0; -} - -bool GlobalEvent::configureEvent(const pugi::xml_node& node) -{ - pugi::xml_attribute nameAttribute = node.attribute("name"); - if (!nameAttribute) { - std::cout << "[Error - GlobalEvent::configureEvent] Missing name for a globalevent" << std::endl; - return false; - } - - m_name = nameAttribute.as_string(); - m_eventType = GLOBALEVENT_NONE; - - pugi::xml_attribute attr; - if ((attr = node.attribute("time"))) { - std::vector params = vectorAtoi(explodeString(attr.as_string(), ":")); - - int32_t hour = params.front(); - if (hour < 0 || hour > 23) { - std::cout << "[Error - GlobalEvent::configureEvent] Invalid hour \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; - return false; - } - - m_interval |= hour << 16; - - int32_t min = 0; - int32_t sec = 0; - if (params.size() > 1) { - min = params[1]; - if (min < 0 || min > 59) { - std::cout << "[Error - GlobalEvent::configureEvent] Invalid minute \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; - return false; - } - - if (params.size() > 2) { - sec = params[2]; - if (sec < 0 || sec > 59) { - std::cout << "[Error - GlobalEvent::configureEvent] Invalid second \"" << attr.as_string() << "\" for globalevent with name: " << m_name << std::endl; - return false; - } - } - } - - time_t current_time = time(nullptr); - tm* timeinfo = localtime(¤t_time); - timeinfo->tm_hour = hour; - timeinfo->tm_min = min; - timeinfo->tm_sec = sec; - - time_t difference = static_cast(difftime(mktime(timeinfo), current_time)); - if (difference < 0) { - difference += 86400; - } - - m_nextExecution = current_time + difference; - m_eventType = GLOBALEVENT_TIMER; - } else if ((attr = node.attribute("type"))) { - const char* value = attr.value(); - if (strcasecmp(value, "startup") == 0) { - m_eventType = GLOBALEVENT_STARTUP; - } else if (strcasecmp(value, "shutdown") == 0) { - m_eventType = GLOBALEVENT_SHUTDOWN; - } else if (strcasecmp(value, "record") == 0) { - m_eventType = GLOBALEVENT_RECORD; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No valid type \"" << attr.as_string() << "\" for globalevent with name " << m_name << std::endl; - return false; - } - } else if ((attr = node.attribute("interval"))) { - m_interval = std::max(SCHEDULER_MINTICKS, pugi::cast(attr.value())); - m_nextExecution = OTSYS_TIME() + m_interval; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No interval for globalevent with name " << m_name << std::endl; - return false; - } - return true; -} - -std::string GlobalEvent::getScriptEventName() const -{ - switch (m_eventType) { - case GLOBALEVENT_STARTUP: return "onStartup"; - case GLOBALEVENT_SHUTDOWN: return "onShutdown"; - case GLOBALEVENT_RECORD: return "onRecord"; - case GLOBALEVENT_TIMER: return "onTime"; - default: return "onThink"; - } -} - -bool GlobalEvent::executeRecord(uint32_t current, uint32_t old) -{ - //onRecord(current, old) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeRecord] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - lua_pushnumber(L, current); - lua_pushnumber(L, old); - return m_scriptInterface->callFunction(2); -} - -bool GlobalEvent::executeEvent() -{ - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeEvent] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_scriptId); - - int32_t params = 0; - if (m_eventType == GLOBALEVENT_NONE || m_eventType == GLOBALEVENT_TIMER) { - lua_pushnumber(L, m_interval); - params = 1; - } - - return m_scriptInterface->callFunction(params); -} diff --git a/path_10_8/src/globalevent.h b/path_10_8/src/globalevent.h deleted file mode 100644 index b0561f123..000000000 --- a/path_10_8/src/globalevent.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_GLOBALEVENT_H_B3FB9B848EA3474B9AFC326873947E3C -#define FS_GLOBALEVENT_H_B3FB9B848EA3474B9AFC326873947E3C -#include "baseevents.h" - -#include "const.h" - -enum GlobalEvent_t { - GLOBALEVENT_NONE, - GLOBALEVENT_TIMER, - - GLOBALEVENT_STARTUP, - GLOBALEVENT_SHUTDOWN, - GLOBALEVENT_RECORD, -}; - -class GlobalEvent; -typedef std::map GlobalEventMap; - -class GlobalEvents final : public BaseEvents -{ - public: - GlobalEvents(); - ~GlobalEvents(); - - // non-copyable - GlobalEvents(const GlobalEvents&) = delete; - GlobalEvents& operator=(const GlobalEvents&) = delete; - - void startup() const; - - void timer(); - void think(); - void execute(GlobalEvent_t type) const; - - GlobalEventMap getEventMap(GlobalEvent_t type); - static void clearMap(GlobalEventMap& map); - - protected: - std::string getScriptBaseName() const final { - return "globalevents"; - } - void clear() final; - - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - - LuaScriptInterface& getScriptInterface() final { - return m_scriptInterface; - } - LuaScriptInterface m_scriptInterface; - - GlobalEventMap thinkMap, serverMap, timerMap; - int32_t thinkEventId, timerEventId; -}; - -class GlobalEvent final : public Event -{ - public: - explicit GlobalEvent(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - - bool executeRecord(uint32_t current, uint32_t old); - bool executeEvent(); - - GlobalEvent_t getEventType() const { - return m_eventType; - } - std::string getName() const { - return m_name; - } - - uint32_t getInterval() const { - return m_interval; - } - - int64_t getNextExecution() const { - return m_nextExecution; - } - void setNextExecution(int64_t time) { - m_nextExecution = time; - } - - protected: - GlobalEvent_t m_eventType; - - std::string getScriptEventName() const final; - - std::string m_name; - int64_t m_nextExecution; - uint32_t m_interval; -}; - -#endif diff --git a/path_10_8/src/groups.cpp b/path_10_8/src/groups.cpp deleted file mode 100644 index 7eb526276..000000000 --- a/path_10_8/src/groups.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "groups.h" - -#include "pugicast.h" -#include "tools.h" - -bool Groups::load() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/groups.xml"); - if (!result) { - printXMLError("Error - Groups::load", "data/XML/groups.xml", result); - return false; - } - - for (auto groupNode : doc.child("groups").children()) { - Group group; - group.id = pugi::cast(groupNode.attribute("id").value()); - group.name = groupNode.attribute("name").as_string(); - group.flags = pugi::cast(groupNode.attribute("flags").value()); - group.access = groupNode.attribute("access").as_bool(); - group.maxDepotItems = pugi::cast(groupNode.attribute("maxdepotitems").value()); - group.maxVipEntries = pugi::cast(groupNode.attribute("maxvipentries").value()); - groups.push_back(group); - } - return true; -} - -Group* Groups::getGroup(uint16_t id) -{ - for (Group& group : groups) { - if (group.id == id) { - return &group; - } - } - return nullptr; -} diff --git a/path_10_8/src/groups.h b/path_10_8/src/groups.h deleted file mode 100644 index ff275bf42..000000000 --- a/path_10_8/src/groups.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_GROUPS_H_EE39438337D148E1983FB79D936DD8F3 -#define FS_GROUPS_H_EE39438337D148E1983FB79D936DD8F3 - -struct Group { - std::string name; - uint64_t flags; - uint32_t maxDepotItems; - uint32_t maxVipEntries; - uint16_t id; - bool access; -}; - -class Groups { - public: - bool load(); - Group* getGroup(uint16_t id); - - private: - std::vector groups; -}; - -#endif diff --git a/path_10_8/src/guild.cpp b/path_10_8/src/guild.cpp deleted file mode 100644 index b1f601be6..000000000 --- a/path_10_8/src/guild.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "guild.h" - -#include "game.h" - -extern Game g_game; - -void Guild::addMember(Player* player) -{ - membersOnline.push_back(player); - for (Player* member : membersOnline) { - g_game.updatePlayerHelpers(*member); - } -} - -void Guild::removeMember(Player* player) -{ - membersOnline.remove(player); - for (Player* member : membersOnline) { - g_game.updatePlayerHelpers(*member); - } - g_game.updatePlayerHelpers(*player); - - if (membersOnline.empty()) { - g_game.removeGuild(id); - delete this; - } -} - -GuildRank* Guild::getRankById(uint32_t rankId) -{ - for (size_t i = 0; i < ranks.size(); ++i) { - if (ranks[i].id == rankId) { - return &ranks[i]; - } - } - return nullptr; -} - -const GuildRank* Guild::getRankByLevel(uint8_t level) const -{ - for (size_t i = 0; i < ranks.size(); ++i) { - if (ranks[i].level == level) { - return &ranks[i]; - } - } - return nullptr; -} - -void Guild::addRank(uint32_t rankId, const std::string& rankName, uint8_t level) -{ - ranks.emplace_back(rankId, rankName, level); -} diff --git a/path_10_8/src/guild.h b/path_10_8/src/guild.h deleted file mode 100644 index 6193e42d8..000000000 --- a/path_10_8/src/guild.h +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_GUILD_H_C00F0A1D732E4BA88FF62ACBE74D76BC -#define FS_GUILD_H_C00F0A1D732E4BA88FF62ACBE74D76BC - -class Player; - -struct GuildRank { - uint32_t id; - std::string name; - uint8_t level; - - GuildRank(uint32_t id, std::string name, uint8_t level) : id(id), name(name), level(level) {} -}; - -class Guild -{ - public: - Guild(uint32_t id, std::string name) : name(name), id(id), memberCount(0) {} - - void addMember(Player* player); - void removeMember(Player* player); - - uint32_t getId() const { - return id; - } - const std::string& getName() const { - return name; - } - const std::list& getMembersOnline() const { - return membersOnline; - } - uint32_t getMemberCount() const { - return memberCount; - } - void setMemberCount(uint32_t count) { - memberCount = count; - } - - GuildRank* getRankById(uint32_t id); - const GuildRank* getRankByLevel(uint8_t level) const; - void addRank(uint32_t id, const std::string& name, uint8_t level); - - const std::string& getMotd() const { - return motd; - } - void setMotd(const std::string& motd) { - this->motd = motd; - } - - private: - std::list membersOnline; - std::vector ranks; - std::string name; - std::string motd; - uint32_t id; - uint32_t memberCount; -}; - -#endif diff --git a/path_10_8/src/house.cpp b/path_10_8/src/house.cpp deleted file mode 100644 index 1201ceb1f..000000000 --- a/path_10_8/src/house.cpp +++ /dev/null @@ -1,754 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "pugicast.h" - -#include "house.h" -#include "iologindata.h" -#include "game.h" -#include "configmanager.h" -#include "bed.h" - -extern ConfigManager g_config; -extern Game g_game; - -House::House(uint32_t _houseid) : - transfer_container(ITEM_LOCKER1) -{ - isLoaded = false; - owner = 0; - posEntry.x = 0; - posEntry.y = 0; - posEntry.z = 0; - paidUntil = 0; - id = _houseid; - rentWarnings = 0; - rent = 0; - townid = 0; - transferItem = nullptr; -} - -void House::addTile(HouseTile* tile) -{ - tile->setFlag(TILESTATE_PROTECTIONZONE); - houseTiles.push_back(tile); -} - -void House::setOwner(uint32_t guid, bool updateDatabase/* = true*/, Player* player/* = nullptr*/) -{ - if (updateDatabase && owner != guid) { - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "UPDATE `houses` SET `owner` = " << guid << ", `bid` = 0, `bid_end` = 0, `last_bid` = 0, `highest_bidder` = 0 WHERE `id` = " << id; - db->executeQuery(query.str()); - } - - if (isLoaded && owner == guid) { - return; - } - - isLoaded = true; - - if (owner != 0) { - //send items to depot - if (player) { - transferToDepot(player); - } else { - transferToDepot(); - } - - for (HouseTile* tile : houseTiles) { - if (const CreatureVector* creatures = tile->getCreatures()) { - for (int32_t i = creatures->size(); --i >= 0;) { - kickPlayer(nullptr, (*creatures)[i]->getPlayer()); - } - } - } - - // Remove players from beds - for (BedItem* bed : bedsList) { - if (bed->getSleeper() != 0) { - bed->wakeUp(nullptr); - } - } - - //clean access lists - owner = 0; - setAccessList(SUBOWNER_LIST, ""); - setAccessList(GUEST_LIST, ""); - - for (Door* door : doorList) { - door->setAccessList(""); - } - - //reset paid date - paidUntil = 0; - rentWarnings = 0; - } - - if (guid != 0) { - std::string name = IOLoginData::getNameByGuid(guid); - if (!name.empty()) { - owner = guid; - ownerName = name; - } - } - - updateDoorDescription(); -} - -void House::updateDoorDescription() const -{ - std::ostringstream ss; - if (owner != 0) { - ss << "It belongs to house '" << houseName << "'. " << ownerName << " owns this house."; - } else { - ss << "It belongs to house '" << houseName << "'. Nobody owns this house."; - - const int32_t housePrice = g_config.getNumber(ConfigManager::HOUSE_PRICE); - if (housePrice != -1) { - ss << " It costs " << (houseTiles.size() * housePrice) << " gold coins."; - } - } - - for (const auto& it : doorList) { - it->setSpecialDescription(ss.str()); - } -} - -AccessHouseLevel_t House::getHouseAccessLevel(const Player* player) -{ - if (!player) { - return HOUSE_OWNER; - } - - if (player->hasFlag(PlayerFlag_CanEditHouses)) { - return HOUSE_OWNER; - } - - if (player->getGUID() == owner) { - return HOUSE_OWNER; - } - - if (subOwnerList.isInList(player)) { - return HOUSE_SUBOWNER; - } - - if (guestList.isInList(player)) { - return HOUSE_GUEST; - } - - return HOUSE_NOT_INVITED; -} - -bool House::kickPlayer(Player* player, Player* target) -{ - if (!target) { - return false; - } - - HouseTile* houseTile = dynamic_cast(target->getTile()); - if (!houseTile || houseTile->getHouse() != this) { - return false; - } - - if (getHouseAccessLevel(player) < getHouseAccessLevel(target) || target->hasFlag(PlayerFlag_CanEditHouses)) { - return false; - } - - Position oldPosition = target->getPosition(); - if (g_game.internalTeleport(target, getEntryPosition()) == RETURNVALUE_NOERROR) { - g_game.addMagicEffect(oldPosition, CONST_ME_POFF); - g_game.addMagicEffect(getEntryPosition(), CONST_ME_TELEPORT); - } - return true; -} - -void House::setAccessList(uint32_t listId, const std::string& textlist) -{ - if (listId == GUEST_LIST) { - guestList.parseList(textlist); - } else if (listId == SUBOWNER_LIST) { - subOwnerList.parseList(textlist); - } else { - Door* door = getDoorByNumber(listId); - if (door) { - door->setAccessList(textlist); - } - - // We dont have kick anyone - return; - } - - //kick uninvited players - for (HouseTile* tile : houseTiles) { - if (CreatureVector* creatures = tile->getCreatures()) { - for (int32_t i = creatures->size(); --i >= 0;) { - Player* player = (*creatures)[i]->getPlayer(); - if (player && !isInvited(player)) { - kickPlayer(nullptr, player); - } - } - } - } -} - -bool House::transferToDepot() const -{ - if (townid == 0 || owner == 0) { - return false; - } - - Player* player = g_game.getPlayerByGUID(owner); - if (player) { - transferToDepot(player); - } else { - Player tmpPlayer(nullptr); - if (!IOLoginData::loadPlayerById(&tmpPlayer, owner)) { - return false; - } - - transferToDepot(&tmpPlayer); - IOLoginData::savePlayer(&tmpPlayer); - } - return true; -} - -bool House::transferToDepot(Player* player) const -{ - if (townid == 0 || owner == 0) { - return false; - } - - ItemList moveItemList; - for (HouseTile* tile : houseTiles) { - if (const TileItemVector* items = tile->getItemList()) { - for (Item* item : *items) { - if (item->isPickupable()) { - moveItemList.push_back(item); - } else { - Container* container = item->getContainer(); - if (container) { - for (Item* containerItem : container->getItemList()) { - moveItemList.push_back(containerItem); - } - } - } - } - } - } - - for (Item* item : moveItemList) { - g_game.internalMoveItem(item->getParent(), player->getInbox(), INDEX_WHEREEVER, item, item->getItemCount(), nullptr, FLAG_NOLIMIT); - } - return true; -} - -bool House::getAccessList(uint32_t listId, std::string& list) const -{ - if (listId == GUEST_LIST) { - guestList.getList(list); - return true; - } else if (listId == SUBOWNER_LIST) { - subOwnerList.getList(list); - return true; - } - - Door* door = getDoorByNumber(listId); - if (!door) { - return false; - } - - return door->getAccessList(list); -} - -bool House::isInvited(const Player* player) -{ - return getHouseAccessLevel(player) != HOUSE_NOT_INVITED; -} - -void House::addDoor(Door* door) -{ - door->incrementReferenceCounter(); - doorList.push_back(door); - door->setHouse(this); - updateDoorDescription(); -} - -void House::removeDoor(Door* door) -{ - auto it = std::find(doorList.begin(), doorList.end(), door); - if (it != doorList.end()) { - door->decrementReferenceCounter(); - doorList.erase(it); - } -} - -void House::addBed(BedItem* bed) -{ - bedsList.push_back(bed); - bed->setHouse(this); -} - -Door* House::getDoorByNumber(uint32_t doorId) const -{ - for (Door* door : doorList) { - if (door->getDoorId() == doorId) { - return door; - } - } - return nullptr; -} - -Door* House::getDoorByPosition(const Position& pos) -{ - for (Door* door : doorList) { - if (door->getPosition() == pos) { - return door; - } - } - return nullptr; -} - -bool House::canEditAccessList(uint32_t listId, const Player* player) -{ - switch (getHouseAccessLevel(player)) { - case HOUSE_OWNER: - return true; - - case HOUSE_SUBOWNER: - return listId == GUEST_LIST; - - default: - return false; - } -} - -HouseTransferItem* House::getTransferItem() -{ - if (transferItem != nullptr) { - return nullptr; - } - - transfer_container.setParent(nullptr); - transferItem = HouseTransferItem::createHouseTransferItem(this); - transfer_container.addThing(transferItem); - return transferItem; -} - -void House::resetTransferItem() -{ - if (transferItem) { - Item* tmpItem = transferItem; - transferItem = nullptr; - transfer_container.setParent(nullptr); - - transfer_container.removeThing(tmpItem, tmpItem->getItemCount()); - g_game.ReleaseItem(tmpItem); - } -} - -HouseTransferItem* HouseTransferItem::createHouseTransferItem(House* house) -{ - HouseTransferItem* transferItem = new HouseTransferItem(house); - transferItem->incrementReferenceCounter(); - transferItem->setID(ITEM_DOCUMENT_RO); - transferItem->setSubType(1); - std::ostringstream ss; - ss << "It is a house transfer document for '" << house->getName() << "'."; - transferItem->setSpecialDescription(ss.str()); - return transferItem; -} - -void HouseTransferItem::onTradeEvent(TradeEvents_t event, Player* owner) -{ - if (event == ON_TRADE_TRANSFER) { - if (house) { - house->executeTransfer(this, owner); - } - - g_game.internalRemoveItem(this, 1); - } else if (event == ON_TRADE_CANCEL) { - if (house) { - house->resetTransferItem(); - } - } -} - -bool House::executeTransfer(HouseTransferItem* item, Player* newOwner) -{ - if (transferItem != item) { - return false; - } - - setOwner(newOwner->getGUID()); - transferItem = nullptr; - return true; -} - -void AccessList::parseList(const std::string& _list) -{ - playerList.clear(); - guildList.clear(); - expressionList.clear(); - regExList.clear(); - list = _list; - if (_list.empty()) { - return; - } - - std::istringstream listStream(_list); - std::string line; - - while (getline(listStream, line)) { - trimString(line); - trim_left(line, '\t'); - trim_right(line, '\t'); - trimString(line); - - if (line.empty() || line.front() == '#' || line.length() > 100) { - continue; - } - - toLowerCaseString(line); - - std::string::size_type at_pos = line.find("@"); - if (at_pos != std::string::npos) { - addGuild(line.substr(at_pos + 1)); - } else if (line.find("!") != std::string::npos || line.find("*") != std::string::npos || line.find("?") != std::string::npos) { - addExpression(line); - } else { - addPlayer(line); - } - } -} - -void AccessList::addPlayer(const std::string& name) -{ - Player* player = g_game.getPlayerByName(name); - if (player) { - playerList.insert(player->getGUID()); - } else { - uint32_t guid = IOLoginData::getGuidByName(name); - if (guid != 0) { - playerList.insert(guid); - } - } -} - -void AccessList::addGuild(const std::string& name) -{ - uint32_t guildId = IOGuild::getGuildIdByName(name); - if (guildId != 0) { - guildList.insert(guildId); - } -} - -void AccessList::addExpression(const std::string& expression) -{ - if (std::find(expressionList.begin(), expressionList.end(), expression) != expressionList.end()) { - return; - } - - std::string outExp; - outExp.reserve(expression.length()); - - std::string metachars = ".[{}()\\+|^$"; - for (const char c : expression) { - if (metachars.find(c) != std::string::npos) { - outExp.push_back('\\'); - } - outExp.push_back(c); - } - - replaceString(outExp, "*", ".*"); - replaceString(outExp, "?", ".?"); - - try { - if (!outExp.empty()) { - expressionList.push_back(outExp); - - if (outExp.front() == '!') { - if (outExp.length() > 1) { - regExList.emplace_front(std::regex(outExp.substr(1)), false); - } - } else { - regExList.emplace_back(std::regex(outExp), true); - } - } - } catch (...) {} -} - -bool AccessList::isInList(const Player* player) -{ - std::string name = asLowerCaseString(player->getName()); - std::cmatch what; - - for (const auto& it : regExList) { - if (std::regex_match(name.c_str(), what, it.first)) { - return it.second; - } - } - - auto playerIt = playerList.find(player->getGUID()); - if (playerIt != playerList.end()) { - return true; - } - - const Guild* guild = player->getGuild(); - return guild && guildList.find(guild->getId()) != guildList.end(); -} - -void AccessList::getList(std::string& _list) const -{ - _list = list; -} - -Door::Door(uint16_t _type) - : Item(_type) -{ - house = nullptr; - accessList = nullptr; -} - -Door::~Door() -{ - delete accessList; -} - -Attr_ReadValue Door::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - if (attr == ATTR_HOUSEDOORID) { - uint8_t _doorId; - if (!propStream.read(_doorId)) { - return ATTR_READ_ERROR; - } - - setDoorId(_doorId); - return ATTR_READ_CONTINUE; - } - return Item::readAttr(attr, propStream); -} - -void Door::setHouse(House* _house) -{ - if (house != nullptr) { - return; - } - - house = _house; - - if (!accessList) { - accessList = new AccessList(); - } -} - -bool Door::canUse(const Player* player) -{ - if (!house) { - return true; - } - - if (house->getHouseAccessLevel(player) >= HOUSE_SUBOWNER) { - return true; - } - - return accessList->isInList(player); -} - -void Door::setAccessList(const std::string& textlist) -{ - if (!accessList) { - accessList = new AccessList(); - } - - accessList->parseList(textlist); -} - -bool Door::getAccessList(std::string& list) const -{ - if (!house) { - return false; - } - - accessList->getList(list); - return true; -} - -void Door::onRemoved() -{ - Item::onRemoved(); - - if (house) { - house->removeDoor(this); - } -} - -House* Houses::getHouseByPlayerId(uint32_t playerId) -{ - for (const auto& it : houseMap) { - if (it.second->getOwner() == playerId) { - return it.second; - } - } - return nullptr; -} - -bool Houses::loadHousesXML(const std::string& filename) -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - if (!result) { - printXMLError("Error - Houses::loadHousesXML", filename, result); - return false; - } - - for (auto houseNode : doc.child("houses").children()) { - pugi::xml_attribute houseIdAttribute = houseNode.attribute("houseid"); - if (!houseIdAttribute) { - return false; - } - - int32_t houseId = pugi::cast(houseIdAttribute.value()); - - House* house = getHouse(houseId); - if (!house) { - std::cout << "Error: [Houses::loadHousesXML] Unknown house, id = " << houseId << std::endl; - return false; - } - - house->setName(houseNode.attribute("name").as_string()); - - Position entryPos( - pugi::cast(houseNode.attribute("entryx").value()), - pugi::cast(houseNode.attribute("entryy").value()), - pugi::cast(houseNode.attribute("entryz").value()) - ); - if (entryPos.x == 0 && entryPos.y == 0 && entryPos.z == 0) { - std::cout << "[Warning - Houses::loadHousesXML] House entry not set" - << " - Name: " << house->getName() - << " - House id: " << houseId << std::endl; - } - house->setEntryPos(entryPos); - - house->setRent(pugi::cast(houseNode.attribute("rent").value())); - house->setTownId(pugi::cast(houseNode.attribute("townid").value())); - - house->setOwner(0, false); - } - return true; -} - -void Houses::payHouses(RentPeriod_t rentPeriod) const -{ - if (rentPeriod == RENTPERIOD_NEVER) { - return; - } - - time_t currentTime = time(nullptr); - for (const auto& it : houseMap) { - House* house = it.second; - if (house->getOwner() == 0) { - continue; - } - - const uint32_t rent = house->getRent(); - if (rent == 0 || house->getPaidUntil() > currentTime) { - continue; - } - - const uint32_t ownerId = house->getOwner(); - Town* town = g_game.map.towns.getTown(house->getTownId()); - if (!town) { - continue; - } - - Player player(nullptr); - if (!IOLoginData::loadPlayerById(&player, ownerId)) { - // Player doesn't exist, reset house owner - house->setOwner(0); - continue; - } - - if (player.getBankBalance() >= rent) { - player.setBankBalance(player.getBankBalance() - rent); - - time_t paidUntil = currentTime; - switch (rentPeriod) { - case RENTPERIOD_DAILY: - paidUntil += 24 * 60 * 60; - break; - case RENTPERIOD_WEEKLY: - paidUntil += 24 * 60 * 60 * 7; - break; - case RENTPERIOD_MONTHLY: - paidUntil += 24 * 60 * 60 * 30; - break; - case RENTPERIOD_YEARLY: - paidUntil += 24 * 60 * 60 * 365; - break; - default: - break; - } - - house->setPaidUntil(paidUntil); - } else { - if (house->getPayRentWarnings() < 7) { - int32_t daysLeft = 7 - house->getPayRentWarnings(); - - Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED); - std::string period; - - switch (rentPeriod) { - case RENTPERIOD_DAILY: - period = "daily"; - break; - - case RENTPERIOD_WEEKLY: - period = "weekly"; - break; - - case RENTPERIOD_MONTHLY: - period = "monthly"; - break; - - case RENTPERIOD_YEARLY: - period = "annual"; - break; - - default: - break; - } - - std::ostringstream ss; - ss << "Warning! \nThe " << period << " rent of " << house->getRent() << " gold for your house \"" << house->getName() << "\" is payable. Have it within " << daysLeft << " days or you will lose this house."; - letter->setText(ss.str()); - g_game.internalAddItem(player.getInbox(), letter, INDEX_WHEREEVER, FLAG_NOLIMIT); - house->setPayRentWarnings(house->getPayRentWarnings() + 1); - } else { - house->setOwner(0, true, &player); - } - } - - IOLoginData::savePlayer(&player); - } -} diff --git a/path_10_8/src/house.h b/path_10_8/src/house.h deleted file mode 100644 index b11abe9b0..000000000 --- a/path_10_8/src/house.h +++ /dev/null @@ -1,318 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_HOUSE_H_EB9732E7771A438F9CD0EFA8CB4C58C4 -#define FS_HOUSE_H_EB9732E7771A438F9CD0EFA8CB4C58C4 - -#include - -#include "container.h" -#include "housetile.h" -#include "position.h" - -class House; -class BedItem; -class Player; - -class AccessList -{ - public: - void parseList(const std::string& _list); - void addPlayer(const std::string& name); - void addGuild(const std::string& name); - void addExpression(const std::string& expression); - - bool isInList(const Player* player); - - void getList(std::string& _list) const; - - private: - std::string list; - std::unordered_set playerList; - std::unordered_set guildList; // TODO: include ranks - std::list expressionList; - std::list> regExList; -}; - -class Door final : public Item -{ - public: - explicit Door(uint16_t _type); - ~Door(); - - // non-copyable - Door(const Door&) = delete; - Door& operator=(const Door&) = delete; - - Door* getDoor() final { - return this; - } - const Door* getDoor() const final { - return this; - } - - House* getHouse() { - return house; - } - - //serialization - Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) final; - void serializeAttr(PropWriteStream&) const final {} - - void setDoorId(uint32_t _doorId) { - setIntAttr(ITEM_ATTRIBUTE_DOORID, _doorId); - } - uint32_t getDoorId() const { - return getIntAttr(ITEM_ATTRIBUTE_DOORID); - } - - bool canUse(const Player* player); - - void setAccessList(const std::string& textlist); - bool getAccessList(std::string& list) const; - - void onRemoved() final; - - protected: - void setHouse(House* _house); - - private: - House* house; - AccessList* accessList; - friend class House; -}; - -enum AccessList_t { - GUEST_LIST = 0x100, - SUBOWNER_LIST = 0x101, -}; - -enum AccessHouseLevel_t { - HOUSE_NOT_INVITED = 0, - HOUSE_GUEST = 1, - HOUSE_SUBOWNER = 2, - HOUSE_OWNER = 3, -}; - -typedef std::list HouseTileList; -typedef std::list HouseBedItemList; - -class HouseTransferItem final : public Item -{ - public: - static HouseTransferItem* createHouseTransferItem(House* house); - - explicit HouseTransferItem(House* _house) : Item(0) { - house = _house; - } - - void onTradeEvent(TradeEvents_t event, Player* owner) final; - bool canTransform() const final { - return false; - } - - protected: - House* house; -}; - -class House -{ - public: - explicit House(uint32_t _houseid); - - void addTile(HouseTile* tile); - void updateDoorDescription() const; - - bool canEditAccessList(uint32_t listId, const Player* player); - // listId special values: - // GUEST_LIST guest list - // SUBOWNER_LIST subowner list - void setAccessList(uint32_t listId, const std::string& textlist); - bool getAccessList(uint32_t listId, std::string& list) const; - - bool isInvited(const Player* player); - - AccessHouseLevel_t getHouseAccessLevel(const Player* player); - bool kickPlayer(Player* player, Player* target); - - void setEntryPos(Position pos) { - posEntry = pos; - } - const Position& getEntryPosition() const { - return posEntry; - } - - void setName(std::string houseName) { - this->houseName = houseName; - } - const std::string& getName() const { - return houseName; - } - - void setOwner(uint32_t guid, bool updateDatabase = true, Player* player = nullptr); - uint32_t getOwner() const { - return owner; - } - - void setPaidUntil(time_t paid) { - paidUntil = paid; - } - time_t getPaidUntil() const { - return paidUntil; - } - - void setRent(uint32_t _rent) { - rent = _rent; - } - uint32_t getRent() const { - return rent; - } - - void setPayRentWarnings(uint32_t warnings) { - rentWarnings = warnings; - } - uint32_t getPayRentWarnings() const { - return rentWarnings; - } - - void setTownId(uint32_t _town) { - townid = _town; - } - uint32_t getTownId() const { - return townid; - } - - uint32_t getId() const { - return id; - } - - void addDoor(Door* door); - void removeDoor(Door* door); - Door* getDoorByNumber(uint32_t doorId) const; - Door* getDoorByPosition(const Position& pos); - - HouseTransferItem* getTransferItem(); - void resetTransferItem(); - bool executeTransfer(HouseTransferItem* item, Player* player); - - const HouseTileList& getTiles() const { - return houseTiles; - } - - const std::list& getDoors() const { - return doorList; - } - - void addBed(BedItem* bed); - const HouseBedItemList& getBeds() const { - return bedsList; - } - uint32_t getBedCount() { - return static_cast(std::ceil(bedsList.size() / 2.)); //each bed takes 2 sqms of space, ceil is just for bad maps - } - - private: - bool transferToDepot() const; - bool transferToDepot(Player* player) const; - - AccessList guestList; - AccessList subOwnerList; - - Container transfer_container; - - HouseTileList houseTiles; - std::list doorList; - HouseBedItemList bedsList; - - std::string houseName; - std::string ownerName; - - HouseTransferItem* transferItem; - - time_t paidUntil; - - uint32_t id; - uint32_t owner; - uint32_t rentWarnings; - uint32_t rent; - uint32_t townid; - - Position posEntry; - - bool isLoaded; -}; - -typedef std::map HouseMap; - -enum RentPeriod_t { - RENTPERIOD_DAILY, - RENTPERIOD_WEEKLY, - RENTPERIOD_MONTHLY, - RENTPERIOD_YEARLY, - RENTPERIOD_NEVER, -}; - -class Houses -{ - public: - Houses() = default; - ~Houses() { - for (const auto& it : houseMap) { - delete it.second; - } - } - - // non-copyable - Houses(const Houses&) = delete; - Houses& operator=(const Houses&) = delete; - - House* addHouse(uint32_t id) { - auto it = houseMap.find(id); - if (it != houseMap.end()) { - return it->second; - } - - House* house = new House(id); - houseMap[id] = house; - return house; - } - - House* getHouse(uint32_t houseid) { - auto it = houseMap.find(houseid); - if (it == houseMap.end()) { - return nullptr; - } - return it->second; - } - - House* getHouseByPlayerId(uint32_t playerId); - - bool loadHousesXML(const std::string& filename); - - void payHouses(RentPeriod_t rentPeriod) const; - - const HouseMap& getHouses() const { - return houseMap; - } - - private: - HouseMap houseMap; -}; - -#endif diff --git a/path_10_8/src/housetile.cpp b/path_10_8/src/housetile.cpp deleted file mode 100644 index f1654cdd3..000000000 --- a/path_10_8/src/housetile.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "housetile.h" -#include "house.h" -#include "game.h" - -extern Game g_game; - -HouseTile::HouseTile(int32_t x, int32_t y, int32_t z, House* _house) : - DynamicTile(x, y, z) -{ - house = _house; - setFlag(TILESTATE_HOUSE); -} - -void HouseTile::addThing(int32_t index, Thing* thing) -{ - Tile::addThing(index, thing); - - if (!thing->getParent()) { - return; - } - - if (Item* item = thing->getItem()) { - updateHouse(item); - } -} - -void HouseTile::internalAddThing(uint32_t index, Thing* thing) -{ - Tile::internalAddThing(index, thing); - - if (!thing->getParent()) { - return; - } - - if (Item* item = thing->getItem()) { - updateHouse(item); - } -} - -void HouseTile::updateHouse(Item* item) -{ - if (item->getParent() != this) { - return; - } - - Door* door = item->getDoor(); - if (door) { - if (door->getDoorId() != 0) { - house->addDoor(door); - } - } else { - BedItem* bed = item->getBed(); - if (bed) { - house->addBed(bed); - } - } -} - -ReturnValue HouseTile::queryAdd(int32_t index, const Thing& thing, uint32_t count, uint32_t flags, Creature* actor/* = nullptr*/) const -{ - if (const Creature* creature = thing.getCreature()) { - if (const Player* player = creature->getPlayer()) { - if (!house->isInvited(player)) { - return RETURNVALUE_PLAYERISNOTINVITED; - } - } else { - return RETURNVALUE_NOTPOSSIBLE; - } - } else if (thing.getItem() && actor) { - Player* actorPlayer = actor->getPlayer(); - if (!house->isInvited(actorPlayer)) { - return RETURNVALUE_CANNOTTHROW; - } - } - return Tile::queryAdd(index, thing, count, flags, actor); -} - -Tile* HouseTile::queryDestination(int32_t& index, const Thing& thing, Item** destItem, uint32_t& flags) -{ - if (const Creature* creature = thing.getCreature()) { - if (const Player* player = creature->getPlayer()) { - if (!house->isInvited(player)) { - const Position& entryPos = house->getEntryPosition(); - Tile* destTile = g_game.map.getTile(entryPos); - if (!destTile) { - std::cout << "Error: [HouseTile::queryDestination] House entry not correct" - << " - Name: " << house->getName() - << " - House id: " << house->getId() - << " - Tile not found: " << entryPos << std::endl; - - destTile = g_game.map.getTile(player->getTemplePosition()); - if (!destTile) { - destTile = &(Tile::nullptr_tile); - } - } - - index = -1; - *destItem = nullptr; - return destTile; - } - } - } - - return Tile::queryDestination(index, thing, destItem, flags); -} diff --git a/path_10_8/src/housetile.h b/path_10_8/src/housetile.h deleted file mode 100644 index bc26e04d4..000000000 --- a/path_10_8/src/housetile.h +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_HOUSETILE_H_57D59BEC1CE741D9B142BFC54634505B -#define FS_HOUSETILE_H_57D59BEC1CE741D9B142BFC54634505B - -#include "tile.h" - -class House; - -class HouseTile final : public DynamicTile -{ - public: - HouseTile(int32_t x, int32_t y, int32_t z, House* _house); - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - - Tile* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) final; - - void addThing(int32_t index, Thing* thing) final; - void internalAddThing(uint32_t index, Thing* thing) final; - - House* getHouse() { - return house; - } - - private: - void updateHouse(Item* item); - - House* house; -}; - -#endif diff --git a/path_10_8/src/inbox.cpp b/path_10_8/src/inbox.cpp deleted file mode 100644 index eb3bac36d..000000000 --- a/path_10_8/src/inbox.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "inbox.h" -#include "tools.h" - -Inbox::Inbox(uint16_t _type) : - Container(_type) -{ - maxSize = 30; - unlocked = false; - pagination = true; -} - -ReturnValue Inbox::queryAdd(int32_t, const Thing& thing, uint32_t, - uint32_t flags, Creature*) const -{ - if (!hasBitSet(FLAG_NOLIMIT, flags)) { - return RETURNVALUE_CONTAINERNOTENOUGHROOM; - } - - const Item* item = thing.getItem(); - if (!item) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (item == this) { - return RETURNVALUE_THISISIMPOSSIBLE; - } - - if (!item->isPickupable()) { - return RETURNVALUE_CANNOTPICKUP; - } - - return RETURNVALUE_NOERROR; -} - -void Inbox::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - Cylinder* parent = getParent(); - if (parent != nullptr) { - parent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void Inbox::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - Cylinder* parent = getParent(); - if (parent != nullptr) { - parent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} - -Cylinder* Inbox::getParent() const -{ - if (parent) { - return parent->getParent(); - } - return nullptr; -} diff --git a/path_10_8/src/inbox.h b/path_10_8/src/inbox.h deleted file mode 100644 index dd723bf70..000000000 --- a/path_10_8/src/inbox.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_INBOX_H_C3EF10190329447883B9C3479234EE5C -#define FS_INBOX_H_C3EF10190329447883B9C3479234EE5C - -#include "container.h" - -class Inbox final : public Container -{ - public: - explicit Inbox(uint16_t _type); - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - //overrides - bool canRemove() const final { - return false; - } - - Cylinder* getParent() const final; - Cylinder* getRealParent() const final { - return parent; - } -}; - -#endif - diff --git a/path_10_8/src/ioguild.cpp b/path_10_8/src/ioguild.cpp deleted file mode 100644 index 5a700e2a9..000000000 --- a/path_10_8/src/ioguild.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "ioguild.h" -#include "database.h" - -uint32_t IOGuild::getGuildIdByName(const std::string& name) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id` FROM `guilds` WHERE `name` = " << db->escapeString(name); - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return 0; - } - return result->getNumber("id"); -} - -void IOGuild::getWarList(uint32_t guildId, GuildWarList& guildWarList) -{ - std::ostringstream query; - query << "SELECT `guild1`, `guild2` FROM `guild_wars` WHERE (`guild1` = " << guildId << " OR `guild2` = " << guildId << ") AND `ended` = 0 AND `status` = 1"; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return; - } - - do { - uint32_t guild1 = result->getNumber("guild1"); - if (guildId != guild1) { - guildWarList.push_back(guild1); - } else { - guildWarList.push_back(result->getNumber("guild2")); - } - } while (result->next()); -} diff --git a/path_10_8/src/ioguild.h b/path_10_8/src/ioguild.h deleted file mode 100644 index 9b4171ae9..000000000 --- a/path_10_8/src/ioguild.h +++ /dev/null @@ -1,32 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_IOGUILD_H_EF9ACEBA0B844C388B70FF52E69F1AFF -#define FS_IOGUILD_H_EF9ACEBA0B844C388B70FF52E69F1AFF - -typedef std::vector GuildWarList; - -class IOGuild -{ - public: - static uint32_t getGuildIdByName(const std::string& name); - static void getWarList(uint32_t guildId, GuildWarList& guildWarList); -}; - -#endif diff --git a/path_10_8/src/iologindata.cpp b/path_10_8/src/iologindata.cpp deleted file mode 100644 index 8ce7acb2b..000000000 --- a/path_10_8/src/iologindata.cpp +++ /dev/null @@ -1,994 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "iologindata.h" -#include "configmanager.h" -#include "game.h" -#include "events.h" - -extern ConfigManager g_config; -extern Game g_game; -extern Events* g_events; - -Account IOLoginData::loadAccount(uint32_t accno) -{ - Account account; - - std::ostringstream query; - query << "SELECT `id`, `name`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `id` = " << accno; - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return account; - } - - account.id = result->getNumber("id"); - account.name = result->getString("name"); - account.accountType = static_cast(result->getNumber("type")); - account.premiumDays = result->getNumber("premdays"); - account.lastDay = result->getNumber("lastday"); - return account; -} - -bool IOLoginData::saveAccount(const Account& acc) -{ - std::ostringstream query; - query << "UPDATE `accounts` SET `premdays` = " << acc.premiumDays << ", `lastday` = " << acc.lastDay << " WHERE `id` = " << acc.id; - return Database::getInstance()->executeQuery(query.str()); -} - -bool IOLoginData::loginserverAuthentication(const std::string& name, const std::string& password, Account& account) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id`, `name`, `password`, `type`, `premdays`, `lastday` FROM `accounts` WHERE `name` = " << db->escapeString(name); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - if (transformToSHA1(password) != result->getString("password")) { - return false; - } - - account.id = result->getNumber("id"); - account.name = result->getString("name"); - account.accountType = static_cast(result->getNumber("type")); - account.premiumDays = result->getNumber("premdays"); - account.lastDay = result->getNumber("lastday"); - - query.str(std::string()); - query << "SELECT `name`, `deletion` FROM `players` WHERE `account_id` = " << account.id; - result = db->storeQuery(query.str()); - if (result) { - do { - if (result->getNumber("deletion") == 0) { - account.characters.push_back(result->getString("name")); - } - } while (result->next()); - std::sort(account.characters.begin(), account.characters.end()); - } - return true; -} - -uint32_t IOLoginData::gameworldAuthentication(const std::string& accountName, const std::string& password, std::string& characterName) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id`, `password` FROM `accounts` WHERE `name` = " << db->escapeString(accountName); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return 0; - } - - if (transformToSHA1(password) != result->getString("password")) { - return 0; - } - - uint32_t accountId = result->getNumber("id"); - - query.str(std::string()); - query << "SELECT `account_id`, `name`, `deletion` FROM `players` WHERE `name` = " << db->escapeString(characterName); - result = db->storeQuery(query.str()); - if (!result) { - return 0; - } - - if (result->getNumber("account_id") != accountId || result->getNumber("deletion") != 0) { - return 0; - } - characterName = result->getString("name"); - return accountId; -} - -AccountType_t IOLoginData::getAccountType(uint32_t accountId) -{ - std::ostringstream query; - query << "SELECT `type` FROM `accounts` WHERE `id` = " << accountId; - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return ACCOUNT_TYPE_NORMAL; - } - return static_cast(result->getNumber("type")); -} - -void IOLoginData::setAccountType(uint32_t accountId, AccountType_t accountType) -{ - std::ostringstream query; - query << "UPDATE `accounts` SET `type` = " << static_cast(accountType) << " WHERE `id` = " << accountId; - Database::getInstance()->executeQuery(query.str()); -} - -void IOLoginData::updateOnlineStatus(uint32_t guid, bool login) -{ - if (g_config.getBoolean(ConfigManager::ALLOW_CLONES)) { - return; - } - - std::ostringstream query; - if (login) { - query << "INSERT INTO `players_online` VALUES (" << guid << ')'; - } else { - query << "DELETE FROM `players_online` WHERE `player_id` = " << guid; - } - Database::getInstance()->executeQuery(query.str()); -} - -bool IOLoginData::preloadPlayer(Player* player, const std::string& name) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id`, `account_id`, `group_id`, `deletion`, (SELECT `type` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `account_type`"; - if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { - query << ", (SELECT `premdays` FROM `accounts` WHERE `accounts`.`id` = `account_id`) AS `premium_days`"; - } - query << " FROM `players` WHERE `name` = " << db->escapeString(name); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - if (result->getNumber("deletion") != 0) { - return false; - } - - player->setGUID(result->getNumber("id")); - Group* group = g_game.groups.getGroup(result->getNumber("group_id")); - if (!group) { - std::cout << "[Error - IOLoginData::preloadPlayer] " << player->name << " has Group ID " << result->getNumber("group_id") << " which doesn't exist." << std::endl; - return false; - } - player->setGroup(group); - player->accountNumber = result->getNumber("account_id"); - player->accountType = static_cast(result->getNumber("account_type")); - if (!g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { - player->premiumDays = result->getNumber("premium_days"); - } else { - player->premiumDays = std::numeric_limits::max(); - } - return true; -} - -bool IOLoginData::loadPlayerById(Player* player, uint32_t id) -{ - std::ostringstream query; - query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `offlinetraining_time`, `offlinetraining_skill`, `stamina`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `id` = " << id; - return loadPlayer(player, Database::getInstance()->storeQuery(query.str())); -} - -bool IOLoginData::loadPlayerByName(Player* player, const std::string& name) -{ - Database* db = Database::getInstance(); - std::ostringstream query; - query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `offlinetraining_time`, `offlinetraining_skill`, `stamina`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `name` = " << db->escapeString(name); - return loadPlayer(player, db->storeQuery(query.str())); -} - -bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result) -{ - if (!result) { - return false; - } - - Database* db = Database::getInstance(); - - uint32_t accno = result->getNumber("account_id"); - Account acc = loadAccount(accno); - - player->setGUID(result->getNumber("id")); - player->name = result->getString("name"); - player->accountNumber = accno; - - player->accountType = acc.accountType; - - if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { - player->premiumDays = std::numeric_limits::max(); - } else { - player->premiumDays = acc.premiumDays; - } - - Group* group = g_game.groups.getGroup(result->getNumber("group_id")); - if (!group) { - std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Group ID " << result->getNumber("group_id") << " which doesn't exist" << std::endl; - return false; - } - player->setGroup(group); - - player->bankBalance = result->getNumber("balance"); - - player->setSex(static_cast(result->getNumber("sex"))); - player->level = std::max(1, result->getNumber("level")); - - uint64_t experience = result->getNumber("experience"); - - uint64_t currExpCount = Player::getExpForLevel(player->level); - uint64_t nextExpCount = Player::getExpForLevel(player->level + 1); - if (experience < currExpCount || experience > nextExpCount) { - experience = currExpCount; - } - - player->experience = experience; - - if (currExpCount < nextExpCount) { - player->levelPercent = Player::getPercentLevel(player->experience - currExpCount, nextExpCount - currExpCount); - } else { - player->levelPercent = 0; - } - - player->soul = result->getNumber("soul"); - player->capacity = result->getNumber("cap") * 100; - player->blessings = result->getNumber("blessings"); - - unsigned long conditionsSize; - const char* conditions = result->getStream("conditions", conditionsSize); - PropStream propStream; - propStream.init(conditions, conditionsSize); - - Condition* condition = Condition::createCondition(propStream); - while (condition) { - if (condition->unserialize(propStream)) { - player->storedConditionList.push_front(condition); - } else { - delete condition; - } - condition = Condition::createCondition(propStream); - } - - if (!player->setVocation(result->getNumber("vocation"))) { - std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Vocation ID " << result->getNumber("vocation") << " which doesn't exist" << std::endl; - return false; - } - - player->mana = result->getNumber("mana"); - player->manaMax = result->getNumber("manamax"); - player->magLevel = result->getNumber("maglevel"); - - uint64_t nextManaCount = player->vocation->getReqMana(player->magLevel + 1); - uint64_t manaSpent = result->getNumber("manaspent"); - if (manaSpent > nextManaCount) { - manaSpent = 0; - } - - player->manaSpent = manaSpent; - player->magLevelPercent = Player::getPercentLevel(player->manaSpent, nextManaCount); - - player->health = result->getNumber("health"); - player->healthMax = result->getNumber("healthmax"); - - player->defaultOutfit.lookType = result->getNumber("looktype"); - player->defaultOutfit.lookHead = result->getNumber("lookhead"); - player->defaultOutfit.lookBody = result->getNumber("lookbody"); - player->defaultOutfit.lookLegs = result->getNumber("looklegs"); - player->defaultOutfit.lookFeet = result->getNumber("lookfeet"); - player->defaultOutfit.lookAddons = result->getNumber("lookaddons"); - player->currentOutfit = player->defaultOutfit; - - if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) { - const time_t skullSeconds = result->getNumber("skulltime") - time(nullptr); - if (skullSeconds > 0) { - //ensure that we round up the number of ticks - player->skullTicks = (skullSeconds + 2) * 1000; - - uint16_t skull = result->getNumber("skull"); - if (skull == SKULL_RED) { - player->skull = SKULL_RED; - } else if (skull == SKULL_BLACK) { - player->skull = SKULL_BLACK; - } - } - } - - player->loginPosition.x = result->getNumber("posx"); - player->loginPosition.y = result->getNumber("posy"); - player->loginPosition.z = result->getNumber("posz"); - - player->lastLoginSaved = result->getNumber("lastlogin"); - player->lastLogout = result->getNumber("lastlogout"); - - player->offlineTrainingTime = result->getNumber("offlinetraining_time") * 1000; - player->offlineTrainingSkill = result->getNumber("offlinetraining_skill"); - - Town* town = g_game.map.towns.getTown(result->getNumber("town_id")); - if (!town) { - std::cout << "[Error - IOLoginData::loadPlayer] " << player->name << " has Town ID " << result->getNumber("town_id") << " which doesn't exist" << std::endl; - return false; - } - - player->town = town; - - const Position& loginPos = player->loginPosition; - if (loginPos.x == 0 && loginPos.y == 0 && loginPos.z == 0) { - player->loginPosition = player->getTemplePosition(); - } - - player->staminaMinutes = result->getNumber("stamina"); - - static const std::string skillNames[] = {"skill_fist", "skill_club", "skill_sword", "skill_axe", "skill_dist", "skill_shielding", "skill_fishing"}; - static const std::string skillNameTries[] = {"skill_fist_tries", "skill_club_tries", "skill_sword_tries", "skill_axe_tries", "skill_dist_tries", "skill_shielding_tries", "skill_fishing_tries"}; - static const size_t size = sizeof(skillNames) / sizeof(std::string); - for (uint8_t i = 0; i < size; ++i) { - uint16_t skillLevel = result->getNumber(skillNames[i]); - uint64_t skillTries = result->getNumber(skillNameTries[i]); - uint64_t nextSkillTries = player->vocation->getReqSkillTries(i, skillLevel + 1); - if (skillTries > nextSkillTries) { - skillTries = 0; - } - - player->skills[i].level = skillLevel; - player->skills[i].tries = skillTries; - player->skills[i].percent = Player::getPercentLevel(skillTries, nextSkillTries); - } - - std::ostringstream query; - query << "SELECT `guild_id`, `rank_id`, `nick` FROM `guild_membership` WHERE `player_id` = " << player->getGUID(); - if ((result = db->storeQuery(query.str()))) { - uint32_t guildId = result->getNumber("guild_id"); - uint32_t playerRankId = result->getNumber("rank_id"); - player->guildNick = result->getString("nick"); - - Guild* guild = g_game.getGuild(guildId); - if (!guild) { - query.str(std::string()); - query << "SELECT `name` FROM `guilds` WHERE `id` = " << guildId; - if ((result = db->storeQuery(query.str()))) { - guild = new Guild(guildId, result->getString("name")); - g_game.addGuild(guild); - - query.str(std::string()); - query << "SELECT `id`, `name`, `level` FROM `guild_ranks` WHERE `guild_id` = " << guildId << " LIMIT 3"; - - if ((result = db->storeQuery(query.str()))) { - do { - guild->addRank(result->getNumber("id"), result->getString("name"), result->getNumber("level")); - } while (result->next()); - } - } - } - - if (guild) { - player->guild = guild; - GuildRank* rank = guild->getRankById(playerRankId); - if (rank) { - player->guildLevel = rank->level; - } else { - player->guildLevel = 1; - } - - IOGuild::getWarList(guildId, player->guildWarList); - - query.str(std::string()); - query << "SELECT COUNT(*) AS `members` FROM `guild_membership` WHERE `guild_id` = " << guildId; - if ((result = db->storeQuery(query.str()))) { - guild->setMemberCount(result->getNumber("members")); - } - } - } - - query.str(std::string()); - query << "SELECT `player_id`, `name` FROM `player_spells` WHERE `player_id` = " << player->getGUID(); - if ((result = db->storeQuery(query.str()))) { - do { - player->learnedInstantSpellList.emplace_front(result->getString("name")); - } while (result->next()); - } - - //load inventory items - ItemMap itemMap; - - query.str(std::string()); - query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_items` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC"; - if ((result = db->storeQuery(query.str()))) { - loadItems(itemMap, result); - - for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) { - const std::pair& pair = it->second; - Item* item = pair.first; - int32_t pid = pair.second; - if (pid >= 1 && pid <= 10) { - player->internalAddThing(pid, item); - } else { - ItemMap::const_iterator it2 = itemMap.find(pid); - if (it2 == itemMap.end()) { - continue; - } - - Container* container = it2->second.first->getContainer(); - if (container) { - container->internalAddThing(item); - } - } - } - } - - //load depot items - itemMap.clear(); - - query.str(std::string()); - query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_depotitems` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC"; - if ((result = db->storeQuery(query.str()))) { - loadItems(itemMap, result); - - for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) { - const std::pair& pair = it->second; - Item* item = pair.first; - - int32_t pid = pair.second; - if (pid >= 0 && pid < 100) { - DepotChest* depotChest = player->getDepotChest(pid, true); - if (depotChest) { - depotChest->internalAddThing(item); - } - } else { - ItemMap::const_iterator it2 = itemMap.find(pid); - if (it2 == itemMap.end()) { - continue; - } - - Container* container = it2->second.first->getContainer(); - if (container) { - container->internalAddThing(item); - } - } - } - } - - //load inbox items - itemMap.clear(); - - query.str(std::string()); - query << "SELECT `pid`, `sid`, `itemtype`, `count`, `attributes` FROM `player_inboxitems` WHERE `player_id` = " << player->getGUID() << " ORDER BY `sid` DESC"; - if ((result = db->storeQuery(query.str()))) { - loadItems(itemMap, result); - - for (ItemMap::const_reverse_iterator it = itemMap.rbegin(), end = itemMap.rend(); it != end; ++it) { - const std::pair& pair = it->second; - Item* item = pair.first; - int32_t pid = pair.second; - - if (pid >= 0 && pid < 100) { - player->getInbox()->internalAddThing(item); - } else { - ItemMap::const_iterator it2 = itemMap.find(pid); - - if (it2 == itemMap.end()) { - continue; - } - - Container* container = it2->second.first->getContainer(); - if (container) { - container->internalAddThing(item); - } - } - } - } - - //load storage map - query.str(std::string()); - query << "SELECT `key`, `value` FROM `player_storage` WHERE `player_id` = " << player->getGUID(); - if ((result = db->storeQuery(query.str()))) { - do { - player->addStorageValue(result->getNumber("key"), result->getNumber("value"), true); - } while (result->next()); - } - - //load vip - query.str(std::string()); - query << "SELECT `player_id` FROM `account_viplist` WHERE `account_id` = " << player->getAccount(); - if ((result = db->storeQuery(query.str()))) { - do { - player->addVIPInternal(result->getNumber("player_id")); - } while (result->next()); - } - - player->updateBaseSpeed(); - player->updateInventoryWeight(); - player->updateItemsLight(true); - return true; -} - -bool IOLoginData::saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& propWriteStream) -{ - std::ostringstream ss; - - typedef std::pair containerBlock; - std::list queue; - - int32_t runningId = 100; - - Database* db = Database::getInstance(); - for (const auto& it : itemList) { - int32_t pid = it.first; - Item* item = it.second; - ++runningId; - - propWriteStream.clear(); - item->serializeAttr(propWriteStream); - - size_t attributesSize; - const char* attributes = propWriteStream.getStream(attributesSize); - - ss << player->getGUID() << ',' << pid << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize); - if (!query_insert.addRow(ss)) { - return false; - } - - if (Container* container = item->getContainer()) { - queue.emplace_back(container, runningId); - } - } - - while (!queue.empty()) { - const containerBlock& cb = queue.front(); - Container* container = cb.first; - int32_t parentId = cb.second; - queue.pop_front(); - - for (Item* item : container->getItemList()) { - ++runningId; - - Container* subContainer = item->getContainer(); - if (subContainer) { - queue.emplace_back(subContainer, runningId); - } - - propWriteStream.clear(); - item->serializeAttr(propWriteStream); - - size_t attributesSize; - const char* attributes = propWriteStream.getStream(attributesSize); - - ss << player->getGUID() << ',' << parentId << ',' << runningId << ',' << item->getID() << ',' << item->getSubType() << ',' << db->escapeBlob(attributes, attributesSize); - if (!query_insert.addRow(ss)) { - return false; - } - } - } - return query_insert.execute(); -} - -bool IOLoginData::savePlayer(Player* player) -{ - if (player->getHealth() <= 0) { - player->changeHealth(1); - } - - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `save` FROM `players` WHERE `id` = " << player->getGUID(); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - if (result->getNumber("save") == 0) { - query.str(std::string()); - query << "UPDATE `players` SET `lastlogin` = " << player->lastLoginSaved << ", `lastip` = " << player->lastIP << " WHERE `id` = " << player->getGUID(); - return db->executeQuery(query.str()); - } - - g_events->eventPlayerOnSave(player); - - //serialize conditions - PropWriteStream propWriteStream; - for (Condition* condition : player->conditions) { - if (condition->isPersistent()) { - condition->serialize(propWriteStream); - propWriteStream.write(CONDITIONATTR_END); - } - } - - size_t conditionsSize; - const char* conditions = propWriteStream.getStream(conditionsSize); - - //First, an UPDATE query to write the player itself - query.str(std::string()); - query << "UPDATE `players` SET "; - query << "`level` = " << player->level << ','; - query << "`group_id` = " << player->group->id << ','; - query << "`vocation` = " << player->getVocationId() << ','; - query << "`health` = " << player->health << ','; - query << "`healthmax` = " << player->healthMax << ','; - query << "`experience` = " << player->experience << ','; - query << "`lookbody` = " << static_cast(player->defaultOutfit.lookBody) << ','; - query << "`lookfeet` = " << static_cast(player->defaultOutfit.lookFeet) << ','; - query << "`lookhead` = " << static_cast(player->defaultOutfit.lookHead) << ','; - query << "`looklegs` = " << static_cast(player->defaultOutfit.lookLegs) << ','; - query << "`looktype` = " << player->defaultOutfit.lookType << ','; - query << "`lookaddons` = " << static_cast(player->defaultOutfit.lookAddons) << ','; - query << "`maglevel` = " << player->magLevel << ','; - query << "`mana` = " << player->mana << ','; - query << "`manamax` = " << player->manaMax << ','; - query << "`manaspent` = " << player->manaSpent << ','; - query << "`soul` = " << static_cast(player->soul) << ','; - query << "`town_id` = " << player->town->getID() << ','; - - const Position& loginPosition = player->getLoginPosition(); - query << "`posx` = " << loginPosition.getX() << ','; - query << "`posy` = " << loginPosition.getY() << ','; - query << "`posz` = " << loginPosition.getZ() << ','; - - query << "`cap` = " << (player->capacity / 100) << ','; - query << "`sex` = " << player->sex << ','; - - if (player->lastLoginSaved != 0) { - query << "`lastlogin` = " << player->lastLoginSaved << ','; - } - - if (player->lastIP != 0) { - query << "`lastip` = " << player->lastIP << ','; - } - - query << "`conditions` = " << db->escapeBlob(conditions, conditionsSize) << ','; - - if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) { - int32_t skullTime = 0; - - if (player->skullTicks > 0) { - skullTime = time(nullptr) + player->skullTicks / 1000; - } - - query << "`skulltime` = " << skullTime << ','; - - Skulls_t skull = SKULL_NONE; - if (player->skull == SKULL_RED) { - skull = SKULL_RED; - } else if (player->skull == SKULL_BLACK) { - skull = SKULL_BLACK; - } - query << "`skull` = " << static_cast(skull) << ','; - } - - query << "`lastlogout` = " << player->getLastLogout() << ','; - query << "`balance` = " << player->bankBalance << ','; - query << "`offlinetraining_time` = " << player->getOfflineTrainingTime() / 1000 << ','; - query << "`offlinetraining_skill` = " << player->getOfflineTrainingSkill() << ','; - query << "`stamina` = " << player->getStaminaMinutes() << ','; - - query << "`skill_fist` = " << player->skills[SKILL_FIST].level << ','; - query << "`skill_fist_tries` = " << player->skills[SKILL_FIST].tries << ','; - query << "`skill_club` = " << player->skills[SKILL_CLUB].level << ','; - query << "`skill_club_tries` = " << player->skills[SKILL_CLUB].tries << ','; - query << "`skill_sword` = " << player->skills[SKILL_SWORD].level << ','; - query << "`skill_sword_tries` = " << player->skills[SKILL_SWORD].tries << ','; - query << "`skill_axe` = " << player->skills[SKILL_AXE].level << ','; - query << "`skill_axe_tries` = " << player->skills[SKILL_AXE].tries << ','; - query << "`skill_dist` = " << player->skills[SKILL_DISTANCE].level << ','; - query << "`skill_dist_tries` = " << player->skills[SKILL_DISTANCE].tries << ','; - query << "`skill_shielding` = " << player->skills[SKILL_SHIELD].level << ','; - query << "`skill_shielding_tries` = " << player->skills[SKILL_SHIELD].tries << ','; - query << "`skill_fishing` = " << player->skills[SKILL_FISHING].level << ','; - query << "`skill_fishing_tries` = " << player->skills[SKILL_FISHING].tries << ','; - - if (!player->isOffline()) { - query << "`onlinetime` = `onlinetime` + " << (time(nullptr) - player->lastLoginSaved) << ','; - } - query << "`blessings` = " << static_cast(player->blessings); - query << " WHERE `id` = " << player->getGUID(); - - DBTransaction transaction; - if (!transaction.begin()) { - return false; - } - - if (!db->executeQuery(query.str())) { - return false; - } - - // learned spells - query.str(std::string()); - query << "DELETE FROM `player_spells` WHERE `player_id` = " << player->getGUID(); - if (!db->executeQuery(query.str())) { - return false; - } - - query.str(std::string()); - - DBInsert spellsQuery("INSERT INTO `player_spells` (`player_id`, `name` ) VALUES "); - for (const std::string& spellName : player->learnedInstantSpellList) { - query << player->getGUID() << ',' << db->escapeString(spellName); - if (!spellsQuery.addRow(query)) { - return false; - } - } - - if (!spellsQuery.execute()) { - return false; - } - - //item saving - query << "DELETE FROM `player_items` WHERE `player_id` = " << player->getGUID(); - if (!db->executeQuery(query.str())) { - return false; - } - - DBInsert itemsQuery("INSERT INTO `player_items` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES "); - - ItemBlockList itemList; - for (int32_t slotId = 1; slotId <= 10; ++slotId) { - Item* item = player->inventory[slotId]; - if (item) { - itemList.emplace_back(slotId, item); - } - } - - if (!saveItems(player, itemList, itemsQuery, propWriteStream)) { - return false; - } - - if (player->lastDepotId != -1) { - //save depot items - query.str(std::string()); - query << "DELETE FROM `player_depotitems` WHERE `player_id` = " << player->getGUID(); - - if (!db->executeQuery(query.str())) { - return false; - } - - DBInsert depotQuery("INSERT INTO `player_depotitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES "); - itemList.clear(); - - for (const auto& it : player->depotChests) { - DepotChest* depotChest = it.second; - for (Item* item : depotChest->getItemList()) { - itemList.emplace_back(it.first, item); - } - } - - if (!saveItems(player, itemList, depotQuery, propWriteStream)) { - return false; - } - } - - //save inbox items - query.str(std::string()); - query << "DELETE FROM `player_inboxitems` WHERE `player_id` = " << player->getGUID(); - if (!db->executeQuery(query.str())) { - return false; - } - - DBInsert inboxQuery("INSERT INTO `player_inboxitems` (`player_id`, `pid`, `sid`, `itemtype`, `count`, `attributes`) VALUES "); - itemList.clear(); - - for (Item* item : player->getInbox()->getItemList()) { - itemList.emplace_back(0, item); - } - - if (!saveItems(player, itemList, inboxQuery, propWriteStream)) { - return false; - } - - query.str(std::string()); - query << "DELETE FROM `player_storage` WHERE `player_id` = " << player->getGUID(); - if (!db->executeQuery(query.str())) { - return false; - } - - query.str(std::string()); - - DBInsert storageQuery("INSERT INTO `player_storage` (`player_id`, `key`, `value`) VALUES "); - player->genReservedStorageRange(); - - for (const auto& it : player->storageMap) { - query << player->getGUID() << ',' << it.first << ',' << it.second; - if (!storageQuery.addRow(query)) { - return false; - } - } - - if (!storageQuery.execute()) { - return false; - } - - //End the transaction - return transaction.commit(); -} - -std::string IOLoginData::getNameByGuid(uint32_t guid) -{ - std::ostringstream query; - query << "SELECT `name` FROM `players` WHERE `id` = " << guid; - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return std::string(); - } - return result->getString("name"); -} - -uint32_t IOLoginData::getGuidByName(const std::string& name) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id` FROM `players` WHERE `name` = " << db->escapeString(name); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return 0; - } - return result->getNumber("id"); -} - -bool IOLoginData::getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `name`, `id`, `group_id`, `account_id` FROM `players` WHERE `name` = " << db->escapeString(name); - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - name = result->getString("name"); - guid = result->getNumber("id"); - Group* group = g_game.groups.getGroup(result->getNumber("group_id")); - - uint64_t flags; - if (group) { - flags = group->flags; - } else { - flags = 0; - } - - specialVip = (flags & PlayerFlag_SpecialVIP) != 0; - return true; -} - -bool IOLoginData::formatPlayerName(std::string& name) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `name` FROM `players` WHERE `name` = " << db->escapeString(name); - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - name = result->getString("name"); - return true; -} - -void IOLoginData::loadItems(ItemMap& itemMap, DBResult_ptr result) -{ - do { - uint32_t sid = result->getNumber("sid"); - uint32_t pid = result->getNumber("pid"); - uint16_t type = result->getNumber("itemtype"); - uint16_t count = result->getNumber("count"); - - unsigned long attrSize; - const char* attr = result->getStream("attributes", attrSize); - - PropStream propStream; - propStream.init(attr, attrSize); - - Item* item = Item::CreateItem(type, count); - if (item) { - if (!item->unserializeAttr(propStream)) { - std::cout << "WARNING: Serialize error in IOLoginData::loadItems" << std::endl; - } - - std::pair pair(item, pid); - itemMap[sid] = pair; - } - } while (result->next()); -} - -void IOLoginData::increaseBankBalance(uint32_t guid, uint64_t bankBalance) -{ - std::ostringstream query; - query << "UPDATE `players` SET `balance` = `balance` + " << bankBalance << " WHERE `id` = " << guid; - Database::getInstance()->executeQuery(query.str()); -} - -bool IOLoginData::hasBiddedOnHouse(uint32_t guid) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id` FROM `houses` WHERE `highest_bidder` = " << guid << " LIMIT 1"; - return db->storeQuery(query.str()).get() != nullptr; -} - -std::forward_list IOLoginData::getVIPEntries(uint32_t accountId) -{ - std::forward_list entries; - - std::ostringstream query; - query << "SELECT `player_id`, (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `name`, `description`, `icon`, `notify` FROM `account_viplist` WHERE `account_id` = " << accountId; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (result) { - do { - entries.emplace_front( - result->getNumber("player_id"), - result->getString("name"), - result->getString("description"), - result->getNumber("icon"), - result->getNumber("notify") != 0 - ); - } while (result->next()); - } - return entries; -} - -void IOLoginData::addVIPEntry(uint32_t accountId, uint32_t guid, const std::string& description, uint32_t icon, bool notify) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "INSERT INTO `account_viplist` (`account_id`, `player_id`, `description`, `icon`, `notify`) VALUES (" << accountId << ',' << guid << ',' << db->escapeString(description) << ',' << icon << ',' << notify << ')'; - db->executeQuery(query.str()); -} - -void IOLoginData::editVIPEntry(uint32_t accountId, uint32_t guid, const std::string& description, uint32_t icon, bool notify) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "UPDATE `account_viplist` SET `description` = " << db->escapeString(description) << ", `icon` = " << icon << ", `notify` = " << notify << " WHERE `account_id` = " << accountId << " AND `player_id` = " << guid; - db->executeQuery(query.str()); -} - -void IOLoginData::removeVIPEntry(uint32_t accountId, uint32_t guid) -{ - std::ostringstream query; - query << "DELETE FROM `account_viplist` WHERE `account_id` = " << accountId << " AND `player_id` = " << guid; - Database::getInstance()->executeQuery(query.str()); -} - -void IOLoginData::addPremiumDays(uint32_t accountId, int32_t addDays) -{ - std::ostringstream query; - query << "UPDATE `accounts` SET `premdays` = `premdays` + " << addDays << " WHERE `id` = " << accountId; - Database::getInstance()->executeQuery(query.str()); -} - -void IOLoginData::removePremiumDays(uint32_t accountId, int32_t removeDays) -{ - std::ostringstream query; - query << "UPDATE `accounts` SET `premdays` = `premdays` - " << removeDays << " WHERE `id` = " << accountId; - Database::getInstance()->executeQuery(query.str()); -} diff --git a/path_10_8/src/iologindata.h b/path_10_8/src/iologindata.h deleted file mode 100644 index 895ed1116..000000000 --- a/path_10_8/src/iologindata.h +++ /dev/null @@ -1,70 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_IOLOGINDATA_H_28B0440BEC594654AC0F4E1A5E42B2EF -#define FS_IOLOGINDATA_H_28B0440BEC594654AC0F4E1A5E42B2EF - -#include "account.h" -#include "player.h" -#include "database.h" - -typedef std::list> ItemBlockList; - -class IOLoginData -{ - public: - static Account loadAccount(uint32_t accno); - static bool saveAccount(const Account& acc); - - static bool loginserverAuthentication(const std::string& name, const std::string& password, Account& account); - static uint32_t gameworldAuthentication(const std::string& accountName, const std::string& password, std::string& characterName); - - static AccountType_t getAccountType(uint32_t accountId); - static void setAccountType(uint32_t accountId, AccountType_t accountType); - static void updateOnlineStatus(uint32_t guid, bool login); - static bool preloadPlayer(Player* player, const std::string& name); - - static bool loadPlayerById(Player* player, uint32_t id); - static bool loadPlayerByName(Player* player, const std::string& name); - static bool loadPlayer(Player* player, DBResult_ptr result); - static bool savePlayer(Player* player); - static uint32_t getGuidByName(const std::string& name); - static bool getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name); - static std::string getNameByGuid(uint32_t guid); - static bool formatPlayerName(std::string& name); - static bool addStorageValue(uint32_t guid, uint32_t storageKey, uint32_t storageValue); - static void increaseBankBalance(uint32_t guid, uint64_t bankBalance); - static bool hasBiddedOnHouse(uint32_t guid); - - static std::forward_list getVIPEntries(uint32_t accountId); - static void addVIPEntry(uint32_t accountId, uint32_t guid, const std::string& description, uint32_t icon, bool notify); - static void editVIPEntry(uint32_t accountId, uint32_t guid, const std::string& description, uint32_t icon, bool notify); - static void removeVIPEntry(uint32_t accountId, uint32_t guid); - - static void addPremiumDays(uint32_t accountId, int32_t addDays); - static void removePremiumDays(uint32_t accountId, int32_t removeDays); - - protected: - typedef std::map> ItemMap; - - static void loadItems(ItemMap& itemMap, DBResult_ptr result); - static bool saveItems(const Player* player, const ItemBlockList& itemList, DBInsert& query_insert, PropWriteStream& stream); -}; - -#endif diff --git a/path_10_8/src/iomap.cpp b/path_10_8/src/iomap.cpp deleted file mode 100644 index eb435cd82..000000000 --- a/path_10_8/src/iomap.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "iomap.h" - -#include "bed.h" - -/* - OTBM_ROOTV1 - | - |--- OTBM_MAP_DATA - | | - | |--- OTBM_TILE_AREA - | | |--- OTBM_TILE - | | |--- OTBM_TILE_SQUARE (not implemented) - | | |--- OTBM_TILE_REF (not implemented) - | | |--- OTBM_HOUSETILE - | | - | |--- OTBM_SPAWNS (not implemented) - | | |--- OTBM_SPAWN_AREA (not implemented) - | | |--- OTBM_MONSTER (not implemented) - | | - | |--- OTBM_TOWNS - | | |--- OTBM_TOWN - | | - | |--- OTBM_WAYPOINTS - | |--- OTBM_WAYPOINT - | - |--- OTBM_ITEM_DEF (not implemented) -*/ - -Tile* IOMap::createTile(Item*& ground, Item* item, int px, int py, int pz) -{ - if (!ground) { - return new StaticTile(px, py, pz); - } - - Tile* tile; - if ((item && item->isBlocking()) || ground->isBlocking()) { - tile = new StaticTile(px, py, pz); - } else { - tile = new DynamicTile(px, py, pz); - } - - tile->internalAddThing(ground); - ground->startDecaying(); - ground = nullptr; - return tile; -} - -bool IOMap::loadMap(Map* map, const std::string& identifier) -{ - int64_t start = OTSYS_TIME(); - - FileLoader f; - if (!f.openFile(identifier.c_str(), "OTBM")) { - std::ostringstream ss; - ss << "Could not open the file " << identifier << '.'; - setLastErrorString(ss.str()); - return false; - } - - uint32_t type; - PropStream propStream; - - NODE root = f.getChildNode(nullptr, type); - if (!f.getProps(root, propStream)) { - setLastErrorString("Could not read root property."); - return false; - } - - OTBM_root_header root_header; - if (!propStream.read(root_header)) { - setLastErrorString("Could not read header."); - return false; - } - - uint32_t headerVersion = root_header.version; - if (headerVersion <= 0) { - //In otbm version 1 the count variable after splashes/fluidcontainers and stackables - //are saved as attributes instead, this solves alot of problems with items - //that is changed (stackable/charges/fluidcontainer/splash) during an update. - setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); - return false; - } - - if (headerVersion > 2) { - setLastErrorString("Unknown OTBM version detected."); - return false; - } - - if (root_header.majorVersionItems < 3) { - setLastErrorString("This map need to be upgraded by using the latest map editor version to be able to load correctly."); - return false; - } - - if (root_header.majorVersionItems > Items::dwMajorVersion) { - setLastErrorString("The map was saved with a different items.otb version, an upgraded items.otb is required."); - return false; - } - - if (root_header.minorVersionItems < CLIENT_VERSION_810) { - setLastErrorString("This map needs to be updated."); - return false; - } - - if (root_header.minorVersionItems > Items::dwMinorVersion) { - std::cout << "[Warning - IOMap::loadMap] This map needs an updated items.otb." << std::endl; - } - - std::cout << "> Map size: " << root_header.width << "x" << root_header.height << '.' << std::endl; - map->width = root_header.width; - map->height = root_header.height; - - NODE nodeMap = f.getChildNode(root, type); - if (type != OTBM_MAP_DATA) { - setLastErrorString("Could not read data node."); - return false; - } - - if (!f.getProps(nodeMap, propStream)) { - setLastErrorString("Could not read map data attributes."); - return false; - } - - std::string mapDescription; - std::string tmp; - - uint8_t attribute; - while (propStream.read(attribute)) { - switch (attribute) { - case OTBM_ATTR_DESCRIPTION: - if (!propStream.readString(mapDescription)) { - setLastErrorString("Invalid description tag."); - return false; - } - break; - - case OTBM_ATTR_EXT_SPAWN_FILE: - if (!propStream.readString(tmp)) { - setLastErrorString("Invalid spawn tag."); - return false; - } - - map->spawnfile = identifier.substr(0, identifier.rfind('/') + 1); - map->spawnfile += tmp; - break; - - case OTBM_ATTR_EXT_HOUSE_FILE: - if (!propStream.readString(tmp)) { - setLastErrorString("Invalid house tag."); - return false; - } - - map->housefile = identifier.substr(0, identifier.rfind('/') + 1); - map->housefile += tmp; - break; - - default: - setLastErrorString("Unknown header node."); - return false; - } - } - - NODE nodeMapData = f.getChildNode(nodeMap, type); - while (nodeMapData != NO_NODE) { - if (f.getError() != ERROR_NONE) { - setLastErrorString("Invalid map node."); - return false; - } - - if (type == OTBM_TILE_AREA) { - if (!f.getProps(nodeMapData, propStream)) { - setLastErrorString("Invalid map node."); - return false; - } - - OTBM_Destination_coords area_coord; - if (!propStream.read(area_coord)) { - setLastErrorString("Invalid map node."); - return false; - } - - int32_t base_x = area_coord.x; - int32_t base_y = area_coord.y; - int32_t base_z = area_coord.z; - - NODE nodeTile = f.getChildNode(nodeMapData, type); - while (nodeTile != NO_NODE) { - if (f.getError() != ERROR_NONE) { - setLastErrorString("Could not read node data."); - return false; - } - - if (type != OTBM_TILE && type != OTBM_HOUSETILE) { - setLastErrorString("Unknown tile node."); - return false; - } - - if (!f.getProps(nodeTile, propStream)) { - setLastErrorString("Could not read node data."); - return false; - } - - OTBM_Tile_coords tile_coord; - if (!propStream.read(tile_coord)) { - setLastErrorString("Could not read tile position."); - return false; - } - - uint16_t px = base_x + tile_coord.x; - uint16_t py = base_y + tile_coord.y; - uint16_t pz = base_z; - - bool isHouseTile = false; - House* house = nullptr; - Tile* tile = nullptr; - Item* ground_item = nullptr; - uint32_t tileflags = TILESTATE_NONE; - - if (type == OTBM_HOUSETILE) { - uint32_t houseId; - if (!propStream.read(houseId)) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not read house id."; - setLastErrorString(ss.str()); - return false; - } - - house = map->houses.addHouse(houseId); - if (!house) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Could not create house id: " << houseId; - setLastErrorString(ss.str()); - return false; - } - - tile = new HouseTile(px, py, pz, house); - house->addTile(static_cast(tile)); - isHouseTile = true; - } - - //read tile attributes - while (propStream.read(attribute)) { - switch (attribute) { - case OTBM_ATTR_TILE_FLAGS: { - uint32_t flags; - if (!propStream.read(flags)) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to read tile flags."; - setLastErrorString(ss.str()); - return false; - } - - if ((flags & TILESTATE_PROTECTIONZONE) == TILESTATE_PROTECTIONZONE) { - tileflags |= TILESTATE_PROTECTIONZONE; - } else if ((flags & TILESTATE_NOPVPZONE) == TILESTATE_NOPVPZONE) { - tileflags |= TILESTATE_NOPVPZONE; - } else if ((flags & TILESTATE_PVPZONE) == TILESTATE_PVPZONE) { - tileflags |= TILESTATE_PVPZONE; - } - - if ((flags & TILESTATE_NOLOGOUT) == TILESTATE_NOLOGOUT) { - tileflags |= TILESTATE_NOLOGOUT; - } - break; - } - - case OTBM_ATTR_ITEM: { - Item* item = Item::CreateItem(propStream); - if (!item) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; - setLastErrorString(ss.str()); - return false; - } - - if (isHouseTile && item->isMoveable()) { - std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; - delete item; - } else { - if (item->getItemCount() <= 0) { - item->setItemCount(1); - } - - if (tile) { - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } else if (item->isGroundTile()) { - delete ground_item; - ground_item = item; - } else { - tile = createTile(ground_item, item, px, py, pz); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - break; - } - - default: - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown tile attribute."; - setLastErrorString(ss.str()); - return false; - } - } - - NODE nodeItem = f.getChildNode(nodeTile, type); - while (nodeItem) { - if (type != OTBM_ITEM) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Unknown node type."; - setLastErrorString(ss.str()); - return false; - } - - PropStream stream; - if (!f.getProps(nodeItem, stream)) { - setLastErrorString("Invalid item node."); - return false; - } - - Item* item = Item::CreateItem(stream); - if (!item) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to create item."; - setLastErrorString(ss.str()); - return false; - } - - if (!item->unserializeItemNode(f, nodeItem, stream)) { - std::ostringstream ss; - ss << "[x:" << px << ", y:" << py << ", z:" << pz << "] Failed to load item " << item->getID() << '.'; - setLastErrorString(ss.str()); - delete item; - return false; - } - - if (isHouseTile && item->isMoveable()) { - std::cout << "[Warning - IOMap::loadMap] Moveable item with ID: " << item->getID() << ", in house: " << house->getId() << ", at position [x: " << px << ", y: " << py << ", z: " << pz << "]." << std::endl; - delete item; - } else { - if (item->getItemCount() <= 0) { - item->setItemCount(1); - } - - if (tile) { - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } else if (item->isGroundTile()) { - delete ground_item; - ground_item = item; - } else { - tile = createTile(ground_item, item, px, py, pz); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - - nodeItem = f.getNextNode(nodeItem, type); - } - - if (!tile) { - tile = createTile(ground_item, nullptr, px, py, pz); - } - - tile->setFlag(static_cast(tileflags)); - - map->setTile(px, py, pz, tile); - - nodeTile = f.getNextNode(nodeTile, type); - } - } else if (type == OTBM_TOWNS) { - NODE nodeTown = f.getChildNode(nodeMapData, type); - while (nodeTown != NO_NODE) { - if (type != OTBM_TOWN) { - setLastErrorString("Unknown town node."); - return false; - } - - if (!f.getProps(nodeTown, propStream)) { - setLastErrorString("Could not read town data."); - return false; - } - - uint32_t townId; - if (!propStream.read(townId)) { - setLastErrorString("Could not read town id."); - return false; - } - - Town* town = map->towns.getTown(townId); - if (!town) { - town = new Town(townId); - map->towns.addTown(townId, town); - } - - std::string townName; - if (!propStream.readString(townName)) { - setLastErrorString("Could not read town name."); - return false; - } - - town->setName(townName); - - OTBM_Destination_coords town_coords; - if (!propStream.read(town_coords)) { - setLastErrorString("Could not read town coordinates."); - return false; - } - - town->setTemplePos(Position(town_coords.x, town_coords.y, town_coords.z)); - - nodeTown = f.getNextNode(nodeTown, type); - } - } else if (type == OTBM_WAYPOINTS && headerVersion > 1) { - NODE nodeWaypoint = f.getChildNode(nodeMapData, type); - while (nodeWaypoint != NO_NODE) { - if (type != OTBM_WAYPOINT) { - setLastErrorString("Unknown waypoint node."); - return false; - } - - if (!f.getProps(nodeWaypoint, propStream)) { - setLastErrorString("Could not read waypoint data."); - return false; - } - - std::string name; - if (!propStream.readString(name)) { - setLastErrorString("Could not read waypoint name."); - return false; - } - - OTBM_Destination_coords waypoint_coords; - if (!propStream.read(waypoint_coords)) { - setLastErrorString("Could not read waypoint coordinates."); - return false; - } - - map->waypoints[name] = Position(waypoint_coords.x, waypoint_coords.y, waypoint_coords.z); - - nodeWaypoint = f.getNextNode(nodeWaypoint, type); - } - } else { - setLastErrorString("Unknown map node."); - return false; - } - - nodeMapData = f.getNextNode(nodeMapData, type); - } - - std::cout << "> Map loading time: " << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; - return true; -} diff --git a/path_10_8/src/iomap.h b/path_10_8/src/iomap.h deleted file mode 100644 index 221d4b40e..000000000 --- a/path_10_8/src/iomap.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_IOMAP_H_8085D4B1037A44288494A52FDBB775E4 -#define FS_IOMAP_H_8085D4B1037A44288494A52FDBB775E4 - -#include "item.h" -#include "map.h" -#include "house.h" -#include "spawn.h" -#include "configmanager.h" - -extern ConfigManager g_config; - -enum OTBM_AttrTypes_t { - OTBM_ATTR_DESCRIPTION = 1, - OTBM_ATTR_EXT_FILE = 2, - OTBM_ATTR_TILE_FLAGS = 3, - OTBM_ATTR_ACTION_ID = 4, - OTBM_ATTR_UNIQUE_ID = 5, - OTBM_ATTR_TEXT = 6, - OTBM_ATTR_DESC = 7, - OTBM_ATTR_TELE_DEST = 8, - OTBM_ATTR_ITEM = 9, - OTBM_ATTR_DEPOT_ID = 10, - OTBM_ATTR_EXT_SPAWN_FILE = 11, - OTBM_ATTR_RUNE_CHARGES = 12, - OTBM_ATTR_EXT_HOUSE_FILE = 13, - OTBM_ATTR_HOUSEDOORID = 14, - OTBM_ATTR_COUNT = 15, - OTBM_ATTR_DURATION = 16, - OTBM_ATTR_DECAYING_STATE = 17, - OTBM_ATTR_WRITTENDATE = 18, - OTBM_ATTR_WRITTENBY = 19, - OTBM_ATTR_SLEEPERGUID = 20, - OTBM_ATTR_SLEEPSTART = 21, - OTBM_ATTR_CHARGES = 22, -}; - -enum OTBM_NodeTypes_t { - OTBM_ROOTV1 = 1, - OTBM_MAP_DATA = 2, - OTBM_ITEM_DEF = 3, - OTBM_TILE_AREA = 4, - OTBM_TILE = 5, - OTBM_ITEM = 6, - OTBM_TILE_SQUARE = 7, - OTBM_TILE_REF = 8, - OTBM_SPAWNS = 9, - OTBM_SPAWN_AREA = 10, - OTBM_MONSTER = 11, - OTBM_TOWNS = 12, - OTBM_TOWN = 13, - OTBM_HOUSETILE = 14, - OTBM_WAYPOINTS = 15, - OTBM_WAYPOINT = 16, -}; - -#pragma pack(1) - -struct OTBM_root_header { - uint32_t version; - uint16_t width; - uint16_t height; - uint32_t majorVersionItems; - uint32_t minorVersionItems; -}; - -struct OTBM_Destination_coords { - uint16_t x; - uint16_t y; - uint8_t z; -}; - -struct OTBM_Tile_coords { - uint8_t x; - uint8_t y; -}; - -struct OTBM_HouseTile_coords { - uint8_t x; - uint8_t y; - uint32_t houseId; -}; - -#pragma pack() - -class IOMap -{ - static Tile* createTile(Item*& ground, Item* item, int px, int py, int pz); - public: - bool loadMap(Map* map, const std::string& identifier); - - /* Load the spawns - * \param map pointer to the Map class - * \returns Returns true if the spawns were loaded successfully - */ - static bool loadSpawns(Map* map) { - if (map->spawnfile.empty()) { - //OTBM file doesn't tell us about the spawnfile, - //lets guess it is mapname-spawn.xml. - map->spawnfile = g_config.getString(ConfigManager::MAP_NAME); - map->spawnfile += "-spawn.xml"; - } - - return map->spawns.loadFromXml(map->spawnfile); - } - - /* Load the houses (not house tile-data) - * \param map pointer to the Map class - * \returns Returns true if the houses were loaded successfully - */ - static bool loadHouses(Map* map) { - if (map->housefile.empty()) { - //OTBM file doesn't tell us about the housefile, - //lets guess it is mapname-house.xml. - map->housefile = g_config.getString(ConfigManager::MAP_NAME); - map->housefile += "-house.xml"; - } - - return map->houses.loadHousesXML(map->housefile); - } - - const std::string& getLastErrorString() const { - return errorString; - } - - void setLastErrorString(std::string error) { - errorString = error; - } - - protected: - std::string errorString; -}; - -#endif diff --git a/path_10_8/src/iomapserialize.cpp b/path_10_8/src/iomapserialize.cpp deleted file mode 100644 index d4390b0dd..000000000 --- a/path_10_8/src/iomapserialize.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "iomapserialize.h" -#include "house.h" -#include "game.h" -#include "bed.h" - -extern Game g_game; - -void IOMapSerialize::loadHouseItems(Map* map) -{ - int64_t start = OTSYS_TIME(); - - DBResult_ptr result = Database::getInstance()->storeQuery("SELECT `data` FROM `tile_store`"); - if (!result) { - return; - } - - do { - unsigned long attrSize; - const char* attr = result->getStream("data", attrSize); - - PropStream propStream; - propStream.init(attr, attrSize); - - uint16_t x, y; - uint8_t z; - if (!propStream.read(x) || !propStream.read(y) || !propStream.read(z)) { - continue; - } - - Tile* tile = map->getTile(x, y, z); - if (!tile) { - continue; - } - - uint32_t item_count; - if (!propStream.read(item_count)) { - continue; - } - - while (item_count--) { - loadItem(propStream, tile); - } - } while (result->next()); - std::cout << "> Loaded house items in: " << (OTSYS_TIME() - start) / (1000.) << " s" << std::endl; -} - -bool IOMapSerialize::saveHouseItems() -{ - int64_t start = OTSYS_TIME(); - Database* db = Database::getInstance(); - std::ostringstream query; - - //Start the transaction - DBTransaction transaction; - if (!transaction.begin()) { - return false; - } - - //clear old tile data - if (!db->executeQuery("DELETE FROM `tile_store`")) { - return false; - } - - DBInsert stmt("INSERT INTO `tile_store` (`house_id`, `data`) VALUES "); - - PropWriteStream stream; - for (const auto& it : g_game.map.houses.getHouses()) { - //save house items - House* house = it.second; - for (HouseTile* tile : house->getTiles()) { - saveTile(stream, tile); - - size_t attributesSize; - const char* attributes = stream.getStream(attributesSize); - if (attributesSize > 0) { - query << house->getId() << ',' << db->escapeBlob(attributes, attributesSize); - if (!stmt.addRow(query)) { - return false; - } - stream.clear(); - } - } - } - - if (!stmt.execute()) { - return false; - } - - //End the transaction - bool success = transaction.commit(); - std::cout << "> Saved house items in: " << - (OTSYS_TIME() - start) / (1000.) << " s" << std::endl; - return success; -} - -bool IOMapSerialize::loadContainer(PropStream& propStream, Container* container) -{ - while (container->serializationCount > 0) { - if (!loadItem(propStream, container)) { - std::cout << "[Warning - IOMapSerialize::loadContainer] Unserialization error for container item: " << container->getID() << std::endl; - return false; - } - container->serializationCount--; - } - - uint8_t endAttr; - if (!propStream.read(endAttr) || endAttr != 0) { - std::cout << "[Warning - IOMapSerialize::loadContainer] Unserialization error for container item: " << container->getID() << std::endl; - return false; - } - return true; -} - -bool IOMapSerialize::loadItem(PropStream& propStream, Cylinder* parent) -{ - uint16_t id; - if (!propStream.read(id)) { - return false; - } - - Tile* tile = nullptr; - if (parent->getParent() == nullptr) { - tile = parent->getTile(); - } - - const ItemType& iType = Item::items[id]; - if (iType.moveable || !tile) { - //create a new item - Item* item = Item::CreateItem(id); - if (item) { - if (item->unserializeAttr(propStream)) { - Container* container = item->getContainer(); - if (container && !loadContainer(propStream, container)) { - delete item; - return false; - } - - parent->internalAddThing(item); - item->startDecaying(); - } else { - std::cout << "WARNING: Unserialization error in IOMapSerialize::loadItem()" << id << std::endl; - delete item; - return false; - } - } - } else { - // Stationary items like doors/beds/blackboards/bookcases - Item* item = nullptr; - if (const TileItemVector* items = tile->getItemList()) { - for (Item* findItem : *items) { - if (findItem->getID() == id) { - item = findItem; - break; - } else if (iType.isDoor() && findItem->getDoor()) { - item = findItem; - break; - } else if (iType.isBed() && findItem->getBed()) { - item = findItem; - break; - } - } - } - - if (item) { - if (item->unserializeAttr(propStream)) { - Container* container = item->getContainer(); - if (container && !loadContainer(propStream, container)) { - return false; - } - - g_game.transformItem(item, id); - } else { - std::cout << "WARNING: Unserialization error in IOMapSerialize::loadItem()" << id << std::endl; - } - } else { - //The map changed since the last save, just read the attributes - std::unique_ptr dummy(Item::CreateItem(id)); - if (dummy) { - dummy->unserializeAttr(propStream); - Container* container = dummy->getContainer(); - if (container) { - if (!loadContainer(propStream, container)) { - return false; - } - } else if (BedItem* bedItem = dynamic_cast(dummy.get())) { - uint32_t sleeperGUID = bedItem->getSleeper(); - if (sleeperGUID != 0) { - g_game.removeBedSleeper(sleeperGUID); - } - } - } - } - } - return true; -} - -void IOMapSerialize::saveItem(PropWriteStream& stream, const Item* item) -{ - const Container* container = item->getContainer(); - - // Write ID & props - stream.write(item->getID()); - item->serializeAttr(stream); - - if (container) { - // Hack our way into the attributes - stream.write(ATTR_CONTAINER_ITEMS); - stream.write(container->size()); - for (ItemDeque::const_reverse_iterator it = container->getReversedItems(), end = container->getReversedEnd(); it != end; ++it) { - saveItem(stream, *it); - } - } - - stream.write(0x00); // attr end -} - -void IOMapSerialize::saveTile(PropWriteStream& stream, const Tile* tile) -{ - const TileItemVector* tileItems = tile->getItemList(); - if (!tileItems) { - return; - } - - std::forward_list items; - uint16_t count = 0; - for (Item* item : *tileItems) { - const ItemType& it = Item::items[item->getID()]; - - // Note that these are NEGATED, ie. these are the items that will be saved. - if (!(it.moveable || item->getDoor() || (item->getContainer() && !item->getContainer()->empty()) || it.canWriteText || item->getBed())) { - continue; - } - - items.push_front(item); - ++count; - } - - if (!items.empty()) { - const Position& tilePosition = tile->getPosition(); - stream.write(tilePosition.x); - stream.write(tilePosition.y); - stream.write(tilePosition.z); - - stream.write(count); - for (const Item* item : items) { - saveItem(stream, item); - } - } -} - -bool IOMapSerialize::loadHouseInfo() -{ - Database* db = Database::getInstance(); - - DBResult_ptr result = db->storeQuery("SELECT `id`, `owner`, `paid`, `warnings` FROM `houses`"); - if (!result) { - return false; - } - - do { - House* house = g_game.map.houses.getHouse(result->getNumber("id")); - if (house) { - house->setOwner(result->getNumber("owner"), false); - house->setPaidUntil(result->getNumber("paid")); - house->setPayRentWarnings(result->getNumber("warnings")); - } - } while (result->next()); - - result = db->storeQuery("SELECT `house_id`, `listid`, `list` FROM `house_lists`"); - if (result) { - do { - House* house = g_game.map.houses.getHouse(result->getNumber("house_id")); - if (house) { - house->setAccessList(result->getNumber("listid"), result->getString("list")); - } - } while (result->next()); - } - return true; -} - -bool IOMapSerialize::saveHouseInfo() -{ - Database* db = Database::getInstance(); - - DBTransaction transaction; - if (!transaction.begin()) { - return false; - } - - if (!db->executeQuery("DELETE FROM `house_lists`")) { - return false; - } - - std::ostringstream query; - for (const auto& it : g_game.map.houses.getHouses()) { - House* house = it.second; - query << "SELECT `id` FROM `houses` WHERE `id` = " << house->getId(); - DBResult_ptr result = db->storeQuery(query.str()); - if (result) { - query.str(std::string()); - query << "UPDATE `houses` SET `owner` = " << house->getOwner() << ", `paid` = " << house->getPaidUntil() << ", `warnings` = " << house->getPayRentWarnings() << ", `name` = " << db->escapeString(house->getName()) << ", `town_id` = " << house->getTownId() << ", `rent` = " << house->getRent() << ", `size` = " << house->getTiles().size() << ", `beds` = " << house->getBedCount() << " WHERE `id` = " << house->getId(); - } else { - query.str(std::string()); - query << "INSERT INTO `houses` (`id`, `owner`, `paid`, `warnings`, `name`, `town_id`, `rent`, `size`, `beds`) VALUES (" << house->getId() << ',' << house->getOwner() << ',' << house->getPaidUntil() << ',' << house->getPayRentWarnings() << ',' << db->escapeString(house->getName()) << ',' << house->getTownId() << ',' << house->getRent() << ',' << house->getTiles().size() << ',' << house->getBedCount() << ')'; - } - - db->executeQuery(query.str()); - query.str(std::string()); - } - - DBInsert stmt("INSERT INTO `house_lists` (`house_id` , `listid` , `list`) VALUES "); - - for (const auto& it : g_game.map.houses.getHouses()) { - House* house = it.second; - - std::string listText; - if (house->getAccessList(GUEST_LIST, listText) && !listText.empty()) { - query << house->getId() << ',' << GUEST_LIST << ',' << db->escapeString(listText); - if (!stmt.addRow(query)) { - return false; - } - - listText.clear(); - } - - if (house->getAccessList(SUBOWNER_LIST, listText) && !listText.empty()) { - query << house->getId() << ',' << SUBOWNER_LIST << ',' << db->escapeString(listText); - if (!stmt.addRow(query)) { - return false; - } - - listText.clear(); - } - - for (Door* door : house->getDoors()) { - if (door->getAccessList(listText) && !listText.empty()) { - query << house->getId() << ',' << door->getDoorId() << ',' << db->escapeString(listText); - if (!stmt.addRow(query)) { - return false; - } - - listText.clear(); - } - } - } - - if (!stmt.execute()) { - return false; - } - - return transaction.commit(); -} diff --git a/path_10_8/src/iomapserialize.h b/path_10_8/src/iomapserialize.h deleted file mode 100644 index 8de71d4cb..000000000 --- a/path_10_8/src/iomapserialize.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_IOMAPSERIALIZE_H_7E903658F34E44F9BE03A713B55A3D6D -#define FS_IOMAPSERIALIZE_H_7E903658F34E44F9BE03A713B55A3D6D - -#include "database.h" -#include "map.h" - -class IOMapSerialize -{ - public: - static void loadHouseItems(Map* map); - static bool saveHouseItems(); - static bool loadHouseInfo(); - static bool saveHouseInfo(); - - protected: - static void saveItem(PropWriteStream& stream, const Item* item); - static void saveTile(PropWriteStream& stream, const Tile* tile); - - static bool loadContainer(PropStream& propStream, Container* container); - static bool loadItem(PropStream& propStream, Cylinder* parent); -}; - -#endif diff --git a/path_10_8/src/iomarket.cpp b/path_10_8/src/iomarket.cpp deleted file mode 100644 index 03ef6595e..000000000 --- a/path_10_8/src/iomarket.cpp +++ /dev/null @@ -1,347 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "iomarket.h" - -#include "configmanager.h" -#include "databasetasks.h" -#include "iologindata.h" -#include "game.h" -#include "scheduler.h" - -extern ConfigManager g_config; -extern Game g_game; - -MarketOfferList IOMarket::getActiveOffers(MarketAction_t action, uint16_t itemId) -{ - MarketOfferList offerList; - - std::ostringstream query; - query << "SELECT `id`, `amount`, `price`, `created`, `anonymous`, (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `player_name` FROM `market_offers` WHERE `sale` = " << action << " AND `itemtype` = " << itemId; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return offerList; - } - - const int32_t marketOfferDuration = g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - do { - MarketOffer offer; - offer.amount = result->getNumber("amount"); - offer.price = result->getNumber("price"); - offer.timestamp = result->getNumber("created") + marketOfferDuration; - offer.counter = result->getNumber("id") & 0xFFFF; - if (result->getNumber("anonymous") == 0) { - offer.playerName = result->getString("player_name"); - } else { - offer.playerName = "Anonymous"; - } - offerList.push_back(offer); - } while (result->next()); - return offerList; -} - -MarketOfferList IOMarket::getOwnOffers(MarketAction_t action, uint32_t playerId) -{ - MarketOfferList offerList; - - const int32_t marketOfferDuration = g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - std::ostringstream query; - query << "SELECT `id`, `amount`, `price`, `created`, `itemtype` FROM `market_offers` WHERE `player_id` = " << playerId << " AND `sale` = " << action; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return offerList; - } - - do { - MarketOffer offer; - offer.amount = result->getNumber("amount"); - offer.price = result->getNumber("price"); - offer.timestamp = result->getNumber("created") + marketOfferDuration; - offer.counter = result->getNumber("id") & 0xFFFF; - offer.itemId = result->getNumber("itemtype"); - offerList.push_back(offer); - } while (result->next()); - return offerList; -} - -HistoryMarketOfferList IOMarket::getOwnHistory(MarketAction_t action, uint32_t playerId) -{ - HistoryMarketOfferList offerList; - - std::ostringstream query; - query << "SELECT `itemtype`, `amount`, `price`, `expires_at`, `state` FROM `market_history` WHERE `player_id` = " << playerId << " AND `sale` = " << action; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return offerList; - } - - do { - HistoryMarketOffer offer; - offer.itemId = result->getNumber("itemtype"); - offer.amount = result->getNumber("amount"); - offer.price = result->getNumber("price"); - offer.timestamp = result->getNumber("expires_at"); - - MarketOfferState_t offerState = static_cast(result->getNumber("state")); - if (offerState == OFFERSTATE_ACCEPTEDEX) { - offerState = OFFERSTATE_ACCEPTED; - } - - offer.state = offerState; - - offerList.push_back(offer); - } while (result->next()); - return offerList; -} - -void IOMarket::processExpiredOffers(DBResult_ptr result, bool) -{ - if (!result) { - return; - } - - do { - if (!IOMarket::moveOfferToHistory(result->getNumber("id"), OFFERSTATE_EXPIRED)) { - continue; - } - - const uint32_t playerId = result->getNumber("player_id"); - const uint16_t amount = result->getNumber("amount"); - if (result->getNumber("sale") == 1) { - const ItemType& itemType = Item::items[result->getNumber("itemtype")]; - if (itemType.id == 0) { - continue; - } - - Player* player = g_game.getPlayerByGUID(playerId); - if (!player) { - player = new Player(nullptr); - if (!IOLoginData::loadPlayerById(player, playerId)) { - delete player; - continue; - } - } - - if (itemType.stackable) { - uint16_t tmpAmount = amount; - while (tmpAmount > 0) { - uint16_t stackCount = std::min(100, tmpAmount); - Item* item = Item::CreateItem(itemType.id, stackCount); - if (g_game.internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - - tmpAmount -= stackCount; - } - } else { - int32_t subType; - if (itemType.charges != 0) { - subType = itemType.charges; - } else { - subType = -1; - } - - for (uint16_t i = 0; i < amount; ++i) { - Item* item = Item::CreateItem(itemType.id, subType); - if (g_game.internalAddItem(player->getInbox(), item, INDEX_WHEREEVER, FLAG_NOLIMIT) != RETURNVALUE_NOERROR) { - delete item; - break; - } - } - } - - if (player->isOffline()) { - IOLoginData::savePlayer(player); - delete player; - } - } else { - uint64_t totalPrice = result->getNumber("price") * amount; - - Player* player = g_game.getPlayerByGUID(playerId); - if (player) { - player->setBankBalance(player->getBankBalance() + totalPrice); - } else { - IOLoginData::increaseBankBalance(playerId, totalPrice); - } - } - } while (result->next()); -} - -void IOMarket::checkExpiredOffers() -{ - const time_t lastExpireDate = time(nullptr) - g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - std::ostringstream query; - query << "SELECT `id`, `amount`, `price`, `itemtype`, `player_id`, `sale` FROM `market_offers` WHERE `created` <= " << lastExpireDate; - g_databaseTasks.addTask(query.str(), IOMarket::processExpiredOffers, true); - - int32_t checkExpiredMarketOffersEachMinutes = g_config.getNumber(ConfigManager::CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES); - if (checkExpiredMarketOffersEachMinutes <= 0) { - return; - } - - g_scheduler.addEvent(createSchedulerTask(checkExpiredMarketOffersEachMinutes * 60 * 1000, IOMarket::checkExpiredOffers)); -} - -uint32_t IOMarket::getPlayerOfferCount(uint32_t playerId) -{ - std::ostringstream query; - query << "SELECT COUNT(*) AS `count` FROM `market_offers` WHERE `player_id` = " << playerId; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return 0; - } - return result->getNumber("count"); -} - -MarketOfferEx IOMarket::getOfferByCounter(uint32_t timestamp, uint16_t counter) -{ - MarketOfferEx offer; - - const int32_t created = timestamp - g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - std::ostringstream query; - query << "SELECT `id`, `sale`, `itemtype`, `amount`, `created`, `price`, `player_id`, `anonymous`, (SELECT `name` FROM `players` WHERE `id` = `player_id`) AS `player_name` FROM `market_offers` WHERE `created` = " << created << " AND (`id` & 65535) = " << counter << " LIMIT 1"; - - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - offer.id = 0; - return offer; - } - - offer.id = result->getNumber("id"); - offer.type = static_cast(result->getNumber("sale")); - offer.amount = result->getNumber("amount"); - offer.counter = result->getNumber("id") & 0xFFFF; - offer.timestamp = result->getNumber("created"); - offer.price = result->getNumber("price"); - offer.itemId = result->getNumber("itemtype"); - offer.playerId = result->getNumber("player_id"); - if (result->getNumber("anonymous") == 0) { - offer.playerName = result->getString("player_name"); - } else { - offer.playerName = "Anonymous"; - } - return offer; -} - -void IOMarket::createOffer(uint32_t playerId, MarketAction_t action, uint32_t itemId, uint16_t amount, uint32_t price, bool anonymous) -{ - std::ostringstream query; - query << "INSERT INTO `market_offers` (`player_id`, `sale`, `itemtype`, `amount`, `price`, `created`, `anonymous`) VALUES (" << playerId << ',' << action << ',' << itemId << ',' << amount << ',' << price << ',' << time(nullptr) << ',' << anonymous << ')'; - Database::getInstance()->executeQuery(query.str()); -} - -void IOMarket::acceptOffer(uint32_t offerId, uint16_t amount) -{ - std::ostringstream query; - query << "UPDATE `market_offers` SET `amount` = `amount` - " << amount << " WHERE `id` = " << offerId; - Database::getInstance()->executeQuery(query.str()); -} - -void IOMarket::deleteOffer(uint32_t offerId) -{ - std::ostringstream query; - query << "DELETE FROM `market_offers` WHERE `id` = " << offerId; - Database::getInstance()->executeQuery(query.str()); -} - -void IOMarket::appendHistory(uint32_t playerId, MarketAction_t type, uint16_t itemId, uint16_t amount, uint32_t price, time_t timestamp, MarketOfferState_t state) -{ - std::ostringstream query; - query << "INSERT INTO `market_history` (`player_id`, `sale`, `itemtype`, `amount`, `price`, `expires_at`, `inserted`, `state`) VALUES (" - << playerId << ',' << type << ',' << itemId << ',' << amount << ',' << price << ',' - << timestamp << ',' << time(nullptr) << ',' << state << ')'; - g_databaseTasks.addTask(query.str()); -} - -bool IOMarket::moveOfferToHistory(uint32_t offerId, MarketOfferState_t state) -{ - const int32_t marketOfferDuration = g_config.getNumber(ConfigManager::MARKET_OFFER_DURATION); - - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `player_id`, `sale`, `itemtype`, `amount`, `price`, `created` FROM `market_offers` WHERE `id` = " << offerId; - - DBResult_ptr result = db->storeQuery(query.str()); - if (!result) { - return false; - } - - query.str(std::string()); - query << "DELETE FROM `market_offers` WHERE `id` = " << offerId; - if (!db->executeQuery(query.str())) { - return false; - } - - appendHistory(result->getNumber("player_id"), static_cast(result->getNumber("sale")), result->getNumber("itemtype"), result->getNumber("amount"), result->getNumber("price"), result->getNumber("created") + marketOfferDuration, state); - return true; -} - -void IOMarket::updateStatistics() -{ - std::ostringstream query; - query << "SELECT `sale` AS `sale`, `itemtype` AS `itemtype`, COUNT(`price`) AS `num`, MIN(`price`) AS `min`, MAX(`price`) AS `max`, SUM(`price`) AS `sum` FROM `market_history` WHERE `state` = " << OFFERSTATE_ACCEPTED << " GROUP BY `itemtype`, `sale`"; - DBResult_ptr result = Database::getInstance()->storeQuery(query.str()); - if (!result) { - return; - } - - do { - MarketStatistics* statistics; - if (result->getNumber("sale") == MARKETACTION_BUY) { - statistics = &purchaseStatistics[result->getNumber("itemtype")]; - } else { - statistics = &saleStatistics[result->getNumber("itemtype")]; - } - - statistics->numTransactions = result->getNumber("num"); - statistics->lowestPrice = result->getNumber("min"); - statistics->totalPrice = result->getNumber("sum"); - statistics->highestPrice = result->getNumber("max"); - } while (result->next()); -} - -MarketStatistics* IOMarket::getPurchaseStatistics(uint16_t itemId) -{ - auto it = purchaseStatistics.find(itemId); - if (it == purchaseStatistics.end()) { - return nullptr; - } - return &it->second; -} - -MarketStatistics* IOMarket::getSaleStatistics(uint16_t itemId) -{ - auto it = saleStatistics.find(itemId); - if (it == saleStatistics.end()) { - return nullptr; - } - return &it->second; -} diff --git a/path_10_8/src/iomarket.h b/path_10_8/src/iomarket.h deleted file mode 100644 index 5a1d5dc60..000000000 --- a/path_10_8/src/iomarket.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_IOMARKET_H_B981E52C218C42D3B9EF726EBF0E92C9 -#define FS_IOMARKET_H_B981E52C218C42D3B9EF726EBF0E92C9 - -#include "enums.h" -#include "database.h" - -class IOMarket -{ - public: - static IOMarket* getInstance() { - static IOMarket instance; - return &instance; - } - - static MarketOfferList getActiveOffers(MarketAction_t action, uint16_t itemId); - static MarketOfferList getOwnOffers(MarketAction_t action, uint32_t playerId); - static HistoryMarketOfferList getOwnHistory(MarketAction_t action, uint32_t playerId); - - static void processExpiredOffers(DBResult_ptr result, bool); - static void checkExpiredOffers(); - - static uint32_t getPlayerOfferCount(uint32_t playerId); - static MarketOfferEx getOfferByCounter(uint32_t timestamp, uint16_t counter); - - static void createOffer(uint32_t playerId, MarketAction_t action, uint32_t itemId, uint16_t amount, uint32_t price, bool anonymous); - static void acceptOffer(uint32_t offerId, uint16_t amount); - static void deleteOffer(uint32_t offerId); - - static void appendHistory(uint32_t playerId, MarketAction_t type, uint16_t itemId, uint16_t amount, uint32_t price, time_t timestamp, MarketOfferState_t state); - static bool moveOfferToHistory(uint32_t offerId, MarketOfferState_t state); - - void updateStatistics(); - - MarketStatistics* getPurchaseStatistics(uint16_t itemId); - MarketStatistics* getSaleStatistics(uint16_t itemId); - - private: - IOMarket() = default; - - std::map purchaseStatistics; - std::map saleStatistics; -}; - -#endif diff --git a/path_10_8/src/item.cpp b/path_10_8/src/item.cpp deleted file mode 100644 index c28072af3..000000000 --- a/path_10_8/src/item.cpp +++ /dev/null @@ -1,1692 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "item.h" -#include "container.h" -#include "teleport.h" -#include "trashholder.h" -#include "mailbox.h" -#include "house.h" -#include "game.h" -#include "luascript.h" -#include "bed.h" - -#include "actions.h" -#include "combat.h" -#include "spells.h" -#include "vocation.h" - -extern Game g_game; -extern Spells* g_spells; -extern Vocations g_vocations; - -Items Item::items; - -Item* Item::CreateItem(const uint16_t _type, uint16_t _count /*= 0*/) -{ - Item* newItem = nullptr; - - const ItemType& it = Item::items[_type]; - if (it.group == ITEM_GROUP_DEPRECATED) { - return nullptr; - } - - if (it.stackable && _count == 0) { - _count = 1; - } - - if (it.id != 0) { - if (it.isDepot()) { - newItem = new DepotLocker(_type); - } else if (it.isContainer()) { - newItem = new Container(_type); - } else if (it.isTeleport()) { - newItem = new Teleport(_type); - } else if (it.isMagicField()) { - newItem = new MagicField(_type); - } else if (it.isDoor()) { - newItem = new Door(_type); - } else if (it.isTrashHolder()) { - newItem = new TrashHolder(_type); - } else if (it.isMailbox()) { - newItem = new Mailbox(_type); - } else if (it.isBed()) { - newItem = new BedItem(_type); - } else if (it.id >= 2210 && it.id <= 2212) { - newItem = new Item(_type - 3, _count); - } else if (it.id == 2215 || it.id == 2216) { - newItem = new Item(_type - 2, _count); - } else if (it.id >= 2202 && it.id <= 2206) { - newItem = new Item(_type - 37, _count); - } else if (it.id == 2640) { - newItem = new Item(6132, _count); - } else if (it.id == 6301) { - newItem = new Item(6300, _count); - } else if (it.id == 18528) { - newItem = new Item(18408, _count); - } else { - newItem = new Item(_type, _count); - } - - newItem->incrementReferenceCounter(); - } - - return newItem; -} - -Container* Item::CreateItemAsContainer(const uint16_t _type, uint16_t _size) -{ - const ItemType& it = Item::items[_type]; - if (it.id == 0 || it.group == ITEM_GROUP_DEPRECATED || it.stackable || it.useable || it.moveable || it.pickupable || it.isDepot() || it.isSplash() || it.isDoor()) { - return nullptr; - } - - Container* newItem = new Container(_type, _size); - newItem->incrementReferenceCounter(); - return newItem; -} - -Item* Item::CreateItem(PropStream& propStream) -{ - uint16_t _id; - if (!propStream.read(_id)) { - return nullptr; - } - - switch (_id) { - case ITEM_FIREFIELD_PVP_FULL: - _id = ITEM_FIREFIELD_PERSISTENT_FULL; - break; - - case ITEM_FIREFIELD_PVP_MEDIUM: - _id = ITEM_FIREFIELD_PERSISTENT_MEDIUM; - break; - - case ITEM_FIREFIELD_PVP_SMALL: - _id = ITEM_FIREFIELD_PERSISTENT_SMALL; - break; - - case ITEM_ENERGYFIELD_PVP: - _id = ITEM_ENERGYFIELD_PERSISTENT; - break; - - case ITEM_POISONFIELD_PVP: - _id = ITEM_POISONFIELD_PERSISTENT; - break; - - case ITEM_MAGICWALL: - _id = ITEM_MAGICWALL_PERSISTENT; - break; - - case ITEM_WILDGROWTH: - _id = ITEM_WILDGROWTH_PERSISTENT; - break; - - default: - break; - } - - return Item::CreateItem(_id, 0); -} - -Item::Item(const uint16_t _type, uint16_t _count /*= 0*/) -{ - parent = nullptr; - referenceCounter = 0; - - id = _type; - attributes = nullptr; - - const ItemType& it = items[id]; - - setItemCount(1); - - if (it.isFluidContainer() || it.isSplash()) { - setFluidType(_count); - } else if (it.stackable) { - if (_count != 0) { - setItemCount(_count); - } else if (it.charges != 0) { - setItemCount(it.charges); - } - } else if (it.charges != 0) { - if (_count != 0) { - setCharges(_count); - } else { - setCharges(it.charges); - } - } - - loadedFromMap = false; - setDefaultDuration(); -} - -Item::Item(const Item& i) : - Thing() -{ - parent = nullptr; - referenceCounter = 0; - - id = i.id; - count = i.count; - loadedFromMap = i.loadedFromMap; - - if (i.attributes) { - attributes = new ItemAttributes(*i.attributes); - } else { - attributes = nullptr; - } -} - -Item* Item::clone() const -{ - Item* _item = Item::CreateItem(id, count); - if (attributes) { - _item->attributes = new ItemAttributes(*attributes); - } - return _item; -} - -Item::~Item() -{ - delete attributes; -} - -bool Item::equals(const Item* otherItem) const -{ - if (!otherItem || id != otherItem->id) { - return false; - } - - if (!attributes) { - return !otherItem->attributes; - } - - const ItemAttributes* otherAttributes = otherItem->attributes; - if (!otherAttributes || attributes->attributeBits != otherAttributes->attributeBits) { - return false; - } - - const auto& attributeList = attributes->attributes; - const auto& otherAttributeList = otherAttributes->attributes; - for (const auto& attribute : attributeList) { - if (ItemAttributes::isStrAttrType(attribute.type)) { - for (const auto& otherAttribute : otherAttributeList) { - if (attribute.type == otherAttribute.type && *attribute.value.string != *otherAttribute.value.string) { - return false; - } - } - } else { - for (const auto& otherAttribute : otherAttributeList) { - if (attribute.type == otherAttribute.type && attribute.value.integer != otherAttribute.value.integer) { - return false; - } - } - } - } - return true; -} - -void Item::setDefaultSubtype() -{ - const ItemType& it = items[id]; - - setItemCount(1); - - if (it.charges != 0) { - if (it.stackable) { - setItemCount(it.charges); - } else { - setCharges(it.charges); - } - } -} - -void Item::onRemoved() -{ - ScriptEnvironment::removeTempItem(this); - - if (hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - g_game.removeUniqueItem(getUniqueId()); - } -} - -void Item::setID(uint16_t newid) -{ - const ItemType& prevIt = Item::items[id]; - id = newid; - - const ItemType& it = Item::items[newid]; - uint32_t newDuration = it.decayTime * 1000; - - if (newDuration == 0 && !it.stopTime && it.decayTo < 0) { - removeAttribute(ITEM_ATTRIBUTE_DECAYSTATE); - removeAttribute(ITEM_ATTRIBUTE_DURATION); - } - - removeAttribute(ITEM_ATTRIBUTE_CORPSEOWNER); - - if (newDuration > 0 && (!prevIt.stopTime || !hasAttribute(ITEM_ATTRIBUTE_DURATION))) { - setDecaying(DECAYING_FALSE); - setDuration(newDuration); - } -} - -Cylinder* Item::getTopParent() -{ - Cylinder* aux = getParent(); - Cylinder* prevaux = dynamic_cast(this); - if (!aux) { - return prevaux; - } - - while (aux->getParent() != nullptr) { - prevaux = aux; - aux = aux->getParent(); - } - - if (prevaux) { - return prevaux; - } - return aux; -} - -const Cylinder* Item::getTopParent() const -{ - const Cylinder* aux = getParent(); - const Cylinder* prevaux = dynamic_cast(this); - if (!aux) { - return prevaux; - } - - while (aux->getParent() != nullptr) { - prevaux = aux; - aux = aux->getParent(); - } - - if (prevaux) { - return prevaux; - } - return aux; -} - -Tile* Item::getTile() -{ - Cylinder* cylinder = getTopParent(); - //get root cylinder - if (cylinder->getParent()) { - cylinder = cylinder->getParent(); - } - return dynamic_cast(cylinder); -} - -const Tile* Item::getTile() const -{ - const Cylinder* cylinder = getTopParent(); - //get root cylinder - if (cylinder->getParent()) { - cylinder = cylinder->getParent(); - } - return dynamic_cast(cylinder); -} - -uint16_t Item::getSubType() const -{ - const ItemType& it = items[id]; - if (it.isFluidContainer() || it.isSplash()) { - return getFluidType(); - } else if (it.stackable) { - return count; - } else if (it.charges != 0) { - return getCharges(); - } - return count; -} - -Player* Item::getHoldingPlayer() const -{ - Cylinder* p = getParent(); - while (p) { - if (p->getCreature()) { - return p->getCreature()->getPlayer(); - } - - p = p->getParent(); - } - return nullptr; -} - -void Item::setSubType(uint16_t n) -{ - const ItemType& it = items[id]; - if (it.isFluidContainer() || it.isSplash()) { - setFluidType(n); - } else if (it.stackable) { - setItemCount(n); - } else if (it.charges != 0) { - setCharges(n); - } else { - setItemCount(n); - } -} - -Attr_ReadValue Item::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - switch (attr) { - case ATTR_COUNT: - case ATTR_RUNE_CHARGES: { - uint8_t _count; - if (!propStream.read(_count)) { - return ATTR_READ_ERROR; - } - - setSubType(_count); - break; - } - - case ATTR_ACTION_ID: { - uint16_t actionId; - if (!propStream.read(actionId)) { - return ATTR_READ_ERROR; - } - - setActionId(actionId); - break; - } - - case ATTR_UNIQUE_ID: { - uint16_t uniqueId; - if (!propStream.read(uniqueId)) { - return ATTR_READ_ERROR; - } - - setUniqueId(uniqueId); - break; - } - - case ATTR_TEXT: { - std::string text; - if (!propStream.readString(text)) { - return ATTR_READ_ERROR; - } - - setText(text); - break; - } - - case ATTR_WRITTENDATE: { - uint32_t writtenDate; - if (!propStream.read(writtenDate)) { - return ATTR_READ_ERROR; - } - - setDate(writtenDate); - break; - } - - case ATTR_WRITTENBY: { - std::string writer; - if (!propStream.readString(writer)) { - return ATTR_READ_ERROR; - } - - setWriter(writer); - break; - } - - case ATTR_DESC: { - std::string text; - if (!propStream.readString(text)) { - return ATTR_READ_ERROR; - } - - setSpecialDescription(text); - break; - } - - case ATTR_CHARGES: { - uint16_t charges; - if (!propStream.read(charges)) { - return ATTR_READ_ERROR; - } - - setSubType(charges); - break; - } - - case ATTR_DURATION: { - int32_t duration; - if (!propStream.read(duration)) { - return ATTR_READ_ERROR; - } - - setDuration(std::max(0, duration)); - break; - } - - case ATTR_DECAYING_STATE: { - uint8_t state; - if (!propStream.read(state)) { - return ATTR_READ_ERROR; - } - - if (state != DECAYING_FALSE) { - setDecaying(DECAYING_PENDING); - } - break; - } - - case ATTR_NAME: { - std::string name; - if (!propStream.readString(name)) { - return ATTR_READ_ERROR; - } - - setStrAttr(ITEM_ATTRIBUTE_NAME, name); - break; - } - - case ATTR_ARTICLE: { - std::string article; - if (!propStream.readString(article)) { - return ATTR_READ_ERROR; - } - - setStrAttr(ITEM_ATTRIBUTE_ARTICLE, article); - break; - } - - case ATTR_PLURALNAME: { - std::string pluralName; - if (!propStream.readString(pluralName)) { - return ATTR_READ_ERROR; - } - - setStrAttr(ITEM_ATTRIBUTE_PLURALNAME, pluralName); - break; - } - - case ATTR_WEIGHT: { - uint32_t weight; - if (!propStream.read(weight)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_WEIGHT, weight); - break; - } - - case ATTR_ATTACK: { - int32_t attack; - if (!propStream.read(attack)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_ATTACK, attack); - break; - } - - case ATTR_DEFENSE: { - int32_t defense; - if (!propStream.read(defense)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_DEFENSE, defense); - break; - } - - case ATTR_EXTRADEFENSE: { - int32_t extraDefense; - if (!propStream.read(extraDefense)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_EXTRADEFENSE, extraDefense); - break; - } - - case ATTR_ARMOR: { - int32_t armor; - if (!propStream.read(armor)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_ARMOR, armor); - break; - } - - case ATTR_HITCHANCE: { - int8_t hitChance; - if (!propStream.read(hitChance)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_HITCHANCE, hitChance); - break; - } - - case ATTR_SHOOTRANGE: { - uint8_t shootRange; - if (!propStream.read(shootRange)) { - return ATTR_READ_ERROR; - } - - setIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE, shootRange); - break; - } - - //these should be handled through derived classes - //If these are called then something has changed in the items.xml since the map was saved - //just read the values - - //Depot class - case ATTR_DEPOT_ID: { - if (!propStream.skip(2)) { - return ATTR_READ_ERROR; - } - break; - } - - //Door class - case ATTR_HOUSEDOORID: { - if (!propStream.skip(1)) { - return ATTR_READ_ERROR; - } - break; - } - - //Bed class - case ATTR_SLEEPERGUID: { - if (!propStream.skip(4)) { - return ATTR_READ_ERROR; - } - break; - } - - case ATTR_SLEEPSTART: { - if (!propStream.skip(4)) { - return ATTR_READ_ERROR; - } - break; - } - - //Teleport class - case ATTR_TELE_DEST: { - if (!propStream.skip(5)) { - return ATTR_READ_ERROR; - } - break; - } - - //Container class - case ATTR_CONTAINER_ITEMS: { - return ATTR_READ_ERROR; - } - - default: - return ATTR_READ_ERROR; - } - - return ATTR_READ_CONTINUE; -} - -bool Item::unserializeAttr(PropStream& propStream) -{ - uint8_t attr_type; - while (propStream.read(attr_type) && attr_type != 0) { - Attr_ReadValue ret = readAttr(static_cast(attr_type), propStream); - if (ret == ATTR_READ_ERROR) { - return false; - } else if (ret == ATTR_READ_END) { - return true; - } - } - return true; -} - -bool Item::unserializeItemNode(FileLoader&, NODE, PropStream& propStream) -{ - return unserializeAttr(propStream); -} - -void Item::serializeAttr(PropWriteStream& propWriteStream) const -{ - const ItemType& it = items[id]; - if (it.stackable || it.isFluidContainer() || it.isSplash()) { - propWriteStream.write(ATTR_COUNT); - propWriteStream.write(getSubType()); - } - - uint16_t charges = getCharges(); - if (charges != 0) { - propWriteStream.write(ATTR_CHARGES); - propWriteStream.write(charges); - } - - if (it.moveable) { - uint16_t actionId = getActionId(); - if (actionId != 0) { - propWriteStream.write(ATTR_ACTION_ID); - propWriteStream.write(actionId); - } - } - - const std::string& text = getText(); - if (!text.empty()) { - propWriteStream.write(ATTR_TEXT); - propWriteStream.writeString(text); - } - - const time_t writtenDate = getDate(); - if (writtenDate != 0) { - propWriteStream.write(ATTR_WRITTENDATE); - propWriteStream.write(writtenDate); - } - - const std::string& writer = getWriter(); - if (!writer.empty()) { - propWriteStream.write(ATTR_WRITTENBY); - propWriteStream.writeString(writer); - } - - const std::string& specialDesc = getSpecialDescription(); - if (!specialDesc.empty()) { - propWriteStream.write(ATTR_DESC); - propWriteStream.writeString(specialDesc); - } - - if (hasAttribute(ITEM_ATTRIBUTE_DURATION)) { - propWriteStream.write(ATTR_DURATION); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_DURATION)); - } - - ItemDecayState_t decayState = getDecaying(); - if (decayState == DECAYING_TRUE || decayState == DECAYING_PENDING) { - propWriteStream.write(ATTR_DECAYING_STATE); - propWriteStream.write(decayState); - } - - if (hasAttribute(ITEM_ATTRIBUTE_NAME)) { - propWriteStream.write(ATTR_NAME); - propWriteStream.writeString(getStrAttr(ITEM_ATTRIBUTE_NAME)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_ARTICLE)) { - propWriteStream.write(ATTR_ARTICLE); - propWriteStream.writeString(getStrAttr(ITEM_ATTRIBUTE_ARTICLE)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_PLURALNAME)) { - propWriteStream.write(ATTR_PLURALNAME); - propWriteStream.writeString(getStrAttr(ITEM_ATTRIBUTE_PLURALNAME)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_WEIGHT)) { - propWriteStream.write(ATTR_WEIGHT); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_WEIGHT)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_ATTACK)) { - propWriteStream.write(ATTR_ATTACK); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_ATTACK)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_DEFENSE)) { - propWriteStream.write(ATTR_DEFENSE); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_DEFENSE)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE)) { - propWriteStream.write(ATTR_EXTRADEFENSE); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_EXTRADEFENSE)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_ARMOR)) { - propWriteStream.write(ATTR_ARMOR); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_ARMOR)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_HITCHANCE)) { - propWriteStream.write(ATTR_HITCHANCE); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_HITCHANCE)); - } - - if (hasAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)) { - propWriteStream.write(ATTR_SHOOTRANGE); - propWriteStream.write(getIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE)); - } -} - -bool Item::hasProperty(ITEMPROPERTY prop) const -{ - const ItemType& it = items[id]; - switch (prop) { - case CONST_PROP_BLOCKSOLID: return it.blockSolid; - case CONST_PROP_MOVEABLE: return it.moveable && !hasAttribute(ITEM_ATTRIBUTE_UNIQUEID); - case CONST_PROP_HASHEIGHT: return it.hasHeight; - case CONST_PROP_BLOCKPROJECTILE: return it.blockProjectile; - case CONST_PROP_BLOCKPATH: return it.blockPathFind; - case CONST_PROP_ISVERTICAL: return it.isVertical; - case CONST_PROP_ISHORIZONTAL: return it.isHorizontal; - case CONST_PROP_IMMOVABLEBLOCKSOLID: return it.blockSolid && (!it.moveable || hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)); - case CONST_PROP_IMMOVABLEBLOCKPATH: return it.blockPathFind && (!it.moveable || hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)); - case CONST_PROP_IMMOVABLENOFIELDBLOCKPATH: return !it.isMagicField() && it.blockPathFind && (!it.moveable || hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)); - case CONST_PROP_NOFIELDBLOCKPATH: return !it.isMagicField() && it.blockPathFind; - case CONST_PROP_SUPPORTHANGABLE: return it.isHorizontal || it.isVertical; - default: return false; - } -} - -uint32_t Item::getWeight() const -{ - uint32_t weight = getBaseWeight(); - if (isStackable()) { - return weight * std::max(1, getItemCount()); - } - return weight; -} - -std::string Item::getDescription(const ItemType& it, int32_t lookDistance, - const Item* item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) -{ - const std::string* text = nullptr; - - std::ostringstream s; - s << getNameDescription(it, item, subType, addArticle); - - if (item) { - subType = item->getSubType(); - } - - if (it.isRune()) { - if (it.runeLevel > 0 || it.runeMagLevel > 0) { - int32_t tmpSubType = subType; - - if (item) { - tmpSubType = item->getSubType(); - } - - s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used by "; - - if (RuneSpell* rune = g_spells->getRuneSpell(it.id)) { - const VocSpellMap& vocMap = rune->getVocMap(); - if (vocMap.empty()) { - s << "players"; - } else { - std::vector showVocMap; - - // vocations listed are mostly unpromoted ones and the promoted version, with the latter hidden from - // description, so probably always `total / 2` is the amount of vocations to be shown. - showVocMap.reserve(vocMap.size() / 2); - - for (const auto& voc : vocMap) { - if (voc.second) { - showVocMap.push_back(g_vocations.getVocation(voc.first)); - } - } - - auto vocIt = showVocMap.begin(), vocLast = (showVocMap.end() - 1); - while (vocIt != vocLast) { - s << asLowerCaseString((*vocIt)->getVocName()) << "s"; - - if (++vocIt == vocLast) { - s << " and "; - } else { - s << ", "; - } - } - s << asLowerCaseString((*vocLast)->getVocName()) << "s"; - } - - s << " with"; - - if (it.runeLevel > 0) { - s << " level " << it.runeLevel; - } - - if (it.runeMagLevel > 0) { - if (it.runeLevel > 0) { - s << " and"; - } - - s << " magic level " << it.runeMagLevel; - } - - s << " or higher"; - } - } - } else if (it.weaponType != WEAPON_NONE) { - if (it.weaponType == WEAPON_DISTANCE && it.ammoType != AMMO_NONE) { - s << " (Range:" << static_cast(item ? item->getShootRange() : it.shootRange); - - int32_t attack; - int8_t hitChance; - if (item) { - attack = item->getAttack(); - hitChance = item->getHitChance(); - } else { - attack = it.attack; - hitChance = it.hitChance; - } - - if (attack != 0) { - s << ", Atk" << std::showpos << attack << std::noshowpos; - } - - if (hitChance != 0) { - s << ", Hit%" << std::showpos << static_cast(hitChance) << std::noshowpos; - } - - s << ')'; - } else if (it.weaponType != WEAPON_AMMO) { - bool begin = true; - - int32_t attack, defense, extraDefense; - if (item) { - attack = item->getAttack(); - defense = item->getDefense(); - extraDefense = item->getExtraDefense(); - } else { - attack = it.attack; - defense = it.defense; - extraDefense = it.extraDefense; - } - - if (attack != 0) { - begin = false; - s << " (Atk:" << attack; - - if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - s << " physical + " << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - } - } - - if (defense != 0 || extraDefense != 0) { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "Def:" << defense; - if (extraDefense != 0) { - s << ' ' << std::showpos << extraDefense << std::noshowpos; - } - } - - if (it.abilities) { - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { - if (!it.abilities->skills[i]) { - continue; - } - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; - } - - if (it.abilities->stats[STAT_MAGICPOINTS]) { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos; - } - - int16_t show = it.abilities->absorbPercent[0]; - if (show != 0) { - for (size_t i = 1; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] != show) { - show = 0; - break; - } - } - } - - if (show == 0) { - bool tmp = true; - - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] == 0) { - continue; - } - - if (tmp) { - tmp = false; - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection "; - } else { - s << ", "; - } - - s << getCombatName(indexToCombatType(i)) << ' ' << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << '%'; - } - } else { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection all " << std::showpos << show << std::noshowpos << '%'; - } - - show = it.abilities->fieldAbsorbPercent[0]; - if (show != 0) { - for (size_t i = 1; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] != show) { - show = 0; - break; - } - } - } - - if (show == 0) { - bool tmp = true; - - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - if (it.abilities->fieldAbsorbPercent[i] == 0) { - continue; - } - - if (tmp) { - tmp = false; - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection "; - } else { - s << ", "; - } - - s << getCombatName(indexToCombatType(i)) << " field " << std::showpos << it.abilities->fieldAbsorbPercent[i] << std::noshowpos << '%'; - } - } else { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection all fields " << std::showpos << show << std::noshowpos << '%'; - } - - if (it.abilities->speed) { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "speed " << std::showpos << (it.abilities->speed >> 1) << std::noshowpos; - } - } - - if (!begin) { - s << ')'; - } - } - } else if (it.armor != 0 || (item && item->getArmor() != 0) || it.showAttributes) { - bool begin = true; - - int32_t armor = (item ? item->getArmor() : it.armor); - if (armor != 0) { - s << " (Arm:" << armor; - begin = false; - } - - if (it.abilities) { - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { - if (!it.abilities->skills[i]) { - continue; - } - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; - } - - if (it.abilities->stats[STAT_MAGICPOINTS]) { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos; - } - - int16_t show = it.abilities->absorbPercent[0]; - if (show != 0) { - for (size_t i = 1; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] != show) { - show = 0; - break; - } - } - } - - if (!show) { - bool protectionBegin = true; - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] == 0) { - continue; - } - - if (protectionBegin) { - protectionBegin = false; - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection "; - } else { - s << ", "; - } - - s << getCombatName(indexToCombatType(i)) << ' ' << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << '%'; - } - } else { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection all " << std::showpos << show << std::noshowpos << '%'; - } - - show = it.abilities->fieldAbsorbPercent[0]; - if (show != 0) { - for (size_t i = 1; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] != show) { - show = 0; - break; - } - } - } - - if (!show) { - bool tmp = true; - - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - if (it.abilities->fieldAbsorbPercent[i] == 0) { - continue; - } - - if (tmp) { - tmp = false; - - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection "; - } else { - s << ", "; - } - - s << getCombatName(indexToCombatType(i)) << " field " << std::showpos << it.abilities->fieldAbsorbPercent[i] << std::noshowpos << '%'; - } - } else { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "protection all fields " << std::showpos << show << std::noshowpos << '%'; - } - - if (it.abilities->speed) { - if (begin) { - begin = false; - s << " ("; - } else { - s << ", "; - } - - s << "speed " << std::showpos << (it.abilities->speed >> 1) << std::noshowpos; - } - } - - if (!begin) { - s << ')'; - } - } else if (it.isContainer() || (item && item->getContainer())) { - int volume = 0; - if (!item || !item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - if (it.isContainer()) { - volume = it.maxItems; - } else { - volume = item->getContainer()->capacity(); - } - } - - if (volume != 0) { - s << " (Vol:" << volume << ')'; - } - } else { - bool found = true; - - if (it.abilities) { - if (it.abilities->speed > 0) { - s << " (speed " << std::showpos << (it.abilities->speed / 2) << std::noshowpos << ')'; - } else if (hasBitSet(CONDITION_DRUNK, it.abilities->conditionSuppressions)) { - s << " (hard drinking)"; - } else if (it.abilities->invisible) { - s << " (invisibility)"; - } else if (it.abilities->regeneration) { - s << " (faster regeneration)"; - } else if (it.abilities->manaShield) { - s << " (mana shield)"; - } else { - found = false; - } - } else { - found = false; - } - - if (!found) { - if (it.isKey()) { - s << " (Key:" << (item ? item->getActionId() : 0) << ')'; - } else if (it.isFluidContainer()) { - if (subType > 0) { - const std::string& itemName = items[subType].name; - s << " of " << (!itemName.empty() ? itemName : "unknown"); - } else { - s << ". It is empty"; - } - } else if (it.isSplash()) { - s << " of "; - - if (subType > 0 && !items[subType].name.empty()) { - s << items[subType].name; - } else { - s << "unknown"; - } - } else if (it.allowDistRead && (it.id < 7369 || it.id > 7371)) { - s << '.' << std::endl; - - if (lookDistance <= 4) { - if (item) { - text = &item->getText(); - if (!text->empty()) { - const std::string& writer = item->getWriter(); - if (!writer.empty()) { - s << writer << " wrote"; - time_t date = item->getDate(); - if (date != 0) { - s << " on " << formatDateShort(date); - } - s << ": "; - } else { - s << "You read: "; - } - s << *text; - } else { - s << "Nothing is written on it"; - } - } else { - s << "Nothing is written on it"; - } - } else { - s << "You are too far away to read it"; - } - } else if (it.levelDoor != 0 && item) { - uint16_t actionId = item->getActionId(); - if (actionId >= it.levelDoor) { - s << " for level " << (actionId - it.levelDoor); - } - } - } - } - - if (it.showCharges) { - s << " that has " << subType << " charge" << (subType != 1 ? "s" : "") << " left"; - } - - if (it.showDuration) { - if (item && item->hasAttribute(ITEM_ATTRIBUTE_DURATION)) { - uint32_t duration = item->getDuration() / 1000; - s << " that will expire in "; - - if (duration >= 86400) { - uint16_t days = duration / 86400; - uint16_t hours = (duration % 86400) / 3600; - s << days << " day" << (days != 1 ? "s" : ""); - - if (hours > 0) { - s << " and " << hours << " hour" << (hours != 1 ? "s" : ""); - } - } else if (duration >= 3600) { - uint16_t hours = duration / 3600; - uint16_t minutes = (duration % 3600) / 60; - s << hours << " hour" << (hours != 1 ? "s" : ""); - - if (minutes > 0) { - s << " and " << minutes << " minute" << (minutes != 1 ? "s" : ""); - } - } else if (duration >= 60) { - uint16_t minutes = duration / 60; - s << minutes << " minute" << (minutes != 1 ? "s" : ""); - uint16_t seconds = duration % 60; - - if (seconds > 0) { - s << " and " << seconds << " second" << (seconds != 1 ? "s" : ""); - } - } else { - s << duration << " second" << (duration != 1 ? "s" : ""); - } - } else { - s << " that is brand-new"; - } - } - - if (!it.allowDistRead || (it.id >= 7369 && it.id <= 7371)) { - s << '.'; - } else { - if (!text && item) { - text = &item->getText(); - } - - if (!text || text->empty()) { - s << '.'; - } - } - - if (it.wieldInfo != 0) { - s << std::endl << "It can only be wielded properly by "; - - if (it.wieldInfo & WIELDINFO_PREMIUM) { - s << "premium "; - } - - if (it.wieldInfo & WIELDINFO_VOCREQ) { - s << it.vocationString; - } else { - s << "players"; - } - - if (it.wieldInfo & WIELDINFO_LEVEL) { - s << " of level " << it.minReqLevel << " or higher"; - } - - if (it.wieldInfo & WIELDINFO_MAGLV) { - if (it.wieldInfo & WIELDINFO_LEVEL) { - s << " and"; - } else { - s << " of"; - } - - s << " magic level " << it.minReqMagicLevel << " or higher"; - } - - s << '.'; - } - - if (lookDistance <= 1) { - if (item) { - const uint32_t weight = item->getWeight(); - if (weight != 0 && it.pickupable) { - s << std::endl << getWeightDescription(it, weight, item->getItemCount()); - } - } else if (it.weight != 0 && it.pickupable) { - s << std::endl << getWeightDescription(it, it.weight); - } - } - - if (item) { - const std::string& specialDescription = item->getSpecialDescription(); - if (!specialDescription.empty()) { - s << std::endl << specialDescription; - } else if (lookDistance <= 1 && !it.description.empty()) { - s << std::endl << it.description; - } - } else if (lookDistance <= 1 && !it.description.empty()) { - s << std::endl << it.description; - } - - if (it.allowDistRead && it.id >= 7369 && it.id <= 7371) { - if (!text && item) { - text = &item->getText(); - } - - if (text && !text->empty()) { - s << std::endl << *text; - } - } - return s.str(); -} - -std::string Item::getDescription(int32_t lookDistance) const -{ - const ItemType& it = items[id]; - return getDescription(it, lookDistance, this); -} - -std::string Item::getNameDescription(const ItemType& it, const Item* item /*= nullptr*/, int32_t subType /*= -1*/, bool addArticle /*= true*/) -{ - if (item) { - subType = item->getSubType(); - } - - std::ostringstream s; - - const std::string& name = (item ? item->getName() : it.name); - if (!name.empty()) { - if (it.stackable && subType > 1) { - if (it.showCount) { - s << subType << ' '; - } - - s << (item ? item->getPluralName() : it.getPluralName()); - } else { - if (addArticle) { - const std::string& article = (item ? item->getArticle() : it.article); - if (!article.empty()) { - s << article << ' '; - } - } - - s << name; - } - } else { - s << "an item of type " << it.id; - } - return s.str(); -} - -std::string Item::getNameDescription() const -{ - const ItemType& it = items[id]; - return getNameDescription(it, this); -} - -std::string Item::getWeightDescription(const ItemType& it, uint32_t weight, uint32_t _count /*= 1*/) -{ - std::ostringstream ss; - if (it.stackable && _count > 1 && it.showCount != 0) { - ss << "They weigh "; - } else { - ss << "It weighs "; - } - - if (weight < 10) { - ss << "0.0" << weight; - } else if (weight < 100) { - ss << "0." << weight; - } else { - std::string weightString = std::to_string(weight); - weightString.insert(weightString.end() - 2, '.'); - ss << weightString; - } - - ss << " oz."; - return ss.str(); -} - -std::string Item::getWeightDescription(uint32_t weight) const -{ - const ItemType& it = Item::items[id]; - return getWeightDescription(it, weight, getItemCount()); -} - -std::string Item::getWeightDescription() const -{ - uint32_t weight = getWeight(); - if (weight == 0) { - return std::string(); - } - return getWeightDescription(weight); -} - -void Item::setUniqueId(uint16_t n) -{ - if (hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - return; - } - - if (g_game.addUniqueItem(n, this)) { - getAttributes()->setUniqueId(n); - } -} - -bool Item::canDecay() const -{ - if (isRemoved()) { - return false; - } - - const ItemType& it = Item::items[id]; - if (it.decayTo < 0 || it.decayTime == 0) { - return false; - } - - if (hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - return false; - } - - return true; -} - -int32_t Item::getWorth() const -{ - switch (id) { - case ITEM_GOLD_COIN: - return count; - - case ITEM_PLATINUM_COIN: - return count * 100; - - case ITEM_CRYSTAL_COIN: - return count * 10000; - - default: - return 0; - } -} - -void Item::getLight(LightInfo& lightInfo) const -{ - const ItemType& it = items[id]; - lightInfo.color = it.lightColor; - lightInfo.level = it.lightLevel; -} - -std::string ItemAttributes::emptyString; - -const std::string& ItemAttributes::getStrAttr(itemAttrTypes type) const -{ - if (!isStrAttrType(type)) { - return emptyString; - } - - const Attribute* attr = getExistingAttr(type); - if (!attr) { - return emptyString; - } - return *attr->value.string; -} - -void ItemAttributes::setStrAttr(itemAttrTypes type, const std::string& value) -{ - if (!isStrAttrType(type)) { - return; - } - - if (value.empty()) { - return; - } - - Attribute& attr = getAttr(type); - delete attr.value.string; - attr.value.string = new std::string(value); -} - -void ItemAttributes::removeAttribute(itemAttrTypes type) -{ - if (!hasAttribute(type)) { - return; - } - - auto prev_it = attributes.cbegin(); - if ((*prev_it).type == type) { - attributes.pop_front(); - } else { - auto it = prev_it, end = attributes.cend(); - while (++it != end) { - if ((*it).type == type) { - attributes.erase_after(prev_it); - break; - } - prev_it = it; - } - } - attributeBits &= ~type; -} - -int64_t ItemAttributes::getIntAttr(itemAttrTypes type) const -{ - if (!isIntAttrType(type)) { - return 0; - } - - const Attribute* attr = getExistingAttr(type); - if (!attr) { - return 0; - } - return attr->value.integer; -} - -void ItemAttributes::setIntAttr(itemAttrTypes type, int64_t value) -{ - if (!isIntAttrType(type)) { - return; - } - - getAttr(type).value.integer = value; -} - -void ItemAttributes::increaseIntAttr(itemAttrTypes type, int64_t value) -{ - if (!isIntAttrType(type)) { - return; - } - - getAttr(type).value.integer += value; -} - -const ItemAttributes::Attribute* ItemAttributes::getExistingAttr(itemAttrTypes type) const -{ - if (hasAttribute(type)) { - for (const Attribute& attribute : attributes) { - if (attribute.type == type) { - return &attribute; - } - } - } - return nullptr; -} - -ItemAttributes::Attribute& ItemAttributes::getAttr(itemAttrTypes type) -{ - if (hasAttribute(type)) { - for (Attribute& attribute : attributes) { - if (attribute.type == type) { - return attribute; - } - } - } - - attributeBits |= type; - attributes.emplace_front(type); - return attributes.front(); -} - -void Item::startDecaying() -{ - g_game.startDecay(this); -} - -bool Item::hasMarketAttributes() const -{ - if (attributes == nullptr) { - return true; - } - - for (const auto& attr : attributes->getList()) { - if (attr.type == ITEM_ATTRIBUTE_CHARGES) { - uint16_t charges = static_cast(attr.value.integer); - if (charges != items[id].charges) { - return false; - } - } else if (attr.type == ITEM_ATTRIBUTE_DURATION) { - uint32_t duration = static_cast(attr.value.integer); - if (duration != getDefaultDuration()) { - return false; - } - } else { - return false; - } - } - return true; -} diff --git a/path_10_8/src/item.h b/path_10_8/src/item.h deleted file mode 100644 index 451e55fa8..000000000 --- a/path_10_8/src/item.h +++ /dev/null @@ -1,777 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ITEM_H_009A319FB13D477D9EEFFBBD9BB83562 -#define FS_ITEM_H_009A319FB13D477D9EEFFBBD9BB83562 - -#include "cylinder.h" -#include "thing.h" -#include "items.h" - -#include - -class Creature; -class Player; -class Container; -class Depot; -class Teleport; -class TrashHolder; -class Mailbox; -class Door; -class MagicField; -class BedItem; - -enum ITEMPROPERTY { - CONST_PROP_BLOCKSOLID = 0, - CONST_PROP_HASHEIGHT, - CONST_PROP_BLOCKPROJECTILE, - CONST_PROP_BLOCKPATH, - CONST_PROP_ISVERTICAL, - CONST_PROP_ISHORIZONTAL, - CONST_PROP_MOVEABLE, - CONST_PROP_IMMOVABLEBLOCKSOLID, - CONST_PROP_IMMOVABLEBLOCKPATH, - CONST_PROP_IMMOVABLENOFIELDBLOCKPATH, - CONST_PROP_NOFIELDBLOCKPATH, - CONST_PROP_SUPPORTHANGABLE, -}; - -enum TradeEvents_t { - ON_TRADE_TRANSFER, - ON_TRADE_CANCEL, -}; - -enum ItemDecayState_t : uint8_t { - DECAYING_FALSE = 0, - DECAYING_TRUE, - DECAYING_PENDING, -}; - -enum AttrTypes_t { - //ATTR_DESCRIPTION = 1, - //ATTR_EXT_FILE = 2, - ATTR_TILE_FLAGS = 3, - ATTR_ACTION_ID = 4, - ATTR_UNIQUE_ID = 5, - ATTR_TEXT = 6, - ATTR_DESC = 7, - ATTR_TELE_DEST = 8, - ATTR_ITEM = 9, - ATTR_DEPOT_ID = 10, - //ATTR_EXT_SPAWN_FILE = 11, - ATTR_RUNE_CHARGES = 12, - //ATTR_EXT_HOUSE_FILE = 13, - ATTR_HOUSEDOORID = 14, - ATTR_COUNT = 15, - ATTR_DURATION = 16, - ATTR_DECAYING_STATE = 17, - ATTR_WRITTENDATE = 18, - ATTR_WRITTENBY = 19, - ATTR_SLEEPERGUID = 20, - ATTR_SLEEPSTART = 21, - ATTR_CHARGES = 22, - ATTR_CONTAINER_ITEMS = 23, - ATTR_NAME = 24, - ATTR_ARTICLE = 25, - ATTR_PLURALNAME = 26, - ATTR_WEIGHT = 27, - ATTR_ATTACK = 28, - ATTR_DEFENSE = 29, - ATTR_EXTRADEFENSE = 30, - ATTR_ARMOR = 31, - ATTR_HITCHANCE = 32, - ATTR_SHOOTRANGE = 33, -}; - -enum Attr_ReadValue { - ATTR_READ_CONTINUE, - ATTR_READ_ERROR, - ATTR_READ_END, -}; - -class ItemAttributes -{ - public: - ItemAttributes() : attributeBits(0) {} - - void setSpecialDescription(const std::string& desc) { - setStrAttr(ITEM_ATTRIBUTE_DESCRIPTION, desc); - } - const std::string& getSpecialDescription() const { - return getStrAttr(ITEM_ATTRIBUTE_DESCRIPTION); - } - - void setText(const std::string& text) { - setStrAttr(ITEM_ATTRIBUTE_TEXT, text); - } - void resetText() { - removeAttribute(ITEM_ATTRIBUTE_TEXT); - } - const std::string& getText() const { - return getStrAttr(ITEM_ATTRIBUTE_TEXT); - } - - void setDate(int32_t n) { - setIntAttr(ITEM_ATTRIBUTE_DATE, n); - } - void resetDate() { - removeAttribute(ITEM_ATTRIBUTE_DATE); - } - time_t getDate() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_DATE)); - } - - void setWriter(const std::string& _writer) { - setStrAttr(ITEM_ATTRIBUTE_WRITER, _writer); - } - void resetWriter() { - removeAttribute(ITEM_ATTRIBUTE_WRITER); - } - const std::string& getWriter() const { - return getStrAttr(ITEM_ATTRIBUTE_WRITER); - } - - void setActionId(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_ACTIONID, n); - } - uint16_t getActionId() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_ACTIONID)); - } - - void setUniqueId(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_UNIQUEID, n); - } - uint16_t getUniqueId() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_UNIQUEID)); - } - - void setCharges(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_CHARGES, n); - } - uint16_t getCharges() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_CHARGES)); - } - - void setFluidType(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_FLUIDTYPE, n); - } - uint16_t getFluidType() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_FLUIDTYPE)); - } - - void setOwner(uint32_t _owner) { - setIntAttr(ITEM_ATTRIBUTE_OWNER, _owner); - } - uint32_t getOwner() const { - return getIntAttr(ITEM_ATTRIBUTE_OWNER); - } - - void setCorpseOwner(uint32_t _corpseOwner) { - setIntAttr(ITEM_ATTRIBUTE_CORPSEOWNER, _corpseOwner); - } - uint32_t getCorpseOwner() const { - return getIntAttr(ITEM_ATTRIBUTE_CORPSEOWNER); - } - - void setDuration(int32_t time) { - setIntAttr(ITEM_ATTRIBUTE_DURATION, time); - } - void decreaseDuration(int32_t time) { - increaseIntAttr(ITEM_ATTRIBUTE_DURATION, -time); - } - uint32_t getDuration() const { - return getIntAttr(ITEM_ATTRIBUTE_DURATION); - } - - void setDecaying(ItemDecayState_t decayState) { - setIntAttr(ITEM_ATTRIBUTE_DECAYSTATE, decayState); - } - ItemDecayState_t getDecaying() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_DECAYSTATE)); - } - - protected: - inline bool hasAttribute(itemAttrTypes type) const { - return (type & attributeBits) != 0; - } - void removeAttribute(itemAttrTypes type); - - static std::string emptyString; - - struct Attribute - { - union { - int64_t integer; - std::string* string; - } value; - itemAttrTypes type; - - explicit Attribute(itemAttrTypes type) : type(type) { - memset(&value, 0, sizeof(value)); - } - Attribute(const Attribute& i) { - type = i.type; - if (ItemAttributes::isIntAttrType(type)) { - value.integer = i.value.integer; - } else if (ItemAttributes::isStrAttrType(type)) { - value.string = new std::string(*i.value.string); - } else { - memset(&value, 0, sizeof(value)); - } - } - Attribute(Attribute&& attribute) : value(attribute.value), type(attribute.type) { - memset(&attribute.value, 0, sizeof(value)); - attribute.type = ITEM_ATTRIBUTE_NONE; - } - ~Attribute() { - if (ItemAttributes::isStrAttrType(type)) { - delete value.string; - } - } - Attribute& operator=(Attribute other) { - Attribute::swap(*this, other); - return *this; - } - Attribute& operator=(Attribute&& other) { - if (this != &other) { - if (ItemAttributes::isStrAttrType(type)) { - delete value.string; - } - - value = other.value; - type = other.type; - - memset(&other.value, 0, sizeof(value)); - other.type = ITEM_ATTRIBUTE_NONE; - } - return *this; - } - - static void swap(Attribute& first, Attribute& second) { - std::swap(first.value, second.value); - std::swap(first.type, second.type); - } - }; - - std::forward_list attributes; - uint32_t attributeBits; - - const std::string& getStrAttr(itemAttrTypes type) const; - void setStrAttr(itemAttrTypes type, const std::string& value); - - int64_t getIntAttr(itemAttrTypes type) const; - void setIntAttr(itemAttrTypes type, int64_t value); - void increaseIntAttr(itemAttrTypes type, int64_t value); - - void addAttr(Attribute* attr); - const Attribute* getExistingAttr(itemAttrTypes type) const; - Attribute& getAttr(itemAttrTypes type); - - public: - inline static bool isIntAttrType(itemAttrTypes type) { - return (type & 0x7FFE13) != 0; - } - inline static bool isStrAttrType(itemAttrTypes type) { - return (type & 0x1EC) != 0; - } - - const std::forward_list& getList() const { - return attributes; - } - - friend class Item; -}; - -class Item : virtual public Thing -{ - public: - //Factory member to create item of right type based on type - static Item* CreateItem(const uint16_t _type, uint16_t _count = 0); - static Container* CreateItemAsContainer(const uint16_t _type, uint16_t size); - static Item* CreateItem(PropStream& propStream); - static Items items; - - // Constructor for items - Item(const uint16_t _type, uint16_t _count = 0); - Item(const Item& i); - virtual Item* clone() const; - - virtual ~Item(); - - // non-assignable - Item& operator=(const Item&) = delete; - - bool equals(const Item* otherItem) const; - - Item* getItem() final { - return this; - } - const Item* getItem() const final { - return this; - } - virtual Teleport* getTeleport() { - return nullptr; - } - virtual const Teleport* getTeleport() const { - return nullptr; - } - virtual TrashHolder* getTrashHolder() { - return nullptr; - } - virtual const TrashHolder* getTrashHolder() const { - return nullptr; - } - virtual Mailbox* getMailbox() { - return nullptr; - } - virtual const Mailbox* getMailbox() const { - return nullptr; - } - virtual Door* getDoor() { - return nullptr; - } - virtual const Door* getDoor() const { - return nullptr; - } - virtual MagicField* getMagicField() { - return nullptr; - } - virtual const MagicField* getMagicField() const { - return nullptr; - } - virtual BedItem* getBed() { - return nullptr; - } - virtual const BedItem* getBed() const { - return nullptr; - } - - const std::string& getStrAttr(itemAttrTypes type) const { - if (!attributes) { - return ItemAttributes::emptyString; - } - return attributes->getStrAttr(type); - } - void setStrAttr(itemAttrTypes type, const std::string& value) { - getAttributes()->setStrAttr(type, value); - } - - int32_t getIntAttr(itemAttrTypes type) const { - if (!attributes) { - return 0; - } - return attributes->getIntAttr(type); - } - void setIntAttr(itemAttrTypes type, int32_t value) { - getAttributes()->setIntAttr(type, value); - } - void increaseIntAttr(itemAttrTypes type, int32_t value) { - getAttributes()->increaseIntAttr(type, value); - } - - void removeAttribute(itemAttrTypes type) { - if (attributes) { - attributes->removeAttribute(type); - } - } - bool hasAttribute(itemAttrTypes type) const { - if (!attributes) { - return false; - } - return attributes->hasAttribute(type); - } - - void setSpecialDescription(const std::string& desc) { - setStrAttr(ITEM_ATTRIBUTE_DESCRIPTION, desc); - } - const std::string& getSpecialDescription() const { - return getStrAttr(ITEM_ATTRIBUTE_DESCRIPTION); - } - - void setText(const std::string& text) { - setStrAttr(ITEM_ATTRIBUTE_TEXT, text); - } - void resetText() { - removeAttribute(ITEM_ATTRIBUTE_TEXT); - } - const std::string& getText() const { - return getStrAttr(ITEM_ATTRIBUTE_TEXT); - } - - void setDate(int32_t n) { - setIntAttr(ITEM_ATTRIBUTE_DATE, n); - } - void resetDate() { - removeAttribute(ITEM_ATTRIBUTE_DATE); - } - time_t getDate() const { - return static_cast(getIntAttr(ITEM_ATTRIBUTE_DATE)); - } - - void setWriter(const std::string& _writer) { - setStrAttr(ITEM_ATTRIBUTE_WRITER, _writer); - } - void resetWriter() { - removeAttribute(ITEM_ATTRIBUTE_WRITER); - } - const std::string& getWriter() const { - return getStrAttr(ITEM_ATTRIBUTE_WRITER); - } - - void setActionId(uint16_t n) { - if (n < 100) { - n = 100; - } - - setIntAttr(ITEM_ATTRIBUTE_ACTIONID, n); - } - uint16_t getActionId() const { - if (!attributes) { - return 0; - } - return static_cast(getIntAttr(ITEM_ATTRIBUTE_ACTIONID)); - } - - uint16_t getUniqueId() const { - if (!attributes) { - return 0; - } - return static_cast(getIntAttr(ITEM_ATTRIBUTE_UNIQUEID)); - } - - void setCharges(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_CHARGES, n); - } - uint16_t getCharges() const { - if (!attributes) { - return 0; - } - return static_cast(getIntAttr(ITEM_ATTRIBUTE_CHARGES)); - } - - void setFluidType(uint16_t n) { - setIntAttr(ITEM_ATTRIBUTE_FLUIDTYPE, n); - } - uint16_t getFluidType() const { - if (!attributes) { - return 0; - } - return static_cast(getIntAttr(ITEM_ATTRIBUTE_FLUIDTYPE)); - } - - void setOwner(uint32_t _owner) { - setIntAttr(ITEM_ATTRIBUTE_OWNER, _owner); - } - uint32_t getOwner() const { - if (!attributes) { - return 0; - } - return getIntAttr(ITEM_ATTRIBUTE_OWNER); - } - - void setCorpseOwner(uint32_t _corpseOwner) { - setIntAttr(ITEM_ATTRIBUTE_CORPSEOWNER, _corpseOwner); - } - uint32_t getCorpseOwner() const { - if (!attributes) { - return 0; - } - return getIntAttr(ITEM_ATTRIBUTE_CORPSEOWNER); - } - - void setDuration(int32_t time) { - setIntAttr(ITEM_ATTRIBUTE_DURATION, time); - } - void decreaseDuration(int32_t time) { - increaseIntAttr(ITEM_ATTRIBUTE_DURATION, -time); - } - uint32_t getDuration() const { - if (!attributes) { - return 0; - } - return getIntAttr(ITEM_ATTRIBUTE_DURATION); - } - - void setDecaying(ItemDecayState_t decayState) { - setIntAttr(ITEM_ATTRIBUTE_DECAYSTATE, decayState); - } - ItemDecayState_t getDecaying() const { - if (!attributes) { - return DECAYING_FALSE; - } - return static_cast(getIntAttr(ITEM_ATTRIBUTE_DECAYSTATE)); - } - - static std::string getDescription(const ItemType& it, int32_t lookDistance, const Item* item = nullptr, int32_t subType = -1, bool addArticle = true); - static std::string getNameDescription(const ItemType& it, const Item* item = nullptr, int32_t subType = -1, bool addArticle = true); - static std::string getWeightDescription(const ItemType& it, uint32_t weight, uint32_t count = 1); - - std::string getDescription(int32_t lookDistance) const final; - std::string getNameDescription() const; - std::string getWeightDescription() const; - - //serialization - virtual Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream); - bool unserializeAttr(PropStream& propStream); - virtual bool unserializeItemNode(FileLoader& f, NODE node, PropStream& propStream); - - virtual void serializeAttr(PropWriteStream& propWriteStream) const; - - bool isPushable() const final { - return isMoveable(); - } - int32_t getThrowRange() const final { - return (isPickupable() ? 15 : 2); - } - - uint16_t getID() const { - return id; - } - uint16_t getClientID() const { - return items[id].clientId; - } - uint16_t getDestroyId() const { - return items[id].destroyTo; - } - void setID(uint16_t newid); - - // Returns the player that is holding this item in his inventory - Player* getHoldingPlayer() const; - - WeaponType_t getWeaponType() const { - return items[id].weaponType; - } - Ammo_t getAmmoType() const { - return items[id].ammoType; - } - uint8_t getShootRange() const { - if (hasAttribute(ITEM_ATTRIBUTE_SHOOTRANGE)) { - return getIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE); - } - return items[id].shootRange; - } - - virtual uint32_t getWeight() const; - uint32_t getBaseWeight() const { - if (hasAttribute(ITEM_ATTRIBUTE_WEIGHT)) { - return getIntAttr(ITEM_ATTRIBUTE_WEIGHT); - } - return items[id].weight; - } - int32_t getAttack() const { - if (hasAttribute(ITEM_ATTRIBUTE_ATTACK)) { - return getIntAttr(ITEM_ATTRIBUTE_ATTACK); - } - return items[id].attack; - } - int32_t getArmor() const { - if (hasAttribute(ITEM_ATTRIBUTE_ARMOR)) { - return getIntAttr(ITEM_ATTRIBUTE_ARMOR); - } - return items[id].armor; - } - int32_t getDefense() const { - if (hasAttribute(ITEM_ATTRIBUTE_DEFENSE)) { - return getIntAttr(ITEM_ATTRIBUTE_DEFENSE); - } - return items[id].defense; - } - int32_t getExtraDefense() const { - if (hasAttribute(ITEM_ATTRIBUTE_EXTRADEFENSE)) { - return getIntAttr(ITEM_ATTRIBUTE_EXTRADEFENSE); - } - return items[id].extraDefense; - } - int32_t getSlotPosition() const { - return items[id].slotPosition; - } - int8_t getHitChance() const { - if (hasAttribute(ITEM_ATTRIBUTE_HITCHANCE)) { - return getIntAttr(ITEM_ATTRIBUTE_HITCHANCE); - } - return items[id].hitChance; - } - - int32_t getWorth() const; - void getLight(LightInfo& lightInfo) const; - - bool hasProperty(ITEMPROPERTY prop) const; - bool isBlocking() const { - return items[id].blockSolid; - } - bool isStackable() const { - return items[id].stackable; - } - bool isAlwaysOnTop() const { - return items[id].alwaysOnTop; - } - bool isGroundTile() const { - return items[id].isGroundTile(); - } - bool isMagicField() const { - return items[id].isMagicField(); - } - bool isMoveable() const { - return items[id].moveable; - } - bool isPickupable() const { - return items[id].pickupable; - } - bool isUseable() const { - return items[id].useable; - } - bool isHangable() const { - return items[id].isHangable; - } - bool isRotatable() const { - const ItemType& it = items[id]; - return it.rotatable && it.rotateTo; - } - bool hasWalkStack() const { - return items[id].walkStack; - } - - const std::string& getName() const { - if (hasAttribute(ITEM_ATTRIBUTE_NAME)) { - return getStrAttr(ITEM_ATTRIBUTE_NAME); - } - return items[id].name; - } - const std::string getPluralName() const { - if (hasAttribute(ITEM_ATTRIBUTE_PLURALNAME)) { - return getStrAttr(ITEM_ATTRIBUTE_PLURALNAME); - } - return items[id].getPluralName(); - } - const std::string& getArticle() const { - if (hasAttribute(ITEM_ATTRIBUTE_ARTICLE)) { - return getStrAttr(ITEM_ATTRIBUTE_ARTICLE); - } - return items[id].article; - } - - // get the number of items - uint16_t getItemCount() const { - return count; - } - void setItemCount(uint8_t n) { - count = n; - } - - static uint32_t countByType(const Item* i, int32_t subType); - - void setDefaultSubtype(); - uint16_t getSubType() const; - void setSubType(uint16_t n); - - void setUniqueId(uint16_t n); - - void setDefaultDuration() { - uint32_t duration = getDefaultDuration(); - if (duration != 0) { - setDuration(duration); - } - } - uint32_t getDefaultDuration() const { - return items[id].decayTime * 1000; - } - bool canDecay() const; - - virtual bool canRemove() const { - return true; - } - virtual bool canTransform() const { - return true; - } - virtual void onRemoved(); - virtual void onTradeEvent(TradeEvents_t, Player*) {} - - virtual void startDecaying(); - - bool isLoadedFromMap() const { - return loadedFromMap; - } - void setLoadedFromMap(bool value) { - loadedFromMap = value; - } - bool isCleanable() const { - return !loadedFromMap && canRemove() && isPickupable() && !hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) && !hasAttribute(ITEM_ATTRIBUTE_ACTIONID); - } - - bool hasMarketAttributes() const; - - ItemAttributes* getAttributes() { - if (!attributes) { - attributes = new ItemAttributes(); - } - return attributes; - } - - void incrementReferenceCounter() { - ++referenceCounter; - } - void decrementReferenceCounter() { - if (--referenceCounter == 0) { - delete this; - } - } - - Cylinder* getParent() const { - return parent; - } - void setParent(Cylinder* cylinder) { - parent = cylinder; - } - Cylinder* getTopParent(); - const Cylinder* getTopParent() const; - Tile* getTile(); - const Tile* getTile() const; - bool isRemoved() const { - return !parent || parent->isRemoved(); - } - - protected: - std::string getWeightDescription(uint32_t weight) const; - - Cylinder* parent; - ItemAttributes* attributes; - - uint32_t referenceCounter; - - uint16_t id; // the same id as in ItemType - uint8_t count; // number of stacked items - - bool loadedFromMap; - - //Don't add variables here, use the ItemAttribute class. -}; - -typedef std::list ItemList; -typedef std::deque ItemDeque; - -inline uint32_t Item::countByType(const Item* i, int32_t subType) -{ - if (subType == -1 || subType == i->getSubType()) { - return i->getItemCount(); - } - - return 0; -} - -#endif diff --git a/path_10_8/src/itemloader.h b/path_10_8/src/itemloader.h deleted file mode 100644 index 2b56768a7..000000000 --- a/path_10_8/src/itemloader.h +++ /dev/null @@ -1,199 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ITEMLOADER_H_107F1D3EECC94CD0A0F528843010D5D4 -#define FS_ITEMLOADER_H_107F1D3EECC94CD0A0F528843010D5D4 - -#include "fileloader.h" - -enum itemgroup_t { - ITEM_GROUP_NONE, - - ITEM_GROUP_GROUND, - ITEM_GROUP_CONTAINER, - ITEM_GROUP_WEAPON, //deprecated - ITEM_GROUP_AMMUNITION, //deprecated - ITEM_GROUP_ARMOR, //deprecated - ITEM_GROUP_CHARGES, - ITEM_GROUP_TELEPORT, //deprecated - ITEM_GROUP_MAGICFIELD, //deprecated - ITEM_GROUP_WRITEABLE, //deprecated - ITEM_GROUP_KEY, //deprecated - ITEM_GROUP_SPLASH, - ITEM_GROUP_FLUID, - ITEM_GROUP_DOOR, //deprecated - ITEM_GROUP_DEPRECATED, - - ITEM_GROUP_LAST -}; - -/////////OTB specific////////////// -enum clientVersion_t { - CLIENT_VERSION_750 = 1, - CLIENT_VERSION_755 = 2, - CLIENT_VERSION_760 = 3, - CLIENT_VERSION_770 = 3, - CLIENT_VERSION_780 = 4, - CLIENT_VERSION_790 = 5, - CLIENT_VERSION_792 = 6, - CLIENT_VERSION_800 = 7, - CLIENT_VERSION_810 = 8, - CLIENT_VERSION_811 = 9, - CLIENT_VERSION_820 = 10, - CLIENT_VERSION_830 = 11, - CLIENT_VERSION_840 = 12, - CLIENT_VERSION_841 = 13, - CLIENT_VERSION_842 = 14, - CLIENT_VERSION_850 = 15, - CLIENT_VERSION_854_BAD = 16, - CLIENT_VERSION_854 = 17, - CLIENT_VERSION_855 = 18, - CLIENT_VERSION_860_OLD = 19, - CLIENT_VERSION_860 = 20, - CLIENT_VERSION_861 = 21, - CLIENT_VERSION_862 = 22, - CLIENT_VERSION_870 = 23, - CLIENT_VERSION_871 = 24, - CLIENT_VERSION_872 = 25, - CLIENT_VERSION_873 = 26, - CLIENT_VERSION_900 = 27, - CLIENT_VERSION_910 = 28, - CLIENT_VERSION_920 = 29, - CLIENT_VERSION_940 = 30, - CLIENT_VERSION_944_V1 = 31, - CLIENT_VERSION_944_V2 = 32, - CLIENT_VERSION_944_V3 = 33, - CLIENT_VERSION_944_V4 = 34, - CLIENT_VERSION_946 = 35, - CLIENT_VERSION_950 = 36, - CLIENT_VERSION_952 = 37, - CLIENT_VERSION_953 = 38, - CLIENT_VERSION_954 = 39, - CLIENT_VERSION_960 = 40, - CLIENT_VERSION_961 = 41, - CLIENT_VERSION_963 = 42, - CLIENT_VERSION_970 = 43, - CLIENT_VERSION_980 = 44, - CLIENT_VERSION_981 = 45, - CLIENT_VERSION_982 = 46, - CLIENT_VERSION_983 = 47, - CLIENT_VERSION_985 = 48, - CLIENT_VERSION_986 = 49, - CLIENT_VERSION_1010 = 50, - CLIENT_VERSION_1020 = 51, - CLIENT_VERSION_1021 = 52, - CLIENT_VERSION_1030 = 53, - CLIENT_VERSION_1031 = 54, - CLIENT_VERSION_1035 = 55, - CLIENT_VERSION_1076 = 56, - CLIENT_VERSION_1082 = 57, - CLIENT_VERSION_1090 = 58, -}; - -enum rootattrib_ { - ROOT_ATTR_VERSION = 0x01, -}; - -enum itemattrib_t { - ITEM_ATTR_FIRST = 0x10, - ITEM_ATTR_SERVERID = ITEM_ATTR_FIRST, - ITEM_ATTR_CLIENTID, - ITEM_ATTR_NAME, - ITEM_ATTR_DESCR, - ITEM_ATTR_SPEED, - ITEM_ATTR_SLOT, - ITEM_ATTR_MAXITEMS, - ITEM_ATTR_WEIGHT, - ITEM_ATTR_WEAPON, - ITEM_ATTR_AMU, - ITEM_ATTR_ARMOR, - ITEM_ATTR_MAGLEVEL, - ITEM_ATTR_MAGFIELDTYPE, - ITEM_ATTR_WRITEABLE, - ITEM_ATTR_ROTATETO, - ITEM_ATTR_DECAY, - ITEM_ATTR_SPRITEHASH, - ITEM_ATTR_MINIMAPCOLOR, - ITEM_ATTR_07, - ITEM_ATTR_08, - ITEM_ATTR_LIGHT, - - //1-byte aligned - ITEM_ATTR_DECAY2, //deprecated - ITEM_ATTR_WEAPON2, //deprecated - ITEM_ATTR_AMU2, //deprecated - ITEM_ATTR_ARMOR2, //deprecated - ITEM_ATTR_WRITEABLE2, //deprecated - ITEM_ATTR_LIGHT2, - ITEM_ATTR_TOPORDER, - ITEM_ATTR_WRITEABLE3, //deprecated - - ITEM_ATTR_WAREID, - - ITEM_ATTR_LAST -}; - -enum itemflags_t { - FLAG_BLOCK_SOLID = 1 << 0, - FLAG_BLOCK_PROJECTILE = 1 << 1, - FLAG_BLOCK_PATHFIND = 1 << 2, - FLAG_HAS_HEIGHT = 1 << 3, - FLAG_USEABLE = 1 << 4, - FLAG_PICKUPABLE = 1 << 5, - FLAG_MOVEABLE = 1 << 6, - FLAG_STACKABLE = 1 << 7, - FLAG_FLOORCHANGEDOWN = 1 << 8, - FLAG_FLOORCHANGENORTH = 1 << 9, - FLAG_FLOORCHANGEEAST = 1 << 10, - FLAG_FLOORCHANGESOUTH = 1 << 11, - FLAG_FLOORCHANGEWEST = 1 << 12, - FLAG_ALWAYSONTOP = 1 << 13, - FLAG_READABLE = 1 << 14, - FLAG_ROTABLE = 1 << 15, - FLAG_HANGABLE = 1 << 16, - FLAG_VERTICAL = 1 << 17, - FLAG_HORIZONTAL = 1 << 18, - FLAG_CANNOTDECAY = 1 << 19, - FLAG_ALLOWDISTREAD = 1 << 20, - FLAG_UNUSED = 1 << 21, - FLAG_CLIENTCHARGES = 1 << 22, /* deprecated */ - FLAG_LOOKTHROUGH = 1 << 23, - FLAG_ANIMATION = 1 << 24, - FLAG_FULLTILE = 1 << 25, - FLAG_FORCEUSE = 1 << 26, -}; - -//1-byte aligned structs -#pragma pack(1) - -struct VERSIONINFO { - uint32_t dwMajorVersion; - uint32_t dwMinorVersion; - uint32_t dwBuildNumber; - uint8_t CSDVersion[128]; -}; - -struct lightBlock2 { - uint16_t lightLevel; - uint16_t lightColor; -}; - -#pragma pack() -/////////OTB specific////////////// -#endif diff --git a/path_10_8/src/items.cpp b/path_10_8/src/items.cpp deleted file mode 100644 index 1e75b5dbe..000000000 --- a/path_10_8/src/items.cpp +++ /dev/null @@ -1,1007 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "items.h" -#include "spells.h" -#include "movement.h" -#include "weapons.h" - -#include "pugicast.h" - -uint32_t Items::dwMajorVersion = 0; -uint32_t Items::dwMinorVersion = 0; -uint32_t Items::dwBuildNumber = 0; - -extern MoveEvents* g_moveEvents; -extern Weapons* g_weapons; - -ItemType::ItemType() -{ - type = ITEM_TYPE_NONE; - alwaysOnTopOrder = 0; - rotateTo = 0; - walkStack = true; - - floorChangeDown = false; - floorChangeNorth = false; - floorChangeSouth = false; - floorChangeSouthAlt = false; - floorChangeEast = false; - floorChangeEastAlt = false; - floorChangeWest = false; - - allowPickupable = false; - - wieldInfo = 0; - minReqLevel = 0; - minReqMagicLevel = 0; - - runeMagLevel = 0; - runeLevel = 0; - - speed = 0; - id = 0; - clientId = 0; - maxItems = 8; // maximum size if this is a container - weight = 0; // weight of the item, e.g. throwing distance depends on it - showCount = true; - weaponType = WEAPON_NONE; - slotPosition = SLOTP_HAND; - ammoType = AMMO_NONE; - shootType = CONST_ANI_NONE; - magicEffect = CONST_ME_NONE; - attack = 0; - defense = 0; - extraDefense = 0; - armor = 0; - decayTo = -1; - decayTime = 0; - stopTime = false; - corpseType = RACE_NONE; - fluidSource = FLUID_NONE; - - lightLevel = 0; - lightColor = 0; - - maxTextLen = 0; - canWriteText = false; - writeOnceItemId = 0; - - transformEquipTo = 0; - transformDeEquipTo = 0; - showDuration = false; - showCharges = false; - showAttributes = false; - charges = 0; - hitChance = 0; - maxHitChance = -1; - shootRange = 1; - - combatType = COMBAT_NONE; - - replaceable = true; - - bedPartnerDir = DIRECTION_NORTH; - transformToOnUse[PLAYERSEX_MALE] = 0; - transformToOnUse[PLAYERSEX_FEMALE] = 0; - transformToFree = 0; - - destroyTo = 0; - - levelDoor = 0; - - wareId = 0; -} - -Items::Items() -{ - items.reserve(30000); -} - -Items::~Items() -{ - clear(); -} - -void Items::clear() -{ - items.clear(); -} - -bool Items::reload() -{ - clear(); - loadFromOtb("data/items/items.otb"); - - if (!loadFromXml()) { - return false; - } - - g_moveEvents->reload(); - g_weapons->reload(); - g_weapons->loadDefaults(); - return true; -} - -FILELOADER_ERRORS Items::loadFromOtb(const std::string& file) -{ - FileLoader f; - if (!f.openFile(file.c_str(), "OTBI")) { - return f.getError(); - } - - uint32_t type; - NODE node = f.getChildNode(NO_NODE, type); - - PropStream props; - if (f.getProps(node, props)) { - //4 byte flags - //attributes - //0x01 = version data - uint32_t flags; - if (!props.read(flags)) { - return ERROR_INVALID_FORMAT; - } - - uint8_t attr; - if (!props.read(attr)) { - return ERROR_INVALID_FORMAT; - } - - if (attr == ROOT_ATTR_VERSION) { - uint16_t datalen; - if (!props.read(datalen)) { - return ERROR_INVALID_FORMAT; - } - - if (datalen != sizeof(VERSIONINFO)) { - return ERROR_INVALID_FORMAT; - } - - VERSIONINFO vi; - if (!props.read(vi)) { - return ERROR_INVALID_FORMAT; - } - - Items::dwMajorVersion = vi.dwMajorVersion; //items otb format file version - Items::dwMinorVersion = vi.dwMinorVersion; //client version - Items::dwBuildNumber = vi.dwBuildNumber; //revision - } - } - - if (Items::dwMajorVersion == 0xFFFFFFFF) { - std::cout << "[Warning - Items::loadFromOtb] items.otb using generic client version." << std::endl; - } else if (Items::dwMajorVersion != 3) { - std::cout << "Old version detected, a newer version of items.otb is required." << std::endl; - return ERROR_INVALID_FORMAT; - } else if (Items::dwMinorVersion < CLIENT_VERSION_1090) { - std::cout << "A newer version of items.otb is required." << std::endl; - return ERROR_INVALID_FORMAT; - } - - node = f.getChildNode(node, type); - while (node != NO_NODE) { - PropStream stream; - if (!f.getProps(node, stream)) { - return f.getError(); - } - - uint32_t flags; - if (!stream.read(flags)) { - return ERROR_INVALID_FORMAT; - } - - uint16_t serverId = 0; - uint16_t clientId = 0; - uint16_t speed = 0; - uint16_t wareId = 0; - uint8_t lightLevel = 0; - uint8_t lightColor = 0; - uint8_t alwaysOnTopOrder = 0; - - uint8_t attrib; - while (stream.read(attrib)) { - uint16_t datalen; - if (!stream.read(datalen)) { - return ERROR_INVALID_FORMAT; - } - - switch (attrib) { - case ITEM_ATTR_SERVERID: { - if (datalen != sizeof(uint16_t)) { - return ERROR_INVALID_FORMAT; - } - - if (!stream.read(serverId)) { - return ERROR_INVALID_FORMAT; - } - - if (serverId > 30000 && serverId < 30100) { - serverId -= 30000; - } - break; - } - - case ITEM_ATTR_CLIENTID: { - if (datalen != sizeof(uint16_t)) { - return ERROR_INVALID_FORMAT; - } - - if (!stream.read(clientId)) { - return ERROR_INVALID_FORMAT; - } - break; - } - - case ITEM_ATTR_SPEED: { - if (datalen != sizeof(uint16_t)) { - return ERROR_INVALID_FORMAT; - } - - if (!stream.read(speed)) { - return ERROR_INVALID_FORMAT; - } - break; - } - - case ITEM_ATTR_LIGHT2: { - if (datalen != sizeof(lightBlock2)) { - return ERROR_INVALID_FORMAT; - } - - lightBlock2 lb2; - if (!stream.read(lb2)) { - return ERROR_INVALID_FORMAT; - } - - lightLevel = static_cast(lb2.lightLevel); - lightColor = static_cast(lb2.lightColor); - break; - } - - case ITEM_ATTR_TOPORDER: { - if (datalen != sizeof(uint8_t)) { - return ERROR_INVALID_FORMAT; - } - - if (!stream.read(alwaysOnTopOrder)) { - return ERROR_INVALID_FORMAT; - } - break; - } - - case ITEM_ATTR_WAREID: { - if (datalen != sizeof(uint16_t)) { - return ERROR_INVALID_FORMAT; - } - - if (!stream.read(wareId)) { - return ERROR_INVALID_FORMAT; - } - break; - } - - default: { - //skip unknown attributes - if (!stream.skip(datalen)) { - return ERROR_INVALID_FORMAT; - } - break; - } - } - } - - reverseItemMap.emplace(clientId, serverId); - - // store the found item - if (serverId >= items.size()) { - items.resize(serverId + 1); - } - ItemType& iType = items[serverId]; - - iType.group = static_cast(type); - switch (type) { - case ITEM_GROUP_CONTAINER: - iType.type = ITEM_TYPE_CONTAINER; - break; - case ITEM_GROUP_DOOR: - //not used - iType.type = ITEM_TYPE_DOOR; - break; - case ITEM_GROUP_MAGICFIELD: - //not used - iType.type = ITEM_TYPE_MAGICFIELD; - break; - case ITEM_GROUP_TELEPORT: - //not used - iType.type = ITEM_TYPE_TELEPORT; - break; - case ITEM_GROUP_NONE: - case ITEM_GROUP_GROUND: - case ITEM_GROUP_SPLASH: - case ITEM_GROUP_FLUID: - case ITEM_GROUP_CHARGES: - case ITEM_GROUP_DEPRECATED: - break; - default: - return ERROR_INVALID_FORMAT; - } - - iType.blockSolid = hasBitSet(FLAG_BLOCK_SOLID, flags); - iType.blockProjectile = hasBitSet(FLAG_BLOCK_PROJECTILE, flags); - iType.blockPathFind = hasBitSet(FLAG_BLOCK_PATHFIND, flags); - iType.hasHeight = hasBitSet(FLAG_HAS_HEIGHT, flags); - iType.useable = hasBitSet(FLAG_USEABLE, flags); - iType.pickupable = hasBitSet(FLAG_PICKUPABLE, flags); - iType.moveable = hasBitSet(FLAG_MOVEABLE, flags); - iType.stackable = hasBitSet(FLAG_STACKABLE, flags); - - iType.alwaysOnTop = hasBitSet(FLAG_ALWAYSONTOP, flags); - iType.isVertical = hasBitSet(FLAG_VERTICAL, flags); - iType.isHorizontal = hasBitSet(FLAG_HORIZONTAL, flags); - iType.isHangable = hasBitSet(FLAG_HANGABLE, flags); - iType.allowDistRead = hasBitSet(FLAG_ALLOWDISTREAD, flags); - iType.rotatable = hasBitSet(FLAG_ROTABLE, flags); - iType.canReadText = hasBitSet(FLAG_READABLE, flags); - iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, flags); - iType.isAnimation = hasBitSet(FLAG_ANIMATION, flags); - // iType.walkStack = !hasBitSet(FLAG_FULLTILE, flags); - iType.forceUse = hasBitSet(FLAG_FORCEUSE, flags); - - iType.id = serverId; - iType.clientId = clientId; - iType.speed = speed; - iType.lightLevel = lightLevel; - iType.lightColor = lightColor; - iType.wareId = wareId; - iType.alwaysOnTopOrder = alwaysOnTopOrder; - - node = f.getNextNode(node, type); - } - - items.shrink_to_fit(); - return ERROR_NONE; -} - -bool Items::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/items/items.xml"); - if (!result) { - printXMLError("Error - Items::loadFromXml", "data/items/items.xml", result); - return false; - } - - for (auto itemNode : doc.child("items").children()) { - pugi::xml_attribute idAttribute = itemNode.attribute("id"); - if (idAttribute) { - parseItemNode(itemNode, pugi::cast(idAttribute.value())); - continue; - } - - pugi::xml_attribute fromIdAttribute = itemNode.attribute("fromid"); - if (!fromIdAttribute) { - std::cout << "[Warning - Items::loadFromXml] No item id found" << std::endl; - continue; - } - - pugi::xml_attribute toIdAttribute = itemNode.attribute("toid"); - if (!toIdAttribute) { - std::cout << "[Warning - Items::loadFromXml] fromid (" << fromIdAttribute.value() << ") without toid" << std::endl; - continue; - } - - uint16_t id = pugi::cast(fromIdAttribute.value()); - uint16_t toId = pugi::cast(toIdAttribute.value()); - while (id <= toId) { - parseItemNode(itemNode, id++); - } - } - return true; -} - -void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id) -{ - if (id > 30000 && id < 30100) { - id -= 30000; - - if (id >= items.size()) { - items.resize(id + 1); - } - ItemType& iType = items[id]; - iType.id = id; - } - - ItemType& it = getItemType(id); - if (it.id == 0) { - return; - } - - it.name = itemNode.attribute("name").as_string(); - - pugi::xml_attribute articleAttribute = itemNode.attribute("article"); - if (articleAttribute) { - it.article = articleAttribute.as_string(); - } - - pugi::xml_attribute pluralAttribute = itemNode.attribute("plural"); - if (pluralAttribute) { - it.pluralName = pluralAttribute.as_string(); - } - - for (auto attributeNode : itemNode.children()) { - pugi::xml_attribute keyAttribute = attributeNode.attribute("key"); - if (!keyAttribute) { - continue; - } - - pugi::xml_attribute valueAttribute = attributeNode.attribute("value"); - if (!valueAttribute) { - continue; - } - - std::string tmpStrValue = asLowerCaseString(keyAttribute.as_string()); - if (tmpStrValue == "type") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "key") { - it.type = ITEM_TYPE_KEY; - } else if (tmpStrValue == "magicfield") { - it.type = ITEM_TYPE_MAGICFIELD; - } else if (tmpStrValue == "container") { - it.group = ITEM_GROUP_CONTAINER; - it.type = ITEM_TYPE_CONTAINER; - } else if (tmpStrValue == "depot") { - it.type = ITEM_TYPE_DEPOT; - } else if (tmpStrValue == "mailbox") { - it.type = ITEM_TYPE_MAILBOX; - } else if (tmpStrValue == "trashholder") { - it.type = ITEM_TYPE_TRASHHOLDER; - } else if (tmpStrValue == "teleport") { - it.type = ITEM_TYPE_TELEPORT; - } else if (tmpStrValue == "door") { - it.type = ITEM_TYPE_DOOR; - } else if (tmpStrValue == "bed") { - it.type = ITEM_TYPE_BED; - } else if (tmpStrValue == "rune") { - it.type = ITEM_TYPE_RUNE; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown type: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "description") { - it.description = valueAttribute.as_string(); - } else if (tmpStrValue == "runespellname") { - it.runeSpellName = valueAttribute.as_string(); - } else if (tmpStrValue == "weight") { - it.weight = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showcount") { - it.showCount = valueAttribute.as_bool(); - } else if (tmpStrValue == "armor") { - it.armor = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "defense") { - it.defense = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "extradef") { - it.extraDefense = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "attack") { - it.attack = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "rotateto") { - it.rotateTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "moveable" || tmpStrValue == "movable") { - it.moveable = valueAttribute.as_bool(); - } else if (tmpStrValue == "blockprojectile") { - it.blockProjectile = valueAttribute.as_bool(); - } else if (tmpStrValue == "allowpickupable" || tmpStrValue == "pickupable") { - it.allowPickupable = valueAttribute.as_bool(); - } else if (tmpStrValue == "floorchange") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "down") { - it.floorChangeDown = true; - } else if (tmpStrValue == "north") { - it.floorChangeNorth = true; - } else if (tmpStrValue == "south") { - it.floorChangeSouth = true; - } else if (tmpStrValue == "southalt" || tmpStrValue == "southex") { - it.floorChangeSouthAlt = true; - } else if (tmpStrValue == "west") { - it.floorChangeWest = true; - } else if (tmpStrValue == "east") { - it.floorChangeEast = true; - } else if (tmpStrValue == "eastalt" || tmpStrValue == "eastex") { - it.floorChangeEastAlt = true; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown floorChange: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "corpsetype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "venom") { - it.corpseType = RACE_VENOM; - } else if (tmpStrValue == "blood") { - it.corpseType = RACE_BLOOD; - } else if (tmpStrValue == "undead") { - it.corpseType = RACE_UNDEAD; - } else if (tmpStrValue == "fire") { - it.corpseType = RACE_FIRE; - } else if (tmpStrValue == "energy") { - it.corpseType = RACE_ENERGY; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown corpseType: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "containersize") { - it.maxItems = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fluidsource") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "water") { - it.fluidSource = FLUID_WATER; - } else if (tmpStrValue == "blood") { - it.fluidSource = FLUID_BLOOD; - } else if (tmpStrValue == "beer") { - it.fluidSource = FLUID_BEER; - } else if (tmpStrValue == "slime") { - it.fluidSource = FLUID_SLIME; - } else if (tmpStrValue == "lemonade") { - it.fluidSource = FLUID_LEMONADE; - } else if (tmpStrValue == "milk") { - it.fluidSource = FLUID_MILK; - } else if (tmpStrValue == "mana") { - it.fluidSource = FLUID_MANA; - } else if (tmpStrValue == "life") { - it.fluidSource = FLUID_LIFE; - } else if (tmpStrValue == "oil") { - it.fluidSource = FLUID_OIL; - } else if (tmpStrValue == "urine") { - it.fluidSource = FLUID_URINE; - } else if (tmpStrValue == "coconut") { - it.fluidSource = FLUID_COCONUTMILK; - } else if (tmpStrValue == "wine") { - it.fluidSource = FLUID_WINE; - } else if (tmpStrValue == "mud") { - it.fluidSource = FLUID_MUD; - } else if (tmpStrValue == "fruitjuice") { - it.fluidSource = FLUID_FRUITJUICE; - } else if (tmpStrValue == "lava") { - it.fluidSource = FLUID_LAVA; - } else if (tmpStrValue == "rum") { - it.fluidSource = FLUID_RUM; - } else if (tmpStrValue == "swamp") { - it.fluidSource = FLUID_SWAMP; - } else if (tmpStrValue == "tea") { - it.fluidSource = FLUID_TEA; - } else if (tmpStrValue == "mead") { - it.fluidSource = FLUID_MEAD; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown fluidSource: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "readable") { - it.canReadText = valueAttribute.as_bool(); - } else if (tmpStrValue == "writeable") { - it.canWriteText = valueAttribute.as_bool(); - it.canReadText = it.canWriteText; - } else if (tmpStrValue == "maxtextlen") { - it.maxTextLen = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "writeonceitemid") { - it.writeOnceItemId = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "weapontype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "sword") { - it.weaponType = WEAPON_SWORD; - } else if (tmpStrValue == "club") { - it.weaponType = WEAPON_CLUB; - } else if (tmpStrValue == "axe") { - it.weaponType = WEAPON_AXE; - } else if (tmpStrValue == "shield") { - it.weaponType = WEAPON_SHIELD; - } else if (tmpStrValue == "distance") { - it.weaponType = WEAPON_DISTANCE; - } else if (tmpStrValue == "wand") { - it.weaponType = WEAPON_WAND; - } else if (tmpStrValue == "ammunition") { - it.weaponType = WEAPON_AMMO; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown weaponType: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "slottype") { - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "head") { - it.slotPosition |= SLOTP_HEAD; - } else if (tmpStrValue == "body") { - it.slotPosition |= SLOTP_ARMOR; - } else if (tmpStrValue == "legs") { - it.slotPosition |= SLOTP_LEGS; - } else if (tmpStrValue == "feet") { - it.slotPosition |= SLOTP_FEET; - } else if (tmpStrValue == "backpack") { - it.slotPosition |= SLOTP_BACKPACK; - } else if (tmpStrValue == "two-handed") { - it.slotPosition |= SLOTP_TWO_HAND; - } else if (tmpStrValue == "right-hand") { - it.slotPosition &= ~SLOTP_LEFT; - } else if (tmpStrValue == "left-hand") { - it.slotPosition &= ~SLOTP_RIGHT; - } else if (tmpStrValue == "necklace") { - it.slotPosition |= SLOTP_NECKLACE; - } else if (tmpStrValue == "ring") { - it.slotPosition |= SLOTP_RING; - } else if (tmpStrValue == "ammo") { - it.slotPosition |= SLOTP_AMMO; - } else if (tmpStrValue == "hand") { - it.slotPosition |= SLOTP_HAND; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown slotType: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "ammotype") { - it.ammoType = getAmmoType(valueAttribute.as_string()); - if (it.ammoType == AMMO_NONE) { - std::cout << "[Warning - Items::parseItemNode] Unknown ammoType: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "shoottype") { - ShootType_t shoot = getShootType(valueAttribute.as_string()); - if (shoot != CONST_ANI_NONE) { - it.shootType = shoot; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown shootType: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "effect") { - MagicEffectClasses effect = getMagicEffect(valueAttribute.as_string()); - if (effect != CONST_ME_NONE) { - it.magicEffect = effect; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown effect: " << valueAttribute.as_string() << std::endl; - } - } else if (tmpStrValue == "range") { - it.shootRange = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "stopduration") { - it.stopTime = valueAttribute.as_bool(); - } else if (tmpStrValue == "decayto") { - it.decayTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "transformequipto") { - it.transformEquipTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "transformdeequipto") { - it.transformDeEquipTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "duration") { - it.decayTime = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showduration") { - it.showDuration = valueAttribute.as_bool(); - } else if (tmpStrValue == "charges") { - it.charges = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "showcharges") { - it.showCharges = valueAttribute.as_bool(); - } else if (tmpStrValue == "showattributes") { - it.showAttributes = valueAttribute.as_bool(); - } else if (tmpStrValue == "hitchance") { - it.hitChance = std::min(100, std::max(-100, pugi::cast(valueAttribute.value()))); - } else if (tmpStrValue == "maxhitchance") { - it.maxHitChance = std::min(100, pugi::cast(valueAttribute.value())); - } else if (tmpStrValue == "invisible") { - it.getAbilities().invisible = valueAttribute.as_bool(); - } else if (tmpStrValue == "speed") { - it.getAbilities().speed = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "healthgain") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.healthGain = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "healthticks") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.healthTicks = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "managain") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.manaGain = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "manaticks") { - Abilities& abilities = it.getAbilities(); - abilities.regeneration = true; - abilities.manaTicks = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "manashield") { - it.getAbilities().manaShield = valueAttribute.as_bool(); - } else if (tmpStrValue == "skillsword") { - it.getAbilities().skills[SKILL_SWORD] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillaxe") { - it.getAbilities().skills[SKILL_AXE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillclub") { - it.getAbilities().skills[SKILL_CLUB] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skilldist") { - it.getAbilities().skills[SKILL_DISTANCE] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillfish") { - it.getAbilities().skills[SKILL_FISHING] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillshield") { - it.getAbilities().skills[SKILL_SHIELD] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "skillfist") { - it.getAbilities().skills[SKILL_FIST] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxhitpoints") { - it.getAbilities().stats[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxhitpointspercent") { - it.getAbilities().statsPercent[STAT_MAXHITPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxmanapoints") { - it.getAbilities().stats[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maxmanapointspercent") { - it.getAbilities().statsPercent[STAT_MAXMANAPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "magicpoints" || tmpStrValue == "magiclevelpoints") { - it.getAbilities().stats[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "magicpointspercent") { - it.getAbilities().statsPercent[STAT_MAGICPOINTS] = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentenergy") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentfire") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "fieldabsorbpercentpoison" || tmpStrValue == "fieldabsorpercentearth") { - it.getAbilities().fieldAbsorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentall" || tmpStrValue == "absorbpercentallelements") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - abilities.absorbPercent[i] += value; - } - } else if (tmpStrValue == "absorbpercentelements") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; - } else if (tmpStrValue == "absorbpercentmagic") { - int16_t value = pugi::cast(valueAttribute.value()); - Abilities& abilities = it.getAbilities(); - abilities.absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += value; - abilities.absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += value; - } else if (tmpStrValue == "absorbpercentenergy") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ENERGYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentfire") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_FIREDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentpoison" || tmpStrValue == "absorbpercentearth") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_EARTHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentice") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_ICEDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentholy") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HOLYDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentdeath") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DEATHDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentlifedrain") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_LIFEDRAIN)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentmanadrain") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_MANADRAIN)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentdrown") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_DROWNDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentphysical") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_PHYSICALDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercenthealing") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_HEALING)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "absorbpercentundefined") { - it.getAbilities().absorbPercent[combatTypeToIndex(COMBAT_UNDEFINEDDAMAGE)] += pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "suppressdrunk") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DRUNK; - } - } else if (tmpStrValue == "suppressenergy") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_ENERGY; - } - } else if (tmpStrValue == "suppressfire") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_FIRE; - } - } else if (tmpStrValue == "suppresspoison") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_POISON; - } - } else if (tmpStrValue == "suppressdrown") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DROWN; - } - } else if (tmpStrValue == "suppressphysical") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_BLEEDING; - } - } else if (tmpStrValue == "suppressfreeze") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_FREEZING; - } - } else if (tmpStrValue == "suppressdazzle") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_DAZZLED; - } - } else if (tmpStrValue == "suppresscurse") { - if (valueAttribute.as_bool()) { - it.getAbilities().conditionSuppressions |= CONDITION_CURSED; - } - } else if (tmpStrValue == "field") { - it.group = ITEM_GROUP_MAGICFIELD; - it.type = ITEM_TYPE_MAGICFIELD; - - CombatType_t combatType = COMBAT_NONE; - ConditionDamage* conditionDamage = nullptr; - - tmpStrValue = asLowerCaseString(valueAttribute.as_string()); - if (tmpStrValue == "fire") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_FIRE); - combatType = COMBAT_FIREDAMAGE; - } else if (tmpStrValue == "energy") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_ENERGY); - combatType = COMBAT_ENERGYDAMAGE; - } else if (tmpStrValue == "poison") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_POISON); - combatType = COMBAT_EARTHDAMAGE; - } else if (tmpStrValue == "drown") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_DROWN); - combatType = COMBAT_DROWNDAMAGE; - } else if (tmpStrValue == "physical") { - conditionDamage = new ConditionDamage(CONDITIONID_COMBAT, CONDITION_BLEEDING); - combatType = COMBAT_PHYSICALDAMAGE; - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown field value: " << valueAttribute.as_string() << std::endl; - } - - if (combatType != COMBAT_NONE) { - it.combatType = combatType; - it.conditionDamage.reset(conditionDamage); - uint32_t ticks = 0; - int32_t damage = 0; - int32_t start = 0; - int32_t count = 1; - - for (auto subAttributeNode : attributeNode.children()) { - pugi::xml_attribute subKeyAttribute = subAttributeNode.attribute("key"); - if (!subKeyAttribute) { - continue; - } - - pugi::xml_attribute subValueAttribute = subAttributeNode.attribute("value"); - if (!subValueAttribute) { - continue; - } - - tmpStrValue = asLowerCaseString(subKeyAttribute.as_string()); - if (tmpStrValue == "ticks") { - ticks = pugi::cast(subValueAttribute.value()); - } else if (tmpStrValue == "count") { - count = std::max(1, pugi::cast(subValueAttribute.value())); - } else if (tmpStrValue == "start") { - start = std::max(0, pugi::cast(subValueAttribute.value())); - } else if (tmpStrValue == "damage") { - damage = -pugi::cast(subValueAttribute.value()); - - if (start > 0) { - std::list damageList; - ConditionDamage::generateDamageList(damage, start, damageList); - for (int32_t damageValue : damageList) { - conditionDamage->addDamage(1, ticks, -damageValue); - } - - start = 0; - } else { - conditionDamage->addDamage(count, ticks, damage); - } - } - } - - conditionDamage->setParam(CONDITION_PARAM_FIELD, 1); - - if (conditionDamage->getTotalDamage() > 0) { - conditionDamage->setParam(CONDITION_PARAM_FORCEUPDATE, 1); - } - } - } else if (tmpStrValue == "replaceable") { - it.replaceable = valueAttribute.as_bool(); - } else if (tmpStrValue == "partnerdirection") { - it.bedPartnerDir = getDirection(valueAttribute.as_string()); - } else if (tmpStrValue == "leveldoor") { - it.levelDoor = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "maletransformto" || tmpStrValue == "malesleeper") { - uint16_t value = pugi::cast(valueAttribute.value()); - it.transformToOnUse[PLAYERSEX_MALE] = value; - ItemType& other = getItemType(value); - if (other.transformToFree == 0) { - other.transformToFree = it.id; - } - - if (it.transformToOnUse[PLAYERSEX_FEMALE] == 0) { - it.transformToOnUse[PLAYERSEX_FEMALE] = value; - } - } else if (tmpStrValue == "femaletransformto" || tmpStrValue == "femalesleeper") { - uint16_t value = pugi::cast(valueAttribute.value()); - it.transformToOnUse[PLAYERSEX_FEMALE] = value; - - ItemType& other = getItemType(value); - if (other.transformToFree == 0) { - other.transformToFree = it.id; - } - - if (it.transformToOnUse[PLAYERSEX_MALE] == 0) { - it.transformToOnUse[PLAYERSEX_MALE] = value; - } - } else if (tmpStrValue == "transformto") { - it.transformToFree = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "destroyto") { - it.destroyTo = pugi::cast(valueAttribute.value()); - } else if (tmpStrValue == "elementice") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_ICEDAMAGE; - } else if (tmpStrValue == "elementearth") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_EARTHDAMAGE; - } else if (tmpStrValue == "elementfire") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_FIREDAMAGE; - } else if (tmpStrValue == "elementenergy") { - Abilities& abilities = it.getAbilities(); - abilities.elementDamage = pugi::cast(valueAttribute.value()); - abilities.elementType = COMBAT_ENERGYDAMAGE; - } else if (tmpStrValue == "walkstack") { - it.walkStack = valueAttribute.as_bool(); - } else if (tmpStrValue == "blocking") { - it.blockSolid = valueAttribute.as_bool(); - } else if (tmpStrValue == "allowdistread") { - it.allowDistRead = booleanString(valueAttribute.as_string()); - } else { - std::cout << "[Warning - Items::parseItemNode] Unknown key value: " << keyAttribute.as_string() << std::endl; - } - } - - //check bed items - if ((it.transformToFree != 0 || it.transformToOnUse[PLAYERSEX_FEMALE] != 0 || it.transformToOnUse[PLAYERSEX_MALE] != 0) && it.type != ITEM_TYPE_BED) { - std::cout << "[Warning - Items::parseItemNode] Item " << it.id << " is not set as a bed-type" << std::endl; - } -} - -ItemType& Items::getItemType(size_t id) -{ - if (id < items.size()) { - return items[id]; - } - return items.front(); -} - -const ItemType& Items::getItemType(size_t id) const -{ - if (id < items.size()) { - return items[id]; - } - return items.front(); -} - -const ItemType& Items::getItemIdByClientId(uint16_t spriteId) const -{ - auto it = reverseItemMap.find(spriteId); - if (it != reverseItemMap.end()) { - return getItemType(it->second); - } - return items.front(); -} - -uint16_t Items::getItemIdByName(const std::string& name) -{ - if (name.empty()) { - return 0; - } - - const char* itemName = name.c_str(); - for (size_t i = 100, size = items.size(); i < size; ++i) { - if (strcasecmp(itemName, items[i].name.c_str()) == 0) { - return i; - } - } - return 0; -} diff --git a/path_10_8/src/items.h b/path_10_8/src/items.h deleted file mode 100644 index 7b2349a6e..000000000 --- a/path_10_8/src/items.h +++ /dev/null @@ -1,328 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_ITEMS_H_4E2221634ABA45FE85BA50F710669B3C -#define FS_ITEMS_H_4E2221634ABA45FE85BA50F710669B3C - -#include "const.h" -#include "enums.h" -#include "itemloader.h" -#include "position.h" - -enum SlotPositionBits : uint32_t { - SLOTP_WHEREEVER = 0xFFFFFFFF, - SLOTP_HEAD = 1 << 0, - SLOTP_NECKLACE = 1 << 1, - SLOTP_BACKPACK = 1 << 2, - SLOTP_ARMOR = 1 << 3, - SLOTP_RIGHT = 1 << 4, - SLOTP_LEFT = 1 << 5, - SLOTP_LEGS = 1 << 6, - SLOTP_FEET = 1 << 7, - SLOTP_RING = 1 << 8, - SLOTP_AMMO = 1 << 9, - SLOTP_DEPOT = 1 << 10, - SLOTP_TWO_HAND = 1 << 11, - SLOTP_HAND = (SLOTP_LEFT | SLOTP_RIGHT) -}; - -enum ItemTypes_t { - ITEM_TYPE_NONE, - ITEM_TYPE_DEPOT, - ITEM_TYPE_MAILBOX, - ITEM_TYPE_TRASHHOLDER, - ITEM_TYPE_CONTAINER, - ITEM_TYPE_DOOR, - ITEM_TYPE_MAGICFIELD, - ITEM_TYPE_TELEPORT, - ITEM_TYPE_BED, - ITEM_TYPE_KEY, - ITEM_TYPE_RUNE, - ITEM_TYPE_LAST -}; - -struct Abilities { - Abilities() : stats(), statsPercent(), skills(), fieldAbsorbPercent(), absorbPercent() { - elementType = COMBAT_NONE; - elementDamage = 0; - - speed = 0; - manaShield = false; - invisible = false; - regeneration = false; - - healthGain = 0; - healthTicks = 0; - manaGain = 0; - manaTicks = 0; - - conditionImmunities = 0; - conditionSuppressions = 0; - } - - uint32_t healthGain; - uint32_t healthTicks; - uint32_t manaGain; - uint32_t manaTicks; - - uint32_t conditionImmunities; - uint32_t conditionSuppressions; - - //stats modifiers - int32_t stats[STAT_LAST + 1]; - int32_t statsPercent[STAT_LAST + 1]; - - //extra skill modifiers - int32_t skills[SKILL_LAST + 1]; - - int32_t speed; - - // field damage abilities modifiers - int16_t fieldAbsorbPercent[COMBAT_COUNT]; - - //damage abilities modifiers - int16_t absorbPercent[COMBAT_COUNT]; - - //elemental damage - uint16_t elementDamage; - CombatType_t elementType; - - bool manaShield; - bool invisible; - bool regeneration; -}; - -class ConditionDamage; - -class ItemType -{ - public: - ItemType(); - - //non-copyable - ItemType(const ItemType& other) = delete; - ItemType& operator=(const ItemType& other) = delete; - - ItemType(ItemType&& other) = default; - ItemType& operator=(ItemType&& other) = default; - - bool isGroundTile() const { - return group == ITEM_GROUP_GROUND; - } - bool isContainer() const { - return group == ITEM_GROUP_CONTAINER; - } - bool isSplash() const { - return group == ITEM_GROUP_SPLASH; - } - bool isFluidContainer() const { - return group == ITEM_GROUP_FLUID; - } - - bool isDoor() const { - return (type == ITEM_TYPE_DOOR); - } - bool isMagicField() const { - return (type == ITEM_TYPE_MAGICFIELD); - } - bool isTeleport() const { - return (type == ITEM_TYPE_TELEPORT); - } - bool isKey() const { - return (type == ITEM_TYPE_KEY); - } - bool isDepot() const { - return (type == ITEM_TYPE_DEPOT); - } - bool isMailbox() const { - return (type == ITEM_TYPE_MAILBOX); - } - bool isTrashHolder() const { - return (type == ITEM_TYPE_TRASHHOLDER); - } - bool isBed() const { - return (type == ITEM_TYPE_BED); - } - bool isRune() const { - return type == ITEM_TYPE_RUNE; - } - bool hasSubType() const { - return (isFluidContainer() || isSplash() || stackable || charges != 0); - } - - Abilities& getAbilities() { - if (!abilities) { - abilities.reset(new Abilities()); - } - return *abilities; - } - - std::string getPluralName() const { - if (!pluralName.empty()) { - return pluralName; - } - - if (showCount == 0) { - return name; - } - - std::string str; - str.reserve(name.length() + 1); - str.assign(name); - str += 's'; - return str; - } - - itemgroup_t group; - ItemTypes_t type; - uint16_t id; - uint16_t clientId; - bool stackable; - bool isAnimation; - - std::string name; - std::string article; - std::string pluralName; - std::string description; - std::string runeSpellName; - std::string vocationString; - - std::unique_ptr abilities; - std::unique_ptr conditionDamage; - - uint32_t weight; - uint32_t levelDoor; - uint32_t decayTime; - uint32_t wieldInfo; - uint32_t minReqLevel; - uint32_t minReqMagicLevel; - uint32_t charges; - int32_t maxHitChance; - int32_t decayTo; - int32_t attack; - int32_t defense; - int32_t extraDefense; - int32_t armor; - int32_t rotateTo; - int32_t runeMagLevel; - int32_t runeLevel; - - CombatType_t combatType; - - uint16_t transformToOnUse[2]; - uint16_t transformToFree; - uint16_t destroyTo; - uint16_t maxTextLen; - uint16_t writeOnceItemId; - uint16_t transformEquipTo; - uint16_t transformDeEquipTo; - uint16_t maxItems; - uint16_t slotPosition; - uint16_t speed; - uint16_t wareId; - - MagicEffectClasses magicEffect; - Direction bedPartnerDir; - WeaponType_t weaponType; - Ammo_t ammoType; - ShootType_t shootType; - RaceType_t corpseType; - FluidTypes_t fluidSource; - - uint8_t alwaysOnTopOrder; - uint8_t lightLevel; - uint8_t lightColor; - uint8_t shootRange; - int8_t hitChance; - - bool forceUse; - bool floorChangeDown; - bool floorChangeNorth; - bool floorChangeSouth; - bool floorChangeSouthAlt; - bool floorChangeEast; - bool floorChangeEastAlt; - bool floorChangeWest; - bool hasHeight; - bool walkStack; - bool blockSolid; - bool blockPickupable; - bool blockProjectile; - bool blockPathFind; - bool allowPickupable; - bool showDuration; - bool showCharges; - bool showAttributes; - bool replaceable; - bool pickupable; - bool rotatable; - bool useable; - bool moveable; - bool alwaysOnTop; - bool canReadText; - bool canWriteText; - bool isVertical; - bool isHorizontal; - bool isHangable; - bool allowDistRead; - bool lookThrough; - bool stopTime; - bool showCount; -}; - -class Items -{ - public: - Items(); - ~Items(); - - // non-copyable - Items(const Items&) = delete; - Items& operator=(const Items&) = delete; - - bool reload(); - void clear(); - - FILELOADER_ERRORS loadFromOtb(const std::string& file); - - const ItemType& operator[](size_t id) const { - return getItemType(id); - } - const ItemType& getItemType(size_t id) const; - ItemType& getItemType(size_t id); - const ItemType& getItemIdByClientId(uint16_t spriteId) const; - - uint16_t getItemIdByName(const std::string& name); - - static uint32_t dwMajorVersion; - static uint32_t dwMinorVersion; - static uint32_t dwBuildNumber; - - bool loadFromXml(); - void parseItemNode(const pugi::xml_node& itemNode, uint16_t id); - - inline size_t size() const { - return items.size(); - } - - protected: - std::map reverseItemMap; - std::vector items; -}; -#endif diff --git a/path_10_8/src/lockfree.h b/path_10_8/src/lockfree.h deleted file mode 100644 index 95a36650a..000000000 --- a/path_10_8/src/lockfree.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_LOCKFREE_H_8C707AEB7C7235A2FBC5D4EDDF03B008 -#define FS_LOCKFREE_H_8C707AEB7C7235A2FBC5D4EDDF03B008 - -#include - -template -class LockfreePoolingAllocator : public std::allocator -{ - public: - template - LockfreePoolingAllocator(const U&) {} - typedef T value_type; - - T* allocate(size_t) const { - T* p; // NOTE: p doesn't have to be initialized - if (!getFreeList().pop(p)) { - //Acquire memory without calling the constructor of T - p = static_cast(operator new (sizeof(T))); - } - return p; - } - - void deallocate(T* p, size_t) const { - if (!getFreeList().bounded_push(p)) { - //Release memory without calling the destructor of T - //(it has already been called at this point) - operator delete(p); - } - } - - private: - typedef boost::lockfree::stack> FreeList; - static FreeList& getFreeList() { - static FreeList freeList; - return freeList; - } -}; - -#endif diff --git a/path_10_8/src/luascript.cpp b/path_10_8/src/luascript.cpp deleted file mode 100644 index 0fa8bcc6b..000000000 --- a/path_10_8/src/luascript.cpp +++ /dev/null @@ -1,12316 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "luascript.h" -#include "chat.h" -#include "player.h" -#include "game.h" -#include "protocolstatus.h" -#include "spells.h" -#include "iologindata.h" -#include "configmanager.h" -#include "teleport.h" -#include "databasemanager.h" -#include "bed.h" -#include "monster.h" -#include "scheduler.h" -#include "databasetasks.h" - -extern Chat* g_chat; -extern Game g_game; -extern Monsters g_monsters; -extern ConfigManager g_config; -extern Vocations g_vocations; -extern Spells* g_spells; - -enum { - EVENT_ID_LOADING = 1, - EVENT_ID_USER = 1000, -}; - -ScriptEnvironment::DBResultMap ScriptEnvironment::m_tempResults; -uint32_t ScriptEnvironment::m_lastResultId = 0; - -std::multimap ScriptEnvironment::tempItems; - -LuaEnvironment g_luaEnvironment; - -ScriptEnvironment::ScriptEnvironment() -{ - m_curNpc = nullptr; - resetEnv(); - m_lastUID = std::numeric_limits::max(); -} - -ScriptEnvironment::~ScriptEnvironment() -{ - resetEnv(); -} - -void ScriptEnvironment::resetEnv() -{ - m_scriptId = 0; - m_callbackId = 0; - m_timerEvent = false; - m_interface = nullptr; - localMap.clear(); - m_tempResults.clear(); - - auto pair = tempItems.equal_range(this); - auto it = pair.first; - while (it != pair.second) { - Item* item = it->second; - if (item->getParent() == VirtualCylinder::virtualCylinder) { - g_game.ReleaseItem(item); - } - it = tempItems.erase(it); - } -} - -bool ScriptEnvironment::setCallbackId(int32_t callbackId, LuaScriptInterface* scriptInterface) -{ - if (m_callbackId != 0) { - //nested callbacks are not allowed - if (m_interface) { - m_interface->reportErrorFunc("Nested callbacks!"); - } - return false; - } - - m_callbackId = callbackId; - m_interface = scriptInterface; - return true; -} - -void ScriptEnvironment::getEventInfo(int32_t& scriptId, std::string& desc, LuaScriptInterface*& scriptInterface, int32_t& callbackId, bool& timerEvent) const -{ - scriptId = m_scriptId; - desc = m_eventdesc; - scriptInterface = m_interface; - callbackId = m_callbackId; - timerEvent = m_timerEvent; -} - -uint32_t ScriptEnvironment::addThing(Thing* thing) -{ - if (!thing || thing->isRemoved()) { - return 0; - } - - Creature* creature = thing->getCreature(); - if (creature) { - return creature->getID(); - } - - Item* item = thing->getItem(); - if (item && item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - return item->getUniqueId(); - } - - for (const auto& it : localMap) { - if (it.second == item) { - return it.first; - } - } - - localMap[++m_lastUID] = item; - return m_lastUID; -} - -void ScriptEnvironment::insertItem(uint32_t uid, Item* item) -{ - auto result = localMap.emplace(uid, item); - if (!result.second) { - std::cout << std::endl << "Lua Script Error: Thing uid already taken."; - } -} - -Thing* ScriptEnvironment::getThingByUID(uint32_t uid) -{ - if (uid >= 0x10000000) { - return g_game.getCreatureByID(uid); - } - - if (uid <= std::numeric_limits::max()) { - Item* item = g_game.getUniqueItem(uid); - if (item && !item->isRemoved()) { - return item; - } - return nullptr; - } - - auto it = localMap.find(uid); - if (it != localMap.end()) { - Item* item = it->second; - if (!item->isRemoved()) { - return item; - } - } - return nullptr; -} - -Item* ScriptEnvironment::getItemByUID(uint32_t uid) -{ - Thing* thing = getThingByUID(uid); - if (!thing) { - return nullptr; - } - return thing->getItem(); -} - -Container* ScriptEnvironment::getContainerByUID(uint32_t uid) -{ - Item* item = getItemByUID(uid); - if (!item) { - return nullptr; - } - return item->getContainer(); -} - -void ScriptEnvironment::removeItemByUID(uint32_t uid) -{ - if (uid <= std::numeric_limits::max()) { - g_game.removeUniqueItem(uid); - return; - } - - auto it = localMap.find(uid); - if (it != localMap.end()) { - localMap.erase(it); - } -} - -void ScriptEnvironment::addTempItem(Item* item) -{ - tempItems.emplace(this, item); -} - -void ScriptEnvironment::removeTempItem(Item* item) -{ - for (auto it = tempItems.begin(), end = tempItems.end(); it != end; ++it) { - if (it->second == item) { - tempItems.erase(it); - break; - } - } -} - -uint32_t ScriptEnvironment::addResult(DBResult_ptr res) -{ - m_tempResults[++m_lastResultId] = res; - return m_lastResultId; -} - -bool ScriptEnvironment::removeResult(uint32_t id) -{ - auto it = m_tempResults.find(id); - if (it == m_tempResults.end()) { - return false; - } - - m_tempResults.erase(it); - return true; -} - -DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) -{ - auto it = m_tempResults.find(id); - if (it == m_tempResults.end()) { - return nullptr; - } - return it->second; -} - -std::string LuaScriptInterface::getErrorDesc(ErrorCode_t code) -{ - switch (code) { - case LUA_ERROR_PLAYER_NOT_FOUND: return "Player not found"; - case LUA_ERROR_CREATURE_NOT_FOUND: return "Creature not found"; - case LUA_ERROR_ITEM_NOT_FOUND: return "Item not found"; - case LUA_ERROR_THING_NOT_FOUND: return "Thing not found"; - case LUA_ERROR_TILE_NOT_FOUND: return "Tile not found"; - case LUA_ERROR_HOUSE_NOT_FOUND: return "House not found"; - case LUA_ERROR_COMBAT_NOT_FOUND: return "Combat not found"; - case LUA_ERROR_CONDITION_NOT_FOUND: return "Condition not found"; - case LUA_ERROR_AREA_NOT_FOUND: return "Area not found"; - case LUA_ERROR_CONTAINER_NOT_FOUND: return "Container not found"; - case LUA_ERROR_VARIANT_NOT_FOUND: return "Variant not found"; - case LUA_ERROR_VARIANT_UNKNOWN: return "Unknown variant type"; - case LUA_ERROR_SPELL_NOT_FOUND: return "Spell not found"; - default: return "Bad error code"; - } -} - -ScriptEnvironment LuaScriptInterface::m_scriptEnv[16]; -int32_t LuaScriptInterface::m_scriptEnvIndex = -1; - -LuaScriptInterface::LuaScriptInterface(std::string interfaceName) - : m_luaState(nullptr), m_interfaceName(interfaceName), m_eventTableRef(-1), m_runningEventId(EVENT_ID_USER) -{ - if (!g_luaEnvironment.getLuaState()) { - g_luaEnvironment.initState(); - } -} - -LuaScriptInterface::~LuaScriptInterface() -{ - closeState(); -} - -bool LuaScriptInterface::reInitState() -{ - g_luaEnvironment.clearCombatObjects(this); - g_luaEnvironment.clearAreaObjects(this); - - closeState(); - return initState(); -} - -/// Same as lua_pcall, but adds stack trace to error strings in called function. -int LuaScriptInterface::protectedCall(lua_State* L, int nargs, int nresults) -{ - int error_index = lua_gettop(L) - nargs; - lua_pushcfunction(L, luaErrorHandler); - lua_insert(L, error_index); - - int ret = lua_pcall(L, nargs, nresults, error_index); - lua_remove(L, error_index); - return ret; -} - -int32_t LuaScriptInterface::loadFile(const std::string& file, Npc* npc /* = nullptr*/) -{ - //loads file as a chunk at stack top - int ret = luaL_loadfile(m_luaState, file.c_str()); - if (ret != 0) { - m_lastLuaError = popString(m_luaState); - return -1; - } - - //check that it is loaded as a function - if (!isFunction(m_luaState, -1)) { - return -1; - } - - m_loadingFile = file; - - if (!reserveScriptEnv()) { - return -1; - } - - ScriptEnvironment* env = getScriptEnv(); - env->setScriptId(EVENT_ID_LOADING, this); - env->setNpc(npc); - - //execute it - ret = protectedCall(m_luaState, 0, 0); - if (ret != 0) { - reportError(nullptr, popString(m_luaState)); - resetScriptEnv(); - return -1; - } - - resetScriptEnv(); - return 0; -} - -int32_t LuaScriptInterface::getEvent(const std::string& eventName) -{ - //get our events table - lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, m_eventTableRef); - if (!isTable(m_luaState, -1)) { - lua_pop(m_luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(m_luaState, eventName.c_str()); - if (!isFunction(m_luaState, -1)) { - lua_pop(m_luaState, 2); - return -1; - } - - //save in our events table - lua_pushvalue(m_luaState, -1); - lua_rawseti(m_luaState, -3, m_runningEventId); - lua_pop(m_luaState, 2); - - //reset global value of this event - lua_pushnil(m_luaState); - lua_setglobal(m_luaState, eventName.c_str()); - - m_cacheFiles[m_runningEventId] = m_loadingFile + ":" + eventName; - return m_runningEventId++; -} - -int32_t LuaScriptInterface::getMetaEvent(const std::string& globalName, const std::string& eventName) -{ - //get our events table - lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, m_eventTableRef); - if (!isTable(m_luaState, -1)) { - lua_pop(m_luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(m_luaState, globalName.c_str()); - lua_getfield(m_luaState, -1, eventName.c_str()); - if (!isFunction(m_luaState, -1)) { - lua_pop(m_luaState, 3); - return -1; - } - - //save in our events table - lua_pushvalue(m_luaState, -1); - lua_rawseti(m_luaState, -4, m_runningEventId); - lua_pop(m_luaState, 1); - - //reset global value of this event - lua_pushnil(m_luaState); - lua_setfield(m_luaState, -2, eventName.c_str()); - lua_pop(m_luaState, 2); - - m_cacheFiles[m_runningEventId] = m_loadingFile + ":" + globalName + "@" + eventName; - return m_runningEventId++; -} - -const std::string& LuaScriptInterface::getFileById(int32_t scriptId) -{ - if (scriptId == EVENT_ID_LOADING) { - return m_loadingFile; - } - - auto it = m_cacheFiles.find(scriptId); - if (it == m_cacheFiles.end()) { - static const std::string& unk = "(Unknown scriptfile)"; - return unk; - } - return it->second; -} - -std::string LuaScriptInterface::getStackTrace(const std::string& error_desc) -{ - lua_getglobal(m_luaState, "debug"); - if (!isTable(m_luaState, -1)) { - lua_pop(m_luaState, 1); - return error_desc; - } - - lua_getfield(m_luaState, -1, "traceback"); - if (!isFunction(m_luaState, -1)) { - lua_pop(m_luaState, 2); - return error_desc; - } - - lua_replace(m_luaState, -2); - pushString(m_luaState, error_desc); - lua_call(m_luaState, 1, 1); - return popString(m_luaState); -} - -void LuaScriptInterface::reportError(const char* function, const std::string& error_desc, bool stack_trace/* = false*/) -{ - int32_t scriptId; - int32_t callbackId; - bool timerEvent; - std::string event_desc; - LuaScriptInterface* scriptInterface; - getScriptEnv()->getEventInfo(scriptId, event_desc, scriptInterface, callbackId, timerEvent); - - std::cout << std::endl << "Lua Script Error: "; - - if (scriptInterface) { - std::cout << '[' << scriptInterface->getInterfaceName() << "] " << std::endl; - - if (timerEvent) { - std::cout << "in a timer event called from: " << std::endl; - } - - if (callbackId) { - std::cout << "in callback: " << scriptInterface->getFileById(callbackId) << std::endl; - } - - std::cout << scriptInterface->getFileById(scriptId) << std::endl; - } - - if (!event_desc.empty()) { - std::cout << "Event: " << event_desc << std::endl; - } - - if (function) { - std::cout << function << "(). "; - } - - if (stack_trace && scriptInterface) { - std::cout << scriptInterface->getStackTrace(error_desc) << std::endl; - } else { - std::cout << error_desc << std::endl; - } -} - -bool LuaScriptInterface::pushFunction(int32_t functionId) -{ - lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, m_eventTableRef); - if (!isTable(m_luaState, -1)) { - return false; - } - - lua_rawgeti(m_luaState, -1, functionId); - lua_replace(m_luaState, -2); - return isFunction(m_luaState, -1); -} - -bool LuaScriptInterface::initState() -{ - m_luaState = g_luaEnvironment.getLuaState(); - if (!m_luaState) { - return false; - } - - lua_newtable(m_luaState); - m_eventTableRef = luaL_ref(m_luaState, LUA_REGISTRYINDEX); - m_runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaScriptInterface::closeState() -{ - if (!g_luaEnvironment.getLuaState() || !m_luaState) { - return false; - } - - m_cacheFiles.clear(); - if (m_eventTableRef != -1) { - luaL_unref(m_luaState, LUA_REGISTRYINDEX, m_eventTableRef); - m_eventTableRef = -1; - } - - m_luaState = nullptr; - return true; -} - -int LuaScriptInterface::luaErrorHandler(lua_State* L) -{ - const std::string& errorMessage = popString(L); - auto interface = getScriptEnv()->getScriptInterface(); - assert(interface); //This fires if the ScriptEnvironment hasn't been setup - pushString(L, interface->getStackTrace(errorMessage)); - return 1; -} - -bool LuaScriptInterface::callFunction(int params) -{ - bool result = false; - int size = lua_gettop(m_luaState); - if (protectedCall(m_luaState, params, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(m_luaState, -1)); - } else { - result = LuaScriptInterface::getBoolean(m_luaState, -1); - } - - lua_pop(m_luaState, 1); - if ((lua_gettop(m_luaState) + params + 1) != size) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - resetScriptEnv(); - return result; -} - -void LuaScriptInterface::callVoidFunction(int params) -{ - int size = lua_gettop(m_luaState); - if (protectedCall(m_luaState, params, 0) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(m_luaState)); - } - - if ((lua_gettop(m_luaState) + params + 1) != size) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - resetScriptEnv(); -} - -void LuaScriptInterface::pushVariant(lua_State* L, const LuaVariant& var) -{ - lua_createtable(L, 0, 2); - setField(L, "type", var.type); - switch (var.type) { - case VARIANT_NUMBER: - setField(L, "number", var.number); - break; - case VARIANT_STRING: - setField(L, "string", var.text); - break; - case VARIANT_TARGETPOSITION: - case VARIANT_POSITION: { - pushPosition(L, var.pos); - lua_setfield(L, -2, "pos"); - break; - } - default: - break; - } - setMetatable(L, -1, "Variant"); -} - -void LuaScriptInterface::pushThing(lua_State* L, Thing* thing) -{ - if (!thing) { - lua_createtable(L, 0, 4); - setField(L, "uid", 0); - setField(L, "itemid", 0); - setField(L, "actionid", 0); - setField(L, "type", 0); - return; - } - - if (Item* item = thing->getItem()) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else if (Creature* creature = thing->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } -} - -void LuaScriptInterface::pushString(lua_State* L, const std::string& value) -{ - lua_pushlstring(L, value.c_str(), value.length()); -} - -void LuaScriptInterface::pushCallback(lua_State* L, int32_t callback) -{ - lua_rawgeti(L, LUA_REGISTRYINDEX, callback); -} - -std::string LuaScriptInterface::popString(lua_State* L) -{ - if (lua_gettop(L) == 0) { - return std::string(); - } - - std::string str(getString(L, -1)); - lua_pop(L, 1); - return str; -} - -int32_t LuaScriptInterface::popCallback(lua_State* L) -{ - return luaL_ref(L, LUA_REGISTRYINDEX); -} - -// Metatables -void LuaScriptInterface::setMetatable(lua_State* L, int32_t index, const std::string& name) -{ - luaL_getmetatable(L, name.c_str()); - lua_setmetatable(L, index - 1); -} - -void LuaScriptInterface::setWeakMetatable(lua_State* L, int32_t index, const std::string& name) -{ - static std::set weakObjectTypes; - const std::string& weakName = name + "_weak"; - - auto result = weakObjectTypes.emplace(name); - if (result.second) { - luaL_getmetatable(L, name.c_str()); - int childMetatable = lua_gettop(L); - - luaL_newmetatable(L, weakName.c_str()); - int metatable = lua_gettop(L); - - static const std::vector methodKeys = {"__index", "__metatable", "__eq"}; - for (const std::string& metaKey : methodKeys) { - lua_getfield(L, childMetatable, metaKey.c_str()); - lua_setfield(L, metatable, metaKey.c_str()); - } - - static const std::vector methodIndexes = {'h', 'p', 't'}; - for (int metaIndex : methodIndexes) { - lua_rawgeti(L, childMetatable, metaIndex); - lua_rawseti(L, metatable, metaIndex); - } - - lua_pushnil(L); - lua_setfield(L, metatable, "__gc"); - - lua_remove(L, childMetatable); - } else { - luaL_getmetatable(L, weakName.c_str()); - } - lua_setmetatable(L, index - 1); -} - -void LuaScriptInterface::setItemMetatable(lua_State* L, int32_t index, const Item* item) -{ - if (item->getContainer()) { - luaL_getmetatable(L, "Container"); - } else if (item->getTeleport()) { - luaL_getmetatable(L, "Teleport"); - } else { - luaL_getmetatable(L, "Item"); - } - lua_setmetatable(L, index - 1); -} - -void LuaScriptInterface::setCreatureMetatable(lua_State* L, int32_t index, const Creature* creature) -{ - if (creature->getPlayer()) { - luaL_getmetatable(L, "Player"); - } else if (creature->getMonster()) { - luaL_getmetatable(L, "Monster"); - } else { - luaL_getmetatable(L, "Npc"); - } - lua_setmetatable(L, index - 1); -} - -// Get -std::string LuaScriptInterface::getString(lua_State* L, int32_t arg) -{ - size_t len; - const char* c_str = lua_tolstring(L, arg, &len); - if (!c_str || len == 0) { - return std::string(); - } - return std::string(c_str, len); -} - -Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg, int32_t& stackpos) -{ - Position position; - position.x = getField(L, arg, "x"); - position.y = getField(L, arg, "y"); - position.z = getField(L, arg, "z"); - - lua_getfield(L, arg, "stackpos"); - if (lua_isnil(L, -1) == 1) { - stackpos = 0; - } else { - stackpos = getNumber(L, -1); - } - - lua_pop(L, 4); - return position; -} - -Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg) -{ - Position position; - position.x = getField(L, arg, "x"); - position.y = getField(L, arg, "y"); - position.z = getField(L, arg, "z"); - - lua_pop(L, 3); - return position; -} - -Outfit_t LuaScriptInterface::getOutfit(lua_State* L, int32_t arg) -{ - Outfit_t outfit; - outfit.lookMount = getField(L, arg, "lookMount"); - outfit.lookAddons = getField(L, arg, "lookAddons"); - - outfit.lookFeet = getField(L, arg, "lookFeet"); - outfit.lookLegs = getField(L, arg, "lookLegs"); - outfit.lookBody = getField(L, arg, "lookBody"); - outfit.lookHead = getField(L, arg, "lookHead"); - - outfit.lookTypeEx = getField(L, arg, "lookTypeEx"); - outfit.lookType = getField(L, arg, "lookType"); - - lua_pop(L, 8); - return outfit; -} - -LuaVariant LuaScriptInterface::getVariant(lua_State* L, int32_t arg) -{ - LuaVariant var; - switch (var.type = getField(L, arg, "type")) { - case VARIANT_NUMBER: { - var.number = getField(L, arg, "number"); - lua_pop(L, 2); - break; - } - - case VARIANT_STRING: { - var.text = getFieldString(L, arg, "string"); - lua_pop(L, 2); - break; - } - - case VARIANT_POSITION: - case VARIANT_TARGETPOSITION: { - lua_getfield(L, arg, "pos"); - var.pos = getPosition(L, lua_gettop(L)); - lua_pop(L, 2); - break; - } - - default: { - var.type = VARIANT_NONE; - lua_pop(L, 1); - break; - } - } - return var; -} - -Thing* LuaScriptInterface::getThing(lua_State* L, int32_t arg) -{ - Thing* thing; - if (lua_getmetatable(L, arg) != 0) { - lua_rawgeti(L, -1, 't'); - switch(getNumber(L, -1)) { - case LuaData_Item: - thing = getUserdata(L, arg); - break; - case LuaData_Container: - thing = getUserdata(L, arg); - break; - case LuaData_Teleport: - thing = getUserdata(L, arg); - break; - case LuaData_Player: - thing = getUserdata(L, arg); - break; - case LuaData_Monster: - thing = getUserdata(L, arg); - break; - case LuaData_Npc: - thing = getUserdata(L, arg); - break; - default: - thing = nullptr; - break; - } - lua_pop(L, 2); - } else { - thing = getScriptEnv()->getThingByUID(getNumber(L, arg)); - } - return thing; -} - -Creature* LuaScriptInterface::getCreature(lua_State* L, int32_t arg) -{ - if (isUserdata(L, arg)) { - return getUserdata(L, arg); - } - return g_game.getCreatureByID(getNumber(L, arg)); -} - -Player* LuaScriptInterface::getPlayer(lua_State* L, int32_t arg) -{ - if (isUserdata(L, arg)) { - return getUserdata(L, arg); - } - return g_game.getPlayerByID(getNumber(L, arg)); -} - -std::string LuaScriptInterface::getFieldString(lua_State* L, int32_t arg, const std::string& key) -{ - lua_getfield(L, arg, key.c_str()); - return getString(L, -1); -} - -LuaDataType LuaScriptInterface::getUserdataType(lua_State* L, int32_t arg) -{ - if (lua_getmetatable(L, arg) == 0) { - return LuaData_Unknown; - } - lua_rawgeti(L, -1, 't'); - - LuaDataType type = getNumber(L, -1); - lua_pop(L, 2); - - return type; -} - -// Push -void LuaScriptInterface::pushBoolean(lua_State* L, bool value) -{ - lua_pushboolean(L, value ? 1 : 0); -} - -void LuaScriptInterface::pushPosition(lua_State* L, const Position& position, int32_t stackpos/* = 0*/) -{ - lua_createtable(L, 0, 4); - - setField(L, "x", position.x); - setField(L, "y", position.y); - setField(L, "z", position.z); - setField(L, "stackpos", stackpos); - - setMetatable(L, -1, "Position"); -} - -void LuaScriptInterface::pushOutfit(lua_State* L, const Outfit_t& outfit) -{ - lua_createtable(L, 0, 8); - setField(L, "lookType", outfit.lookType); - setField(L, "lookTypeEx", outfit.lookTypeEx); - setField(L, "lookHead", outfit.lookHead); - setField(L, "lookBody", outfit.lookBody); - setField(L, "lookLegs", outfit.lookLegs); - setField(L, "lookFeet", outfit.lookFeet); - setField(L, "lookAddons", outfit.lookAddons); - setField(L, "lookMount", outfit.lookMount); -} - -#define registerEnum(value) { std::string enumName = #value; registerGlobalVariable(enumName.substr(enumName.find_last_of(':') + 1), value); } -#define registerEnumIn(tableName, value) { std::string enumName = #value; registerVariable(tableName, enumName.substr(enumName.find_last_of(':') + 1), value); } - -void LuaScriptInterface::registerFunctions() -{ - //getPlayerFlagValue(cid, flag) - lua_register(m_luaState, "getPlayerFlagValue", LuaScriptInterface::luaGetPlayerFlagValue); - - //getPlayerInstantSpellCount(cid) - lua_register(m_luaState, "getPlayerInstantSpellCount", LuaScriptInterface::luaGetPlayerInstantSpellCount); - - //getPlayerInstantSpellInfo(cid, index) - lua_register(m_luaState, "getPlayerInstantSpellInfo", LuaScriptInterface::luaGetPlayerInstantSpellInfo); - - //doPlayerAddItem(uid, itemid, count/subtype) - //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) - //Returns uid of the created item - lua_register(m_luaState, "doPlayerAddItem", LuaScriptInterface::luaDoPlayerAddItem); - - //doCreateItem(itemid, type/count, pos) - //Returns uid of the created item, only works on tiles. - lua_register(m_luaState, "doCreateItem", LuaScriptInterface::luaDoCreateItem); - - //doCreateItemEx(itemid, count/subtype) - lua_register(m_luaState, "doCreateItemEx", LuaScriptInterface::luaDoCreateItemEx); - - //doTileAddItemEx(pos, uid) - lua_register(m_luaState, "doTileAddItemEx", LuaScriptInterface::luaDoTileAddItemEx); - - //doMoveCreature(cid, direction) - lua_register(m_luaState, "doMoveCreature", LuaScriptInterface::luaDoMoveCreature); - - //doSetCreatureLight(cid, lightLevel, lightColor, time) - lua_register(m_luaState, "doSetCreatureLight", LuaScriptInterface::luaDoSetCreatureLight); - - //getCreatureCondition(cid, condition[, subId]) - lua_register(m_luaState, "getCreatureCondition", LuaScriptInterface::luaGetCreatureCondition); - - //isValidUID(uid) - lua_register(m_luaState, "isValidUID", LuaScriptInterface::luaIsValidUID); - - //isDepot(uid) - lua_register(m_luaState, "isDepot", LuaScriptInterface::luaIsDepot); - - //isMovable(uid) - lua_register(m_luaState, "isMovable", LuaScriptInterface::luaIsMoveable); - - //doAddContainerItem(uid, itemid, count/subtype) - lua_register(m_luaState, "doAddContainerItem", LuaScriptInterface::luaDoAddContainerItem); - - //getDepotId(uid) - lua_register(m_luaState, "getDepotId", LuaScriptInterface::luaGetDepotId); - - //getWorldTime() - lua_register(m_luaState, "getWorldTime", LuaScriptInterface::luaGetWorldTime); - - //getWorldLight() - lua_register(m_luaState, "getWorldLight", LuaScriptInterface::luaGetWorldLight); - - //getWorldUpTime() - lua_register(m_luaState, "getWorldUpTime", LuaScriptInterface::luaGetWorldUpTime); - - //createCombatArea( {area}, {extArea} ) - lua_register(m_luaState, "createCombatArea", LuaScriptInterface::luaCreateCombatArea); - - //doAreaCombatHealth(cid, type, pos, area, min, max, effect) - lua_register(m_luaState, "doAreaCombatHealth", LuaScriptInterface::luaDoAreaCombatHealth); - - //doTargetCombatHealth(cid, target, type, min, max, effect) - lua_register(m_luaState, "doTargetCombatHealth", LuaScriptInterface::luaDoTargetCombatHealth); - - //doAreaCombatMana(cid, pos, area, min, max, effect) - lua_register(m_luaState, "doAreaCombatMana", LuaScriptInterface::luaDoAreaCombatMana); - - //doTargetCombatMana(cid, target, min, max, effect) - lua_register(m_luaState, "doTargetCombatMana", LuaScriptInterface::luaDoTargetCombatMana); - - //doAreaCombatCondition(cid, pos, area, condition, effect) - lua_register(m_luaState, "doAreaCombatCondition", LuaScriptInterface::luaDoAreaCombatCondition); - - //doTargetCombatCondition(cid, target, condition, effect) - lua_register(m_luaState, "doTargetCombatCondition", LuaScriptInterface::luaDoTargetCombatCondition); - - //doAreaCombatDispel(cid, pos, area, type, effect) - lua_register(m_luaState, "doAreaCombatDispel", LuaScriptInterface::luaDoAreaCombatDispel); - - //doTargetCombatDispel(cid, target, type, effect) - lua_register(m_luaState, "doTargetCombatDispel", LuaScriptInterface::luaDoTargetCombatDispel); - - //doChallengeCreature(cid, target) - lua_register(m_luaState, "doChallengeCreature", LuaScriptInterface::luaDoChallengeCreature); - - //doSetMonsterOutfit(cid, name, time) - lua_register(m_luaState, "doSetMonsterOutfit", LuaScriptInterface::luaSetMonsterOutfit); - - //doSetItemOutfit(cid, item, time) - lua_register(m_luaState, "doSetItemOutfit", LuaScriptInterface::luaSetItemOutfit); - - //doSetCreatureOutfit(cid, outfit, time) - lua_register(m_luaState, "doSetCreatureOutfit", LuaScriptInterface::luaSetCreatureOutfit); - - //isInArray(array, value) - lua_register(m_luaState, "isInArray", LuaScriptInterface::luaIsInArray); - - //addEvent(callback, delay, ...) - lua_register(m_luaState, "addEvent", LuaScriptInterface::luaAddEvent); - - //stopEvent(eventid) - lua_register(m_luaState, "stopEvent", LuaScriptInterface::luaStopEvent); - - //saveServer() - lua_register(m_luaState, "saveServer", LuaScriptInterface::luaSaveServer); - - //cleanMap() - lua_register(m_luaState, "cleanMap", LuaScriptInterface::luaCleanMap); - - //debugPrint(text) - lua_register(m_luaState, "debugPrint", LuaScriptInterface::luaDebugPrint); - - //isInWar(cid, target) - lua_register(m_luaState, "isInWar", LuaScriptInterface::luaIsInWar); - - //getWaypointPosition(name) - lua_register(m_luaState, "getWaypointPositionByName", LuaScriptInterface::luaGetWaypointPositionByName); - - //sendChannelMessage(channelId, type, message) - lua_register(m_luaState, "sendChannelMessage", LuaScriptInterface::luaSendChannelMessage); - - //sendGuildChannelMessage(guildId, type, message) - lua_register(m_luaState, "sendGuildChannelMessage", LuaScriptInterface::luaSendGuildChannelMessage); - -#ifndef LUAJIT_VERSION - //bit operations for Lua, based on bitlib project release 24 - //bit.bnot, bit.band, bit.bor, bit.bxor, bit.lshift, bit.rshift - luaL_register(m_luaState, "bit", LuaScriptInterface::luaBitReg); -#endif - - //configManager table - luaL_register(m_luaState, "configManager", LuaScriptInterface::luaConfigManagerTable); - - //db table - luaL_register(m_luaState, "db", LuaScriptInterface::luaDatabaseTable); - - //result table - luaL_register(m_luaState, "result", LuaScriptInterface::luaResultTable); - - /* New functions */ - //registerClass(className, baseClass, newFunction) - //registerTable(tableName) - //registerMethod(className, functionName, function) - //registerMetaMethod(className, functionName, function) - //registerGlobalMethod(functionName, function) - //registerVariable(tableName, name, value) - //registerGlobalVariable(name, value) - //registerEnum(value) - //registerEnumIn(tableName, value) - - // Enums - registerEnum(ACCOUNT_TYPE_NORMAL) - registerEnum(ACCOUNT_TYPE_TUTOR) - registerEnum(ACCOUNT_TYPE_SENIORTUTOR) - registerEnum(ACCOUNT_TYPE_GAMEMASTER) - registerEnum(ACCOUNT_TYPE_GOD) - - registerEnum(CALLBACK_PARAM_LEVELMAGICVALUE) - registerEnum(CALLBACK_PARAM_SKILLVALUE) - registerEnum(CALLBACK_PARAM_TARGETTILE) - registerEnum(CALLBACK_PARAM_TARGETCREATURE) - - registerEnum(COMBAT_FORMULA_UNDEFINED) - registerEnum(COMBAT_FORMULA_LEVELMAGIC) - registerEnum(COMBAT_FORMULA_SKILL) - registerEnum(COMBAT_FORMULA_DAMAGE) - - registerEnum(DIRECTION_NORTH) - registerEnum(DIRECTION_EAST) - registerEnum(DIRECTION_SOUTH) - registerEnum(DIRECTION_WEST) - registerEnum(DIRECTION_SOUTHWEST) - registerEnum(DIRECTION_SOUTHEAST) - registerEnum(DIRECTION_NORTHWEST) - registerEnum(DIRECTION_NORTHEAST) - - registerEnum(COMBAT_NONE) - registerEnum(COMBAT_PHYSICALDAMAGE) - registerEnum(COMBAT_ENERGYDAMAGE) - registerEnum(COMBAT_EARTHDAMAGE) - registerEnum(COMBAT_FIREDAMAGE) - registerEnum(COMBAT_UNDEFINEDDAMAGE) - registerEnum(COMBAT_LIFEDRAIN) - registerEnum(COMBAT_MANADRAIN) - registerEnum(COMBAT_HEALING) - registerEnum(COMBAT_DROWNDAMAGE) - registerEnum(COMBAT_ICEDAMAGE) - registerEnum(COMBAT_HOLYDAMAGE) - registerEnum(COMBAT_DEATHDAMAGE) - - registerEnum(COMBAT_PARAM_TYPE) - registerEnum(COMBAT_PARAM_EFFECT) - registerEnum(COMBAT_PARAM_DISTANCEEFFECT) - registerEnum(COMBAT_PARAM_BLOCKSHIELD) - registerEnum(COMBAT_PARAM_BLOCKARMOR) - registerEnum(COMBAT_PARAM_TARGETCASTERORTOPMOST) - registerEnum(COMBAT_PARAM_CREATEITEM) - registerEnum(COMBAT_PARAM_AGGRESSIVE) - registerEnum(COMBAT_PARAM_DISPEL) - registerEnum(COMBAT_PARAM_USECHARGES) - - registerEnum(CONDITION_NONE) - registerEnum(CONDITION_POISON) - registerEnum(CONDITION_FIRE) - registerEnum(CONDITION_ENERGY) - registerEnum(CONDITION_BLEEDING) - registerEnum(CONDITION_HASTE) - registerEnum(CONDITION_PARALYZE) - registerEnum(CONDITION_OUTFIT) - registerEnum(CONDITION_INVISIBLE) - registerEnum(CONDITION_LIGHT) - registerEnum(CONDITION_MANASHIELD) - registerEnum(CONDITION_INFIGHT) - registerEnum(CONDITION_DRUNK) - registerEnum(CONDITION_EXHAUST_WEAPON) - registerEnum(CONDITION_REGENERATION) - registerEnum(CONDITION_SOUL) - registerEnum(CONDITION_DROWN) - registerEnum(CONDITION_MUTED) - registerEnum(CONDITION_CHANNELMUTEDTICKS) - registerEnum(CONDITION_YELLTICKS) - registerEnum(CONDITION_ATTRIBUTES) - registerEnum(CONDITION_FREEZING) - registerEnum(CONDITION_DAZZLED) - registerEnum(CONDITION_CURSED) - registerEnum(CONDITION_EXHAUST_COMBAT) - registerEnum(CONDITION_EXHAUST_HEAL) - registerEnum(CONDITION_PACIFIED) - registerEnum(CONDITION_SPELLCOOLDOWN) - registerEnum(CONDITION_SPELLGROUPCOOLDOWN) - - registerEnum(CONDITIONID_DEFAULT) - registerEnum(CONDITIONID_COMBAT) - registerEnum(CONDITIONID_HEAD) - registerEnum(CONDITIONID_NECKLACE) - registerEnum(CONDITIONID_BACKPACK) - registerEnum(CONDITIONID_ARMOR) - registerEnum(CONDITIONID_RIGHT) - registerEnum(CONDITIONID_LEFT) - registerEnum(CONDITIONID_LEGS) - registerEnum(CONDITIONID_FEET) - registerEnum(CONDITIONID_RING) - registerEnum(CONDITIONID_AMMO) - - registerEnum(CONDITION_PARAM_OWNER) - registerEnum(CONDITION_PARAM_TICKS) - registerEnum(CONDITION_PARAM_HEALTHGAIN) - registerEnum(CONDITION_PARAM_HEALTHTICKS) - registerEnum(CONDITION_PARAM_MANAGAIN) - registerEnum(CONDITION_PARAM_MANATICKS) - registerEnum(CONDITION_PARAM_DELAYED) - registerEnum(CONDITION_PARAM_SPEED) - registerEnum(CONDITION_PARAM_LIGHT_LEVEL) - registerEnum(CONDITION_PARAM_LIGHT_COLOR) - registerEnum(CONDITION_PARAM_SOULGAIN) - registerEnum(CONDITION_PARAM_SOULTICKS) - registerEnum(CONDITION_PARAM_MINVALUE) - registerEnum(CONDITION_PARAM_MAXVALUE) - registerEnum(CONDITION_PARAM_STARTVALUE) - registerEnum(CONDITION_PARAM_TICKINTERVAL) - registerEnum(CONDITION_PARAM_FORCEUPDATE) - registerEnum(CONDITION_PARAM_SKILL_MELEE) - registerEnum(CONDITION_PARAM_SKILL_FIST) - registerEnum(CONDITION_PARAM_SKILL_CLUB) - registerEnum(CONDITION_PARAM_SKILL_SWORD) - registerEnum(CONDITION_PARAM_SKILL_AXE) - registerEnum(CONDITION_PARAM_SKILL_DISTANCE) - registerEnum(CONDITION_PARAM_SKILL_SHIELD) - registerEnum(CONDITION_PARAM_SKILL_FISHING) - registerEnum(CONDITION_PARAM_STAT_MAXHITPOINTS) - registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTS) - registerEnum(CONDITION_PARAM_STAT_MAGICPOINTS) - registerEnum(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT) - registerEnum(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT) - registerEnum(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT) - registerEnum(CONDITION_PARAM_PERIODICDAMAGE) - registerEnum(CONDITION_PARAM_SKILL_MELEEPERCENT) - registerEnum(CONDITION_PARAM_SKILL_FISTPERCENT) - registerEnum(CONDITION_PARAM_SKILL_CLUBPERCENT) - registerEnum(CONDITION_PARAM_SKILL_SWORDPERCENT) - registerEnum(CONDITION_PARAM_SKILL_AXEPERCENT) - registerEnum(CONDITION_PARAM_SKILL_DISTANCEPERCENT) - registerEnum(CONDITION_PARAM_SKILL_SHIELDPERCENT) - registerEnum(CONDITION_PARAM_SKILL_FISHINGPERCENT) - registerEnum(CONDITION_PARAM_BUFF_SPELL) - registerEnum(CONDITION_PARAM_SUBID) - registerEnum(CONDITION_PARAM_FIELD) - - registerEnum(CONST_ME_NONE) - registerEnum(CONST_ME_DRAWBLOOD) - registerEnum(CONST_ME_LOSEENERGY) - registerEnum(CONST_ME_POFF) - registerEnum(CONST_ME_BLOCKHIT) - registerEnum(CONST_ME_EXPLOSIONAREA) - registerEnum(CONST_ME_EXPLOSIONHIT) - registerEnum(CONST_ME_FIREAREA) - registerEnum(CONST_ME_YELLOW_RINGS) - registerEnum(CONST_ME_GREEN_RINGS) - registerEnum(CONST_ME_HITAREA) - registerEnum(CONST_ME_TELEPORT) - registerEnum(CONST_ME_ENERGYHIT) - registerEnum(CONST_ME_MAGIC_BLUE) - registerEnum(CONST_ME_MAGIC_RED) - registerEnum(CONST_ME_MAGIC_GREEN) - registerEnum(CONST_ME_HITBYFIRE) - registerEnum(CONST_ME_HITBYPOISON) - registerEnum(CONST_ME_MORTAREA) - registerEnum(CONST_ME_SOUND_GREEN) - registerEnum(CONST_ME_SOUND_RED) - registerEnum(CONST_ME_POISONAREA) - registerEnum(CONST_ME_SOUND_YELLOW) - registerEnum(CONST_ME_SOUND_PURPLE) - registerEnum(CONST_ME_SOUND_BLUE) - registerEnum(CONST_ME_SOUND_WHITE) - registerEnum(CONST_ME_BUBBLES) - registerEnum(CONST_ME_CRAPS) - registerEnum(CONST_ME_GIFT_WRAPS) - registerEnum(CONST_ME_FIREWORK_YELLOW) - registerEnum(CONST_ME_FIREWORK_RED) - registerEnum(CONST_ME_FIREWORK_BLUE) - registerEnum(CONST_ME_STUN) - registerEnum(CONST_ME_SLEEP) - registerEnum(CONST_ME_WATERCREATURE) - registerEnum(CONST_ME_GROUNDSHAKER) - registerEnum(CONST_ME_HEARTS) - registerEnum(CONST_ME_FIREATTACK) - registerEnum(CONST_ME_ENERGYAREA) - registerEnum(CONST_ME_SMALLCLOUDS) - registerEnum(CONST_ME_HOLYDAMAGE) - registerEnum(CONST_ME_BIGCLOUDS) - registerEnum(CONST_ME_ICEAREA) - registerEnum(CONST_ME_ICETORNADO) - registerEnum(CONST_ME_ICEATTACK) - registerEnum(CONST_ME_STONES) - registerEnum(CONST_ME_SMALLPLANTS) - registerEnum(CONST_ME_CARNIPHILA) - registerEnum(CONST_ME_PURPLEENERGY) - registerEnum(CONST_ME_YELLOWENERGY) - registerEnum(CONST_ME_HOLYAREA) - registerEnum(CONST_ME_BIGPLANTS) - registerEnum(CONST_ME_CAKE) - registerEnum(CONST_ME_GIANTICE) - registerEnum(CONST_ME_WATERSPLASH) - registerEnum(CONST_ME_PLANTATTACK) - registerEnum(CONST_ME_TUTORIALARROW) - registerEnum(CONST_ME_TUTORIALSQUARE) - registerEnum(CONST_ME_MIRRORHORIZONTAL) - registerEnum(CONST_ME_MIRRORVERTICAL) - registerEnum(CONST_ME_SKULLHORIZONTAL) - registerEnum(CONST_ME_SKULLVERTICAL) - registerEnum(CONST_ME_ASSASSIN) - registerEnum(CONST_ME_STEPSHORIZONTAL) - registerEnum(CONST_ME_BLOODYSTEPS) - registerEnum(CONST_ME_STEPSVERTICAL) - registerEnum(CONST_ME_YALAHARIGHOST) - registerEnum(CONST_ME_BATS) - registerEnum(CONST_ME_SMOKE) - registerEnum(CONST_ME_INSECTS) - registerEnum(CONST_ME_DRAGONHEAD) - registerEnum(CONST_ME_ORCSHAMAN) - registerEnum(CONST_ME_ORCSHAMAN_FIRE) - registerEnum(CONST_ME_THUNDER) - registerEnum(CONST_ME_FERUMBRAS) - registerEnum(CONST_ME_CONFETTI_HORIZONTAL) - registerEnum(CONST_ME_CONFETTI_VERTICAL) - registerEnum(CONST_ME_BLACKSMOKE) - registerEnum(CONST_ME_REDSMOKE) - registerEnum(CONST_ME_YELLOWSMOKE) - registerEnum(CONST_ME_GREENSMOKE) - registerEnum(CONST_ME_PURPLESMOKE) - - registerEnum(CONST_ANI_NONE) - registerEnum(CONST_ANI_SPEAR) - registerEnum(CONST_ANI_BOLT) - registerEnum(CONST_ANI_ARROW) - registerEnum(CONST_ANI_FIRE) - registerEnum(CONST_ANI_ENERGY) - registerEnum(CONST_ANI_POISONARROW) - registerEnum(CONST_ANI_BURSTARROW) - registerEnum(CONST_ANI_THROWINGSTAR) - registerEnum(CONST_ANI_THROWINGKNIFE) - registerEnum(CONST_ANI_SMALLSTONE) - registerEnum(CONST_ANI_DEATH) - registerEnum(CONST_ANI_LARGEROCK) - registerEnum(CONST_ANI_SNOWBALL) - registerEnum(CONST_ANI_POWERBOLT) - registerEnum(CONST_ANI_POISON) - registerEnum(CONST_ANI_INFERNALBOLT) - registerEnum(CONST_ANI_HUNTINGSPEAR) - registerEnum(CONST_ANI_ENCHANTEDSPEAR) - registerEnum(CONST_ANI_REDSTAR) - registerEnum(CONST_ANI_GREENSTAR) - registerEnum(CONST_ANI_ROYALSPEAR) - registerEnum(CONST_ANI_SNIPERARROW) - registerEnum(CONST_ANI_ONYXARROW) - registerEnum(CONST_ANI_PIERCINGBOLT) - registerEnum(CONST_ANI_WHIRLWINDSWORD) - registerEnum(CONST_ANI_WHIRLWINDAXE) - registerEnum(CONST_ANI_WHIRLWINDCLUB) - registerEnum(CONST_ANI_ETHEREALSPEAR) - registerEnum(CONST_ANI_ICE) - registerEnum(CONST_ANI_EARTH) - registerEnum(CONST_ANI_HOLY) - registerEnum(CONST_ANI_SUDDENDEATH) - registerEnum(CONST_ANI_FLASHARROW) - registerEnum(CONST_ANI_FLAMMINGARROW) - registerEnum(CONST_ANI_SHIVERARROW) - registerEnum(CONST_ANI_ENERGYBALL) - registerEnum(CONST_ANI_SMALLICE) - registerEnum(CONST_ANI_SMALLHOLY) - registerEnum(CONST_ANI_SMALLEARTH) - registerEnum(CONST_ANI_EARTHARROW) - registerEnum(CONST_ANI_EXPLOSION) - registerEnum(CONST_ANI_CAKE) - registerEnum(CONST_ANI_TARSALARROW) - registerEnum(CONST_ANI_VORTEXBOLT) - registerEnum(CONST_ANI_PRISMATICBOLT) - registerEnum(CONST_ANI_CRYSTALLINEARROW) - registerEnum(CONST_ANI_DRILLBOLT) - registerEnum(CONST_ANI_ENVENOMEDARROW) - registerEnum(CONST_ANI_GLOOTHSPEAR) - registerEnum(CONST_ANI_SIMPLEARROW) - registerEnum(CONST_ANI_WEAPONTYPE) - - registerEnum(CONST_PROP_BLOCKSOLID) - registerEnum(CONST_PROP_HASHEIGHT) - registerEnum(CONST_PROP_BLOCKPROJECTILE) - registerEnum(CONST_PROP_BLOCKPATH) - registerEnum(CONST_PROP_ISVERTICAL) - registerEnum(CONST_PROP_ISHORIZONTAL) - registerEnum(CONST_PROP_MOVEABLE) - registerEnum(CONST_PROP_IMMOVABLEBLOCKSOLID) - registerEnum(CONST_PROP_IMMOVABLEBLOCKPATH) - registerEnum(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH) - registerEnum(CONST_PROP_NOFIELDBLOCKPATH) - registerEnum(CONST_PROP_SUPPORTHANGABLE) - - registerEnum(CONST_SLOT_HEAD) - registerEnum(CONST_SLOT_NECKLACE) - registerEnum(CONST_SLOT_BACKPACK) - registerEnum(CONST_SLOT_ARMOR) - registerEnum(CONST_SLOT_RIGHT) - registerEnum(CONST_SLOT_LEFT) - registerEnum(CONST_SLOT_LEGS) - registerEnum(CONST_SLOT_FEET) - registerEnum(CONST_SLOT_RING) - registerEnum(CONST_SLOT_AMMO) - - registerEnum(GAME_STATE_STARTUP) - registerEnum(GAME_STATE_INIT) - registerEnum(GAME_STATE_NORMAL) - registerEnum(GAME_STATE_CLOSED) - registerEnum(GAME_STATE_SHUTDOWN) - registerEnum(GAME_STATE_CLOSING) - registerEnum(GAME_STATE_MAINTAIN) - - registerEnum(MESSAGE_STATUS_CONSOLE_BLUE) - registerEnum(MESSAGE_STATUS_CONSOLE_RED) - registerEnum(MESSAGE_STATUS_DEFAULT) - registerEnum(MESSAGE_STATUS_WARNING) - registerEnum(MESSAGE_EVENT_ADVANCE) - registerEnum(MESSAGE_STATUS_SMALL) - registerEnum(MESSAGE_INFO_DESCR) - registerEnum(MESSAGE_DAMAGE_DEALT) - registerEnum(MESSAGE_DAMAGE_RECEIVED) - registerEnum(MESSAGE_HEALED) - registerEnum(MESSAGE_EXPERIENCE) - registerEnum(MESSAGE_DAMAGE_OTHERS) - registerEnum(MESSAGE_HEALED_OTHERS) - registerEnum(MESSAGE_EXPERIENCE_OTHERS) - registerEnum(MESSAGE_EVENT_DEFAULT) - registerEnum(MESSAGE_EVENT_ORANGE) - registerEnum(MESSAGE_STATUS_CONSOLE_ORANGE) - - registerEnum(CREATURETYPE_PLAYER) - registerEnum(CREATURETYPE_MONSTER) - registerEnum(CREATURETYPE_NPC) - registerEnum(CREATURETYPE_SUMMON_OWN) - registerEnum(CREATURETYPE_SUMMON_OTHERS) - - registerEnum(CLIENTOS_LINUX) - registerEnum(CLIENTOS_WINDOWS) - registerEnum(CLIENTOS_FLASH) - registerEnum(CLIENTOS_OTCLIENT_LINUX) - registerEnum(CLIENTOS_OTCLIENT_WINDOWS) - registerEnum(CLIENTOS_OTCLIENT_MAC) - - registerEnum(ITEM_ATTRIBUTE_NONE) - registerEnum(ITEM_ATTRIBUTE_ACTIONID) - registerEnum(ITEM_ATTRIBUTE_UNIQUEID) - registerEnum(ITEM_ATTRIBUTE_DESCRIPTION) - registerEnum(ITEM_ATTRIBUTE_TEXT) - registerEnum(ITEM_ATTRIBUTE_DATE) - registerEnum(ITEM_ATTRIBUTE_WRITER) - registerEnum(ITEM_ATTRIBUTE_NAME) - registerEnum(ITEM_ATTRIBUTE_ARTICLE) - registerEnum(ITEM_ATTRIBUTE_PLURALNAME) - registerEnum(ITEM_ATTRIBUTE_WEIGHT) - registerEnum(ITEM_ATTRIBUTE_ATTACK) - registerEnum(ITEM_ATTRIBUTE_DEFENSE) - registerEnum(ITEM_ATTRIBUTE_EXTRADEFENSE) - registerEnum(ITEM_ATTRIBUTE_ARMOR) - registerEnum(ITEM_ATTRIBUTE_HITCHANCE) - registerEnum(ITEM_ATTRIBUTE_SHOOTRANGE) - registerEnum(ITEM_ATTRIBUTE_OWNER) - registerEnum(ITEM_ATTRIBUTE_DURATION) - registerEnum(ITEM_ATTRIBUTE_DECAYSTATE) - registerEnum(ITEM_ATTRIBUTE_CORPSEOWNER) - registerEnum(ITEM_ATTRIBUTE_CHARGES) - registerEnum(ITEM_ATTRIBUTE_FLUIDTYPE) - registerEnum(ITEM_ATTRIBUTE_DOORID) - - registerEnum(ITEM_TYPE_DEPOT) - registerEnum(ITEM_TYPE_MAILBOX) - registerEnum(ITEM_TYPE_TRASHHOLDER) - registerEnum(ITEM_TYPE_CONTAINER) - registerEnum(ITEM_TYPE_DOOR) - registerEnum(ITEM_TYPE_MAGICFIELD) - registerEnum(ITEM_TYPE_TELEPORT) - registerEnum(ITEM_TYPE_BED) - registerEnum(ITEM_TYPE_KEY) - registerEnum(ITEM_TYPE_RUNE) - - registerEnum(ITEM_BAG) - registerEnum(ITEM_GOLD_COIN) - registerEnum(ITEM_PLATINUM_COIN) - registerEnum(ITEM_CRYSTAL_COIN) - registerEnum(ITEM_AMULETOFLOSS) - registerEnum(ITEM_PARCEL) - registerEnum(ITEM_LABEL) - registerEnum(ITEM_FIREFIELD_PVP_FULL) - registerEnum(ITEM_FIREFIELD_PVP_MEDIUM) - registerEnum(ITEM_FIREFIELD_PVP_SMALL) - registerEnum(ITEM_FIREFIELD_PERSISTENT_FULL) - registerEnum(ITEM_FIREFIELD_PERSISTENT_MEDIUM) - registerEnum(ITEM_FIREFIELD_PERSISTENT_SMALL) - registerEnum(ITEM_FIREFIELD_NOPVP) - registerEnum(ITEM_POISONFIELD_PVP) - registerEnum(ITEM_POISONFIELD_PERSISTENT) - registerEnum(ITEM_POISONFIELD_NOPVP) - registerEnum(ITEM_ENERGYFIELD_PVP) - registerEnum(ITEM_ENERGYFIELD_PERSISTENT) - registerEnum(ITEM_ENERGYFIELD_NOPVP) - registerEnum(ITEM_MAGICWALL) - registerEnum(ITEM_MAGICWALL_PERSISTENT) - registerEnum(ITEM_MAGICWALL_SAFE) - registerEnum(ITEM_WILDGROWTH) - registerEnum(ITEM_WILDGROWTH_PERSISTENT) - registerEnum(ITEM_WILDGROWTH_SAFE) - - registerEnum(PlayerFlag_CannotUseCombat) - registerEnum(PlayerFlag_CannotAttackPlayer) - registerEnum(PlayerFlag_CannotAttackMonster) - registerEnum(PlayerFlag_CannotBeAttacked) - registerEnum(PlayerFlag_CanConvinceAll) - registerEnum(PlayerFlag_CanSummonAll) - registerEnum(PlayerFlag_CanIllusionAll) - registerEnum(PlayerFlag_CanSenseInvisibility) - registerEnum(PlayerFlag_IgnoredByMonsters) - registerEnum(PlayerFlag_NotGainInFight) - registerEnum(PlayerFlag_HasInfiniteMana) - registerEnum(PlayerFlag_HasInfiniteSoul) - registerEnum(PlayerFlag_HasNoExhaustion) - registerEnum(PlayerFlag_CannotUseSpells) - registerEnum(PlayerFlag_CannotPickupItem) - registerEnum(PlayerFlag_CanAlwaysLogin) - registerEnum(PlayerFlag_CanBroadcast) - registerEnum(PlayerFlag_CanEditHouses) - registerEnum(PlayerFlag_CannotBeBanned) - registerEnum(PlayerFlag_CannotBePushed) - registerEnum(PlayerFlag_HasInfiniteCapacity) - registerEnum(PlayerFlag_CanPushAllCreatures) - registerEnum(PlayerFlag_CanTalkRedPrivate) - registerEnum(PlayerFlag_CanTalkRedChannel) - registerEnum(PlayerFlag_TalkOrangeHelpChannel) - registerEnum(PlayerFlag_NotGainExperience) - registerEnum(PlayerFlag_NotGainMana) - registerEnum(PlayerFlag_NotGainHealth) - registerEnum(PlayerFlag_NotGainSkill) - registerEnum(PlayerFlag_SetMaxSpeed) - registerEnum(PlayerFlag_SpecialVIP) - registerEnum(PlayerFlag_NotGenerateLoot) - registerEnum(PlayerFlag_CanTalkRedChannelAnonymous) - registerEnum(PlayerFlag_IgnoreProtectionZone) - registerEnum(PlayerFlag_IgnoreSpellCheck) - registerEnum(PlayerFlag_IgnoreWeaponCheck) - registerEnum(PlayerFlag_CannotBeMuted) - registerEnum(PlayerFlag_IsAlwaysPremium) - - registerEnum(PLAYERSEX_FEMALE) - registerEnum(PLAYERSEX_MALE) - - registerEnum(VOCATION_NONE) - - registerEnum(SKILL_FIST) - registerEnum(SKILL_CLUB) - registerEnum(SKILL_SWORD) - registerEnum(SKILL_AXE) - registerEnum(SKILL_DISTANCE) - registerEnum(SKILL_SHIELD) - registerEnum(SKILL_FISHING) - registerEnum(SKILL_MAGLEVEL) - registerEnum(SKILL_LEVEL) - - registerEnum(SKULL_NONE) - registerEnum(SKULL_YELLOW) - registerEnum(SKULL_GREEN) - registerEnum(SKULL_WHITE) - registerEnum(SKULL_RED) - registerEnum(SKULL_BLACK) - registerEnum(SKULL_ORANGE) - - registerEnum(TALKTYPE_SAY) - registerEnum(TALKTYPE_WHISPER) - registerEnum(TALKTYPE_YELL) - registerEnum(TALKTYPE_PRIVATE_FROM) - registerEnum(TALKTYPE_PRIVATE_TO) - registerEnum(TALKTYPE_CHANNEL_Y) - registerEnum(TALKTYPE_CHANNEL_O) - registerEnum(TALKTYPE_PRIVATE_NP) - registerEnum(TALKTYPE_PRIVATE_PN) - registerEnum(TALKTYPE_BROADCAST) - registerEnum(TALKTYPE_CHANNEL_R1) - registerEnum(TALKTYPE_PRIVATE_RED_FROM) - registerEnum(TALKTYPE_PRIVATE_RED_TO) - registerEnum(TALKTYPE_MONSTER_SAY) - registerEnum(TALKTYPE_MONSTER_YELL) - registerEnum(TALKTYPE_CHANNEL_R2) - - registerEnum(TEXTCOLOR_BLUE) - registerEnum(TEXTCOLOR_LIGHTGREEN) - registerEnum(TEXTCOLOR_LIGHTBLUE) - registerEnum(TEXTCOLOR_MAYABLUE) - registerEnum(TEXTCOLOR_DARKRED) - registerEnum(TEXTCOLOR_LIGHTGREY) - registerEnum(TEXTCOLOR_SKYBLUE) - registerEnum(TEXTCOLOR_PURPLE) - registerEnum(TEXTCOLOR_RED) - registerEnum(TEXTCOLOR_ORANGE) - registerEnum(TEXTCOLOR_YELLOW) - registerEnum(TEXTCOLOR_WHITE_EXP) - registerEnum(TEXTCOLOR_NONE) - - registerEnum(TILESTATE_NONE) - registerEnum(TILESTATE_PROTECTIONZONE) - registerEnum(TILESTATE_DEPRECATED_HOUSE) - registerEnum(TILESTATE_NOPVPZONE) - registerEnum(TILESTATE_NOLOGOUT) - registerEnum(TILESTATE_PVPZONE) - registerEnum(TILESTATE_REFRESH) - registerEnum(TILESTATE_HOUSE) - registerEnum(TILESTATE_FLOORCHANGE) - registerEnum(TILESTATE_FLOORCHANGE_DOWN) - registerEnum(TILESTATE_FLOORCHANGE_NORTH) - registerEnum(TILESTATE_FLOORCHANGE_SOUTH) - registerEnum(TILESTATE_FLOORCHANGE_EAST) - registerEnum(TILESTATE_FLOORCHANGE_WEST) - registerEnum(TILESTATE_TELEPORT) - registerEnum(TILESTATE_MAGICFIELD) - registerEnum(TILESTATE_MAILBOX) - registerEnum(TILESTATE_TRASHHOLDER) - registerEnum(TILESTATE_BED) - registerEnum(TILESTATE_DEPOT) - registerEnum(TILESTATE_BLOCKSOLID) - registerEnum(TILESTATE_BLOCKPATH) - registerEnum(TILESTATE_IMMOVABLEBLOCKSOLID) - registerEnum(TILESTATE_IMMOVABLEBLOCKPATH) - registerEnum(TILESTATE_IMMOVABLENOFIELDBLOCKPATH) - registerEnum(TILESTATE_NOFIELDBLOCKPATH) - registerEnum(TILESTATE_DYNAMIC_TILE) - registerEnum(TILESTATE_FLOORCHANGE_SOUTH_ALT) - registerEnum(TILESTATE_FLOORCHANGE_EAST_ALT) - registerEnum(TILESTATE_SUPPORTS_HANGABLE) - - registerEnum(WEAPON_NONE) - registerEnum(WEAPON_SWORD) - registerEnum(WEAPON_CLUB) - registerEnum(WEAPON_AXE) - registerEnum(WEAPON_SHIELD) - registerEnum(WEAPON_DISTANCE) - registerEnum(WEAPON_WAND) - registerEnum(WEAPON_AMMO) - - registerEnum(WORLD_TYPE_NO_PVP) - registerEnum(WORLD_TYPE_PVP) - registerEnum(WORLD_TYPE_PVP_ENFORCED) - - // Use with container:addItem, container:addItemEx and possibly other functions. - registerEnum(FLAG_NOLIMIT) - registerEnum(FLAG_IGNOREBLOCKITEM) - registerEnum(FLAG_IGNOREBLOCKCREATURE) - registerEnum(FLAG_CHILDISOWNER) - registerEnum(FLAG_PATHFINDING) - registerEnum(FLAG_IGNOREFIELDDAMAGE) - registerEnum(FLAG_IGNORENOTMOVEABLE) - registerEnum(FLAG_IGNOREAUTOSTACK) - - // Use with itemType:getSlotPosition - registerEnum(SLOTP_WHEREEVER) - registerEnum(SLOTP_HEAD) - registerEnum(SLOTP_NECKLACE) - registerEnum(SLOTP_BACKPACK) - registerEnum(SLOTP_ARMOR) - registerEnum(SLOTP_RIGHT) - registerEnum(SLOTP_LEFT) - registerEnum(SLOTP_LEGS) - registerEnum(SLOTP_FEET) - registerEnum(SLOTP_RING) - registerEnum(SLOTP_AMMO) - registerEnum(SLOTP_DEPOT) - registerEnum(SLOTP_TWO_HAND) - - // Use with combat functions - registerEnum(ORIGIN_NONE) - registerEnum(ORIGIN_CONDITION) - registerEnum(ORIGIN_SPELL) - registerEnum(ORIGIN_MELEE) - registerEnum(ORIGIN_RANGED) - - // Use with house:getAccessList, house:setAccessList - registerEnum(GUEST_LIST) - registerEnum(SUBOWNER_LIST) - - // Use with npc:setSpeechBubble - registerEnum(SPEECHBUBBLE_NONE) - registerEnum(SPEECHBUBBLE_NORMAL) - registerEnum(SPEECHBUBBLE_TRADE) - registerEnum(SPEECHBUBBLE_QUEST) - registerEnum(SPEECHBUBBLE_QUESTTRADER) - - // Use with player:addMapMark - registerEnum(MAPMARK_TICK) - registerEnum(MAPMARK_QUESTION) - registerEnum(MAPMARK_EXCLAMATION) - registerEnum(MAPMARK_STAR) - registerEnum(MAPMARK_CROSS) - registerEnum(MAPMARK_TEMPLE) - registerEnum(MAPMARK_KISS) - registerEnum(MAPMARK_SHOVEL) - registerEnum(MAPMARK_SWORD) - registerEnum(MAPMARK_FLAG) - registerEnum(MAPMARK_LOCK) - registerEnum(MAPMARK_BAG) - registerEnum(MAPMARK_SKULL) - registerEnum(MAPMARK_DOLLAR) - registerEnum(MAPMARK_REDNORTH) - registerEnum(MAPMARK_REDSOUTH) - registerEnum(MAPMARK_REDEAST) - registerEnum(MAPMARK_REDWEST) - registerEnum(MAPMARK_GREENNORTH) - registerEnum(MAPMARK_GREENSOUTH) - - // Use with Game.getReturnMessage - registerEnum(RETURNVALUE_NOERROR) - registerEnum(RETURNVALUE_NOTPOSSIBLE) - registerEnum(RETURNVALUE_NOTENOUGHROOM) - registerEnum(RETURNVALUE_PLAYERISPZLOCKED) - registerEnum(RETURNVALUE_PLAYERISNOTINVITED) - registerEnum(RETURNVALUE_CANNOTTHROW) - registerEnum(RETURNVALUE_THEREISNOWAY) - registerEnum(RETURNVALUE_DESTINATIONOUTOFREACH) - registerEnum(RETURNVALUE_CREATUREBLOCK) - registerEnum(RETURNVALUE_NOTMOVEABLE) - registerEnum(RETURNVALUE_DROPTWOHANDEDITEM) - registerEnum(RETURNVALUE_BOTHHANDSNEEDTOBEFREE) - registerEnum(RETURNVALUE_CANONLYUSEONEWEAPON) - registerEnum(RETURNVALUE_NEEDEXCHANGE) - registerEnum(RETURNVALUE_CANNOTBEDRESSED) - registerEnum(RETURNVALUE_PUTTHISOBJECTINYOURHAND) - registerEnum(RETURNVALUE_PUTTHISOBJECTINBOTHHANDS) - registerEnum(RETURNVALUE_TOOFARAWAY) - registerEnum(RETURNVALUE_FIRSTGODOWNSTAIRS) - registerEnum(RETURNVALUE_FIRSTGOUPSTAIRS) - registerEnum(RETURNVALUE_CONTAINERNOTENOUGHROOM) - registerEnum(RETURNVALUE_NOTENOUGHCAPACITY) - registerEnum(RETURNVALUE_CANNOTPICKUP) - registerEnum(RETURNVALUE_THISISIMPOSSIBLE) - registerEnum(RETURNVALUE_DEPOTISFULL) - registerEnum(RETURNVALUE_CREATUREDOESNOTEXIST) - registerEnum(RETURNVALUE_CANNOTUSETHISOBJECT) - registerEnum(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE) - registerEnum(RETURNVALUE_NOTREQUIREDLEVELTOUSERUNE) - registerEnum(RETURNVALUE_YOUAREALREADYTRADING) - registerEnum(RETURNVALUE_THISPLAYERISALREADYTRADING) - registerEnum(RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT) - registerEnum(RETURNVALUE_DIRECTPLAYERSHOOT) - registerEnum(RETURNVALUE_NOTENOUGHLEVEL) - registerEnum(RETURNVALUE_NOTENOUGHMAGICLEVEL) - registerEnum(RETURNVALUE_NOTENOUGHMANA) - registerEnum(RETURNVALUE_NOTENOUGHSOUL) - registerEnum(RETURNVALUE_YOUAREEXHAUSTED) - registerEnum(RETURNVALUE_PLAYERISNOTREACHABLE) - registerEnum(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES) - registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE) - registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER) - registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE) - registerEnum(RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE) - registerEnum(RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE) - registerEnum(RETURNVALUE_YOUCANONLYUSEITONCREATURES) - registerEnum(RETURNVALUE_CREATUREISNOTREACHABLE) - registerEnum(RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS) - registerEnum(RETURNVALUE_YOUNEEDPREMIUMACCOUNT) - registerEnum(RETURNVALUE_YOUNEEDTOLEARNTHISSPELL) - registerEnum(RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL) - registerEnum(RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL) - registerEnum(RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE) - registerEnum(RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE) - registerEnum(RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE) - registerEnum(RETURNVALUE_YOUCANNOTLOGOUTHERE) - registerEnum(RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL) - registerEnum(RETURNVALUE_CANNOTCONJUREITEMHERE) - registerEnum(RETURNVALUE_YOUNEEDTOSPLITYOURSPEARS) - registerEnum(RETURNVALUE_NAMEISTOOAMBIGIOUS) - registerEnum(RETURNVALUE_CANONLYUSEONESHIELD) - registerEnum(RETURNVALUE_NOPARTYMEMBERSINRANGE) - registerEnum(RETURNVALUE_YOUARENOTTHEOWNER) - - // _G - registerGlobalVariable("INDEX_WHEREEVER", INDEX_WHEREEVER); - registerGlobalBoolean("VIRTUAL_PARENT", true); - - registerGlobalMethod("isType", LuaScriptInterface::luaIsType); - registerGlobalMethod("rawgetmetatable", LuaScriptInterface::luaRawGetMetatable); - - // configKeys - registerTable("configKeys"); - - registerEnumIn("configKeys", ConfigManager::ALLOW_CHANGEOUTFIT) - registerEnumIn("configKeys", ConfigManager::ONE_PLAYER_ON_ACCOUNT) - registerEnumIn("configKeys", ConfigManager::AIMBOT_HOTKEY_ENABLED) - registerEnumIn("configKeys", ConfigManager::REMOVE_RUNE_CHARGES) - registerEnumIn("configKeys", ConfigManager::EXPERIENCE_FROM_PLAYERS) - registerEnumIn("configKeys", ConfigManager::FREE_PREMIUM) - registerEnumIn("configKeys", ConfigManager::REPLACE_KICK_ON_LOGIN) - registerEnumIn("configKeys", ConfigManager::ALLOW_CLONES) - registerEnumIn("configKeys", ConfigManager::BIND_ONLY_GLOBAL_ADDRESS) - registerEnumIn("configKeys", ConfigManager::OPTIMIZE_DATABASE) - registerEnumIn("configKeys", ConfigManager::MARKET_PREMIUM) - registerEnumIn("configKeys", ConfigManager::EMOTE_SPELLS) - registerEnumIn("configKeys", ConfigManager::STAMINA_SYSTEM) - registerEnumIn("configKeys", ConfigManager::WARN_UNSAFE_SCRIPTS) - registerEnumIn("configKeys", ConfigManager::CONVERT_UNSAFE_SCRIPTS) - registerEnumIn("configKeys", ConfigManager::CLASSIC_EQUIPMENT_SLOTS) - registerEnumIn("configKeys", ConfigManager::ALLOW_WALKTHROUGH) - - registerEnumIn("configKeys", ConfigManager::MAP_NAME) - registerEnumIn("configKeys", ConfigManager::HOUSE_RENT_PERIOD) - registerEnumIn("configKeys", ConfigManager::SERVER_NAME) - registerEnumIn("configKeys", ConfigManager::OWNER_NAME) - registerEnumIn("configKeys", ConfigManager::OWNER_EMAIL) - registerEnumIn("configKeys", ConfigManager::URL) - registerEnumIn("configKeys", ConfigManager::LOCATION) - registerEnumIn("configKeys", ConfigManager::IP) - registerEnumIn("configKeys", ConfigManager::MOTD) - registerEnumIn("configKeys", ConfigManager::WORLD_TYPE) - registerEnumIn("configKeys", ConfigManager::MYSQL_HOST) - registerEnumIn("configKeys", ConfigManager::MYSQL_USER) - registerEnumIn("configKeys", ConfigManager::MYSQL_PASS) - registerEnumIn("configKeys", ConfigManager::MYSQL_DB) - registerEnumIn("configKeys", ConfigManager::MYSQL_SOCK) - registerEnumIn("configKeys", ConfigManager::DEFAULT_PRIORITY) - registerEnumIn("configKeys", ConfigManager::MAP_AUTHOR) - - registerEnumIn("configKeys", ConfigManager::SQL_PORT) - registerEnumIn("configKeys", ConfigManager::MAX_PLAYERS) - registerEnumIn("configKeys", ConfigManager::PZ_LOCKED) - registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRANGE) - registerEnumIn("configKeys", ConfigManager::DEFAULT_DESPAWNRADIUS) - registerEnumIn("configKeys", ConfigManager::RATE_EXPERIENCE) - registerEnumIn("configKeys", ConfigManager::RATE_SKILL) - registerEnumIn("configKeys", ConfigManager::RATE_LOOT) - registerEnumIn("configKeys", ConfigManager::RATE_MAGIC) - registerEnumIn("configKeys", ConfigManager::RATE_SPAWN) - registerEnumIn("configKeys", ConfigManager::HOUSE_PRICE) - registerEnumIn("configKeys", ConfigManager::KILLS_TO_RED) - registerEnumIn("configKeys", ConfigManager::KILLS_TO_BLACK) - registerEnumIn("configKeys", ConfigManager::MAX_MESSAGEBUFFER) - registerEnumIn("configKeys", ConfigManager::ACTIONS_DELAY_INTERVAL) - registerEnumIn("configKeys", ConfigManager::EX_ACTIONS_DELAY_INTERVAL) - registerEnumIn("configKeys", ConfigManager::KICK_AFTER_MINUTES) - registerEnumIn("configKeys", ConfigManager::PROTECTION_LEVEL) - registerEnumIn("configKeys", ConfigManager::DEATH_LOSE_PERCENT) - registerEnumIn("configKeys", ConfigManager::STATUSQUERY_TIMEOUT) - registerEnumIn("configKeys", ConfigManager::FRAG_TIME) - registerEnumIn("configKeys", ConfigManager::WHITE_SKULL_TIME) - registerEnumIn("configKeys", ConfigManager::GAME_PORT) - registerEnumIn("configKeys", ConfigManager::LOGIN_PORT) - registerEnumIn("configKeys", ConfigManager::STATUS_PORT) - registerEnumIn("configKeys", ConfigManager::STAIRHOP_DELAY) - registerEnumIn("configKeys", ConfigManager::MARKET_OFFER_DURATION) - registerEnumIn("configKeys", ConfigManager::CHECK_EXPIRED_MARKET_OFFERS_EACH_MINUTES) - registerEnumIn("configKeys", ConfigManager::MAX_MARKET_OFFERS_AT_A_TIME_PER_PLAYER) - registerEnumIn("configKeys", ConfigManager::EXP_FROM_PLAYERS_LEVEL_RANGE) - registerEnumIn("configKeys", ConfigManager::MAX_PACKETS_PER_SECOND) - registerEnumIn("configKeys", ConfigManager::CRITICAL_HIT_CHANCE) - registerEnumIn("configKeys", ConfigManager::CRITICAL_HIT_EXTRA) - - // os - registerMethod("os", "mtime", LuaScriptInterface::luaSystemTime); - - // table - registerMethod("table", "create", LuaScriptInterface::luaTableCreate); - - // Game - registerTable("Game"); - - registerMethod("Game", "getSpectators", LuaScriptInterface::luaGameGetSpectators); - registerMethod("Game", "getPlayers", LuaScriptInterface::luaGameGetPlayers); - registerMethod("Game", "loadMap", LuaScriptInterface::luaGameLoadMap); - - registerMethod("Game", "getExperienceStage", LuaScriptInterface::luaGameGetExperienceStage); - registerMethod("Game", "getMonsterCount", LuaScriptInterface::luaGameGetMonsterCount); - registerMethod("Game", "getPlayerCount", LuaScriptInterface::luaGameGetPlayerCount); - registerMethod("Game", "getNpcCount", LuaScriptInterface::luaGameGetNpcCount); - - registerMethod("Game", "getTowns", LuaScriptInterface::luaGameGetTowns); - registerMethod("Game", "getHouses", LuaScriptInterface::luaGameGetHouses); - - registerMethod("Game", "getGameState", LuaScriptInterface::luaGameGetGameState); - registerMethod("Game", "setGameState", LuaScriptInterface::luaGameSetGameState); - - registerMethod("Game", "getWorldType", LuaScriptInterface::luaGameGetWorldType); - registerMethod("Game", "setWorldType", LuaScriptInterface::luaGameSetWorldType); - - registerMethod("Game", "getReturnMessage", LuaScriptInterface::luaGameGetReturnMessage); - - registerMethod("Game", "createItem", LuaScriptInterface::luaGameCreateItem); - registerMethod("Game", "createContainer", LuaScriptInterface::luaGameCreateContainer); - registerMethod("Game", "createMonster", LuaScriptInterface::luaGameCreateMonster); - registerMethod("Game", "createNpc", LuaScriptInterface::luaGameCreateNpc); - registerMethod("Game", "createTile", LuaScriptInterface::luaGameCreateTile); - - registerMethod("Game", "startRaid", LuaScriptInterface::luaGameStartRaid); - - registerMethod("Game", "hasDistanceEffect", LuaScriptInterface::luaGameHasDistanceEffect); - registerMethod("Game", "hasEffect", LuaScriptInterface::luaGameHasEffect); - - // Variant - registerClass("Variant", "", LuaScriptInterface::luaVariantCreate); - - registerMethod("Variant", "getNumber", LuaScriptInterface::luaVariantGetNumber); - registerMethod("Variant", "getString", LuaScriptInterface::luaVariantGetString); - registerMethod("Variant", "getPosition", LuaScriptInterface::luaVariantGetPosition); - - // Position - registerClass("Position", "", LuaScriptInterface::luaPositionCreate); - registerMetaMethod("Position", "__add", LuaScriptInterface::luaPositionAdd); - registerMetaMethod("Position", "__sub", LuaScriptInterface::luaPositionSub); - registerMetaMethod("Position", "__eq", LuaScriptInterface::luaPositionCompare); - - registerMethod("Position", "getDistance", LuaScriptInterface::luaPositionGetDistance); - registerMethod("Position", "isSightClear", LuaScriptInterface::luaPositionIsSightClear); - - registerMethod("Position", "sendMagicEffect", LuaScriptInterface::luaPositionSendMagicEffect); - registerMethod("Position", "sendDistanceEffect", LuaScriptInterface::luaPositionSendDistanceEffect); - - // Tile - registerClass("Tile", "", LuaScriptInterface::luaTileCreate); - registerMetaMethod("Tile", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Tile", "getPosition", LuaScriptInterface::luaTileGetPosition); - registerMethod("Tile", "getGround", LuaScriptInterface::luaTileGetGround); - registerMethod("Tile", "getThing", LuaScriptInterface::luaTileGetThing); - registerMethod("Tile", "getThingCount", LuaScriptInterface::luaTileGetThingCount); - registerMethod("Tile", "getTopVisibleThing", LuaScriptInterface::luaTileGetTopVisibleThing); - - registerMethod("Tile", "getTopTopItem", LuaScriptInterface::luaTileGetTopTopItem); - registerMethod("Tile", "getTopDownItem", LuaScriptInterface::luaTileGetTopDownItem); - registerMethod("Tile", "getFieldItem", LuaScriptInterface::luaTileGetFieldItem); - - registerMethod("Tile", "getItemById", LuaScriptInterface::luaTileGetItemById); - registerMethod("Tile", "getItemByType", LuaScriptInterface::luaTileGetItemByType); - registerMethod("Tile", "getItemByTopOrder", LuaScriptInterface::luaTileGetItemByTopOrder); - registerMethod("Tile", "getItemCountById", LuaScriptInterface::luaTileGetItemCountById); - - registerMethod("Tile", "getBottomCreature", LuaScriptInterface::luaTileGetBottomCreature); - registerMethod("Tile", "getTopCreature", LuaScriptInterface::luaTileGetTopCreature); - registerMethod("Tile", "getBottomVisibleCreature", LuaScriptInterface::luaTileGetBottomVisibleCreature); - registerMethod("Tile", "getTopVisibleCreature", LuaScriptInterface::luaTileGetTopVisibleCreature); - - registerMethod("Tile", "getItems", LuaScriptInterface::luaTileGetItems); - registerMethod("Tile", "getItemCount", LuaScriptInterface::luaTileGetItemCount); - registerMethod("Tile", "getDownItemCount", LuaScriptInterface::luaTileGetDownItemCount); - registerMethod("Tile", "getTopItemCount", LuaScriptInterface::luaTileGetTopItemCount); - - registerMethod("Tile", "getCreatures", LuaScriptInterface::luaTileGetCreatures); - registerMethod("Tile", "getCreatureCount", LuaScriptInterface::luaTileGetCreatureCount); - - registerMethod("Tile", "getThingIndex", LuaScriptInterface::luaTileGetThingIndex); - - registerMethod("Tile", "hasProperty", LuaScriptInterface::luaTileHasProperty); - registerMethod("Tile", "hasFlag", LuaScriptInterface::luaTileHasFlag); - - registerMethod("Tile", "queryAdd", LuaScriptInterface::luaTileQueryAdd); - - registerMethod("Tile", "getHouse", LuaScriptInterface::luaTileGetHouse); - - // NetworkMessage - registerClass("NetworkMessage", "", LuaScriptInterface::luaNetworkMessageCreate); - registerMetaMethod("NetworkMessage", "__eq", LuaScriptInterface::luaUserdataCompare); - registerMetaMethod("NetworkMessage", "__gc", LuaScriptInterface::luaNetworkMessageDelete); - registerMethod("NetworkMessage", "delete", LuaScriptInterface::luaNetworkMessageDelete); - - registerMethod("NetworkMessage", "getByte", LuaScriptInterface::luaNetworkMessageGetByte); - registerMethod("NetworkMessage", "getU16", LuaScriptInterface::luaNetworkMessageGetU16); - registerMethod("NetworkMessage", "getU32", LuaScriptInterface::luaNetworkMessageGetU32); - registerMethod("NetworkMessage", "getU64", LuaScriptInterface::luaNetworkMessageGetU64); - registerMethod("NetworkMessage", "getString", LuaScriptInterface::luaNetworkMessageGetString); - registerMethod("NetworkMessage", "getPosition", LuaScriptInterface::luaNetworkMessageGetPosition); - - registerMethod("NetworkMessage", "addByte", LuaScriptInterface::luaNetworkMessageAddByte); - registerMethod("NetworkMessage", "addU16", LuaScriptInterface::luaNetworkMessageAddU16); - registerMethod("NetworkMessage", "addU32", LuaScriptInterface::luaNetworkMessageAddU32); - registerMethod("NetworkMessage", "addU64", LuaScriptInterface::luaNetworkMessageAddU64); - registerMethod("NetworkMessage", "addString", LuaScriptInterface::luaNetworkMessageAddString); - registerMethod("NetworkMessage", "addPosition", LuaScriptInterface::luaNetworkMessageAddPosition); - registerMethod("NetworkMessage", "addDouble", LuaScriptInterface::luaNetworkMessageAddDouble); - registerMethod("NetworkMessage", "addItem", LuaScriptInterface::luaNetworkMessageAddItem); - registerMethod("NetworkMessage", "addItemId", LuaScriptInterface::luaNetworkMessageAddItemId); - - registerMethod("NetworkMessage", "reset", LuaScriptInterface::luaNetworkMessageReset); - registerMethod("NetworkMessage", "skipBytes", LuaScriptInterface::luaNetworkMessageSkipBytes); - registerMethod("NetworkMessage", "sendToPlayer", LuaScriptInterface::luaNetworkMessageSendToPlayer); - - // ModalWindow - registerClass("ModalWindow", "", LuaScriptInterface::luaModalWindowCreate); - registerMetaMethod("ModalWindow", "__eq", LuaScriptInterface::luaUserdataCompare); - registerMetaMethod("ModalWindow", "__gc", LuaScriptInterface::luaModalWindowDelete); - registerMethod("ModalWindow", "delete", LuaScriptInterface::luaModalWindowDelete); - - registerMethod("ModalWindow", "getId", LuaScriptInterface::luaModalWindowGetId); - registerMethod("ModalWindow", "getTitle", LuaScriptInterface::luaModalWindowGetTitle); - registerMethod("ModalWindow", "getMessage", LuaScriptInterface::luaModalWindowGetMessage); - - registerMethod("ModalWindow", "setTitle", LuaScriptInterface::luaModalWindowSetTitle); - registerMethod("ModalWindow", "setMessage", LuaScriptInterface::luaModalWindowSetMessage); - - registerMethod("ModalWindow", "getButtonCount", LuaScriptInterface::luaModalWindowGetButtonCount); - registerMethod("ModalWindow", "getChoiceCount", LuaScriptInterface::luaModalWindowGetChoiceCount); - - registerMethod("ModalWindow", "addButton", LuaScriptInterface::luaModalWindowAddButton); - registerMethod("ModalWindow", "addChoice", LuaScriptInterface::luaModalWindowAddChoice); - - registerMethod("ModalWindow", "getDefaultEnterButton", LuaScriptInterface::luaModalWindowGetDefaultEnterButton); - registerMethod("ModalWindow", "setDefaultEnterButton", LuaScriptInterface::luaModalWindowSetDefaultEnterButton); - - registerMethod("ModalWindow", "getDefaultEscapeButton", LuaScriptInterface::luaModalWindowGetDefaultEscapeButton); - registerMethod("ModalWindow", "setDefaultEscapeButton", LuaScriptInterface::luaModalWindowSetDefaultEscapeButton); - - registerMethod("ModalWindow", "hasPriority", LuaScriptInterface::luaModalWindowHasPriority); - registerMethod("ModalWindow", "setPriority", LuaScriptInterface::luaModalWindowSetPriority); - - registerMethod("ModalWindow", "sendToPlayer", LuaScriptInterface::luaModalWindowSendToPlayer); - - // Item - registerClass("Item", "", LuaScriptInterface::luaItemCreate); - registerMetaMethod("Item", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Item", "isItem", LuaScriptInterface::luaItemIsItem); - - registerMethod("Item", "getParent", LuaScriptInterface::luaItemGetParent); - registerMethod("Item", "getTopParent", LuaScriptInterface::luaItemGetTopParent); - - registerMethod("Item", "getId", LuaScriptInterface::luaItemGetId); - - registerMethod("Item", "clone", LuaScriptInterface::luaItemClone); - registerMethod("Item", "split", LuaScriptInterface::luaItemSplit); - registerMethod("Item", "remove", LuaScriptInterface::luaItemRemove); - - registerMethod("Item", "getUniqueId", LuaScriptInterface::luaItemGetUniqueId); - registerMethod("Item", "getActionId", LuaScriptInterface::luaItemGetActionId); - registerMethod("Item", "setActionId", LuaScriptInterface::luaItemSetActionId); - - registerMethod("Item", "getCount", LuaScriptInterface::luaItemGetCount); - registerMethod("Item", "getCharges", LuaScriptInterface::luaItemGetCharges); - registerMethod("Item", "getFluidType", LuaScriptInterface::luaItemGetFluidType); - registerMethod("Item", "getWeight", LuaScriptInterface::luaItemGetWeight); - - registerMethod("Item", "getSubType", LuaScriptInterface::luaItemGetSubType); - - registerMethod("Item", "getName", LuaScriptInterface::luaItemGetName); - registerMethod("Item", "getPluralName", LuaScriptInterface::luaItemGetPluralName); - registerMethod("Item", "getArticle", LuaScriptInterface::luaItemGetArticle); - - registerMethod("Item", "getPosition", LuaScriptInterface::luaItemGetPosition); - registerMethod("Item", "getTile", LuaScriptInterface::luaItemGetTile); - - registerMethod("Item", "hasAttribute", LuaScriptInterface::luaItemHasAttribute); - registerMethod("Item", "getAttribute", LuaScriptInterface::luaItemGetAttribute); - registerMethod("Item", "setAttribute", LuaScriptInterface::luaItemSetAttribute); - registerMethod("Item", "removeAttribute", LuaScriptInterface::luaItemRemoveAttribute); - registerMethod("Item", "serializeAttributes", LuaScriptInterface::luaItemSerializeAttributes); - - registerMethod("Item", "moveTo", LuaScriptInterface::luaItemMoveTo); - registerMethod("Item", "transform", LuaScriptInterface::luaItemTransform); - registerMethod("Item", "decay", LuaScriptInterface::luaItemDecay); - - registerMethod("Item", "getDescription", LuaScriptInterface::luaItemGetDescription); - - registerMethod("Item", "hasProperty", LuaScriptInterface::luaItemHasProperty); - - // Container - registerClass("Container", "Item", LuaScriptInterface::luaContainerCreate); - registerMetaMethod("Container", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Container", "getSize", LuaScriptInterface::luaContainerGetSize); - registerMethod("Container", "getCapacity", LuaScriptInterface::luaContainerGetCapacity); - registerMethod("Container", "getEmptySlots", LuaScriptInterface::luaContainerGetEmptySlots); - - registerMethod("Container", "getItemHoldingCount", LuaScriptInterface::luaContainerGetItemHoldingCount); - registerMethod("Container", "getItemCountById", LuaScriptInterface::luaContainerGetItemCountById); - - registerMethod("Container", "getItem", LuaScriptInterface::luaContainerGetItem); - registerMethod("Container", "hasItem", LuaScriptInterface::luaContainerHasItem); - registerMethod("Container", "addItem", LuaScriptInterface::luaContainerAddItem); - registerMethod("Container", "addItemEx", LuaScriptInterface::luaContainerAddItemEx); - - // Teleport - registerClass("Teleport", "Item", LuaScriptInterface::luaTeleportCreate); - registerMetaMethod("Teleport", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Teleport", "getDestination", LuaScriptInterface::luaTeleportGetDestination); - registerMethod("Teleport", "setDestination", LuaScriptInterface::luaTeleportSetDestination); - - // Creature - registerClass("Creature", "", LuaScriptInterface::luaCreatureCreate); - registerMetaMethod("Creature", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Creature", "registerEvent", LuaScriptInterface::luaCreatureRegisterEvent); - registerMethod("Creature", "unregisterEvent", LuaScriptInterface::luaCreatureUnregisterEvent); - - registerMethod("Creature", "isRemoved", LuaScriptInterface::luaCreatureIsRemoved); - registerMethod("Creature", "isCreature", LuaScriptInterface::luaCreatureIsCreature); - registerMethod("Creature", "isInGhostMode", LuaScriptInterface::luaCreatureIsInGhostMode); - registerMethod("Creature", "isHealthHidden", LuaScriptInterface::luaCreatureIsHealthHidden); - - registerMethod("Creature", "canSee", LuaScriptInterface::luaCreatureCanSee); - registerMethod("Creature", "canSeeCreature", LuaScriptInterface::luaCreatureCanSeeCreature); - - registerMethod("Creature", "getParent", LuaScriptInterface::luaCreatureGetParent); - - registerMethod("Creature", "getId", LuaScriptInterface::luaCreatureGetId); - registerMethod("Creature", "getName", LuaScriptInterface::luaCreatureGetName); - - registerMethod("Creature", "getTarget", LuaScriptInterface::luaCreatureGetTarget); - registerMethod("Creature", "setTarget", LuaScriptInterface::luaCreatureSetTarget); - - registerMethod("Creature", "getFollowCreature", LuaScriptInterface::luaCreatureGetFollowCreature); - registerMethod("Creature", "setFollowCreature", LuaScriptInterface::luaCreatureSetFollowCreature); - - registerMethod("Creature", "getMaster", LuaScriptInterface::luaCreatureGetMaster); - registerMethod("Creature", "setMaster", LuaScriptInterface::luaCreatureSetMaster); - - registerMethod("Creature", "getLight", LuaScriptInterface::luaCreatureGetLight); - registerMethod("Creature", "setLight", LuaScriptInterface::luaCreatureSetLight); - - registerMethod("Creature", "getSpeed", LuaScriptInterface::luaCreatureGetSpeed); - registerMethod("Creature", "getBaseSpeed", LuaScriptInterface::luaCreatureGetBaseSpeed); - registerMethod("Creature", "changeSpeed", LuaScriptInterface::luaCreatureChangeSpeed); - - registerMethod("Creature", "setDropLoot", LuaScriptInterface::luaCreatureSetDropLoot); - - registerMethod("Creature", "getPosition", LuaScriptInterface::luaCreatureGetPosition); - registerMethod("Creature", "getTile", LuaScriptInterface::luaCreatureGetTile); - registerMethod("Creature", "getDirection", LuaScriptInterface::luaCreatureGetDirection); - registerMethod("Creature", "setDirection", LuaScriptInterface::luaCreatureSetDirection); - - registerMethod("Creature", "getHealth", LuaScriptInterface::luaCreatureGetHealth); - registerMethod("Creature", "addHealth", LuaScriptInterface::luaCreatureAddHealth); - registerMethod("Creature", "getMaxHealth", LuaScriptInterface::luaCreatureGetMaxHealth); - registerMethod("Creature", "setMaxHealth", LuaScriptInterface::luaCreatureSetMaxHealth); - registerMethod("Creature", "setHiddenHealth", LuaScriptInterface::luaCreatureSetHiddenHealth); - - registerMethod("Creature", "getMana", LuaScriptInterface::luaCreatureGetMana); - registerMethod("Creature", "addMana", LuaScriptInterface::luaCreatureAddMana); - registerMethod("Creature", "getMaxMana", LuaScriptInterface::luaCreatureGetMaxMana); - - registerMethod("Creature", "getSkull", LuaScriptInterface::luaCreatureGetSkull); - registerMethod("Creature", "setSkull", LuaScriptInterface::luaCreatureSetSkull); - - registerMethod("Creature", "getOutfit", LuaScriptInterface::luaCreatureGetOutfit); - registerMethod("Creature", "setOutfit", LuaScriptInterface::luaCreatureSetOutfit); - - registerMethod("Creature", "getCondition", LuaScriptInterface::luaCreatureGetCondition); - registerMethod("Creature", "addCondition", LuaScriptInterface::luaCreatureAddCondition); - registerMethod("Creature", "removeCondition", LuaScriptInterface::luaCreatureRemoveCondition); - - registerMethod("Creature", "remove", LuaScriptInterface::luaCreatureRemove); - registerMethod("Creature", "teleportTo", LuaScriptInterface::luaCreatureTeleportTo); - registerMethod("Creature", "say", LuaScriptInterface::luaCreatureSay); - - registerMethod("Creature", "getDamageMap", LuaScriptInterface::luaCreatureGetDamageMap); - - registerMethod("Creature", "getSummons", LuaScriptInterface::luaCreatureGetSummons); - - registerMethod("Creature", "getDescription", LuaScriptInterface::luaCreatureGetDescription); - - registerMethod("Creature", "getPathTo", LuaScriptInterface::luaCreatureGetPathTo); - - // Player - registerClass("Player", "Creature", LuaScriptInterface::luaPlayerCreate); - registerMetaMethod("Player", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Player", "isPlayer", LuaScriptInterface::luaPlayerIsPlayer); - - registerMethod("Player", "getGuid", LuaScriptInterface::luaPlayerGetGuid); - registerMethod("Player", "getIp", LuaScriptInterface::luaPlayerGetIp); - registerMethod("Player", "getAccountId", LuaScriptInterface::luaPlayerGetAccountId); - registerMethod("Player", "getLastLoginSaved", LuaScriptInterface::luaPlayerGetLastLoginSaved); - registerMethod("Player", "getLastLogout", LuaScriptInterface::luaPlayerGetLastLogout); - - registerMethod("Player", "getAccountType", LuaScriptInterface::luaPlayerGetAccountType); - registerMethod("Player", "setAccountType", LuaScriptInterface::luaPlayerSetAccountType); - - registerMethod("Player", "getCapacity", LuaScriptInterface::luaPlayerGetCapacity); - registerMethod("Player", "setCapacity", LuaScriptInterface::luaPlayerSetCapacity); - - registerMethod("Player", "getFreeCapacity", LuaScriptInterface::luaPlayerGetFreeCapacity); - - registerMethod("Player", "getDepotChest", LuaScriptInterface::luaPlayerGetDepotChest); - registerMethod("Player", "getInbox", LuaScriptInterface::luaPlayerGetInbox); - - registerMethod("Player", "getSkullTime", LuaScriptInterface::luaPlayerGetSkullTime); - registerMethod("Player", "setSkullTime", LuaScriptInterface::luaPlayerSetSkullTime); - registerMethod("Player", "getDeathPenalty", LuaScriptInterface::luaPlayerGetDeathPenalty); - - registerMethod("Player", "getExperience", LuaScriptInterface::luaPlayerGetExperience); - registerMethod("Player", "addExperience", LuaScriptInterface::luaPlayerAddExperience); - registerMethod("Player", "removeExperience", LuaScriptInterface::luaPlayerRemoveExperience); - registerMethod("Player", "getLevel", LuaScriptInterface::luaPlayerGetLevel); - - registerMethod("Player", "getMagicLevel", LuaScriptInterface::luaPlayerGetMagicLevel); - registerMethod("Player", "getBaseMagicLevel", LuaScriptInterface::luaPlayerGetBaseMagicLevel); - registerMethod("Player", "setMaxMana", LuaScriptInterface::luaPlayerSetMaxMana); - registerMethod("Player", "getManaSpent", LuaScriptInterface::luaPlayerGetManaSpent); - registerMethod("Player", "addManaSpent", LuaScriptInterface::luaPlayerAddManaSpent); - - registerMethod("Player", "getSkillLevel", LuaScriptInterface::luaPlayerGetSkillLevel); - registerMethod("Player", "getEffectiveSkillLevel", LuaScriptInterface::luaPlayerGetEffectiveSkillLevel); - registerMethod("Player", "getSkillPercent", LuaScriptInterface::luaPlayerGetSkillPercent); - registerMethod("Player", "getSkillTries", LuaScriptInterface::luaPlayerGetSkillTries); - registerMethod("Player", "addSkillTries", LuaScriptInterface::luaPlayerAddSkillTries); - - registerMethod("Player", "addOfflineTrainingTime", LuaScriptInterface::luaPlayerAddOfflineTrainingTime); - registerMethod("Player", "getOfflineTrainingTime", LuaScriptInterface::luaPlayerGetOfflineTrainingTime); - registerMethod("Player", "removeOfflineTrainingTime", LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime); - - registerMethod("Player", "addOfflineTrainingTries", LuaScriptInterface::luaPlayerAddOfflineTrainingTries); - - registerMethod("Player", "getOfflineTrainingSkill", LuaScriptInterface::luaPlayerGetOfflineTrainingSkill); - registerMethod("Player", "setOfflineTrainingSkill", LuaScriptInterface::luaPlayerSetOfflineTrainingSkill); - - registerMethod("Player", "getItemCount", LuaScriptInterface::luaPlayerGetItemCount); - registerMethod("Player", "getItemById", LuaScriptInterface::luaPlayerGetItemById); - - registerMethod("Player", "getVocation", LuaScriptInterface::luaPlayerGetVocation); - registerMethod("Player", "setVocation", LuaScriptInterface::luaPlayerSetVocation); - - registerMethod("Player", "getSex", LuaScriptInterface::luaPlayerGetSex); - registerMethod("Player", "setSex", LuaScriptInterface::luaPlayerSetSex); - - registerMethod("Player", "getTown", LuaScriptInterface::luaPlayerGetTown); - registerMethod("Player", "setTown", LuaScriptInterface::luaPlayerSetTown); - - registerMethod("Player", "getGuild", LuaScriptInterface::luaPlayerGetGuild); - registerMethod("Player", "setGuild", LuaScriptInterface::luaPlayerSetGuild); - - registerMethod("Player", "getGuildLevel", LuaScriptInterface::luaPlayerGetGuildLevel); - registerMethod("Player", "setGuildLevel", LuaScriptInterface::luaPlayerSetGuildLevel); - - registerMethod("Player", "getGuildNick", LuaScriptInterface::luaPlayerGetGuildNick); - registerMethod("Player", "setGuildNick", LuaScriptInterface::luaPlayerSetGuildNick); - - registerMethod("Player", "getGroup", LuaScriptInterface::luaPlayerGetGroup); - registerMethod("Player", "setGroup", LuaScriptInterface::luaPlayerSetGroup); - - registerMethod("Player", "getStamina", LuaScriptInterface::luaPlayerGetStamina); - registerMethod("Player", "setStamina", LuaScriptInterface::luaPlayerSetStamina); - - registerMethod("Player", "getSoul", LuaScriptInterface::luaPlayerGetSoul); - registerMethod("Player", "addSoul", LuaScriptInterface::luaPlayerAddSoul); - registerMethod("Player", "getMaxSoul", LuaScriptInterface::luaPlayerGetMaxSoul); - - registerMethod("Player", "getBankBalance", LuaScriptInterface::luaPlayerGetBankBalance); - registerMethod("Player", "setBankBalance", LuaScriptInterface::luaPlayerSetBankBalance); - - registerMethod("Player", "getStorageValue", LuaScriptInterface::luaPlayerGetStorageValue); - registerMethod("Player", "setStorageValue", LuaScriptInterface::luaPlayerSetStorageValue); - - registerMethod("Player", "addItem", LuaScriptInterface::luaPlayerAddItem); - registerMethod("Player", "addItemEx", LuaScriptInterface::luaPlayerAddItemEx); - registerMethod("Player", "removeItem", LuaScriptInterface::luaPlayerRemoveItem); - - registerMethod("Player", "getMoney", LuaScriptInterface::luaPlayerGetMoney); - registerMethod("Player", "addMoney", LuaScriptInterface::luaPlayerAddMoney); - registerMethod("Player", "removeMoney", LuaScriptInterface::luaPlayerRemoveMoney); - - registerMethod("Player", "showTextDialog", LuaScriptInterface::luaPlayerShowTextDialog); - - registerMethod("Player", "sendTextMessage", LuaScriptInterface::luaPlayerSendTextMessage); - registerMethod("Player", "sendChannelMessage", LuaScriptInterface::luaPlayerSendChannelMessage); - registerMethod("Player", "sendPrivateMessage", LuaScriptInterface::luaPlayerSendPrivateMessage); - registerMethod("Player", "channelSay", LuaScriptInterface::luaPlayerChannelSay); - registerMethod("Player", "openChannel", LuaScriptInterface::luaPlayerOpenChannel); - - registerMethod("Player", "getSlotItem", LuaScriptInterface::luaPlayerGetSlotItem); - - registerMethod("Player", "getParty", LuaScriptInterface::luaPlayerGetParty); - - registerMethod("Player", "addOutfit", LuaScriptInterface::luaPlayerAddOutfit); - registerMethod("Player", "addOutfitAddon", LuaScriptInterface::luaPlayerAddOutfitAddon); - registerMethod("Player", "removeOutfit", LuaScriptInterface::luaPlayerRemoveOutfit); - registerMethod("Player", "removeOutfitAddon", LuaScriptInterface::luaPlayerRemoveOutfitAddon); - registerMethod("Player", "hasOutfit", LuaScriptInterface::luaPlayerHasOutfit); - registerMethod("Player", "sendOutfitWindow", LuaScriptInterface::luaPlayerSendOutfitWindow); - - registerMethod("Player", "addMount", LuaScriptInterface::luaPlayerAddMount); - registerMethod("Player", "removeMount", LuaScriptInterface::luaPlayerRemoveMount); - registerMethod("Player", "hasMount", LuaScriptInterface::luaPlayerHasMount); - - registerMethod("Player", "getPremiumDays", LuaScriptInterface::luaPlayerGetPremiumDays); - registerMethod("Player", "addPremiumDays", LuaScriptInterface::luaPlayerAddPremiumDays); - registerMethod("Player", "removePremiumDays", LuaScriptInterface::luaPlayerRemovePremiumDays); - - registerMethod("Player", "hasBlessing", LuaScriptInterface::luaPlayerHasBlessing); - registerMethod("Player", "addBlessing", LuaScriptInterface::luaPlayerAddBlessing); - registerMethod("Player", "removeBlessing", LuaScriptInterface::luaPlayerRemoveBlessing); - - registerMethod("Player", "canLearnSpell", LuaScriptInterface::luaPlayerCanLearnSpell); - registerMethod("Player", "learnSpell", LuaScriptInterface::luaPlayerLearnSpell); - registerMethod("Player", "forgetSpell", LuaScriptInterface::luaPlayerForgetSpell); - registerMethod("Player", "hasLearnedSpell", LuaScriptInterface::luaPlayerHasLearnedSpell); - - registerMethod("Player", "sendTutorial", LuaScriptInterface::luaPlayerSendTutorial); - registerMethod("Player", "addMapMark", LuaScriptInterface::luaPlayerAddMapMark); - - registerMethod("Player", "save", LuaScriptInterface::luaPlayerSave); - registerMethod("Player", "popupFYI", LuaScriptInterface::luaPlayerPopupFYI); - - registerMethod("Player", "isPzLocked", LuaScriptInterface::luaPlayerIsPzLocked); - - registerMethod("Player", "getClient", LuaScriptInterface::luaPlayerGetClient); - registerMethod("Player", "getHouse", LuaScriptInterface::luaPlayerGetHouse); - - registerMethod("Player", "setGhostMode", LuaScriptInterface::luaPlayerSetGhostMode); - - registerMethod("Player", "getContainerId", LuaScriptInterface::luaPlayerGetContainerId); - registerMethod("Player", "getContainerById", LuaScriptInterface::luaPlayerGetContainerById); - registerMethod("Player", "getContainerIndex", LuaScriptInterface::luaPlayerGetContainerIndex); - - // Monster - registerClass("Monster", "Creature", LuaScriptInterface::luaMonsterCreate); - registerMetaMethod("Monster", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Monster", "isMonster", LuaScriptInterface::luaMonsterIsMonster); - - registerMethod("Monster", "getType", LuaScriptInterface::luaMonsterGetType); - - registerMethod("Monster", "getSpawnPosition", LuaScriptInterface::luaMonsterGetSpawnPosition); - registerMethod("Monster", "isInSpawnRange", LuaScriptInterface::luaMonsterIsInSpawnRange); - - registerMethod("Monster", "isIdle", LuaScriptInterface::luaMonsterIsIdle); - registerMethod("Monster", "setIdle", LuaScriptInterface::luaMonsterSetIdle); - - registerMethod("Monster", "isTarget", LuaScriptInterface::luaMonsterIsTarget); - registerMethod("Monster", "isOpponent", LuaScriptInterface::luaMonsterIsOpponent); - registerMethod("Monster", "isFriend", LuaScriptInterface::luaMonsterIsFriend); - - registerMethod("Monster", "addFriend", LuaScriptInterface::luaMonsterAddFriend); - registerMethod("Monster", "removeFriend", LuaScriptInterface::luaMonsterRemoveFriend); - registerMethod("Monster", "getFriendList", LuaScriptInterface::luaMonsterGetFriendList); - registerMethod("Monster", "getFriendCount", LuaScriptInterface::luaMonsterGetFriendCount); - - registerMethod("Monster", "addTarget", LuaScriptInterface::luaMonsterAddTarget); - registerMethod("Monster", "removeTarget", LuaScriptInterface::luaMonsterRemoveTarget); - registerMethod("Monster", "getTargetList", LuaScriptInterface::luaMonsterGetTargetList); - registerMethod("Monster", "getTargetCount", LuaScriptInterface::luaMonsterGetTargetCount); - - registerMethod("Monster", "selectTarget", LuaScriptInterface::luaMonsterSelectTarget); - registerMethod("Monster", "searchTarget", LuaScriptInterface::luaMonsterSearchTarget); - - // Npc - registerClass("Npc", "Creature", LuaScriptInterface::luaNpcCreate); - registerMetaMethod("Npc", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Npc", "isNpc", LuaScriptInterface::luaNpcIsNpc); - - registerMethod("Npc", "setMasterPos", LuaScriptInterface::luaNpcSetMasterPos); - - registerMethod("Npc", "getSpeechBubble", LuaScriptInterface::luaNpcGetSpeechBubble); - registerMethod("Npc", "setSpeechBubble", LuaScriptInterface::luaNpcSetSpeechBubble); - - // Guild - registerClass("Guild", "", LuaScriptInterface::luaGuildCreate); - registerMetaMethod("Guild", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Guild", "getId", LuaScriptInterface::luaGuildGetId); - registerMethod("Guild", "getName", LuaScriptInterface::luaGuildGetName); - registerMethod("Guild", "getMembersOnline", LuaScriptInterface::luaGuildGetMembersOnline); - - registerMethod("Guild", "addRank", LuaScriptInterface::luaGuildAddRank); - registerMethod("Guild", "getRankById", LuaScriptInterface::luaGuildGetRankById); - registerMethod("Guild", "getRankByLevel", LuaScriptInterface::luaGuildGetRankByLevel); - - registerMethod("Guild", "getMotd", LuaScriptInterface::luaGuildGetMotd); - registerMethod("Guild", "setMotd", LuaScriptInterface::luaGuildSetMotd); - - // Group - registerClass("Group", "", LuaScriptInterface::luaGroupCreate); - registerMetaMethod("Group", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Group", "getId", LuaScriptInterface::luaGroupGetId); - registerMethod("Group", "getName", LuaScriptInterface::luaGroupGetName); - registerMethod("Group", "getFlags", LuaScriptInterface::luaGroupGetFlags); - registerMethod("Group", "getAccess", LuaScriptInterface::luaGroupGetAccess); - registerMethod("Group", "getMaxDepotItems", LuaScriptInterface::luaGroupGetMaxDepotItems); - registerMethod("Group", "getMaxVipEntries", LuaScriptInterface::luaGroupGetMaxVipEntries); - - // Vocation - registerClass("Vocation", "", LuaScriptInterface::luaVocationCreate); - registerMetaMethod("Vocation", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Vocation", "getId", LuaScriptInterface::luaVocationGetId); - registerMethod("Vocation", "getClientId", LuaScriptInterface::luaVocationGetClientId); - registerMethod("Vocation", "getName", LuaScriptInterface::luaVocationGetName); - registerMethod("Vocation", "getDescription", LuaScriptInterface::luaVocationGetDescription); - - registerMethod("Vocation", "getRequiredSkillTries", LuaScriptInterface::luaVocationGetRequiredSkillTries); - registerMethod("Vocation", "getRequiredManaSpent", LuaScriptInterface::luaVocationGetRequiredManaSpent); - - registerMethod("Vocation", "getCapacityGain", LuaScriptInterface::luaVocationGetCapacityGain); - - registerMethod("Vocation", "getHealthGain", LuaScriptInterface::luaVocationGetHealthGain); - registerMethod("Vocation", "getHealthGainTicks", LuaScriptInterface::luaVocationGetHealthGainTicks); - registerMethod("Vocation", "getHealthGainAmount", LuaScriptInterface::luaVocationGetHealthGainAmount); - - registerMethod("Vocation", "getManaGain", LuaScriptInterface::luaVocationGetManaGain); - registerMethod("Vocation", "getManaGainTicks", LuaScriptInterface::luaVocationGetManaGainTicks); - registerMethod("Vocation", "getManaGainAmount", LuaScriptInterface::luaVocationGetManaGainAmount); - - registerMethod("Vocation", "getMaxSoul", LuaScriptInterface::luaVocationGetMaxSoul); - registerMethod("Vocation", "getSoulGainTicks", LuaScriptInterface::luaVocationGetSoulGainTicks); - - registerMethod("Vocation", "getAttackSpeed", LuaScriptInterface::luaVocationGetAttackSpeed); - registerMethod("Vocation", "getBaseSpeed", LuaScriptInterface::luaVocationGetBaseSpeed); - - registerMethod("Vocation", "getDemotion", LuaScriptInterface::luaVocationGetDemotion); - registerMethod("Vocation", "getPromotion", LuaScriptInterface::luaVocationGetPromotion); - - // Town - registerClass("Town", "", LuaScriptInterface::luaTownCreate); - registerMetaMethod("Town", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Town", "getId", LuaScriptInterface::luaTownGetId); - registerMethod("Town", "getName", LuaScriptInterface::luaTownGetName); - registerMethod("Town", "getTemplePosition", LuaScriptInterface::luaTownGetTemplePosition); - - // House - registerClass("House", "", LuaScriptInterface::luaHouseCreate); - registerMetaMethod("House", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("House", "getId", LuaScriptInterface::luaHouseGetId); - registerMethod("House", "getName", LuaScriptInterface::luaHouseGetName); - registerMethod("House", "getTown", LuaScriptInterface::luaHouseGetTown); - registerMethod("House", "getExitPosition", LuaScriptInterface::luaHouseGetExitPosition); - registerMethod("House", "getRent", LuaScriptInterface::luaHouseGetRent); - - registerMethod("House", "getOwnerGuid", LuaScriptInterface::luaHouseGetOwnerGuid); - registerMethod("House", "setOwnerGuid", LuaScriptInterface::luaHouseSetOwnerGuid); - - registerMethod("House", "getBeds", LuaScriptInterface::luaHouseGetBeds); - registerMethod("House", "getBedCount", LuaScriptInterface::luaHouseGetBedCount); - - registerMethod("House", "getDoors", LuaScriptInterface::luaHouseGetDoors); - registerMethod("House", "getDoorCount", LuaScriptInterface::luaHouseGetDoorCount); - - registerMethod("House", "getTiles", LuaScriptInterface::luaHouseGetTiles); - registerMethod("House", "getTileCount", LuaScriptInterface::luaHouseGetTileCount); - - registerMethod("House", "getAccessList", LuaScriptInterface::luaHouseGetAccessList); - registerMethod("House", "setAccessList", LuaScriptInterface::luaHouseSetAccessList); - - // ItemType - registerClass("ItemType", "", LuaScriptInterface::luaItemTypeCreate); - registerMetaMethod("ItemType", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("ItemType", "isCorpse", LuaScriptInterface::luaItemTypeIsCorpse); - registerMethod("ItemType", "isDoor", LuaScriptInterface::luaItemTypeIsDoor); - registerMethod("ItemType", "isContainer", LuaScriptInterface::luaItemTypeIsContainer); - registerMethod("ItemType", "isFluidContainer", LuaScriptInterface::luaItemTypeIsFluidContainer); - registerMethod("ItemType", "isMovable", LuaScriptInterface::luaItemTypeIsMovable); - registerMethod("ItemType", "isRune", LuaScriptInterface::luaItemTypeIsRune); - registerMethod("ItemType", "isStackable", LuaScriptInterface::luaItemTypeIsStackable); - registerMethod("ItemType", "isReadable", LuaScriptInterface::luaItemTypeIsReadable); - registerMethod("ItemType", "isWritable", LuaScriptInterface::luaItemTypeIsWritable); - - registerMethod("ItemType", "getType", LuaScriptInterface::luaItemTypeGetType); - registerMethod("ItemType", "getId", LuaScriptInterface::luaItemTypeGetId); - registerMethod("ItemType", "getClientId", LuaScriptInterface::luaItemTypeGetClientId); - registerMethod("ItemType", "getName", LuaScriptInterface::luaItemTypeGetName); - registerMethod("ItemType", "getPluralName", LuaScriptInterface::luaItemTypeGetPluralName); - registerMethod("ItemType", "getArticle", LuaScriptInterface::luaItemTypeGetArticle); - registerMethod("ItemType", "getDescription", LuaScriptInterface::luaItemTypeGetDescription); - registerMethod("ItemType", "getSlotPosition", LuaScriptInterface::luaItemTypeGetSlotPosition); - - registerMethod("ItemType", "getCharges", LuaScriptInterface::luaItemTypeGetCharges); - registerMethod("ItemType", "getFluidSource", LuaScriptInterface::luaItemTypeGetFluidSource); - registerMethod("ItemType", "getCapacity", LuaScriptInterface::luaItemTypeGetCapacity); - registerMethod("ItemType", "getWeight", LuaScriptInterface::luaItemTypeGetWeight); - - registerMethod("ItemType", "getHitChance", LuaScriptInterface::luaItemTypeGetHitChance); - registerMethod("ItemType", "getShootRange", LuaScriptInterface::luaItemTypeGetShootRange); - - registerMethod("ItemType", "getAttack", LuaScriptInterface::luaItemTypeGetAttack); - registerMethod("ItemType", "getDefense", LuaScriptInterface::luaItemTypeGetDefense); - registerMethod("ItemType", "getExtraDefense", LuaScriptInterface::luaItemTypeGetExtraDefense); - registerMethod("ItemType", "getArmor", LuaScriptInterface::luaItemTypeGetArmor); - registerMethod("ItemType", "getWeaponType", LuaScriptInterface::luaItemTypeGetWeaponType); - - registerMethod("ItemType", "getElementType", LuaScriptInterface::luaItemTypeGetElementType); - registerMethod("ItemType", "getElementDamage", LuaScriptInterface::luaItemTypeGetElementDamage); - - registerMethod("ItemType", "getTransformEquipId", LuaScriptInterface::luaItemTypeGetTransformEquipId); - registerMethod("ItemType", "getTransformDeEquipId", LuaScriptInterface::luaItemTypeGetTransformDeEquipId); - registerMethod("ItemType", "getDestroyId", LuaScriptInterface::luaItemTypeGetDestroyId); - registerMethod("ItemType", "getDecayId", LuaScriptInterface::luaItemTypeGetDecayId); - registerMethod("ItemType", "getRequiredLevel", LuaScriptInterface::luaItemTypeGetRequiredLevel); - - registerMethod("ItemType", "hasSubType", LuaScriptInterface::luaItemTypeHasSubType); - - // Combat - registerClass("Combat", "", LuaScriptInterface::luaCombatCreate); - registerMetaMethod("Combat", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Combat", "setParameter", LuaScriptInterface::luaCombatSetParameter); - registerMethod("Combat", "setFormula", LuaScriptInterface::luaCombatSetFormula); - - registerMethod("Combat", "setArea", LuaScriptInterface::luaCombatSetArea); - registerMethod("Combat", "setCondition", LuaScriptInterface::luaCombatSetCondition); - registerMethod("Combat", "setCallback", LuaScriptInterface::luaCombatSetCallback); - registerMethod("Combat", "setOrigin", LuaScriptInterface::luaCombatSetOrigin); - - registerMethod("Combat", "execute", LuaScriptInterface::luaCombatExecute); - - // Condition - registerClass("Condition", "", LuaScriptInterface::luaConditionCreate); - registerMetaMethod("Condition", "__eq", LuaScriptInterface::luaUserdataCompare); - registerMetaMethod("Condition", "__gc", LuaScriptInterface::luaConditionDelete); - registerMethod("Condition", "delete", LuaScriptInterface::luaConditionDelete); - - registerMethod("Condition", "getId", LuaScriptInterface::luaConditionGetId); - registerMethod("Condition", "getSubId", LuaScriptInterface::luaConditionGetSubId); - registerMethod("Condition", "getType", LuaScriptInterface::luaConditionGetType); - registerMethod("Condition", "getIcons", LuaScriptInterface::luaConditionGetIcons); - registerMethod("Condition", "getEndTime", LuaScriptInterface::luaConditionGetEndTime); - - registerMethod("Condition", "clone", LuaScriptInterface::luaConditionClone); - - registerMethod("Condition", "getTicks", LuaScriptInterface::luaConditionGetTicks); - registerMethod("Condition", "setTicks", LuaScriptInterface::luaConditionSetTicks); - - registerMethod("Condition", "setParameter", LuaScriptInterface::luaConditionSetParameter); - registerMethod("Condition", "setFormula", LuaScriptInterface::luaConditionSetFormula); - registerMethod("Condition", "setOutfit", LuaScriptInterface::luaConditionSetOutfit); - - registerMethod("Condition", "addDamage", LuaScriptInterface::luaConditionAddDamage); - - // MonsterType - registerClass("MonsterType", "", LuaScriptInterface::luaMonsterTypeCreate); - registerMetaMethod("MonsterType", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("MonsterType", "isAttackable", LuaScriptInterface::luaMonsterTypeIsAttackable); - registerMethod("MonsterType", "isConvinceable", LuaScriptInterface::luaMonsterTypeIsConvinceable); - registerMethod("MonsterType", "isSummonable", LuaScriptInterface::luaMonsterTypeIsSummonable); - registerMethod("MonsterType", "isIllusionable", LuaScriptInterface::luaMonsterTypeIsIllusionable); - registerMethod("MonsterType", "isHostile", LuaScriptInterface::luaMonsterTypeIsHostile); - registerMethod("MonsterType", "isPassive", LuaScriptInterface::luaMonsterTypeIsHostile); - registerMethod("MonsterType", "isPushable", LuaScriptInterface::luaMonsterTypeIsPushable); - registerMethod("MonsterType", "isHealthShown", LuaScriptInterface::luaMonsterTypeIsHealthShown); - - registerMethod("MonsterType", "canPushItems", LuaScriptInterface::luaMonsterTypeCanPushItems); - registerMethod("MonsterType", "canPushCreatures", LuaScriptInterface::luaMonsterTypeCanPushCreatures); - - registerMethod("MonsterType", "getName", LuaScriptInterface::luaMonsterTypeGetName); - registerMethod("MonsterType", "getNameDescription", LuaScriptInterface::luaMonsterTypeGetNameDescription); - - registerMethod("MonsterType", "getHealth", LuaScriptInterface::luaMonsterTypeGetHealth); - registerMethod("MonsterType", "getMaxHealth", LuaScriptInterface::luaMonsterTypeGetMaxHealth); - registerMethod("MonsterType", "getRunHealth", LuaScriptInterface::luaMonsterTypeGetRunHealth); - registerMethod("MonsterType", "getExperience", LuaScriptInterface::luaMonsterTypeGetExperience); - - registerMethod("MonsterType", "getCombatImmunities", LuaScriptInterface::luaMonsterTypeGetCombatImmunities); - registerMethod("MonsterType", "getConditionImmunities", LuaScriptInterface::luaMonsterTypeGetConditionImmunities); - - registerMethod("MonsterType", "getAttackList", LuaScriptInterface::luaMonsterTypeGetAttackList); - registerMethod("MonsterType", "getDefenseList", LuaScriptInterface::luaMonsterTypeGetDefenseList); - registerMethod("MonsterType", "getElementList", LuaScriptInterface::luaMonsterTypeGetElementList); - - registerMethod("MonsterType", "getVoices", LuaScriptInterface::luaMonsterTypeGetVoices); - registerMethod("MonsterType", "getLoot", LuaScriptInterface::luaMonsterTypeGetLoot); - registerMethod("MonsterType", "getCreatureEvents", LuaScriptInterface::luaMonsterTypeGetCreatureEvents); - - registerMethod("MonsterType", "getSummonList", LuaScriptInterface::luaMonsterTypeGetSummonList); - registerMethod("MonsterType", "getMaxSummons", LuaScriptInterface::luaMonsterTypeGetMaxSummons); - - registerMethod("MonsterType", "getArmor", LuaScriptInterface::luaMonsterTypeGetArmor); - registerMethod("MonsterType", "getDefense", LuaScriptInterface::luaMonsterTypeGetDefense); - registerMethod("MonsterType", "getOutfit", LuaScriptInterface::luaMonsterTypeGetOutfit); - registerMethod("MonsterType", "getRace", LuaScriptInterface::luaMonsterTypeGetRace); - registerMethod("MonsterType", "getCorpseId", LuaScriptInterface::luaMonsterTypeGetCorpseId); - registerMethod("MonsterType", "getManaCost", LuaScriptInterface::luaMonsterTypeGetManaCost); - registerMethod("MonsterType", "getBaseSpeed", LuaScriptInterface::luaMonsterTypeGetBaseSpeed); - registerMethod("MonsterType", "getLight", LuaScriptInterface::luaMonsterTypeGetLight); - - registerMethod("MonsterType", "getStaticAttackChance", LuaScriptInterface::luaMonsterTypeGetStaticAttackChance); - registerMethod("MonsterType", "getTargetDistance", LuaScriptInterface::luaMonsterTypeGetTargetDistance); - registerMethod("MonsterType", "getYellChance", LuaScriptInterface::luaMonsterTypeGetYellChance); - registerMethod("MonsterType", "getYellSpeedTicks", LuaScriptInterface::luaMonsterTypeGetYellSpeedTicks); - registerMethod("MonsterType", "getChangeTargetChance", LuaScriptInterface::luaMonsterTypeGetChangeTargetChance); - registerMethod("MonsterType", "getChangeTargetSpeed", LuaScriptInterface::luaMonsterTypeGetChangeTargetSpeed); - - // Party - registerClass("Party", "", nullptr); - registerMetaMethod("Party", "__eq", LuaScriptInterface::luaUserdataCompare); - - registerMethod("Party", "disband", LuaScriptInterface::luaPartyDisband); - - registerMethod("Party", "getLeader", LuaScriptInterface::luaPartyGetLeader); - registerMethod("Party", "setLeader", LuaScriptInterface::luaPartySetLeader); - - registerMethod("Party", "getMembers", LuaScriptInterface::luaPartyGetMembers); - registerMethod("Party", "getMemberCount", LuaScriptInterface::luaPartyGetMemberCount); - - registerMethod("Party", "getInvitees", LuaScriptInterface::luaPartyGetInvitees); - registerMethod("Party", "getInviteeCount", LuaScriptInterface::luaPartyGetInviteeCount); - - registerMethod("Party", "addInvite", LuaScriptInterface::luaPartyAddInvite); - registerMethod("Party", "removeInvite", LuaScriptInterface::luaPartyRemoveInvite); - - registerMethod("Party", "addMember", LuaScriptInterface::luaPartyAddMember); - registerMethod("Party", "removeMember", LuaScriptInterface::luaPartyRemoveMember); - - registerMethod("Party", "isSharedExperienceActive", LuaScriptInterface::luaPartyIsSharedExperienceActive); - registerMethod("Party", "isSharedExperienceEnabled", LuaScriptInterface::luaPartyIsSharedExperienceEnabled); - registerMethod("Party", "shareExperience", LuaScriptInterface::luaPartyShareExperience); - registerMethod("Party", "setSharedExperience", LuaScriptInterface::luaPartySetSharedExperience); -} - -#undef registerEnum -#undef registerEnumIn - -void LuaScriptInterface::registerClass(const std::string& className, const std::string& baseClass, lua_CFunction newFunction/* = nullptr*/) -{ - // className = {} - lua_newtable(m_luaState); - lua_pushvalue(m_luaState, -1); - lua_setglobal(m_luaState, className.c_str()); - int methods = lua_gettop(m_luaState); - - // methodsTable = {} - lua_newtable(m_luaState); - int methodsTable = lua_gettop(m_luaState); - - if (newFunction) { - // className.__call = newFunction - lua_pushcfunction(m_luaState, newFunction); - lua_setfield(m_luaState, methodsTable, "__call"); - } - - uint32_t parents = 0; - if (!baseClass.empty()) { - lua_getglobal(m_luaState, baseClass.c_str()); - lua_rawgeti(m_luaState, -1, 'p'); - parents = getNumber(m_luaState, -1) + 1; - lua_pop(m_luaState, 1); - lua_setfield(m_luaState, methodsTable, "__index"); - } - - // setmetatable(className, methodsTable) - lua_setmetatable(m_luaState, methods); - - // className.metatable = {} - luaL_newmetatable(m_luaState, className.c_str()); - int metatable = lua_gettop(m_luaState); - - // className.metatable.__metatable = className - lua_pushvalue(m_luaState, methods); - lua_setfield(m_luaState, metatable, "__metatable"); - - // className.metatable.__index = className - lua_pushvalue(m_luaState, methods); - lua_setfield(m_luaState, metatable, "__index"); - - // className.metatable['h'] = hash - lua_pushnumber(m_luaState, std::hash()(className)); - lua_rawseti(m_luaState, metatable, 'h'); - - // className.metatable['p'] = parents - lua_pushnumber(m_luaState, parents); - lua_rawseti(m_luaState, metatable, 'p'); - - // className.metatable['t'] = type - if (className == "Item") { - lua_pushnumber(m_luaState, LuaData_Item); - } else if (className == "Container") { - lua_pushnumber(m_luaState, LuaData_Container); - } else if (className == "Teleport") { - lua_pushnumber(m_luaState, LuaData_Teleport); - } else if (className == "Player") { - lua_pushnumber(m_luaState, LuaData_Player); - } else if (className == "Monster") { - lua_pushnumber(m_luaState, LuaData_Monster); - } else if (className == "Npc") { - lua_pushnumber(m_luaState, LuaData_Npc); - } else if (className == "Tile") { - lua_pushnumber(m_luaState, LuaData_Tile); - } else { - lua_pushnumber(m_luaState, LuaData_Unknown); - } - lua_rawseti(m_luaState, metatable, 't'); - - // pop className, className.metatable - lua_pop(m_luaState, 2); -} - -void LuaScriptInterface::registerTable(const std::string& tableName) -{ - // _G[tableName] = {} - lua_newtable(m_luaState); - lua_setglobal(m_luaState, tableName.c_str()); -} - -void LuaScriptInterface::registerMethod(const std::string& globalName, const std::string& methodName, lua_CFunction func) -{ - // globalName.methodName = func - lua_getglobal(m_luaState, globalName.c_str()); - lua_pushcfunction(m_luaState, func); - lua_setfield(m_luaState, -2, methodName.c_str()); - - // pop globalName - lua_pop(m_luaState, 1); -} - -void LuaScriptInterface::registerMetaMethod(const std::string& className, const std::string& methodName, lua_CFunction func) -{ - // className.metatable.methodName = func - luaL_getmetatable(m_luaState, className.c_str()); - lua_pushcfunction(m_luaState, func); - lua_setfield(m_luaState, -2, methodName.c_str()); - - // pop className.metatable - lua_pop(m_luaState, 1); -} - -void LuaScriptInterface::registerGlobalMethod(const std::string& functionName, lua_CFunction func) -{ - // _G[functionName] = func - lua_pushcfunction(m_luaState, func); - lua_setglobal(m_luaState, functionName.c_str()); -} - -void LuaScriptInterface::registerVariable(const std::string& tableName, const std::string& name, lua_Number value) -{ - // tableName.name = value - lua_getglobal(m_luaState, tableName.c_str()); - setField(m_luaState, name.c_str(), value); - - // pop tableName - lua_pop(m_luaState, 1); -} - -void LuaScriptInterface::registerGlobalVariable(const std::string& name, lua_Number value) -{ - // _G[name] = value - lua_pushnumber(m_luaState, value); - lua_setglobal(m_luaState, name.c_str()); -} - -void LuaScriptInterface::registerGlobalBoolean(const std::string& name, bool value) -{ - // _G[name] = value - pushBoolean(m_luaState, value); - lua_setglobal(m_luaState, name.c_str()); -} - -int LuaScriptInterface::luaGetPlayerFlagValue(lua_State* L) -{ - //getPlayerFlagValue(cid, flag) - Player* player = getPlayer(L, 1); - if (player) { - PlayerFlags flag = getNumber(L, 2); - pushBoolean(L, player->hasFlag(flag)); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaGetPlayerInstantSpellCount(lua_State* L) -{ - //getPlayerInstantSpellCount(cid) - Player* player = getPlayer(L, 1); - if (player) { - lua_pushnumber(L, g_spells->getInstantSpellCount(player)); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaGetPlayerInstantSpellInfo(lua_State* L) -{ - //getPlayerInstantSpellInfo(cid, index) - Player* player = getPlayer(L, 1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t index = getNumber(L, 2); - InstantSpell* spell = g_spells->getInstantSpellByIndex(player, index); - if (!spell) { - reportErrorFunc(getErrorDesc(LUA_ERROR_SPELL_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - lua_createtable(L, 0, 6); - setField(L, "name", spell->getName()); - setField(L, "words", spell->getWords()); - setField(L, "level", spell->getLevel()); - setField(L, "mlevel", spell->getMagicLevel()); - setField(L, "mana", spell->getManaCost(player)); - setField(L, "manapercent", spell->getManaPercent()); - return 1; -} - -int LuaScriptInterface::luaDoPlayerAddItem(lua_State* L) -{ - //doPlayerAddItem(cid, itemid, count/subtype, canDropOnMap) - //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) - Player* player = getPlayer(L, 1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint16_t itemId = getNumber(L, 2); - int32_t count = getNumber(L, 3, 1); - bool canDropOnMap = getBoolean(L, 4, true); - uint16_t subType = getNumber(L, 5, 1); - - const ItemType& it = Item::items[itemId]; - int32_t itemCount; - - auto parameters = lua_gettop(L); - if (parameters > 4) { - //subtype already supplied, count then is the amount - itemCount = std::max(1, count); - } else if (it.hasSubType()) { - if (it.stackable) { - itemCount = static_cast(std::ceil(static_cast(count) / 100)); - } else { - itemCount = 1; - } - subType = count; - } else { - itemCount = std::max(1, count); - } - - while (itemCount > 0) { - uint16_t stackCount = subType; - if (it.stackable && stackCount > 100) { - stackCount = 100; - } - - Item* newItem = Item::CreateItem(itemId, stackCount); - if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - if (it.stackable) { - subType -= stackCount; - } - - ReturnValue ret = g_game.internalPlayerAddItem(player, newItem, canDropOnMap); - if (ret != RETURNVALUE_NOERROR) { - delete newItem; - pushBoolean(L, false); - return 1; - } - - if (--itemCount == 0) { - if (newItem->getParent()) { - uint32_t uid = getScriptEnv()->addThing(newItem); - lua_pushnumber(L, uid); - return 1; - } else { - //stackable item stacked with existing object, newItem will be released - pushBoolean(L, false); - return 1; - } - } - } - - pushBoolean(L, false); - return 1; -} - -int LuaScriptInterface::luaDoTileAddItemEx(lua_State* L) -{ - //doTileAddItemEx(pos, uid) - const Position& pos = getPosition(L, 1); - - Tile* tile = g_game.map.getTile(pos); - if (!tile) { - std::ostringstream ss; - ss << pos << ' ' << getErrorDesc(LUA_ERROR_TILE_NOT_FOUND); - reportErrorFunc(ss.str()); - pushBoolean(L, false); - return 1; - } - - uint32_t uid = getNumber(L, 2); - Item* item = getScriptEnv()->getItemByUID(uid); - if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); - pushBoolean(L, false); - return 1; - } - - lua_pushnumber(L, g_game.internalAddItem(tile, item)); - return 1; -} - -int LuaScriptInterface::luaDoCreateItem(lua_State* L) -{ - //doCreateItem(itemid, type/count, pos) - //Returns uid of the created item, only works on tiles. - const Position& pos = getPosition(L, 3); - Tile* tile = g_game.map.getTile(pos); - if (!tile) { - std::ostringstream ss; - ss << pos << ' ' << getErrorDesc(LUA_ERROR_TILE_NOT_FOUND); - reportErrorFunc(ss.str()); - pushBoolean(L, false); - return 1; - } - - ScriptEnvironment* env = getScriptEnv(); - - int32_t itemCount = 1; - int32_t subType = 1; - - uint16_t itemId = getNumber(L, 1); - uint32_t count = getNumber(L, 2, 1); - - const ItemType& it = Item::items[itemId]; - if (it.hasSubType()) { - if (it.stackable) { - itemCount = static_cast(std::ceil(static_cast(count) / 100)); - } - - subType = count; - } else { - itemCount = std::max(1, count); - } - - while (itemCount > 0) { - int32_t stackCount = std::min(100, subType); - Item* newItem = Item::CreateItem(itemId, stackCount); - if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - if (it.stackable) { - subType -= stackCount; - } - - ReturnValue ret = g_game.internalAddItem(tile, newItem, INDEX_WHEREEVER, FLAG_NOLIMIT); - if (ret != RETURNVALUE_NOERROR) { - delete newItem; - pushBoolean(L, false); - return 1; - } - - if (--itemCount == 0) { - if (newItem->getParent()) { - uint32_t uid = env->addThing(newItem); - lua_pushnumber(L, uid); - return 1; - } else { - //stackable item stacked with existing object, newItem will be released - pushBoolean(L, false); - return 1; - } - } - } - - pushBoolean(L, false); - return 1; -} - -int LuaScriptInterface::luaDoCreateItemEx(lua_State* L) -{ - //doCreateItemEx(itemid, count/subtype) - //Returns uid of the created item - uint16_t itemId = getNumber(L, 1); - uint32_t count = getNumber(L, 2, 1); - - const ItemType& it = Item::items[itemId]; - if (it.stackable && count > 100) { - reportErrorFunc("Stack count cannot be higher than 100."); - count = 100; - } - - Item* newItem = Item::CreateItem(itemId, count); - if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - newItem->setParent(VirtualCylinder::virtualCylinder); - - ScriptEnvironment* env = getScriptEnv(); - env->addTempItem(newItem); - - uint32_t uid = env->addThing(newItem); - lua_pushnumber(L, uid); - return 1; -} - -int LuaScriptInterface::luaDebugPrint(lua_State* L) -{ - //debugPrint(text) - reportErrorFunc(getString(L, -1)); - return 0; -} - -int LuaScriptInterface::luaGetWorldTime(lua_State* L) -{ - //getWorldTime() - uint32_t time = g_game.getLightHour(); - lua_pushnumber(L, time); - return 1; -} - -int LuaScriptInterface::luaGetWorldLight(lua_State* L) -{ - //getWorldLight() - LightInfo lightInfo; - g_game.getWorldLightInfo(lightInfo); - lua_pushnumber(L, lightInfo.level); - lua_pushnumber(L, lightInfo.color); - return 2; -} - -int LuaScriptInterface::luaGetWorldUpTime(lua_State* L) -{ - //getWorldUpTime() - uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; - lua_pushnumber(L, uptime); - return 1; -} - -bool LuaScriptInterface::getArea(lua_State* L, std::list& list, uint32_t& rows) -{ - lua_pushnil(L); - for (rows = 0; lua_next(L, -2) != 0; ++rows) { - if (!isTable(L, -1)) { - return false; - } - - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - if (!isNumber(L, -1)) { - return false; - } - list.push_back(getNumber(L, -1)); - lua_pop(L, 1); - } - - lua_pop(L, 1); - } - - lua_pop(L, 1); - return (rows != 0); -} - -int LuaScriptInterface::luaCreateCombatArea(lua_State* L) -{ - //createCombatArea( {area}, {extArea} ) - ScriptEnvironment* env = getScriptEnv(); - if (env->getScriptId() != EVENT_ID_LOADING) { - reportErrorFunc("This function can only be used while loading the script."); - pushBoolean(L, false); - return 1; - } - - uint32_t areaId = g_luaEnvironment.createAreaObject(env->getScriptInterface()); - AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); - - int parameters = lua_gettop(L); - if (parameters >= 2) { - uint32_t rowsExtArea; - std::list listExtArea; - if (!getArea(L, listExtArea, rowsExtArea)) { - reportErrorFunc("Invalid extended area table."); - pushBoolean(L, false); - return 1; - } - area->setupExtArea(listExtArea, rowsExtArea); - } - - uint32_t rowsArea = 0; - std::list listArea; - if (!getArea(L, listArea, rowsArea)) { - reportErrorFunc("Invalid area table."); - pushBoolean(L, false); - return 1; - } - - area->setupArea(listArea, rowsArea); - lua_pushnumber(L, areaId); - return 1; -} - -int LuaScriptInterface::luaDoAreaCombatHealth(lua_State* L) -{ - //doAreaCombatHealth(cid, type, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t areaId = getNumber(L, 4); - const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); - if (area || areaId == 0) { - CombatType_t combatType = getNumber(L, 2); - - CombatParams params; - params.combatType = combatType; - params.impactEffect = getNumber(L, 7); - - CombatDamage damage; - damage.origin = getNumber(L, 8, ORIGIN_SPELL); - damage.primary.type = combatType; - damage.primary.value = normal_random(getNumber(L, 6), getNumber(L, 5)); - - Combat::doCombatHealth(creature, getPosition(L, 3), area, damage, params); - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaDoTargetCombatHealth(lua_State* L) -{ - //doTargetCombatHealth(cid, target, type, min, max, effect[, origin = ORIGIN_SPELL]) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Creature* target = getCreature(L, 2); - if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - CombatType_t combatType = getNumber(L, 3); - - CombatParams params; - params.combatType = combatType; - params.impactEffect = getNumber(L, 6); - - CombatDamage damage; - damage.origin = getNumber(L, 7, ORIGIN_SPELL); - damage.primary.type = combatType; - damage.primary.value = normal_random(getNumber(L, 4), getNumber(L, 5)); - - Combat::doCombatHealth(creature, target, damage, params); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaDoAreaCombatMana(lua_State* L) -{ - //doAreaCombatMana(cid, pos, area, min, max, effect[, origin = ORIGIN_SPELL]) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t areaId = getNumber(L, 3); - const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); - if (area || areaId == 0) { - CombatParams params; - params.impactEffect = getNumber(L, 6); - - CombatDamage damage; - damage.origin = getNumber(L, 7, ORIGIN_SPELL); - damage.primary.type = COMBAT_MANADRAIN; - damage.primary.value = normal_random(getNumber(L, 4), getNumber(L, 5)); - - Position pos = getPosition(L, 2); - Combat::doCombatMana(creature, pos, area, damage, params); - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaDoTargetCombatMana(lua_State* L) -{ - //doTargetCombatMana(cid, target, min, max, effect[, origin = ORIGIN_SPELL) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Creature* target = getCreature(L, 2); - if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - CombatParams params; - params.impactEffect = getNumber(L, 5); - - CombatDamage damage; - damage.origin = getNumber(L, 6, ORIGIN_SPELL); - damage.primary.type = COMBAT_MANADRAIN; - damage.primary.value = normal_random(getNumber(L, 3), getNumber(L, 4)); - - Combat::doCombatMana(creature, target, damage, params); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaDoAreaCombatCondition(lua_State* L) -{ - //doAreaCombatCondition(cid, pos, area, condition, effect) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - const Condition* condition = getUserdata(L, 4); - if (!condition) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t areaId = getNumber(L, 3); - const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); - if (area || areaId == 0) { - CombatParams params; - params.impactEffect = getNumber(L, 5); - params.conditionList.emplace_front(condition); - Combat::doCombatCondition(creature, getPosition(L, 2), area, params); - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaDoTargetCombatCondition(lua_State* L) -{ - //doTargetCombatCondition(cid, target, condition, effect) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Creature* target = getCreature(L, 2); - if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - const Condition* condition = getUserdata(L, 3); - if (!condition) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONDITION_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - CombatParams params; - params.impactEffect = getNumber(L, 4); - params.conditionList.emplace_front(condition); - Combat::doCombatCondition(creature, target, params); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaDoAreaCombatDispel(lua_State* L) -{ - //doAreaCombatDispel(cid, pos, area, type, effect) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t areaId = getNumber(L, 3); - const AreaCombat* area = g_luaEnvironment.getAreaObject(areaId); - if (area || areaId == 0) { - CombatParams params; - params.impactEffect = getNumber(L, 5); - params.dispelType = getNumber(L, 4); - Combat::doCombatDispel(creature, getPosition(L, 2), area, params); - - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaDoTargetCombatDispel(lua_State* L) -{ - //doTargetCombatDispel(cid, target, type, effect) - Creature* creature = getCreature(L, 1); - if (!creature && (!isNumber(L, 1) || getNumber(L, 1) != 0)) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Creature* target = getCreature(L, 2); - if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - CombatParams params; - params.dispelType = getNumber(L, 3); - params.impactEffect = getNumber(L, 4); - Combat::doCombatDispel(creature, target, params); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaDoChallengeCreature(lua_State* L) -{ - //doChallengeCreature(cid, target) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Creature* target = getCreature(L, 2); - if (!target) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - target->challengeCreature(creature); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaSetCreatureOutfit(lua_State* L) -{ - //doSetCreatureOutfit(cid, outfit, time) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Outfit_t outfit = getOutfit(L, 2); - int32_t time = getNumber(L, 3); - pushBoolean(L, Spell::CreateIllusion(creature, outfit, time) == RETURNVALUE_NOERROR); - return 1; -} - -int LuaScriptInterface::luaSetMonsterOutfit(lua_State* L) -{ - //doSetMonsterOutfit(cid, name, time) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - std::string name = getString(L, 2); - int32_t time = getNumber(L, 3); - pushBoolean(L, Spell::CreateIllusion(creature, name, time) == RETURNVALUE_NOERROR); - return 1; -} - -int LuaScriptInterface::luaSetItemOutfit(lua_State* L) -{ - //doSetItemOutfit(cid, item, time) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t item = getNumber(L, 2); - int32_t time = getNumber(L, 3); - pushBoolean(L, Spell::CreateIllusion(creature, item, time) == RETURNVALUE_NOERROR); - return 1; -} - -int LuaScriptInterface::luaDoMoveCreature(lua_State* L) -{ - //doMoveCreature(cid, direction) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Direction direction = getNumber(L, 2); - if (direction > DIRECTION_LAST) { - reportErrorFunc("No valid direction"); - pushBoolean(L, false); - return 1; - } - - ReturnValue ret = g_game.internalMoveCreature(creature, direction, FLAG_NOLIMIT); - lua_pushnumber(L, ret); - return 1; -} - -int LuaScriptInterface::luaIsValidUID(lua_State* L) -{ - //isValidUID(uid) - pushBoolean(L, getScriptEnv()->getThingByUID(getNumber(L, -1)) != nullptr); - return 1; -} - -int LuaScriptInterface::luaIsDepot(lua_State* L) -{ - //isDepot(uid) - Container* container = getScriptEnv()->getContainerByUID(getNumber(L, -1)); - pushBoolean(L, container && container->getDepotLocker()); - return 1; -} - -int LuaScriptInterface::luaIsMoveable(lua_State* L) -{ - //isMoveable(uid) - //isMovable(uid) - Thing* thing = getScriptEnv()->getThingByUID(getNumber(L, -1)); - pushBoolean(L, thing && thing->isPushable()); - return 1; -} - -int LuaScriptInterface::luaDoAddContainerItem(lua_State* L) -{ - //doAddContainerItem(uid, itemid, count/subtype) - uint32_t uid = getNumber(L, 1); - - ScriptEnvironment* env = getScriptEnv(); - Container* container = env->getContainerByUID(uid); - if (!container) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint16_t itemId = getNumber(L, 2); - const ItemType& it = Item::items[itemId]; - - int32_t itemCount = 1; - int32_t subType = 1; - uint32_t count = getNumber(L, 3, 1); - - if (it.hasSubType()) { - if (it.stackable) { - itemCount = static_cast(std::ceil(static_cast(count) / 100)); - } - - subType = count; - } else { - itemCount = std::max(1, count); - } - - while (itemCount > 0) { - int32_t stackCount = std::min(100, subType); - Item* newItem = Item::CreateItem(itemId, stackCount); - if (!newItem) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - if (it.stackable) { - subType -= stackCount; - } - - ReturnValue ret = g_game.internalAddItem(container, newItem); - if (ret != RETURNVALUE_NOERROR) { - delete newItem; - pushBoolean(L, false); - return 1; - } - - if (--itemCount == 0) { - if (newItem->getParent()) { - lua_pushnumber(L, env->addThing(newItem)); - } else { - //stackable item stacked with existing object, newItem will be released - pushBoolean(L, false); - } - return 1; - } - } - - pushBoolean(L, false); - return 1; -} - -int LuaScriptInterface::luaGetDepotId(lua_State* L) -{ - //getDepotId(uid) - uint32_t uid = getNumber(L, -1); - - Container* container = getScriptEnv()->getContainerByUID(uid); - if (!container) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CONTAINER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - DepotLocker* depotLocker = container->getDepotLocker(); - if (!depotLocker) { - reportErrorFunc("Depot not found"); - pushBoolean(L, false); - return 1; - } - - lua_pushnumber(L, depotLocker->getDepotId()); - return 1; -} - -int LuaScriptInterface::luaIsInArray(lua_State* L) -{ - //isInArray(array, value) - if (!isTable(L, 1)) { - pushBoolean(L, false); - return 1; - } - - lua_pushnil(L); - while (lua_next(L, 1)) { - if (lua_equal(L, 2, -1) != 0) { - pushBoolean(L, true); - return 1; - } - lua_pop(L, 1); - } - - pushBoolean(L, false); - return 1; -} - -int LuaScriptInterface::luaDoSetCreatureLight(lua_State* L) -{ - //doSetCreatureLight(cid, lightLevel, lightColor, time) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint16_t level = getNumber(L, 2); - uint16_t color = getNumber(L, 3); - uint32_t time = getNumber(L, 4); - Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_LIGHT, time, level | (color << 8)); - creature->addCondition(condition); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaAddEvent(lua_State* L) -{ - //addEvent(callback, delay, ...) - lua_State* globalState = g_luaEnvironment.getLuaState(); - if (!globalState) { - reportErrorFunc("No valid script interface!"); - pushBoolean(L, false); - return 1; - } else if (globalState != L) { - lua_xmove(L, globalState, lua_gettop(L)); - } - - int parameters = lua_gettop(globalState); - if (!isFunction(globalState, -parameters)) { //-parameters means the first parameter from left to right - reportErrorFunc("callback parameter should be a function."); - pushBoolean(L, false); - return 1; - } - - if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS) || g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) { - std::vector> indexes; - for (int i = 3; i <= parameters; ++i) { - if (lua_getmetatable(globalState, i) == 0) { - continue; - } - lua_rawgeti(L, -1, 't'); - - LuaDataType type = getNumber(L, -1); - if (type != LuaData_Unknown && type != LuaData_Tile) { - indexes.push_back({i, type}); - } - lua_pop(globalState, 2); - } - - if (!indexes.empty()) { - if (g_config.getBoolean(ConfigManager::WARN_UNSAFE_SCRIPTS)) { - bool plural = indexes.size() > 1; - - std::string warningString = "Argument"; - if (plural) { - warningString += 's'; - } - - for (const auto& entry : indexes) { - if (entry == indexes.front()) { - warningString += ' '; - } else if (entry == indexes.back()) { - warningString += " and "; - } else { - warningString += ", "; - } - warningString += '#'; - warningString += std::to_string(entry.first); - } - - if (plural) { - warningString += " are unsafe"; - } else { - warningString += " is unsafe"; - } - - reportErrorFunc(warningString); - } - - if (g_config.getBoolean(ConfigManager::CONVERT_UNSAFE_SCRIPTS)) { - for (const auto& entry : indexes) { - switch (entry.second) { - case LuaData_Item: - case LuaData_Container: - case LuaData_Teleport: { - lua_getglobal(globalState, "Item"); - lua_getfield(globalState, -1, "getUniqueId"); - break; - } - case LuaData_Player: - case LuaData_Monster: - case LuaData_Npc: { - lua_getglobal(globalState, "Creature"); - lua_getfield(globalState, -1, "getId"); - break; - } - default: - break; - } - lua_replace(globalState, -2); - lua_pushvalue(globalState, entry.first); - lua_call(globalState, 1, 1); - lua_replace(globalState, entry.first); - } - } - } - } - - LuaTimerEventDesc eventDesc; - for (int i = 0; i < parameters - 2; ++i) { //-2 because addEvent needs at least two parameters - eventDesc.parameters.push_back(luaL_ref(globalState, LUA_REGISTRYINDEX)); - } - - uint32_t delay = std::max(100, getNumber(globalState, 2)); - lua_pop(globalState, 1); - - eventDesc.function = luaL_ref(globalState, LUA_REGISTRYINDEX); - eventDesc.scriptId = getScriptEnv()->getScriptId(); - - auto& lastTimerEventId = g_luaEnvironment.m_lastEventTimerId; - eventDesc.eventId = g_scheduler.addEvent(createSchedulerTask( - delay, std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment, lastTimerEventId) - )); - - g_luaEnvironment.m_timerEvents.emplace(lastTimerEventId, std::move(eventDesc)); - lua_pushnumber(L, lastTimerEventId++); - return 1; -} - -int LuaScriptInterface::luaStopEvent(lua_State* L) -{ - //stopEvent(eventid) - lua_State* globalState = g_luaEnvironment.getLuaState(); - if (!globalState) { - reportErrorFunc("No valid script interface!"); - pushBoolean(L, false); - return 1; - } - - uint32_t eventId = getNumber(L, 1); - - auto& timerEvents = g_luaEnvironment.m_timerEvents; - auto it = timerEvents.find(eventId); - if (it == timerEvents.end()) { - pushBoolean(L, false); - return 1; - } - - LuaTimerEventDesc timerEventDesc = std::move(it->second); - timerEvents.erase(it); - - g_scheduler.stopEvent(timerEventDesc.eventId); - luaL_unref(globalState, LUA_REGISTRYINDEX, timerEventDesc.function); - - for (auto parameter : timerEventDesc.parameters) { - luaL_unref(globalState, LUA_REGISTRYINDEX, parameter); - } - - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaGetCreatureCondition(lua_State* L) -{ - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - ConditionType_t condition = getNumber(L, 2); - uint32_t subId = getNumber(L, 3, 0); - pushBoolean(L, creature->hasCondition(condition, subId)); - return 1; -} - -int LuaScriptInterface::luaSaveServer(lua_State* L) -{ - g_game.saveGameState(); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCleanMap(lua_State* L) -{ - lua_pushnumber(L, g_game.map.clean()); - return 1; -} - -int LuaScriptInterface::luaIsInWar(lua_State* L) -{ - //isInWar(cid, target) - Player* player = getPlayer(L, 1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Player* targetPlayer = getPlayer(L, 2); - if (!targetPlayer) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - pushBoolean(L, player->isInWar(targetPlayer)); - return 1; -} - -int LuaScriptInterface::luaGetWaypointPositionByName(lua_State* L) -{ - //getWaypointPositionByName(name) - auto& waypoints = g_game.map.waypoints; - - auto it = waypoints.find(getString(L, -1)); - if (it != waypoints.end()) { - pushPosition(L, it->second); - } else { - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaSendChannelMessage(lua_State* L) -{ - //sendChannelMessage(channelId, type, message) - uint32_t channelId = getNumber(L, 1); - ChatChannel* channel = g_chat->getChannelById(channelId); - if (!channel) { - pushBoolean(L, false); - return 1; - } - - SpeakClasses type = getNumber(L, 2); - std::string message = getString(L, 3); - channel->sendToAll(message, type); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaSendGuildChannelMessage(lua_State* L) -{ - //sendGuildChannelMessage(guildId, type, message) - uint32_t guildId = getNumber(L, 1); - ChatChannel* channel = g_chat->getGuildChannelById(guildId); - if (!channel) { - pushBoolean(L, false); - return 1; - } - - SpeakClasses type = getNumber(L, 2); - std::string message = getString(L, 3); - channel->sendToAll(message, type); - pushBoolean(L, true); - return 1; -} - -std::string LuaScriptInterface::escapeString(const std::string& string) -{ - std::string s = string; - replaceString(s, "\\", "\\\\"); - replaceString(s, "\"", "\\\""); - replaceString(s, "'", "\\'"); - replaceString(s, "[[", "\\[["); - return s; -} - -#ifndef LUAJIT_VERSION -const luaL_Reg LuaScriptInterface::luaBitReg[] = { - //{"tobit", LuaScriptInterface::luaBitToBit}, - {"bnot", LuaScriptInterface::luaBitNot}, - {"band", LuaScriptInterface::luaBitAnd}, - {"bor", LuaScriptInterface::luaBitOr}, - {"bxor", LuaScriptInterface::luaBitXor}, - {"lshift", LuaScriptInterface::luaBitLeftShift}, - {"rshift", LuaScriptInterface::luaBitRightShift}, - //{"arshift", LuaScriptInterface::luaBitArithmeticalRightShift}, - //{"rol", LuaScriptInterface::luaBitRotateLeft}, - //{"ror", LuaScriptInterface::luaBitRotateRight}, - //{"bswap", LuaScriptInterface::luaBitSwapEndian}, - //{"tohex", LuaScriptInterface::luaBitToHex}, - {nullptr, nullptr} -}; - -int LuaScriptInterface::luaBitNot(lua_State* L) -{ - lua_pushnumber(L, ~getNumber(L, -1)); - return 1; -} - -#define MULTIOP(name, op) \ -int LuaScriptInterface::luaBit##name(lua_State* L) \ -{ \ - int n = lua_gettop(L); \ - uint32_t w = getNumber(L, -1); \ - for (int i = 1; i < n; ++i) \ - w op getNumber(L, i); \ - lua_pushnumber(L, w); \ - return 1; \ -} - -MULTIOP(And, &= ) -MULTIOP(Or, |= ) -MULTIOP(Xor, ^= ) - -#define SHIFTOP(name, op) \ -int LuaScriptInterface::luaBit##name(lua_State* L) \ -{ \ - uint32_t n1 = getNumber(L, 1), n2 = getNumber(L, 2); \ - lua_pushnumber(L, (n1 op n2)); \ - return 1; \ -} - -SHIFTOP(LeftShift, << ) -SHIFTOP(RightShift, >> ) -#endif - -const luaL_Reg LuaScriptInterface::luaConfigManagerTable[] = { - {"getString", LuaScriptInterface::luaConfigManagerGetString}, - {"getNumber", LuaScriptInterface::luaConfigManagerGetNumber}, - {"getBoolean", LuaScriptInterface::luaConfigManagerGetBoolean}, - {nullptr, nullptr} -}; - -int LuaScriptInterface::luaConfigManagerGetString(lua_State* L) -{ - pushString(L, g_config.getString(getNumber(L, -1))); - return 1; -} - -int LuaScriptInterface::luaConfigManagerGetNumber(lua_State* L) -{ - lua_pushnumber(L, g_config.getNumber(getNumber(L, -1))); - return 1; -} - -int LuaScriptInterface::luaConfigManagerGetBoolean(lua_State* L) -{ - pushBoolean(L, g_config.getBoolean(getNumber(L, -1))); - return 1; -} - -const luaL_Reg LuaScriptInterface::luaDatabaseTable[] = { - {"query", LuaScriptInterface::luaDatabaseExecute}, - {"asyncQuery", LuaScriptInterface::luaDatabaseAsyncExecute}, - {"storeQuery", LuaScriptInterface::luaDatabaseStoreQuery}, - {"asyncStoreQuery", LuaScriptInterface::luaDatabaseAsyncStoreQuery}, - {"escapeString", LuaScriptInterface::luaDatabaseEscapeString}, - {"escapeBlob", LuaScriptInterface::luaDatabaseEscapeBlob}, - {"lastInsertId", LuaScriptInterface::luaDatabaseLastInsertId}, - {"tableExists", LuaScriptInterface::luaDatabaseTableExists}, - {nullptr, nullptr} -}; - -int LuaScriptInterface::luaDatabaseExecute(lua_State* L) -{ - pushBoolean(L, Database::getInstance()->executeQuery(getString(L, -1))); - return 1; -} - -int LuaScriptInterface::luaDatabaseAsyncExecute(lua_State* L) -{ - std::function callback; - if (lua_gettop(L) > 1) { - int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); - auto scriptId = getScriptEnv()->getScriptId(); - callback = [ref, scriptId](DBResult_ptr, bool success) { - lua_State* luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return; - } - - if (!LuaScriptInterface::reserveScriptEnv()) { - luaL_unref(luaState, LUA_REGISTRYINDEX, ref); - return; - } - - lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref); - pushBoolean(luaState, success); - auto env = getScriptEnv(); - env->setScriptId(scriptId, &g_luaEnvironment); - g_luaEnvironment.callFunction(1); - - luaL_unref(luaState, LUA_REGISTRYINDEX, ref); - }; - } - g_databaseTasks.addTask(getString(L, -1), callback); - return 0; -} - -int LuaScriptInterface::luaDatabaseStoreQuery(lua_State* L) -{ - if (DBResult_ptr res = Database::getInstance()->storeQuery(getString(L, -1))) { - lua_pushnumber(L, ScriptEnvironment::addResult(res)); - } else { - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaDatabaseAsyncStoreQuery(lua_State* L) -{ - std::function callback; - if (lua_gettop(L) > 1) { - int32_t ref = luaL_ref(L, LUA_REGISTRYINDEX); - auto scriptId = getScriptEnv()->getScriptId(); - callback = [ref, scriptId](DBResult_ptr result, bool) { - lua_State* luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return; - } - - if (!LuaScriptInterface::reserveScriptEnv()) { - luaL_unref(luaState, LUA_REGISTRYINDEX, ref); - return; - } - - lua_rawgeti(luaState, LUA_REGISTRYINDEX, ref); - if (result) { - lua_pushnumber(luaState, ScriptEnvironment::addResult(result)); - } else { - pushBoolean(luaState, false); - } - auto env = getScriptEnv(); - env->setScriptId(scriptId, &g_luaEnvironment); - g_luaEnvironment.callFunction(1); - - luaL_unref(luaState, LUA_REGISTRYINDEX, ref); - }; - } - g_databaseTasks.addTask(getString(L, -1), callback, true); - return 0; -} - -int LuaScriptInterface::luaDatabaseEscapeString(lua_State* L) -{ - pushString(L, Database::getInstance()->escapeString(getString(L, -1))); - return 1; -} - -int LuaScriptInterface::luaDatabaseEscapeBlob(lua_State* L) -{ - uint32_t length = getNumber(L, 2); - pushString(L, Database::getInstance()->escapeBlob(getString(L, 1).c_str(), length)); - return 1; -} - -int LuaScriptInterface::luaDatabaseLastInsertId(lua_State* L) -{ - lua_pushnumber(L, Database::getInstance()->getLastInsertId()); - return 1; -} - -int LuaScriptInterface::luaDatabaseTableExists(lua_State* L) -{ - pushBoolean(L, DatabaseManager::tableExists(getString(L, -1))); - return 1; -} - -const luaL_Reg LuaScriptInterface::luaResultTable[] = { - {"getNumber", LuaScriptInterface::luaResultGetNumber}, - {"getString", LuaScriptInterface::luaResultGetString}, - {"getStream", LuaScriptInterface::luaResultGetStream}, - {"next", LuaScriptInterface::luaResultNext}, - {"free", LuaScriptInterface::luaResultFree}, - {nullptr, nullptr} -}; - -int LuaScriptInterface::luaResultGetNumber(lua_State* L) -{ - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); - if (!res) { - pushBoolean(L, false); - return 1; - } - - const std::string& s = getString(L, 2); - lua_pushnumber(L, res->getNumber(s)); - return 1; -} - -int LuaScriptInterface::luaResultGetString(lua_State* L) -{ - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); - if (!res) { - pushBoolean(L, false); - return 1; - } - - const std::string& s = getString(L, 2); - pushString(L, res->getString(s)); - return 1; -} - -int LuaScriptInterface::luaResultGetStream(lua_State* L) -{ - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, 1)); - if (!res) { - pushBoolean(L, false); - return 1; - } - - unsigned long length; - const char* stream = res->getStream(getString(L, 2), length); - lua_pushlstring(L, stream, length); - lua_pushnumber(L, length); - return 2; -} - -int LuaScriptInterface::luaResultNext(lua_State* L) -{ - DBResult_ptr res = ScriptEnvironment::getResultByID(getNumber(L, -1)); - if (!res) { - pushBoolean(L, false); - return 1; - } - - pushBoolean(L, res->next()); - return 1; -} - -int LuaScriptInterface::luaResultFree(lua_State* L) -{ - pushBoolean(L, ScriptEnvironment::removeResult(getNumber(L, -1))); - return 1; -} - -// Userdata -int LuaScriptInterface::luaUserdataCompare(lua_State* L) -{ - // userdataA == userdataB - pushBoolean(L, getUserdata(L, 1) == getUserdata(L, 2)); - return 1; -} - -// _G -int LuaScriptInterface::luaIsType(lua_State* L) -{ - // isType(derived, base) - lua_getmetatable(L, -2); - lua_getmetatable(L, -2); - - lua_rawgeti(L, -2, 'p'); - uint_fast8_t parentsB = getNumber(L, 1); - - lua_rawgeti(L, -3, 'h'); - size_t hashB = getNumber(L, 1); - - lua_rawgeti(L, -3, 'p'); - uint_fast8_t parentsA = getNumber(L, 1); - for (uint_fast8_t i = parentsA; i < parentsB; ++i) { - lua_getfield(L, -3, "__index"); - lua_replace(L, -4); - } - - lua_rawgeti(L, -4, 'h'); - size_t hashA = getNumber(L, 1); - - pushBoolean(L, hashA == hashB); - return 1; -} - -int LuaScriptInterface::luaRawGetMetatable(lua_State* L) -{ - // rawgetmetatable(metatableName) - luaL_getmetatable(L, getString(L, 1).c_str()); - return 1; -} - -// os -int LuaScriptInterface::luaSystemTime(lua_State* L) -{ - // os.mtime() - lua_pushnumber(L, OTSYS_TIME()); - return 1; -} - -// table -int LuaScriptInterface::luaTableCreate(lua_State* L) -{ - // table.create(arrayLength, keyLength) - lua_createtable(L, getNumber(L, 1), getNumber(L, 2)); - return 1; -} - -// Game -int LuaScriptInterface::luaGameGetSpectators(lua_State* L) -{ - // Game.getSpectators(position[, multifloor = false[, onlyPlayer = false[, minRangeX = 0[, maxRangeX = 0[, minRangeY = 0[, maxRangeY = 0]]]]]]) - const Position& position = getPosition(L, 1); - bool multifloor = getBoolean(L, 2, false); - bool onlyPlayers = getBoolean(L, 3, false); - int32_t minRangeX = getNumber(L, 4, 0); - int32_t maxRangeX = getNumber(L, 5, 0); - int32_t minRangeY = getNumber(L, 6, 0); - int32_t maxRangeY = getNumber(L, 7, 0); - - SpectatorVec spectators; - g_game.map.getSpectators(spectators, position, multifloor, onlyPlayers, minRangeX, maxRangeX, minRangeY, maxRangeY); - - lua_createtable(L, spectators.size(), 0); - - int index = 0; - for (Creature* creature : spectators) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaGameGetPlayers(lua_State* L) -{ - // Game.getPlayers() - lua_createtable(L, g_game.getPlayersOnline(), 0); - - int index = 0; - for (const auto& playerEntry : g_game.getPlayers()) { - pushUserdata(L, playerEntry.second); - setMetatable(L, -1, "Player"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaGameLoadMap(lua_State* L) -{ - // Game.loadMap(path) - const std::string& path = getString(L, 1); - g_dispatcher.addTask(createTask(std::bind(&Game::loadMap, &g_game, path))); - return 0; -} - -int LuaScriptInterface::luaGameGetExperienceStage(lua_State* L) -{ - // Game.getExperienceStage(level) - uint32_t level = getNumber(L, 1); - lua_pushnumber(L, g_game.getExperienceStage(level)); - return 1; -} - -int LuaScriptInterface::luaGameGetMonsterCount(lua_State* L) -{ - // Game.getMonsterCount() - lua_pushnumber(L, g_game.getMonstersOnline()); - return 1; -} - -int LuaScriptInterface::luaGameGetPlayerCount(lua_State* L) -{ - // Game.getPlayerCount() - lua_pushnumber(L, g_game.getPlayersOnline()); - return 1; -} - -int LuaScriptInterface::luaGameGetNpcCount(lua_State* L) -{ - // Game.getNpcCount() - lua_pushnumber(L, g_game.getNpcsOnline()); - return 1; -} - -int LuaScriptInterface::luaGameGetTowns(lua_State* L) -{ - // Game.getTowns() - const auto& towns = g_game.map.towns.getTowns(); - lua_createtable(L, towns.size(), 0); - - int index = 0; - for (auto townEntry : towns) { - pushUserdata(L, townEntry.second); - setMetatable(L, -1, "Town"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaGameGetHouses(lua_State* L) -{ - // Game.getHouses() - const auto& houses = g_game.map.houses.getHouses(); - lua_createtable(L, houses.size(), 0); - - int index = 0; - for (auto houseEntry : houses) { - pushUserdata(L, houseEntry.second); - setMetatable(L, -1, "House"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaGameGetGameState(lua_State* L) -{ - // Game.getGameState() - lua_pushnumber(L, g_game.getGameState()); - return 1; -} - -int LuaScriptInterface::luaGameSetGameState(lua_State* L) -{ - // Game.setGameState(state) - GameState_t state = getNumber(L, 1); - g_game.setGameState(state); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaGameGetWorldType(lua_State* L) -{ - // Game.getWorldType() - lua_pushnumber(L, g_game.getWorldType()); - return 1; -} - -int LuaScriptInterface::luaGameSetWorldType(lua_State* L) -{ - // Game.setWorldType(type) - WorldType_t type = getNumber(L, 1); - g_game.setWorldType(type); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaGameGetReturnMessage(lua_State* L) -{ - // Game.getReturnMessage(value) - ReturnValue value = getNumber(L, 1); - pushString(L, getReturnMessage(value)); - return 1; -} - -int LuaScriptInterface::luaGameCreateItem(lua_State* L) -{ - // Game.createItem(itemId[, count[, position]]) - uint16_t count = getNumber(L, 2, 1); - uint16_t id; - if (isNumber(L, 1)) { - id = getNumber(L, 1); - } else { - id = Item::items.getItemIdByName(getString(L, 1)); - if (id == 0) { - lua_pushnil(L); - return 1; - } - } - - const ItemType& it = Item::items[id]; - if (it.stackable) { - count = std::min(count, 100); - } - - Item* item = Item::CreateItem(id, count); - if (!item) { - lua_pushnil(L); - return 1; - } - - if (lua_gettop(L) >= 3) { - const Position& position = getPosition(L, 3); - Tile* tile = g_game.map.getTile(position); - if (!tile) { - delete item; - lua_pushnil(L); - return 1; - } - - g_game.internalAddItem(tile, item, INDEX_WHEREEVER, FLAG_NOLIMIT); - } else { - getScriptEnv()->addTempItem(item); - item->setParent(VirtualCylinder::virtualCylinder); - } - - pushUserdata(L, item); - setItemMetatable(L, -1, item); - return 1; -} - -int LuaScriptInterface::luaGameCreateContainer(lua_State* L) -{ - // Game.createContainer(itemId, size[, position]) - uint16_t size = getNumber(L, 2); - uint16_t id; - if (isNumber(L, 1)) { - id = getNumber(L, 1); - } else { - id = Item::items.getItemIdByName(getString(L, 1)); - if (id == 0) { - lua_pushnil(L); - return 1; - } - } - - Container* container = Item::CreateItemAsContainer(id, size); - if (!container) { - lua_pushnil(L); - return 1; - } - - if (lua_gettop(L) >= 3) { - const Position& position = getPosition(L, 3); - Tile* tile = g_game.map.getTile(position); - if (!tile) { - delete container; - lua_pushnil(L); - return 1; - } - - g_game.internalAddItem(tile, container, INDEX_WHEREEVER, FLAG_NOLIMIT); - } else { - getScriptEnv()->addTempItem(container); - container->setParent(VirtualCylinder::virtualCylinder); - } - - pushUserdata(L, container); - setMetatable(L, -1, "Container"); - return 1; -} - -int LuaScriptInterface::luaGameCreateMonster(lua_State* L) -{ - // Game.createMonster(monsterName, position[, extended = false[, force = false]]) - Monster* monster = Monster::createMonster(getString(L, 1)); - if (!monster) { - lua_pushnil(L); - return 1; - } - - const Position& position = getPosition(L, 2); - bool extended = getBoolean(L, 3, false); - bool force = getBoolean(L, 4, false); - if (g_game.placeCreature(monster, position, extended, force)) { - pushUserdata(L, monster); - setMetatable(L, -1, "Monster"); - } else { - delete monster; - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGameCreateNpc(lua_State* L) -{ - // Game.createNpc(npcName, position[, extended = false[, force = false]]) - Npc* npc = Npc::createNpc(getString(L, 1)); - if (!npc) { - lua_pushnil(L); - return 1; - } - - const Position& position = getPosition(L, 2); - bool extended = getBoolean(L, 3, false); - bool force = getBoolean(L, 4, false); - if (g_game.placeCreature(npc, position, extended, force)) { - pushUserdata(L, npc); - setMetatable(L, -1, "Npc"); - } else { - delete npc; - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGameCreateTile(lua_State* L) -{ - // Game.createTile(x, y, z[, isDynamic = false]) - // Game.createTile(position[, isDynamic = false]) - Position position; - bool isDynamic; - if (isTable(L, 1)) { - position = getPosition(L, 1); - isDynamic = getBoolean(L, 2, false); - } else { - position.x = getNumber(L, 1); - position.y = getNumber(L, 2); - position.z = getNumber(L, 3); - isDynamic = getBoolean(L, 4, false); - } - - Tile* tile = g_game.map.getTile(position); - if (!tile) { - if (isDynamic) { - tile = new DynamicTile(position.x, position.y, position.z); - } else { - tile = new StaticTile(position.x, position.y, position.z); - } - - g_game.map.setTile(position, tile); - } - - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - return 1; -} - -int LuaScriptInterface::luaGameStartRaid(lua_State* L) -{ - // Game.startRaid(raidName) - const std::string& raidName = getString(L, 1); - - Raid* raid = g_game.raids.getRaidByName(raidName); - if (raid) { - raid->startRaid(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGameHasEffect(lua_State* L) -{ - // Game.hasEffect(effectId) - uint8_t effectId = getNumber(L, 1); - pushBoolean(L, g_game.hasEffect(effectId)); - return 1; -} - -int LuaScriptInterface::luaGameHasDistanceEffect(lua_State* L) -{ - // Game.hasDistanceEffect(effectId) - uint8_t effectId = getNumber(L, 1); - pushBoolean(L, g_game.hasDistanceEffect(effectId)); - return 1; -} - -// Variant -int LuaScriptInterface::luaVariantCreate(lua_State* L) -{ - // Variant(number or string or position or thing) - LuaVariant variant; - if (isUserdata(L, 2)) { - if (Thing* thing = getThing(L, 2)) { - variant.type = VARIANT_TARGETPOSITION; - variant.pos = thing->getPosition(); - } - } else if (isTable(L, 2)) { - variant.type = VARIANT_POSITION; - variant.pos = getPosition(L, 2); - } else if (isNumber(L, 2)) { - variant.type = VARIANT_NUMBER; - variant.number = getNumber(L, 2); - } else if (isString(L, 2)) { - variant.type = VARIANT_STRING; - variant.text = getString(L, 2); - } - pushVariant(L, variant); - return 1; -} - -int LuaScriptInterface::luaVariantGetNumber(lua_State* L) -{ - // Variant:getNumber() - const LuaVariant& variant = getVariant(L, 1); - if (variant.type == VARIANT_NUMBER) { - lua_pushnumber(L, variant.number); - } else { - lua_pushnumber(L, 0); - } - return 1; -} - -int LuaScriptInterface::luaVariantGetString(lua_State* L) -{ - // Variant:getString() - const LuaVariant& variant = getVariant(L, 1); - if (variant.type == VARIANT_STRING) { - pushString(L, variant.text); - } else { - pushString(L, std::string()); - } - return 1; -} - -int LuaScriptInterface::luaVariantGetPosition(lua_State* L) -{ - // Variant:getPosition() - const LuaVariant& variant = getVariant(L, 1); - if (variant.type == VARIANT_POSITION || variant.type == VARIANT_TARGETPOSITION) { - pushPosition(L, variant.pos); - } else { - pushPosition(L, Position()); - } - return 1; -} - -// Position -int LuaScriptInterface::luaPositionCreate(lua_State* L) -{ - // Position([x = 0[, y = 0[, z = 0[, stackpos = 0]]]]) - // Position([position]) - if (lua_gettop(L) <= 1) { - pushPosition(L, Position()); - return 1; - } - - int32_t stackpos; - if (isTable(L, 2)) { - const Position& position = getPosition(L, 2, stackpos); - pushPosition(L, position, stackpos); - } else { - uint16_t x = getNumber(L, 2, 0); - uint16_t y = getNumber(L, 3, 0); - uint8_t z = getNumber(L, 4, 0); - stackpos = getNumber(L, 5, 0); - - pushPosition(L, Position(x, y, z), stackpos); - } - return 1; -} - -int LuaScriptInterface::luaPositionAdd(lua_State* L) -{ - // positionValue = position + positionEx - int32_t stackpos; - const Position& position = getPosition(L, 1, stackpos); - - Position positionEx; - if (stackpos == 0) { - positionEx = getPosition(L, 2, stackpos); - } else { - positionEx = getPosition(L, 2); - } - - pushPosition(L, position + positionEx, stackpos); - return 1; -} - -int LuaScriptInterface::luaPositionSub(lua_State* L) -{ - // positionValue = position - positionEx - int32_t stackpos; - const Position& position = getPosition(L, 1, stackpos); - - Position positionEx; - if (stackpos == 0) { - positionEx = getPosition(L, 2, stackpos); - } else { - positionEx = getPosition(L, 2); - } - - pushPosition(L, position - positionEx, stackpos); - return 1; -} - -int LuaScriptInterface::luaPositionCompare(lua_State* L) -{ - // position == positionEx - const Position& positionEx = getPosition(L, 2); - const Position& position = getPosition(L, 1); - pushBoolean(L, position == positionEx); - return 1; -} - -int LuaScriptInterface::luaPositionGetDistance(lua_State* L) -{ - // position:getDistance(positionEx) - const Position& positionEx = getPosition(L, 2); - const Position& position = getPosition(L, 1); - lua_pushnumber(L, std::max( - std::max( - std::abs(Position::getDistanceX(position, positionEx)), - std::abs(Position::getDistanceY(position, positionEx)) - ), - std::abs(Position::getDistanceZ(position, positionEx)) - )); - return 1; -} - -int LuaScriptInterface::luaPositionIsSightClear(lua_State* L) -{ - // position:isSightClear(positionEx[, sameFloor = true]) - bool sameFloor = getBoolean(L, 3, true); - const Position& positionEx = getPosition(L, 2); - const Position& position = getPosition(L, 1); - pushBoolean(L, g_game.isSightClear(position, positionEx, sameFloor)); - return 1; -} - -int LuaScriptInterface::luaPositionSendMagicEffect(lua_State* L) -{ - // position:sendMagicEffect(magicEffect[, player = nullptr]) - SpectatorVec list; - if (lua_gettop(L) >= 3) { - Player* player = getPlayer(L, 3); - if (player) { - list.insert(player); - } - } - - MagicEffectClasses magicEffect = getNumber(L, 2); - const Position& position = getPosition(L, 1); - if (!list.empty()) { - Game::addMagicEffect(list, position, magicEffect); - } else { - g_game.addMagicEffect(position, magicEffect); - } - - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPositionSendDistanceEffect(lua_State* L) -{ - // position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr]) - SpectatorVec list; - if (lua_gettop(L) >= 4) { - Player* player = getPlayer(L, 4); - if (player) { - list.insert(player); - } - } - - ShootType_t distanceEffect = getNumber(L, 3); - const Position& positionEx = getPosition(L, 2); - const Position& position = getPosition(L, 1); - if (!list.empty()) { - Game::addDistanceEffect(list, position, positionEx, distanceEffect); - } else { - g_game.addDistanceEffect(position, positionEx, distanceEffect); - } - - pushBoolean(L, true); - return 1; -} - -// Tile -int LuaScriptInterface::luaTileCreate(lua_State* L) -{ - // Tile(x, y, z) - // Tile(position) - Tile* tile; - if (isTable(L, 2)) { - tile = g_game.map.getTile(getPosition(L, 2)); - } else { - uint8_t z = getNumber(L, 4); - uint16_t y = getNumber(L, 3); - uint16_t x = getNumber(L, 2); - tile = g_game.map.getTile(x, y, z); - } - - if (tile) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetPosition(lua_State* L) -{ - // tile:getPosition() - Tile* tile = getUserdata(L, 1); - if (tile) { - pushPosition(L, tile->getPosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetGround(lua_State* L) -{ - // tile:getGround() - Tile* tile = getUserdata(L, 1); - if (tile && tile->getGround()) { - pushUserdata(L, tile->getGround()); - setItemMetatable(L, -1, tile->getGround()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetThing(lua_State* L) -{ - // tile:getThing(index) - int32_t index = getNumber(L, 2); - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Thing* thing = tile->getThing(index); - if (!thing) { - lua_pushnil(L); - return 1; - } - - if (Creature* creature = thing->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (Item* item = thing->getItem()) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetThingCount(lua_State* L) -{ - // tile:getThingCount() - Tile* tile = getUserdata(L, 1); - if (tile) { - lua_pushnumber(L, tile->getThingCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetTopVisibleThing(lua_State* L) -{ - // tile:getTopVisibleThing(creature) - Creature* creature = getCreature(L, 2); - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Thing* thing = tile->getTopVisibleThing(creature); - if (!thing) { - lua_pushnil(L); - return 1; - } - - if (Creature* visibleCreature = thing->getCreature()) { - pushUserdata(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); - } else if (Item* visibleItem = thing->getItem()) { - pushUserdata(L, visibleItem); - setItemMetatable(L, -1, visibleItem); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetTopTopItem(lua_State* L) -{ - // tile:getTopTopItem() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Item* item = tile->getTopTopItem(); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetTopDownItem(lua_State* L) -{ - // tile:getTopDownItem() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Item* item = tile->getTopDownItem(); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetFieldItem(lua_State* L) -{ - // tile:getFieldItem() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Item* item = tile->getFieldItem(); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetItemById(lua_State* L) -{ - // tile:getItemById(itemId[, subType = -1]) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - int32_t subType = getNumber(L, 3, -1); - - Item* item = g_game.findItemOfType(tile, itemId, false, subType); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetItemByType(lua_State* L) -{ - // tile:getItemByType(itemType) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - bool found; - - ItemTypes_t itemType = getNumber(L, 2); - switch (itemType) { - case ITEM_TYPE_TELEPORT: - found = tile->hasFlag(TILESTATE_TELEPORT); - break; - case ITEM_TYPE_MAGICFIELD: - found = tile->hasFlag(TILESTATE_MAGICFIELD); - break; - case ITEM_TYPE_MAILBOX: - found = tile->hasFlag(TILESTATE_MAILBOX); - break; - case ITEM_TYPE_TRASHHOLDER: - found = tile->hasFlag(TILESTATE_TRASHHOLDER); - break; - case ITEM_TYPE_BED: - found = tile->hasFlag(TILESTATE_BED); - break; - case ITEM_TYPE_DEPOT: - found = tile->hasFlag(TILESTATE_DEPOT); - break; - default: - found = true; - break; - } - - if (!found) { - lua_pushnil(L); - return 1; - } - - if (Item* item = tile->getGround()) { - const ItemType& it = Item::items[item->getID()]; - if (it.type == itemType) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - return 1; - } - } - - if (const TileItemVector* items = tile->getItemList()) { - for (Item* item : *items) { - const ItemType& it = Item::items[item->getID()]; - if (it.type == itemType) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - return 1; - } - } - } - - lua_pushnil(L); - return 1; -} - -int LuaScriptInterface::luaTileGetItemByTopOrder(lua_State* L) -{ - // tile:getItemByTopOrder(topOrder) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - int32_t topOrder = getNumber(L, 2); - - Item* item = tile->getItemByTopOrder(topOrder); - if (!item) { - lua_pushnil(L); - return 1; - } - - pushUserdata(L, item); - setItemMetatable(L, -1, item); - return 1; -} - -int LuaScriptInterface::luaTileGetItemCountById(lua_State* L) -{ - // tile:getItemCountById(itemId[, subType = -1]) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - int32_t subType = getNumber(L, 3, -1); - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - lua_pushnumber(L, tile->getItemTypeCount(itemId, subType)); - return 1; -} - -int LuaScriptInterface::luaTileGetBottomCreature(lua_State* L) -{ - // tile:getBottomCreature() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - const Creature* creature = tile->getBottomCreature(); - if (!creature) { - lua_pushnil(L); - return 1; - } - - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - return 1; -} - -int LuaScriptInterface::luaTileGetTopCreature(lua_State* L) -{ - // tile:getTopCreature() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Creature* creature = tile->getTopCreature(); - if (!creature) { - lua_pushnil(L); - return 1; - } - - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - return 1; -} - -int LuaScriptInterface::luaTileGetBottomVisibleCreature(lua_State* L) -{ - // tile:getBottomVisibleCreature(creature) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Creature* creature = getCreature(L, 2); - if (!creature) { - lua_pushnil(L); - return 1; - } - - const Creature* visibleCreature = tile->getBottomVisibleCreature(creature); - if (visibleCreature) { - pushUserdata(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetTopVisibleCreature(lua_State* L) -{ - // tile:getTopVisibleCreature(creature) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Creature* creature = getCreature(L, 2); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Creature* visibleCreature = tile->getTopVisibleCreature(creature); - if (visibleCreature) { - pushUserdata(L, visibleCreature); - setCreatureMetatable(L, -1, visibleCreature); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetItems(lua_State* L) -{ - // tile:getItems() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - TileItemVector* itemVector = tile->getItemList(); - if (!itemVector) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, itemVector->size(), 0); - - int index = 0; - for (Item* item : *itemVector) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaTileGetItemCount(lua_State* L) -{ - // tile:getItemCount() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - lua_pushnumber(L, tile->getItemCount()); - return 1; -} - -int LuaScriptInterface::luaTileGetDownItemCount(lua_State* L) -{ - // tile:getDownItemCount() - Tile* tile = getUserdata(L, 1); - if (tile) { - lua_pushnumber(L, tile->getDownItemCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetTopItemCount(lua_State* L) -{ - // tile:getTopItemCount() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - lua_pushnumber(L, tile->getTopItemCount()); - return 1; -} - -int LuaScriptInterface::luaTileGetCreatures(lua_State* L) -{ - // tile:getCreatures() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - CreatureVector* creatureVector = tile->getCreatures(); - if (!creatureVector) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, creatureVector->size(), 0); - - int index = 0; - for (Creature* creature : *creatureVector) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaTileGetCreatureCount(lua_State* L) -{ - // tile:getCreatureCount() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - lua_pushnumber(L, tile->getCreatureCount()); - return 1; -} - -int LuaScriptInterface::luaTileHasProperty(lua_State* L) -{ - // tile:hasProperty(property[, item]) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Item* item; - if (lua_gettop(L) >= 3) { - item = getUserdata(L, 3); - } else { - item = nullptr; - } - - ITEMPROPERTY property = getNumber(L, 2); - if (item) { - pushBoolean(L, tile->hasProperty(item, property)); - } else { - pushBoolean(L, tile->hasProperty(property)); - } - return 1; -} - -int LuaScriptInterface::luaTileGetThingIndex(lua_State* L) -{ - // tile:getThingIndex(thing) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Thing* thing = getThing(L, 2); - if (thing) { - lua_pushnumber(L, tile->getThingIndex(thing)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileHasFlag(lua_State* L) -{ - // tile:hasFlag(flag) - Tile* tile = getUserdata(L, 1); - if (tile) { - tileflags_t flag = getNumber(L, 2); - pushBoolean(L, tile->hasFlag(flag)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileQueryAdd(lua_State* L) -{ - // tile:queryAdd(thing[, flags]) - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - Thing* thing = getThing(L, 2); - if (thing) { - uint32_t flags = getNumber(L, 3, 0); - lua_pushnumber(L, tile->queryAdd(0, *thing, 1, flags)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTileGetHouse(lua_State* L) -{ - // tile:getHouse() - Tile* tile = getUserdata(L, 1); - if (!tile) { - lua_pushnil(L); - return 1; - } - - if (HouseTile* houseTile = dynamic_cast(tile)) { - pushUserdata(L, houseTile->getHouse()); - setMetatable(L, -1, "House"); - } else { - lua_pushnil(L); - } - return 1; -} - -// NetworkMessage -int LuaScriptInterface::luaNetworkMessageCreate(lua_State* L) -{ - // NetworkMessage() - pushUserdata(L, new NetworkMessage); - setMetatable(L, -1, "NetworkMessage"); - return 1; -} - -int LuaScriptInterface::luaNetworkMessageDelete(lua_State* L) -{ - NetworkMessage** messagePtr = getRawUserdata(L, 1); - if (messagePtr && *messagePtr) { - delete *messagePtr; - *messagePtr = nullptr; - } - return 0; -} - -int LuaScriptInterface::luaNetworkMessageGetByte(lua_State* L) -{ - // networkMessage:getByte() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - lua_pushnumber(L, message->getByte()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageGetU16(lua_State* L) -{ - // networkMessage:getU16() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - lua_pushnumber(L, message->get()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageGetU32(lua_State* L) -{ - // networkMessage:getU32() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - lua_pushnumber(L, message->get()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageGetU64(lua_State* L) -{ - // networkMessage:getU64() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - lua_pushnumber(L, message->get()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageGetString(lua_State* L) -{ - // networkMessage:getString() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - pushString(L, message->getString()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageGetPosition(lua_State* L) -{ - // networkMessage:getPosition() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - pushPosition(L, message->getPosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddByte(lua_State* L) -{ - // networkMessage:addByte(number) - uint8_t number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->addByte(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddU16(lua_State* L) -{ - // networkMessage:addU16(number) - uint16_t number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->add(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddU32(lua_State* L) -{ - // networkMessage:addU32(number) - uint32_t number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->add(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddU64(lua_State* L) -{ - // networkMessage:addU64(number) - uint64_t number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->add(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddString(lua_State* L) -{ - // networkMessage:addString(string) - const std::string& string = getString(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->addString(string); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddPosition(lua_State* L) -{ - // networkMessage:addPosition(position) - const Position& position = getPosition(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->addPosition(position); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddDouble(lua_State* L) -{ - // networkMessage:addDouble(number) - double number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->addDouble(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddItem(lua_State* L) -{ - // networkMessage:addItem(item) - Item* item = getUserdata(L, 2); - if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - lua_pushnil(L); - return 1; - } - - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->addItem(item); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageAddItemId(lua_State* L) -{ - // networkMessage:addItemId(itemId) - NetworkMessage* message = getUserdata(L, 1); - if (!message) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - message->addItemId(itemId); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaNetworkMessageReset(lua_State* L) -{ - // networkMessage:reset() - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->reset(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageSkipBytes(lua_State* L) -{ - // networkMessage:skipBytes(number) - int16_t number = getNumber(L, 2); - NetworkMessage* message = getUserdata(L, 1); - if (message) { - message->skipBytes(number); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNetworkMessageSendToPlayer(lua_State* L) -{ - // networkMessage:sendToPlayer(player) - NetworkMessage* message = getUserdata(L, 1); - if (!message) { - lua_pushnil(L); - return 1; - } - - Player* player = getPlayer(L, 2); - if (player) { - player->sendNetworkMessage(*message); - pushBoolean(L, true); - } else { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - lua_pushnil(L); - } - return 1; -} - -// ModalWindow -int LuaScriptInterface::luaModalWindowCreate(lua_State* L) -{ - // ModalWindow(id, title, message) - const std::string& message = getString(L, 4); - const std::string& title = getString(L, 3); - uint32_t id = getNumber(L, 2); - - pushUserdata(L, new ModalWindow(id, title, message)); - setMetatable(L, -1, "ModalWindow"); - return 1; -} - -int LuaScriptInterface::luaModalWindowDelete(lua_State* L) -{ - ModalWindow** windowPtr = getRawUserdata(L, 1); - if (windowPtr && *windowPtr) { - delete *windowPtr; - *windowPtr = nullptr; - } - return 0; -} - -int LuaScriptInterface::luaModalWindowGetId(lua_State* L) -{ - // modalWindow:getId() - ModalWindow* window = getUserdata(L, 1); - if (window) { - lua_pushnumber(L, window->id); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetTitle(lua_State* L) -{ - // modalWindow:getTitle() - ModalWindow* window = getUserdata(L, 1); - if (window) { - pushString(L, window->title); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetMessage(lua_State* L) -{ - // modalWindow:getMessage() - ModalWindow* window = getUserdata(L, 1); - if (window) { - pushString(L, window->message); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSetTitle(lua_State* L) -{ - // modalWindow:setTitle(text) - const std::string& text = getString(L, 2); - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->title = text; - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSetMessage(lua_State* L) -{ - // modalWindow:setMessage(text) - const std::string& text = getString(L, 2); - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->message = text; - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetButtonCount(lua_State* L) -{ - // modalWindow:getButtonCount() - ModalWindow* window = getUserdata(L, 1); - if (window) { - lua_pushnumber(L, window->buttons.size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetChoiceCount(lua_State* L) -{ - // modalWindow:getChoiceCount() - ModalWindow* window = getUserdata(L, 1); - if (window) { - lua_pushnumber(L, window->choices.size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowAddButton(lua_State* L) -{ - // modalWindow:addButton(id, text) - const std::string& text = getString(L, 3); - uint8_t id = getNumber(L, 2); - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->buttons.emplace_back(text, id); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowAddChoice(lua_State* L) -{ - // modalWindow:addChoice(id, text) - const std::string& text = getString(L, 3); - uint8_t id = getNumber(L, 2); - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->choices.emplace_back(text, id); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetDefaultEnterButton(lua_State* L) -{ - // modalWindow:getDefaultEnterButton() - ModalWindow* window = getUserdata(L, 1); - if (window) { - lua_pushnumber(L, window->defaultEnterButton); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSetDefaultEnterButton(lua_State* L) -{ - // modalWindow:setDefaultEnterButton(buttonId) - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->defaultEnterButton = getNumber(L, 2); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowGetDefaultEscapeButton(lua_State* L) -{ - // modalWindow:getDefaultEscapeButton() - ModalWindow* window = getUserdata(L, 1); - if (window) { - lua_pushnumber(L, window->defaultEscapeButton); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSetDefaultEscapeButton(lua_State* L) -{ - // modalWindow:setDefaultEscapeButton(buttonId) - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->defaultEscapeButton = getNumber(L, 2); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowHasPriority(lua_State* L) -{ - // modalWindow:hasPriority() - ModalWindow* window = getUserdata(L, 1); - if (window) { - pushBoolean(L, window->priority); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSetPriority(lua_State* L) -{ - // modalWindow:setPriority(priority) - ModalWindow* window = getUserdata(L, 1); - if (window) { - window->priority = getBoolean(L, 2); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaModalWindowSendToPlayer(lua_State* L) -{ - // modalWindow:sendToPlayer(player) - Player* player = getPlayer(L, 2); - if (!player) { - lua_pushnil(L); - return 1; - } - - ModalWindow* window = getUserdata(L, 1); - if (window) { - if (!player->hasModalWindowOpen(window->id)) { - player->sendModalWindow(*window); - } - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -// Item -int LuaScriptInterface::luaItemCreate(lua_State* L) -{ - // Item(uid) - uint32_t id = getNumber(L, 2); - - Item* item = getScriptEnv()->getItemByUID(id); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemIsItem(lua_State* L) -{ - // item:isItem() - pushBoolean(L, getUserdata(L, 1) != nullptr); - return 1; -} - -int LuaScriptInterface::luaItemGetParent(lua_State* L) -{ - // item:getParent() - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - Cylinder* parent = item->getParent(); - if (!parent) { - lua_pushnil(L); - return 1; - } - - if (Creature* creature = parent->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (Item* parentItem = parent->getItem()) { - pushUserdata(L, parentItem); - setItemMetatable(L, -1, parentItem); - } else if (Tile* tile = parent->getTile()) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else if (parent == VirtualCylinder::virtualCylinder) { - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetTopParent(lua_State* L) -{ - // item:getTopParent() - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - Cylinder* topParent = item->getTopParent(); - if (!topParent) { - lua_pushnil(L); - return 1; - } - - if (Creature* creature = topParent->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (Item* topParentItem = topParent->getItem()) { - pushUserdata(L, topParentItem); - setItemMetatable(L, -1, topParentItem); - } else if (Tile* tile = topParent->getTile()) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else if (topParent == VirtualCylinder::virtualCylinder) { - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetId(lua_State* L) -{ - // item:getId() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getID()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemClone(lua_State* L) -{ - // item:clone() - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - Item* clone = item->clone(); - if (!clone) { - lua_pushnil(L); - return 1; - } - - getScriptEnv()->addTempItem(clone); - clone->setParent(VirtualCylinder::virtualCylinder); - - pushUserdata(L, clone); - setItemMetatable(L, -1, clone); - return 1; -} - -int LuaScriptInterface::luaItemSplit(lua_State* L) -{ - // item:split([count = 1]) - Item** itemPtr = getRawUserdata(L, 1); - if (!itemPtr) { - lua_pushnil(L); - return 1; - } - - Item* item = *itemPtr; - if (!item || !item->isStackable()) { - lua_pushnil(L); - return 1; - } - - uint16_t count = std::min(getNumber(L, 2, 1), item->getItemCount()); - uint16_t diff = item->getItemCount() - count; - - Item* splitItem = item->clone(); - if (!splitItem) { - lua_pushnil(L); - return 1; - } - - ScriptEnvironment* env = getScriptEnv(); - uint32_t uid = env->addThing(item); - - Item* newItem = g_game.transformItem(item, item->getID(), diff); - if (item->isRemoved()) { - env->removeItemByUID(uid); - } - - if (newItem && newItem != item) { - env->insertItem(uid, newItem); - } - - *itemPtr = newItem; - - splitItem->setParent(VirtualCylinder::virtualCylinder); - env->addTempItem(splitItem); - - pushUserdata(L, splitItem); - setItemMetatable(L, -1, splitItem); - return 1; -} - -int LuaScriptInterface::luaItemRemove(lua_State* L) -{ - // item:remove([count = -1]) - Item* item = getUserdata(L, 1); - if (item) { - int32_t count = getNumber(L, 2, -1); - pushBoolean(L, g_game.internalRemoveItem(item, count) == RETURNVALUE_NOERROR); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetUniqueId(lua_State* L) -{ - // item:getUniqueId() - Item* item = getUserdata(L, 1); - if (item) { - uint32_t uniqueId = item->getUniqueId(); - if (uniqueId == 0) { - uniqueId = getScriptEnv()->addThing(item); - } - lua_pushnumber(L, uniqueId); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetActionId(lua_State* L) -{ - // item:getActionId() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getActionId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemSetActionId(lua_State* L) -{ - // item:setActionId(actionId) - uint16_t actionId = getNumber(L, 2); - Item* item = getUserdata(L, 1); - if (item) { - item->setActionId(actionId); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetCount(lua_State* L) -{ - // item:getCount() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getItemCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetCharges(lua_State* L) -{ - // item:getCharges() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getCharges()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetFluidType(lua_State* L) -{ - // item:getFluidType() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getFluidType()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetWeight(lua_State* L) -{ - // item:getWeight() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getWeight()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetSubType(lua_State* L) -{ - // item:getSubType() - Item* item = getUserdata(L, 1); - if (item) { - lua_pushnumber(L, item->getSubType()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetName(lua_State* L) -{ - // item:getName() - Item* item = getUserdata(L, 1); - if (item) { - pushString(L, item->getName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetPluralName(lua_State* L) -{ - // item:getPluralName() - Item* item = getUserdata(L, 1); - if (item) { - pushString(L, item->getPluralName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetArticle(lua_State* L) -{ - // item:getArticle() - Item* item = getUserdata(L, 1); - if (item) { - pushString(L, item->getArticle()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetPosition(lua_State* L) -{ - // item:getPosition() - Item* item = getUserdata(L, 1); - if (item) { - pushPosition(L, item->getPosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetTile(lua_State* L) -{ - // item:getTile() - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - Tile* tile = item->getTile(); - if (tile) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemHasAttribute(lua_State* L) -{ - // item:hasAttribute(key) - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - itemAttrTypes attribute; - if (isNumber(L, 2)) { - attribute = getNumber(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); - } else { - attribute = ITEM_ATTRIBUTE_NONE; - } - - pushBoolean(L, item->hasAttribute(attribute)); - return 1; -} - -int LuaScriptInterface::luaItemGetAttribute(lua_State* L) -{ - // item:getAttribute(key) - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - itemAttrTypes attribute; - if (isNumber(L, 2)) { - attribute = getNumber(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); - } else { - attribute = ITEM_ATTRIBUTE_NONE; - } - - if (ItemAttributes::isIntAttrType(attribute)) { - lua_pushnumber(L, item->getIntAttr(attribute)); - } else if (ItemAttributes::isStrAttrType(attribute)) { - pushString(L, item->getStrAttr(attribute)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemSetAttribute(lua_State* L) -{ - // item:setAttribute(key, value) - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - itemAttrTypes attribute; - if (isNumber(L, 2)) { - attribute = getNumber(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); - } else { - attribute = ITEM_ATTRIBUTE_NONE; - } - - if (ItemAttributes::isIntAttrType(attribute)) { - if (attribute == ITEM_ATTRIBUTE_UNIQUEID) { - reportErrorFunc("Attempt to set protected key \"uid\""); - pushBoolean(L, false); - return 1; - } - - item->setIntAttr(attribute, getNumber(L, 3)); - pushBoolean(L, true); - } else if (ItemAttributes::isStrAttrType(attribute)) { - item->setStrAttr(attribute, getString(L, 3)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemRemoveAttribute(lua_State* L) -{ - // item:removeAttribute(key) - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - itemAttrTypes attribute; - if (isNumber(L, 2)) { - attribute = getNumber(L, 2); - } else if (isString(L, 2)) { - attribute = stringToItemAttribute(getString(L, 2)); - } else { - attribute = ITEM_ATTRIBUTE_NONE; - } - - bool ret = attribute != ITEM_ATTRIBUTE_UNIQUEID; - if (ret) { - item->removeAttribute(attribute); - } else { - reportErrorFunc("Attempt to erase protected key \"uid\""); - } - pushBoolean(L, ret); - return 1; -} - -int LuaScriptInterface::luaItemSerializeAttributes(lua_State* L) -{ - // item:serializeAttributes() - Item* item = getUserdata(L, 1); - if (!item) { - lua_pushnil(L); - return 1; - } - - PropWriteStream propWriteStream; - item->serializeAttr(propWriteStream); - - size_t attributesSize; - const char* attributes = propWriteStream.getStream(attributesSize); - lua_pushlstring(L, attributes, attributesSize); - return 1; -} - -int LuaScriptInterface::luaItemMoveTo(lua_State* L) -{ - // item:moveTo(position or cylinder) - Item** itemPtr = getRawUserdata(L, 1); - if (!itemPtr) { - lua_pushnil(L); - return 1; - } - - Item* item = *itemPtr; - if (!item || item->isRemoved()) { - lua_pushnil(L); - return 1; - } - - Cylinder* toCylinder; - if (isUserdata(L, 2)) { - const LuaDataType type = getUserdataType(L, 2); - switch (type) { - case LuaData_Container: - toCylinder = getUserdata(L, 2); - break; - case LuaData_Player: - toCylinder = getUserdata(L, 2); - break; - case LuaData_Tile: - toCylinder = getUserdata(L, 2); - break; - default: - toCylinder = nullptr; - break; - } - } else { - toCylinder = g_game.map.getTile(getPosition(L, 2)); - } - - if (!toCylinder) { - lua_pushnil(L); - return 1; - } - - if (item->getParent() == toCylinder) { - pushBoolean(L, true); - return 1; - } - - if (item->getParent() == VirtualCylinder::virtualCylinder) { - pushBoolean(L, g_game.internalAddItem(toCylinder, item) == RETURNVALUE_NOERROR); - } else { - Item* moveItem = nullptr; - ReturnValue ret = g_game.internalMoveItem(item->getParent(), toCylinder, INDEX_WHEREEVER, item, item->getItemCount(), &moveItem, FLAG_NOLIMIT | FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE | FLAG_IGNORENOTMOVEABLE); - if (moveItem) { - *itemPtr = moveItem; - } - pushBoolean(L, ret == RETURNVALUE_NOERROR); - } - return 1; -} - -int LuaScriptInterface::luaItemTransform(lua_State* L) -{ - // item:transform(itemId[, count/subType = -1]) - Item** itemPtr = getRawUserdata(L, 1); - if (!itemPtr) { - lua_pushnil(L); - return 1; - } - - Item*& item = *itemPtr; - if (!item) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - int32_t subType = getNumber(L, 3, -1); - if (item->getID() == itemId && (subType == -1 || subType == item->getSubType())) { - pushBoolean(L, true); - return 1; - } - - const ItemType& it = Item::items[itemId]; - if (it.stackable) { - subType = std::min(subType, 100); - } - - ScriptEnvironment* env = getScriptEnv(); - uint32_t uid = env->addThing(item); - - Item* newItem = g_game.transformItem(item, itemId, subType); - if (item->isRemoved()) { - env->removeItemByUID(uid); - } - - if (newItem && newItem != item) { - env->insertItem(uid, newItem); - } - - item = newItem; - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaItemDecay(lua_State* L) -{ - // item:decay() - Item* item = getUserdata(L, 1); - if (item) { - g_game.startDecay(item); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemGetDescription(lua_State* L) -{ - // item:getDescription(distance) - Item* item = getUserdata(L, 1); - if (item) { - int32_t distance = getNumber(L, 2); - pushString(L, item->getDescription(distance)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemHasProperty(lua_State* L) -{ - // item:hasProperty(property) - Item* item = getUserdata(L, 1); - if (item) { - ITEMPROPERTY property = getNumber(L, 2); - pushBoolean(L, item->hasProperty(property)); - } else { - lua_pushnil(L); - } - return 1; -} - -// Container -int LuaScriptInterface::luaContainerCreate(lua_State* L) -{ - // Container(uid) - uint32_t id = getNumber(L, 2); - - Container* container = getScriptEnv()->getContainerByUID(id); - if (container) { - pushUserdata(L, container); - setMetatable(L, -1, "Container"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerGetSize(lua_State* L) -{ - // container:getSize() - Container* container = getUserdata(L, 1); - if (container) { - lua_pushnumber(L, container->size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerGetCapacity(lua_State* L) -{ - // container:getCapacity() - Container* container = getUserdata(L, 1); - if (container) { - lua_pushnumber(L, container->capacity()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerGetEmptySlots(lua_State* L) -{ - // container:getEmptySlots([recursive = false]) - Container* container = getUserdata(L, 1); - if (!container) { - lua_pushnil(L); - return 1; - } - - uint32_t slots = container->capacity() - container->size(); - bool recursive = getBoolean(L, 2, false); - if (recursive) { - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - if (Container* tmpContainer = (*it)->getContainer()) { - slots += tmpContainer->capacity() - tmpContainer->size(); - } - } - } - lua_pushnumber(L, slots); - return 1; -} - -int LuaScriptInterface::luaContainerGetItemHoldingCount(lua_State* L) -{ - // container:getItemHoldingCount() - Container* container = getUserdata(L, 1); - if (container) { - lua_pushnumber(L, container->getItemHoldingCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerGetItem(lua_State* L) -{ - // container:getItem(index) - Container* container = getUserdata(L, 1); - if (!container) { - lua_pushnil(L); - return 1; - } - - uint32_t index = getNumber(L, 2); - Item* item = container->getItemByIndex(index); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerHasItem(lua_State* L) -{ - // container:hasItem(item) - Item* item = getUserdata(L, 2); - Container* container = getUserdata(L, 1); - if (container) { - pushBoolean(L, container->isHoldingItem(item)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerAddItem(lua_State* L) -{ - // container:addItem(itemId[, count/subType = 1[, index = INDEX_WHEREEVER[, flags = 0]]]) - Container* container = getUserdata(L, 1); - if (!container) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - uint32_t subType = getNumber(L, 3, 1); - - Item* item = Item::CreateItem(itemId, std::min(subType, 100)); - if (!item) { - lua_pushnil(L); - return 1; - } - - int32_t index = getNumber(L, 4, INDEX_WHEREEVER); - uint32_t flags = getNumber(L, 5, 0); - - ReturnValue ret = g_game.internalAddItem(container, item, index, flags); - if (ret == RETURNVALUE_NOERROR) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - delete item; - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaContainerAddItemEx(lua_State* L) -{ - // container:addItemEx(item[, index = INDEX_WHEREEVER[, flags = 0]]) - Item* item = getUserdata(L, 2); - if (!item) { - lua_pushnil(L); - return 1; - } - - Container* container = getUserdata(L, 1); - if (!container) { - lua_pushnil(L); - return 1; - } - - if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); - lua_pushnil(L); - return 1; - } - - int32_t index = getNumber(L, 3, INDEX_WHEREEVER); - uint32_t flags = getNumber(L, 4, 0); - ReturnValue ret = g_game.internalAddItem(container, item, index, flags); - if (ret == RETURNVALUE_NOERROR) { - ScriptEnvironment::removeTempItem(item); - } - lua_pushnumber(L, ret); - return 1; -} - -int LuaScriptInterface::luaContainerGetItemCountById(lua_State* L) -{ - // container:getItemCountById(itemId[, subType = -1]) - Container* container = getUserdata(L, 1); - if (!container) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - int32_t subType = getNumber(L, 3, -1); - lua_pushnumber(L, container->getItemTypeCount(itemId, subType)); - return 1; -} - -// Teleport -int LuaScriptInterface::luaTeleportCreate(lua_State* L) -{ - // Teleport(uid) - uint32_t id = getNumber(L, 2); - - Item* item = getScriptEnv()->getItemByUID(id); - if (item && item->getTeleport()) { - pushUserdata(L, item); - setMetatable(L, -1, "Teleport"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTeleportGetDestination(lua_State* L) -{ - // teleport:getDestination() - Teleport* teleport = getUserdata(L, 1); - if (teleport) { - pushPosition(L, teleport->getDestPos()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTeleportSetDestination(lua_State* L) -{ - // teleport:setDestination(position) - Teleport* teleport = getUserdata(L, 1); - if (teleport) { - teleport->setDestPos(getPosition(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -// Creature -int LuaScriptInterface::luaCreatureCreate(lua_State* L) -{ - // Creature(id or name or userdata) - Creature* creature; - if (isNumber(L, 2)) { - creature = g_game.getCreatureByID(getNumber(L, 2)); - } else if (isString(L, 2)) { - creature = g_game.getCreatureByName(getString(L, 2)); - } else if (isUserdata(L, 2)) { - LuaDataType type = getUserdataType(L, 2); - if (type != LuaData_Player && type != LuaData_Monster && type != LuaData_Npc) { - lua_pushnil(L); - return 1; - } - creature = getUserdata(L, 2); - } else { - creature = nullptr; - } - - if (creature) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureRegisterEvent(lua_State* L) -{ - // creature:registerEvent(name) - Creature* creature = getUserdata(L, 1); - if (creature) { - const std::string& name = getString(L, 2); - pushBoolean(L, creature->registerCreatureEvent(name)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureUnregisterEvent(lua_State* L) -{ - // creature:unregisterEvent(name) - const std::string& name = getString(L, 2); - Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->unregisterCreatureEvent(name)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureIsRemoved(lua_State* L) -{ - // creature:isRemoved() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->isRemoved()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureIsCreature(lua_State* L) -{ - // creature:isCreature() - pushBoolean(L, getUserdata(L, 1) != nullptr); - return 1; -} - -int LuaScriptInterface::luaCreatureIsInGhostMode(lua_State* L) -{ - // creature:isInGhostMode() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->isInGhostMode()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureIsHealthHidden(lua_State* L) -{ - // creature:isHealthHidden() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->isHealthHidden()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureCanSee(lua_State* L) -{ - // creature:canSee(position) - const Creature* creature = getUserdata(L, 1); - if (creature) { - const Position& position = getPosition(L, 2); - pushBoolean(L, creature->canSee(position)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureCanSeeCreature(lua_State* L) -{ - // creature:canSeeCreature(creature) - const Creature* creature = getUserdata(L, 1); - if (creature) { - const Creature* otherCreature = getCreature(L, 2); - pushBoolean(L, creature->canSeeCreature(otherCreature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetParent(lua_State* L) -{ - // creature:getParent() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Cylinder* parent = creature->getParent(); - if (!parent) { - lua_pushnil(L); - return 1; - } - - if (Creature* parentCreature = parent->getCreature()) { - pushUserdata(L, parentCreature); - setCreatureMetatable(L, -1, parentCreature); - } else if (Item* item = parent->getItem()) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else if (Tile* tile = parent->getTile()) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetId(lua_State* L) -{ - // creature:getId() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getID()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetName(lua_State* L) -{ - // creature:getName() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushString(L, creature->getName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetTarget(lua_State* L) -{ - // creature:getTarget() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Creature* target = creature->getAttackedCreature(); - if (target) { - pushUserdata(L, target); - setCreatureMetatable(L, -1, target); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetTarget(lua_State* L) -{ - // creature:setTarget(target) - Creature* creature = getUserdata(L, 1); - if (creature) { - Creature* target = getCreature(L, 2); - pushBoolean(L, creature->setAttackedCreature(target)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetFollowCreature(lua_State* L) -{ - // creature:getFollowCreature() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Creature* followCreature = creature->getFollowCreature(); - if (followCreature) { - pushUserdata(L, followCreature); - setCreatureMetatable(L, -1, followCreature); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetFollowCreature(lua_State* L) -{ - // creature:setFollowCreature(followedCreature) - Creature* creature = getUserdata(L, 1); - if (creature) { - Creature* followCreature = getCreature(L, 2); - pushBoolean(L, creature->setFollowCreature(followCreature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetMaster(lua_State* L) -{ - // creature:getMaster() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Creature* master = creature->getMaster(); - if (!master) { - lua_pushnil(L); - return 1; - } - - pushUserdata(L, master); - setCreatureMetatable(L, -1, master); - return 1; -} - -int LuaScriptInterface::luaCreatureSetMaster(lua_State* L) -{ - // creature:setMaster(master) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Creature* master = getCreature(L, 2); - if (master) { - pushBoolean(L, creature->convinceCreature(master)); - } else { - master = creature->getMaster(); - if (master) { - master->removeSummon(creature); - creature->incrementReferenceCounter(); - creature->setDropLoot(true); - } - pushBoolean(L, true); - } - g_game.updateCreatureType(creature); - return 1; -} - -int LuaScriptInterface::luaCreatureGetLight(lua_State* L) -{ - // creature:getLight() - const Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - LightInfo light; - creature->getCreatureLight(light); - lua_pushnumber(L, light.level); - lua_pushnumber(L, light.color); - return 2; -} - -int LuaScriptInterface::luaCreatureSetLight(lua_State* L) -{ - // creature:setLight(color, level) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - LightInfo light; - light.color = getNumber(L, 2); - light.level = getNumber(L, 3); - creature->setCreatureLight(light); - g_game.changeLight(creature); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureGetSpeed(lua_State* L) -{ - // creature:getSpeed() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getSpeed()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetBaseSpeed(lua_State* L) -{ - // creature:getBaseSpeed() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getBaseSpeed()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureChangeSpeed(lua_State* L) -{ - // creature:changeSpeed(delta) - Creature* creature = getCreature(L, 1); - if (!creature) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - int32_t delta = getNumber(L, 2); - g_game.changeSpeed(creature, delta); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureSetDropLoot(lua_State* L) -{ - // creature:setDropLoot(doDrop) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->setDropLoot(getBoolean(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetPosition(lua_State* L) -{ - // creature:getPosition() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushPosition(L, creature->getPosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetTile(lua_State* L) -{ - // creature:getTile() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - Tile* tile = creature->getTile(); - if (tile) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetDirection(lua_State* L) -{ - // creature:getDirection() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getDirection()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetDirection(lua_State* L) -{ - // creature:setDirection(direction) - Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, g_game.internalCreatureTurn(creature, getNumber(L, 2))); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetHealth(lua_State* L) -{ - // creature:getHealth() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getHealth()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureAddHealth(lua_State* L) -{ - // creature:addHealth(healthChange) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - CombatDamage damage; - damage.primary.value = getNumber(L, 2); - if (damage.primary.value >= 0) { - damage.primary.type = COMBAT_HEALING; - } else { - damage.primary.type = COMBAT_UNDEFINEDDAMAGE; - } - pushBoolean(L, g_game.combatChangeHealth(nullptr, creature, damage)); - return 1; -} - -int LuaScriptInterface::luaCreatureGetMaxHealth(lua_State* L) -{ - // creature:getMaxHealth() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getMaxHealth()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetMaxHealth(lua_State* L) -{ - // creature:setMaxHealth(maxHealth) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - creature->healthMax = getNumber(L, 2); - creature->health = std::min(creature->health, creature->healthMax); - g_game.addCreatureHealth(creature); - - Player* player = creature->getPlayer(); - if (player) { - player->sendStats(); - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureSetHiddenHealth(lua_State* L) -{ - // creature:setHiddenHealth(hide) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->setHiddenHealth(getBoolean(L, 2)); - g_game.addCreatureHealth(creature); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetMana(lua_State* L) -{ - // creature:getMana() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getMana()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureAddMana(lua_State* L) -{ - // creature:addMana(manaChange[, animationOnLoss = false]) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - int32_t manaChange = getNumber(L, 2); - bool animationOnLoss = getBoolean(L, 3, false); - if (!animationOnLoss && manaChange < 0) { - creature->changeMana(manaChange); - } else { - g_game.combatChangeMana(nullptr, creature, manaChange, ORIGIN_NONE); - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureGetMaxMana(lua_State* L) -{ - // creature:getMaxMana() - const Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getMaxMana()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetSkull(lua_State* L) -{ - // creature:getSkull() - Creature* creature = getUserdata(L, 1); - if (creature) { - lua_pushnumber(L, creature->getSkull()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetSkull(lua_State* L) -{ - // creature:setSkull(skull) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->setSkull(getNumber(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetOutfit(lua_State* L) -{ - // creature:getOutfit() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushOutfit(L, creature->getCurrentOutfit()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetOutfit(lua_State* L) -{ - // creature:setOutfit(outfit) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->defaultOutfit = getOutfit(L, 2); - g_game.internalCreatureChangeOutfit(creature, creature->defaultOutfit); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetCondition(lua_State* L) -{ - // creature:getCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0]]) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - ConditionType_t conditionType = getNumber(L, 2); - ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); - uint32_t subId = getNumber(L, 4, 0); - - Condition* condition = creature->getCondition(conditionType, conditionId, subId); - if (condition) { - pushUserdata(L, condition); - setWeakMetatable(L, -1, "Condition"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureAddCondition(lua_State* L) -{ - // creature:addCondition(condition[, force = false]) - Creature* creature = getUserdata(L, 1); - Condition* condition = getUserdata(L, 2); - if (creature && condition) { - bool force = getBoolean(L, 3, false); - pushBoolean(L, creature->addCondition(condition->clone(), force)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureRemoveCondition(lua_State* L) -{ - // creature:removeCondition(conditionType[, conditionId = CONDITIONID_COMBAT[, subId = 0[, force = false]]]) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - ConditionType_t conditionType = getNumber(L, 2); - ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); - uint32_t subId = getNumber(L, 4, 0); - Condition* condition = creature->getCondition(conditionType, conditionId, subId); - if (condition) { - bool force = getBoolean(L, 5, false); - creature->removeCondition(condition, force); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureRemove(lua_State* L) -{ - // creature:remove() - Creature** creaturePtr = getRawUserdata(L, 1); - if (!creaturePtr) { - lua_pushnil(L); - return 1; - } - - Creature* creature = *creaturePtr; - if (!creature) { - lua_pushnil(L); - return 1; - } - - Player* player = creature->getPlayer(); - if (player) { - player->kickPlayer(true); - } else { - g_game.removeCreature(creature); - } - - *creaturePtr = nullptr; - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureTeleportTo(lua_State* L) -{ - // creature:teleportTo(position[, pushMovement = false]) - bool pushMovement = getBoolean(L, 3, false); - - const Position& position = getPosition(L, 2); - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - const Position oldPosition = creature->getPosition(); - if (g_game.internalTeleport(creature, position, pushMovement) != RETURNVALUE_NOERROR) { - pushBoolean(L, false); - return 1; - } - - if (!pushMovement) { - if (oldPosition.x == position.x) { - if (oldPosition.y < position.y) { - g_game.internalCreatureTurn(creature, DIRECTION_SOUTH); - } else { - g_game.internalCreatureTurn(creature, DIRECTION_NORTH); - } - } else if (oldPosition.x > position.x) { - g_game.internalCreatureTurn(creature, DIRECTION_WEST); - } else if (oldPosition.x < position.x) { - g_game.internalCreatureTurn(creature, DIRECTION_EAST); - } - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCreatureSay(lua_State* L) -{ - // creature:say(text, type[, ghost = false[, target = nullptr[, position]]]) - int parameters = lua_gettop(L); - - Position position; - if (parameters >= 6) { - position = getPosition(L, 6); - if (!position.x || !position.y) { - reportErrorFunc("Invalid position specified."); - pushBoolean(L, false); - return 1; - } - } - - Creature* target = nullptr; - if (parameters >= 5) { - target = getCreature(L, 5); - } - - bool ghost = getBoolean(L, 4, false); - - SpeakClasses type = getNumber(L, 3); - const std::string& text = getString(L, 2); - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - SpectatorVec list; - if (target) { - list.insert(target); - } - - if (position.x != 0) { - pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list, &position)); - } else { - pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list)); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetDamageMap(lua_State* L) -{ - // creature:getDamageMap() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, creature->damageMap.size(), 0); - for (auto damageEntry : creature->damageMap) { - lua_createtable(L, 0, 2); - setField(L, "total", damageEntry.second.total); - setField(L, "ticks", damageEntry.second.ticks); - lua_rawseti(L, -2, damageEntry.first); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetSummons(lua_State* L) -{ - // creature:getSummons() - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, creature->getSummonCount(), 0); - - int index = 0; - for (Creature* summon : creature->getSummons()) { - pushUserdata(L, summon); - setCreatureMetatable(L, -1, summon); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetDescription(lua_State* L) -{ - // creature:getDescription(distance) - int32_t distance = getNumber(L, 2); - Creature* creature = getUserdata(L, 1); - if (creature) { - pushString(L, creature->getDescription(distance)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureGetPathTo(lua_State* L) -{ - // creature:getPathTo(pos[, minTargetDist = 0[, maxTargetDist = 1[, fullPathSearch = true[, clearSight = true[, maxSearchDist = 0]]]]]) - Creature* creature = getUserdata(L, 1); - if (!creature) { - lua_pushnil(L); - return 1; - } - - const Position& position = getPosition(L, 2); - - FindPathParams fpp; - fpp.minTargetDist = getNumber(L, 3, 0); - fpp.maxTargetDist = getNumber(L, 4, 1); - fpp.fullPathSearch = getBoolean(L, 5, fpp.fullPathSearch); - fpp.clearSight = getBoolean(L, 6, fpp.clearSight); - fpp.maxSearchDist = getNumber(L, 7, fpp.maxSearchDist); - - std::forward_list dirList; - if (creature->getPathTo(position, dirList, fpp)) { - lua_newtable(L); - - int index = 0; - for (Direction dir : dirList) { - lua_pushnumber(L, dir); - lua_rawseti(L, -2, ++index); - } - } else { - pushBoolean(L, false); - } - return 1; -} - -// Player -int LuaScriptInterface::luaPlayerCreate(lua_State* L) -{ - // Player(id or name or userdata) - Player* player; - if (isNumber(L, 2)) { - player = g_game.getPlayerByID(getNumber(L, 2)); - } else if (isString(L, 2)) { - ReturnValue ret = g_game.getPlayerByNameWildcard(getString(L, 2), player); - if (ret != RETURNVALUE_NOERROR) { - lua_pushnil(L); - lua_pushnumber(L, ret); - return 2; - } - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_Player) { - lua_pushnil(L); - return 1; - } - player = getUserdata(L, 2); - } else { - player = nullptr; - } - - if (player) { - pushUserdata(L, player); - setMetatable(L, -1, "Player"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerIsPlayer(lua_State* L) -{ - // player:isPlayer() - pushBoolean(L, getUserdata(L, 1) != nullptr); - return 1; -} - -int LuaScriptInterface::luaPlayerGetGuid(lua_State* L) -{ - // player:getGuid() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getGUID()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetIp(lua_State* L) -{ - // player:getIp() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getIP()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetAccountId(lua_State* L) -{ - // player:getAccountId() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getAccount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetLastLoginSaved(lua_State* L) -{ - // player:getLastLoginSaved() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getLastLoginSaved()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetLastLogout(lua_State* L) -{ - // player:getLastLogout() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getLastLogout()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetAccountType(lua_State* L) -{ - // player:getAccountType() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getAccountType()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetAccountType(lua_State* L) -{ - // player:setAccountType(accountType) - Player* player = getUserdata(L, 1); - if (player) { - player->accountType = getNumber(L, 2); - IOLoginData::setAccountType(player->getAccount(), player->accountType); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetCapacity(lua_State* L) -{ - // player:getCapacity() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getCapacity()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetCapacity(lua_State* L) -{ - // player:setCapacity(capacity) - Player* player = getUserdata(L, 1); - if (player) { - player->capacity = getNumber(L, 2); - player->sendStats(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetFreeCapacity(lua_State* L) -{ - // player:getFreeCapacity() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getFreeCapacity()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetDepotChest(lua_State* L) -{ - // player:getDepotChest(depotId[, autoCreate = false]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint32_t depotId = getNumber(L, 2); - bool autoCreate = getBoolean(L, 3, false); - DepotChest* depotChest = player->getDepotChest(depotId, autoCreate); - if (depotChest) { - pushUserdata(L, depotChest); - setItemMetatable(L, -1, depotChest); - } else { - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetInbox(lua_State* L) -{ - // player:getInbox() - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Inbox* inbox = player->getInbox(); - if (inbox) { - pushUserdata(L, inbox); - setItemMetatable(L, -1, inbox); - } else { - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSkullTime(lua_State* L) -{ - // player:getSkullTime() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getSkullTicks()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetSkullTime(lua_State* L) -{ - // player:setSkullTime(skullTime) - Player* player = getUserdata(L, 1); - if (player) { - player->setSkullTicks(getNumber(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetDeathPenalty(lua_State* L) -{ - // player:getDeathPenalty() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, static_cast(player->getLostPercent() * 100)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetExperience(lua_State* L) -{ - // player:getExperience() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getExperience()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddExperience(lua_State* L) -{ - // player:addExperience(experience[, sendText = false]) - Player* player = getUserdata(L, 1); - if (player) { - int64_t experience = getNumber(L, 2); - bool sendText = getBoolean(L, 3, false); - player->addExperience(nullptr, experience, sendText); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveExperience(lua_State* L) -{ - // player:removeExperience(experience[, sendText = false]) - Player* player = getUserdata(L, 1); - if (player) { - int64_t experience = getNumber(L, 2); - bool sendText = getBoolean(L, 3, false); - player->removeExperience(experience, sendText); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetLevel(lua_State* L) -{ - // player:getLevel() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getLevel()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetMagicLevel(lua_State* L) -{ - // player:getMagicLevel() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getMagicLevel()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetBaseMagicLevel(lua_State* L) -{ - // player:getBaseMagicLevel() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getBaseMagicLevel()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetMaxMana(lua_State* L) -{ - // player:setMaxMana(maxMana) - Player* player = getPlayer(L, 1); - if (player) { - player->manaMax = getNumber(L, 2); - player->mana = std::min(player->mana, player->manaMax); - player->sendStats(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetManaSpent(lua_State* L) -{ - // player:getManaSpent() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getSpentMana()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddManaSpent(lua_State* L) -{ - // player:addManaSpent(amount) - Player* player = getUserdata(L, 1); - if (player) { - player->addManaSpent(getNumber(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSkillLevel(lua_State* L) -{ - // player:getSkillLevel(skillType) - skills_t skillType = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player && skillType <= SKILL_LAST) { - lua_pushnumber(L, player->skills[skillType].level); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetEffectiveSkillLevel(lua_State* L) -{ - // player:getEffectiveSkillLevel(skillType) - skills_t skillType = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player && skillType <= SKILL_LAST) { - lua_pushnumber(L, player->getSkillLevel(skillType)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSkillPercent(lua_State* L) -{ - // player:getSkillPercent(skillType) - skills_t skillType = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player && skillType <= SKILL_LAST) { - lua_pushnumber(L, player->skills[skillType].percent); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSkillTries(lua_State* L) -{ - // player:getSkillTries(skillType) - skills_t skillType = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player && skillType <= SKILL_LAST) { - lua_pushnumber(L, player->skills[skillType].tries); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddSkillTries(lua_State* L) -{ - // player:addSkillTries(skillType, tries) - Player* player = getUserdata(L, 1); - if (player) { - skills_t skillType = getNumber(L, 2); - uint64_t tries = getNumber(L, 3); - player->addSkillAdvance(skillType, tries); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddOfflineTrainingTime(lua_State* L) -{ - // player:addOfflineTrainingTime(time) - Player* player = getUserdata(L, 1); - if (player) { - int32_t time = getNumber(L, 2); - player->addOfflineTrainingTime(time); - player->sendStats(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - - -int LuaScriptInterface::luaPlayerGetOfflineTrainingTime(lua_State* L) -{ - // player:getOfflineTrainingTime() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getOfflineTrainingTime()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveOfflineTrainingTime(lua_State* L) -{ - // player:removeOfflineTrainingTime(time) - Player* player = getUserdata(L, 1); - if (player) { - int32_t time = getNumber(L, 2); - player->removeOfflineTrainingTime(time); - player->sendStats(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddOfflineTrainingTries(lua_State* L) -{ - // player:addOfflineTrainingTries(skillType, tries) - Player* player = getUserdata(L, 1); - if (player) { - skills_t skillType = getNumber(L, 2); - uint64_t tries = getNumber(L, 3); - pushBoolean(L, player->addOfflineTrainingTries(skillType, tries)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetOfflineTrainingSkill(lua_State* L) -{ - // player:getOfflineTrainingSkill() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getOfflineTrainingSkill()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetOfflineTrainingSkill(lua_State* L) -{ - // player:setOfflineTrainingSkill(skillId) - Player* player = getUserdata(L, 1); - if (player) { - uint32_t skillId = getNumber(L, 2); - player->setOfflineTrainingSkill(skillId); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetItemCount(lua_State* L) -{ - // player:getItemCount(itemId[, subType = -1]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - int32_t subType = getNumber(L, 3, -1); - lua_pushnumber(L, player->getItemTypeCount(itemId, subType)); - return 1; -} - -int LuaScriptInterface::luaPlayerGetItemById(lua_State* L) -{ - // player:getItemById(itemId, deepSearch[, subType = -1]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - bool deepSearch = getBoolean(L, 3); - int32_t subType = getNumber(L, 4, -1); - - Item* item = g_game.findItemOfType(player, itemId, deepSearch, subType); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetVocation(lua_State* L) -{ - // player:getVocation() - Player* player = getUserdata(L, 1); - if (player) { - pushUserdata(L, player->getVocation()); - setMetatable(L, -1, "Vocation"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetVocation(lua_State* L) -{ - // player:setVocation(id or name or userdata) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Vocation* vocation; - if (isNumber(L, 2)) { - vocation = g_vocations.getVocation(getNumber(L, 2)); - } else if (isString(L, 2)) { - vocation = g_vocations.getVocation(g_vocations.getVocationId(getString(L, 2))); - } else if (isUserdata(L, 2)) { - vocation = getUserdata(L, 2); - } else { - vocation = nullptr; - } - - if (!vocation) { - pushBoolean(L, false); - return 1; - } - - player->setVocation(vocation->getId()); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerGetSex(lua_State* L) -{ - // player:getSex() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getSex()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetSex(lua_State* L) -{ - // player:setSex(newSex) - Player* player = getUserdata(L, 1); - if (player) { - PlayerSex_t newSex = getNumber(L, 2); - player->setSex(newSex); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetTown(lua_State* L) -{ - // player:getTown() - Player* player = getUserdata(L, 1); - if (player) { - pushUserdata(L, player->getTown()); - setMetatable(L, -1, "Town"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetTown(lua_State* L) -{ - // player:setTown(town) - Town* town = getUserdata(L, 2); - if (!town) { - pushBoolean(L, false); - return 1; - } - - Player* player = getUserdata(L, 1); - if (player) { - player->setTown(town); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetGuild(lua_State* L) -{ - // player:getGuild() - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Guild* guild = player->getGuild(); - if (!guild) { - lua_pushnil(L); - return 1; - } - - pushUserdata(L, guild); - setMetatable(L, -1, "Guild"); - return 1; -} - -int LuaScriptInterface::luaPlayerSetGuild(lua_State* L) -{ - // player:setGuild(guild) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - player->setGuild(getUserdata(L, 2)); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerGetGuildLevel(lua_State* L) -{ - // player:getGuildLevel() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getGuildLevel()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetGuildLevel(lua_State* L) -{ - // player:setGuildLevel(level) - uint8_t level = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - player->setGuildLevel(level); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetGuildNick(lua_State* L) -{ - // player:getGuildNick() - Player* player = getUserdata(L, 1); - if (player) { - pushString(L, player->getGuildNick()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetGuildNick(lua_State* L) -{ - // player:setGuildNick(nick) - const std::string& nick = getString(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - player->setGuildNick(nick); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetGroup(lua_State* L) -{ - // player:getGroup() - Player* player = getUserdata(L, 1); - if (player) { - pushUserdata(L, player->getGroup()); - setMetatable(L, -1, "Group"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetGroup(lua_State* L) -{ - // player:setGroup(group) - Group* group = getUserdata(L, 2); - if (!group) { - pushBoolean(L, false); - return 1; - } - - Player* player = getUserdata(L, 1); - if (player) { - player->setGroup(group); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetStamina(lua_State* L) -{ - // player:getStamina() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getStaminaMinutes()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetStamina(lua_State* L) -{ - // player:setStamina(stamina) - uint16_t stamina = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - player->staminaMinutes = std::min(2520, stamina); - player->sendStats(); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSoul(lua_State* L) -{ - // player:getSoul() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getSoul()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddSoul(lua_State* L) -{ - // player:addSoul(soulChange) - int32_t soulChange = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - player->changeSoul(soulChange); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetMaxSoul(lua_State* L) -{ - // player:getMaxSoul() - Player* player = getUserdata(L, 1); - if (player && player->vocation) { - lua_pushnumber(L, player->vocation->getSoulMax()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetBankBalance(lua_State* L) -{ - // player:getBankBalance() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getBankBalance()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetBankBalance(lua_State* L) -{ - // player:setBankBalance(bankBalance) - Player* player = getUserdata(L, 1); - if (player) { - player->setBankBalance(getNumber(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetStorageValue(lua_State* L) -{ - // player:getStorageValue(key) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint32_t key = getNumber(L, 2); - int32_t value; - if (player->getStorageValue(key, value)) { - lua_pushnumber(L, value); - } else { - lua_pushnumber(L, -1); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetStorageValue(lua_State* L) -{ - // player:setStorageValue(key, value) - int32_t value = getNumber(L, 3); - uint32_t key = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (IS_IN_KEYRANGE(key, RESERVED_RANGE)) { - std::ostringstream ss; - ss << "Accessing reserved range: " << key; - reportErrorFunc(ss.str()); - pushBoolean(L, false); - return 1; - } - - if (player) { - player->addStorageValue(key, value); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddItem(lua_State* L) -{ - // player:addItem(itemId[, count = 1[, canDropOnMap = true[, subType = 1[, slot = CONST_SLOT_WHEREEVER]]]]) - Player* player = getUserdata(L, 1); - if (!player) { - pushBoolean(L, false); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - int32_t count = getNumber(L, 3, 1); - int32_t subType = getNumber(L, 5, 1); - - const ItemType& it = Item::items[itemId]; - - int32_t itemCount = 1; - int parameters = lua_gettop(L); - if (parameters >= 4) { - itemCount = std::max(1, count); - } else if (it.hasSubType()) { - if (it.stackable) { - itemCount = std::ceil(count / 100.f); - } - - subType = count; - } else { - itemCount = std::max(1, count); - } - - bool hasTable = itemCount > 1; - if (hasTable) { - lua_newtable(L); - } else if (itemCount == 0) { - lua_pushnil(L); - return 1; - } - - bool canDropOnMap = getBoolean(L, 4, true); - slots_t slot = getNumber(L, 6, CONST_SLOT_WHEREEVER); - for (int32_t i = 1; i <= itemCount; ++i) { - int32_t stackCount = subType; - if (it.stackable) { - stackCount = std::min(stackCount, 100); - subType -= stackCount; - } - - Item* item = Item::CreateItem(itemId, stackCount); - if (!item) { - if (!hasTable) { - lua_pushnil(L); - } - return 1; - } - - ReturnValue ret = g_game.internalPlayerAddItem(player, item, canDropOnMap, slot); - if (ret != RETURNVALUE_NOERROR) { - delete item; - if (!hasTable) { - lua_pushnil(L); - } - return 1; - } - - if (hasTable) { - lua_pushnumber(L, i); - pushUserdata(L, item); - setItemMetatable(L, -1, item); - lua_settable(L, -3); - } else { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddItemEx(lua_State* L) -{ - // player:addItemEx(item[, canDropOnMap = false[, index = INDEX_WHEREEVER[, flags = 0]]]) - // player:addItemEx(item[, canDropOnMap = true[, slot = CONST_SLOT_WHEREEVER]]) - Item* item = getUserdata(L, 2); - if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - if (item->getParent() != VirtualCylinder::virtualCylinder) { - reportErrorFunc("Item already has a parent"); - pushBoolean(L, false); - return 1; - } - - bool canDropOnMap = getBoolean(L, 3, false); - ReturnValue returnValue; - if (canDropOnMap) { - slots_t slot = getNumber(L, 4, CONST_SLOT_WHEREEVER); - returnValue = g_game.internalPlayerAddItem(player, item, true, slot); - } else { - int32_t index = getNumber(L, 4, INDEX_WHEREEVER); - uint32_t flags = getNumber(L, 5, 0); - returnValue = g_game.internalAddItem(player, item, index, flags); - } - - if (returnValue == RETURNVALUE_NOERROR) { - ScriptEnvironment::removeTempItem(item); - } - lua_pushnumber(L, returnValue); - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveItem(lua_State* L) -{ - // player:removeItem(itemId, count[, subType = -1[, ignoreEquipped = false]]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - uint32_t count = getNumber(L, 3); - int32_t subType = getNumber(L, 4, -1); - bool ignoreEquipped = getBoolean(L, 5, false); - pushBoolean(L, player->removeItemOfType(itemId, count, subType, ignoreEquipped)); - return 1; -} - -int LuaScriptInterface::luaPlayerGetMoney(lua_State* L) -{ - // player:getMoney() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getMoney()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddMoney(lua_State* L) -{ - // player:addMoney(money) - uint64_t money = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - g_game.addMoney(player, money); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveMoney(lua_State* L) -{ - // player:removeMoney(money) - Player* player = getUserdata(L, 1); - if (player) { - uint64_t money = getNumber(L, 2); - pushBoolean(L, g_game.removeMoney(player, money)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerShowTextDialog(lua_State* L) -{ - // player:showTextDialog(itemId[, text[, canWrite[, length]]]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - int32_t length = getNumber(L, 5, -1); - bool canWrite = getBoolean(L, 4, false); - std::string text; - - int parameters = lua_gettop(L); - if (parameters >= 3) { - text = getString(L, 3); - } - - uint16_t itemId; - if (isNumber(L, 2)) { - itemId = getNumber(L, 2); - } else { - itemId = Item::items.getItemIdByName(getString(L, 2)); - if (itemId == 0) { - lua_pushnil(L); - return 1; - } - } - - Item* item = Item::CreateItem(itemId); - if (!item) { - reportErrorFunc(getErrorDesc(LUA_ERROR_ITEM_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - if (length < 0) { - length = Item::items[item->getID()].maxTextLen; - } - - if (!text.empty()) { - item->setText(text); - length = std::max(text.size(), length); - } - - item->setParent(player); - player->setWriteItem(item, length); - player->sendTextWindow(item, length, canWrite); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerSendTextMessage(lua_State* L) -{ - // player:sendTextMessage(type, text[, position, primaryValue = 0, primaryColor = TEXTCOLOR_NONE[, secondaryValue = 0, secondaryColor = TEXTCOLOR_NONE]]) - int parameters = lua_gettop(L); - - TextMessage message(getNumber(L, 2), getString(L, 3)); - if (parameters >= 6) { - message.position = getPosition(L, 4); - message.primary.value = getNumber(L, 5); - message.primary.color = getNumber(L, 6); - } - - if (parameters >= 8) { - message.secondary.value = getNumber(L, 7); - message.secondary.color = getNumber(L, 8); - } - - Player* player = getUserdata(L, 1); - if (player) { - player->sendTextMessage(message); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSendChannelMessage(lua_State* L) -{ - // player:sendChannelMessage(author, text, type, channelId) - uint16_t channelId = getNumber(L, 5); - SpeakClasses type = getNumber(L, 4); - const std::string& text = getString(L, 3); - const std::string& author = getString(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - player->sendChannelMessage(author, text, type, channelId); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSendPrivateMessage(lua_State* L) -{ - // player:sendPrivateMessage(speaker, text[, type]) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - const Player* speaker = getUserdata(L, 2); - const std::string& text = getString(L, 3); - SpeakClasses type = getNumber(L, 4, TALKTYPE_PRIVATE_FROM); - player->sendPrivateMessage(speaker, type, text); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerChannelSay(lua_State* L) -{ - // player:channelSay(speaker, type, text, channelId) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Creature* speaker = getCreature(L, 2); - SpeakClasses type = getNumber(L, 3); - const std::string& text = getString(L, 4); - uint16_t channelId = getNumber(L, 5); - player->sendToChannel(speaker, type, text, channelId); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerOpenChannel(lua_State* L) -{ - // player:openChannel(channelId) - uint16_t channelId = getNumber(L, 2); - Player* player = getUserdata(L, 1); - if (player) { - g_game.playerOpenChannel(player->getID(), channelId); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetSlotItem(lua_State* L) -{ - // player:getSlotItem(slot) - const Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint32_t slot = getNumber(L, 2); - Thing* thing = player->getThing(slot); - if (!thing) { - lua_pushnil(L); - return 1; - } - - Item* item = thing->getItem(); - if (item) { - pushUserdata(L, item); - setItemMetatable(L, -1, item); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetParty(lua_State* L) -{ - // player:getParty() - const Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Party* party = player->getParty(); - if (party) { - pushUserdata(L, party); - setMetatable(L, -1, "Party"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddOutfit(lua_State* L) -{ - // player:addOutfit(lookType) - Player* player = getUserdata(L, 1); - if (player) { - player->addOutfit(getNumber(L, 2), 0); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddOutfitAddon(lua_State* L) -{ - // player:addOutfitAddon(lookType, addon) - Player* player = getUserdata(L, 1); - if (player) { - uint16_t lookType = getNumber(L, 2); - uint8_t addon = getNumber(L, 3); - player->addOutfit(lookType, addon); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveOutfit(lua_State* L) -{ - // player:removeOutfit(lookType) - Player* player = getUserdata(L, 1); - if (player) { - uint16_t lookType = getNumber(L, 2); - pushBoolean(L, player->removeOutfit(lookType)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveOutfitAddon(lua_State* L) -{ - // player:removeOutfitAddon(lookType, addon) - Player* player = getUserdata(L, 1); - if (player) { - uint16_t lookType = getNumber(L, 2); - uint8_t addon = getNumber(L, 3); - pushBoolean(L, player->removeOutfitAddon(lookType, addon)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerHasOutfit(lua_State* L) -{ - // player:hasOutfit(lookType[, addon = 0]) - Player* player = getUserdata(L, 1); - if (player) { - uint16_t lookType = getNumber(L, 2); - uint8_t addon = getNumber(L, 3, 0); - pushBoolean(L, player->canWear(lookType, addon)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSendOutfitWindow(lua_State* L) -{ - // player:sendOutfitWindow() - Player* player = getUserdata(L, 1); - if (player) { - player->sendOutfitWindow(); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddMount(lua_State* L) -{ - // player:addMount(mountId) - Player* player = getUserdata(L, 1); - if (player) { - uint8_t mountId = getNumber(L, 2); - pushBoolean(L, player->tameMount(mountId)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveMount(lua_State* L) -{ - // player:removeMount(mountId) - Player* player = getUserdata(L, 1); - if (player) { - uint8_t mountId = getNumber(L, 2); - pushBoolean(L, player->untameMount(mountId)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerHasMount(lua_State* L) -{ - // player:hasMount(mountId) - const Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint8_t mountId = getNumber(L, 2); - Mount* mount = g_game.mounts.getMountByID(mountId); - if (mount) { - pushBoolean(L, player->hasMount(mount)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetPremiumDays(lua_State* L) -{ - // player:getPremiumDays() - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->premiumDays); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddPremiumDays(lua_State* L) -{ - // player:addPremiumDays(days) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - if (player->premiumDays != std::numeric_limits::max()) { - uint16_t days = getNumber(L, 2); - int32_t addDays = std::min(0xFFFE - player->premiumDays, days); - if (addDays > 0) { - player->setPremiumDays(player->premiumDays + addDays); - IOLoginData::addPremiumDays(player->getAccount(), addDays); - } - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerRemovePremiumDays(lua_State* L) -{ - // player:removePremiumDays(days) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - if (player->premiumDays != std::numeric_limits::max()) { - uint16_t days = getNumber(L, 2); - int32_t removeDays = std::min(player->premiumDays, days); - if (removeDays > 0) { - player->setPremiumDays(player->premiumDays - removeDays); - IOLoginData::removePremiumDays(player->getAccount(), removeDays); - } - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerHasBlessing(lua_State* L) -{ - // player:hasBlessing(blessing) - uint8_t blessing = getNumber(L, 2) - 1; - Player* player = getUserdata(L, 1); - if (player) { - pushBoolean(L, player->hasBlessing(blessing)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddBlessing(lua_State* L) -{ - // player:addBlessing(blessing) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint8_t blessing = getNumber(L, 2) - 1; - if (player->hasBlessing(blessing)) { - pushBoolean(L, false); - return 1; - } - - player->addBlessing(1 << blessing); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerRemoveBlessing(lua_State* L) -{ - // player:removeBlessing(blessing) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - uint8_t blessing = getNumber(L, 2) - 1; - if (!player->hasBlessing(blessing)) { - pushBoolean(L, false); - return 1; - } - - player->removeBlessing(1 << blessing); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerCanLearnSpell(lua_State* L) -{ - // player:canLearnSpell(spellName) - const Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - const std::string& spellName = getString(L, 2); - InstantSpell* spell = g_spells->getInstantSpellByName(spellName); - if (!spell) { - reportErrorFunc("Spell \"" + spellName + "\" not found"); - pushBoolean(L, false); - return 1; - } - - if (player->hasFlag(PlayerFlag_IgnoreSpellCheck)) { - pushBoolean(L, true); - return 1; - } - - const auto& vocMap = spell->getVocMap(); - if (vocMap.count(player->getVocationId()) == 0) { - pushBoolean(L, false); - } else if (player->getLevel() < spell->getLevel()) { - pushBoolean(L, false); - } else if (player->getMagicLevel() < spell->getMagicLevel()) { - pushBoolean(L, false); - } else { - pushBoolean(L, true); - } - return 1; -} - -int LuaScriptInterface::luaPlayerLearnSpell(lua_State* L) -{ - // player:learnSpell(spellName) - Player* player = getUserdata(L, 1); - if (player) { - const std::string& spellName = getString(L, 2); - player->learnInstantSpell(spellName); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerForgetSpell(lua_State* L) -{ - // player:forgetSpell(spellName) - Player* player = getUserdata(L, 1); - if (player) { - const std::string& spellName = getString(L, 2); - player->forgetInstantSpell(spellName); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerHasLearnedSpell(lua_State* L) -{ - // player:hasLearnedSpell(spellName) - Player* player = getUserdata(L, 1); - if (player) { - const std::string& spellName = getString(L, 2); - pushBoolean(L, player->hasLearnedInstantSpell(spellName)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSendTutorial(lua_State* L) -{ - // player:sendTutorial(tutorialId) - Player* player = getUserdata(L, 1); - if (player) { - uint8_t tutorialId = getNumber(L, 2); - player->sendTutorial(tutorialId); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerAddMapMark(lua_State* L) -{ - // player:addMapMark(position, type, description) - Player* player = getUserdata(L, 1); - if (player) { - const Position& position = getPosition(L, 2); - uint8_t type = getNumber(L, 3); - const std::string& description = getString(L, 4); - player->sendAddMarker(position, type, description); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSave(lua_State* L) -{ - // player:save() - Player* player = getUserdata(L, 1); - if (player) { - player->loginPosition = player->getPosition(); - pushBoolean(L, IOLoginData::savePlayer(player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerPopupFYI(lua_State* L) -{ - // player:popupFYI(message) - Player* player = getUserdata(L, 1); - if (player) { - const std::string& message = getString(L, 2); - player->sendFYIBox(message); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerIsPzLocked(lua_State* L) -{ - // player:isPzLocked() - Player* player = getUserdata(L, 1); - if (player) { - pushBoolean(L, player->isPzLocked()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetClient(lua_State* L) -{ - // player:getClient() - Player* player = getUserdata(L, 1); - if (player) { - lua_createtable(L, 0, 2); - setField(L, "version", player->getProtocolVersion()); - setField(L, "os", player->getOperatingSystem()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetHouse(lua_State* L) -{ - // player:getHouse() - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - House* house = g_game.map.houses.getHouseByPlayerId(player->getGUID()); - if (house) { - pushUserdata(L, house); - setMetatable(L, -1, "House"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerSetGhostMode(lua_State* L) -{ - // player:setGhostMode(enabled) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - bool enabled = getBoolean(L, 2); - if (player->isInGhostMode() == enabled) { - pushBoolean(L, true); - return 1; - } - - player->switchGhostMode(); - - Tile* tile = player->getTile(); - const Position& position = player->getPosition(); - - SpectatorVec list; - g_game.map.getSpectators(list, position, true, true); - for (Creature* spectator : list) { - Player* tmpPlayer = spectator->getPlayer(); - if (tmpPlayer != player && !tmpPlayer->isAccessPlayer()) { - if (enabled) { - tmpPlayer->sendRemoveTileThing(position, tile->getStackposOfCreature(tmpPlayer, player)); - } else { - tmpPlayer->sendCreatureAppear(player, position, true); - } - } else { - tmpPlayer->sendCreatureChangeVisible(player, !enabled); - } - } - - if (player->isInGhostMode()) { - for (const auto& it : g_game.getPlayers()) { - if (!it.second->isAccessPlayer()) { - it.second->notifyStatusChange(player, VIPSTATUS_OFFLINE); - } - } - IOLoginData::updateOnlineStatus(player->getGUID(), false); - } else { - for (const auto& it : g_game.getPlayers()) { - if (!it.second->isAccessPlayer()) { - it.second->notifyStatusChange(player, VIPSTATUS_ONLINE); - } - } - IOLoginData::updateOnlineStatus(player->getGUID(), true); - } - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaPlayerGetContainerId(lua_State* L) -{ - // player:getContainerId(container) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Container* container = getUserdata(L, 2); - if (container) { - lua_pushnumber(L, player->getContainerID(container)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetContainerById(lua_State* L) -{ - // player:getContainerById(id) - Player* player = getUserdata(L, 1); - if (!player) { - lua_pushnil(L); - return 1; - } - - Container* container = player->getContainerByID(getNumber(L, 2)); - if (container) { - pushUserdata(L, container); - setMetatable(L, -1, "Container"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPlayerGetContainerIndex(lua_State* L) -{ - // player:getContainerIndex(id) - Player* player = getUserdata(L, 1); - if (player) { - lua_pushnumber(L, player->getContainerIndex(getNumber(L, 2))); - } else { - lua_pushnil(L); - } - return 1; -} - -// Monster -int LuaScriptInterface::luaMonsterCreate(lua_State* L) -{ - // Monster(id or userdata) - Monster* monster; - if (isNumber(L, 2)) { - monster = g_game.getMonsterByID(getNumber(L, 2)); - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_Monster) { - lua_pushnil(L); - return 1; - } - monster = getUserdata(L, 2); - } else { - monster = nullptr; - } - - if (monster) { - pushUserdata(L, monster); - setMetatable(L, -1, "Monster"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterIsMonster(lua_State* L) -{ - // monster:isMonster() - pushBoolean(L, getUserdata(L, 1) != nullptr); - return 1; -} - -int LuaScriptInterface::luaMonsterGetType(lua_State* L) -{ - // monster:getType() - const Monster* monster = getUserdata(L, 1); - if (monster) { - pushUserdata(L, monster->mType); - setMetatable(L, -1, "MonsterType"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterGetSpawnPosition(lua_State* L) -{ - // monster:getSpawnPosition() - const Monster* monster = getUserdata(L, 1); - if (monster) { - pushPosition(L, monster->getMasterPos()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterIsInSpawnRange(lua_State* L) -{ - // monster:isInSpawnRange([position]) - Monster* monster = getUserdata(L, 1); - if (monster) { - pushBoolean(L, monster->isInSpawnRange(lua_gettop(L) >= 2 ? getPosition(L, 2) : monster->getPosition())); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterIsIdle(lua_State* L) -{ - // monster:isIdle() - Monster* monster = getUserdata(L, 1); - if (monster) { - pushBoolean(L, monster->getIdleStatus()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterSetIdle(lua_State* L) -{ - // monster:setIdle(idle) - Monster* monster = getUserdata(L, 1); - if (!monster) { - lua_pushnil(L); - return 1; - } - - monster->setIdle(getBoolean(L, 2)); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaMonsterIsTarget(lua_State* L) -{ - // monster:isTarget(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - const Creature* creature = getCreature(L, 2); - pushBoolean(L, monster->isTarget(creature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterIsOpponent(lua_State* L) -{ - // monster:isOpponent(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - const Creature* creature = getCreature(L, 2); - pushBoolean(L, monster->isOpponent(creature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterIsFriend(lua_State* L) -{ - // monster:isFriend(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - const Creature* creature = getCreature(L, 2); - pushBoolean(L, monster->isFriend(creature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterAddFriend(lua_State* L) -{ - // monster:addFriend(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - Creature* creature = getCreature(L, 2); - monster->addFriend(creature); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterRemoveFriend(lua_State* L) -{ - // monster:removeFriend(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - Creature* creature = getCreature(L, 2); - monster->removeFriend(creature); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterGetFriendList(lua_State* L) -{ - // monster:getFriendList() - Monster* monster = getUserdata(L, 1); - if (!monster) { - lua_pushnil(L); - return 1; - } - - const auto& friendList = monster->getFriendList(); - lua_createtable(L, friendList.size(), 0); - - int index = 0; - for (Creature* creature : friendList) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterGetFriendCount(lua_State* L) -{ - // monster:getFriendCount() - Monster* monster = getUserdata(L, 1); - if (monster) { - lua_pushnumber(L, monster->getFriendList().size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterAddTarget(lua_State* L) -{ - // monster:addTarget(creature[, pushFront = false]) - Monster* monster = getUserdata(L, 1); - if (!monster) { - lua_pushnil(L); - return 1; - } - - Creature* creature = getCreature(L, 2); - bool pushFront = getBoolean(L, 3, false); - monster->addTarget(creature, pushFront); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaMonsterRemoveTarget(lua_State* L) -{ - // monster:removeTarget(creature) - Monster* monster = getUserdata(L, 1); - if (!monster) { - lua_pushnil(L); - return 1; - } - - monster->removeTarget(getCreature(L, 2)); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaMonsterGetTargetList(lua_State* L) -{ - // monster:getTargetList() - Monster* monster = getUserdata(L, 1); - if (!monster) { - lua_pushnil(L); - return 1; - } - - const auto& targetList = monster->getTargetList(); - lua_createtable(L, targetList.size(), 0); - - int index = 0; - for (Creature* creature : targetList) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterGetTargetCount(lua_State* L) -{ - // monster:getTargetCount() - Monster* monster = getUserdata(L, 1); - if (monster) { - lua_pushnumber(L, monster->getTargetList().size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterSelectTarget(lua_State* L) -{ - // monster:selectTarget(creature) - Monster* monster = getUserdata(L, 1); - if (monster) { - Creature* creature = getCreature(L, 2); - pushBoolean(L, monster->selectTarget(creature)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterSearchTarget(lua_State* L) -{ - // monster:searchTarget([searchType = TARGETSEARCH_DEFAULT]) - Monster* monster = getUserdata(L, 1); - if (monster) { - TargetSearchType_t searchType = getNumber(L, 2, TARGETSEARCH_DEFAULT); - pushBoolean(L, monster->searchTarget(searchType)); - } else { - lua_pushnil(L); - } - return 1; -} - -// Npc -int LuaScriptInterface::luaNpcCreate(lua_State* L) -{ - // Npc([id or name or userdata]) - Npc* npc; - if (lua_gettop(L) >= 2) { - if (isNumber(L, 2)) { - npc = g_game.getNpcByID(getNumber(L, 2)); - } else if (isString(L, 2)) { - npc = g_game.getNpcByName(getString(L, 2)); - } else if (isUserdata(L, 2)) { - if (getUserdataType(L, 2) != LuaData_Npc) { - lua_pushnil(L); - return 1; - } - npc = getUserdata(L, 2); - } else { - npc = nullptr; - } - } else { - npc = getScriptEnv()->getNpc(); - } - - if (npc) { - pushUserdata(L, npc); - setMetatable(L, -1, "Npc"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNpcIsNpc(lua_State* L) -{ - // npc:isNpc() - pushBoolean(L, getUserdata(L, 1) != nullptr); - return 1; -} - -int LuaScriptInterface::luaNpcSetMasterPos(lua_State* L) -{ - // npc:setMasterPos(pos[, radius]) - Npc* npc = getUserdata(L, 1); - if (!npc) { - lua_pushnil(L); - return 1; - } - - const Position& pos = getPosition(L, 2); - int32_t radius = getNumber(L, 3, 1); - npc->setMasterPos(pos, radius); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaNpcGetSpeechBubble(lua_State* L) -{ - // npc:getSpeechBubble() - Npc* npc = getUserdata(L, 1); - if (npc) { - lua_pushnumber(L, npc->getSpeechBubble()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaNpcSetSpeechBubble(lua_State* L) -{ - // npc:setSpeechBubble(speechBubble) - Npc* npc = getUserdata(L, 1); - if (npc) { - npc->setSpeechBubble(getNumber(L, 2)); - } - return 0; -} - -// Guild -int LuaScriptInterface::luaGuildCreate(lua_State* L) -{ - // Guild(id) - uint32_t id = getNumber(L, 2); - - Guild* guild = g_game.getGuild(id); - if (guild) { - pushUserdata(L, guild); - setMetatable(L, -1, "Guild"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetId(lua_State* L) -{ - // guild:getId() - Guild* guild = getUserdata(L, 1); - if (guild) { - lua_pushnumber(L, guild->getId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetName(lua_State* L) -{ - // guild:getName() - Guild* guild = getUserdata(L, 1); - if (guild) { - pushString(L, guild->getName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetMembersOnline(lua_State* L) -{ - // guild:getMembersOnline() - const Guild* guild = getUserdata(L, 1); - if (!guild) { - lua_pushnil(L); - return 1; - } - - const auto& members = guild->getMembersOnline(); - lua_createtable(L, members.size(), 0); - - int index = 0; - for (Player* player : members) { - pushUserdata(L, player); - setMetatable(L, -1, "Player"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaGuildAddRank(lua_State* L) -{ - // guild:addRank(id, name, level) - Guild* guild = getUserdata(L, 1); - if (guild) { - uint32_t id = getNumber(L, 2); - const std::string& name = getString(L, 3); - uint8_t level = getNumber(L, 4); - guild->addRank(id, name, level); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetRankById(lua_State* L) -{ - // guild:getRankById(id) - Guild* guild = getUserdata(L, 1); - if (!guild) { - lua_pushnil(L); - return 1; - } - - uint32_t id = getNumber(L, 2); - GuildRank* rank = guild->getRankById(id); - if (rank) { - lua_createtable(L, 0, 3); - setField(L, "id", rank->id); - setField(L, "name", rank->name); - setField(L, "level", rank->level); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetRankByLevel(lua_State* L) -{ - // guild:getRankByLevel(level) - const Guild* guild = getUserdata(L, 1); - if (!guild) { - lua_pushnil(L); - return 1; - } - - uint8_t level = getNumber(L, 2); - const GuildRank* rank = guild->getRankByLevel(level); - if (rank) { - lua_createtable(L, 0, 3); - setField(L, "id", rank->id); - setField(L, "name", rank->name); - setField(L, "level", rank->level); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildGetMotd(lua_State* L) -{ - // guild:getMotd() - Guild* guild = getUserdata(L, 1); - if (guild) { - pushString(L, guild->getMotd()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGuildSetMotd(lua_State* L) -{ - // guild:setMotd(motd) - const std::string& motd = getString(L, 2); - Guild* guild = getUserdata(L, 1); - if (guild) { - guild->setMotd(motd); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -// Group -int LuaScriptInterface::luaGroupCreate(lua_State* L) -{ - // Group(id) - uint32_t id = getNumber(L, 2); - - Group* group = g_game.groups.getGroup(id); - if (group) { - pushUserdata(L, group); - setMetatable(L, -1, "Group"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetId(lua_State* L) -{ - // group:getId() - Group* group = getUserdata(L, 1); - if (group) { - lua_pushnumber(L, group->id); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetName(lua_State* L) -{ - // group:getName() - Group* group = getUserdata(L, 1); - if (group) { - pushString(L, group->name); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetFlags(lua_State* L) -{ - // group:getFlags() - Group* group = getUserdata(L, 1); - if (group) { - lua_pushnumber(L, group->flags); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetAccess(lua_State* L) -{ - // group:getAccess() - Group* group = getUserdata(L, 1); - if (group) { - pushBoolean(L, group->access); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetMaxDepotItems(lua_State* L) -{ - // group:getMaxDepotItems() - Group* group = getUserdata(L, 1); - if (group) { - lua_pushnumber(L, group->maxDepotItems); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaGroupGetMaxVipEntries(lua_State* L) -{ - // group:getMaxVipEntries() - Group* group = getUserdata(L, 1); - if (group) { - lua_pushnumber(L, group->maxVipEntries); - } else { - lua_pushnil(L); - } - return 1; -} - -// Vocation -int LuaScriptInterface::luaVocationCreate(lua_State* L) -{ - // Vocation(id or name) - uint32_t id; - if (isNumber(L, 2)) { - id = getNumber(L, 2); - } else { - id = g_vocations.getVocationId(getString(L, 2)); - } - - Vocation* vocation = g_vocations.getVocation(id); - if (vocation) { - pushUserdata(L, vocation); - setMetatable(L, -1, "Vocation"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetId(lua_State* L) -{ - // vocation:getId() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetClientId(lua_State* L) -{ - // vocation:getClientId() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getClientId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetName(lua_State* L) -{ - // vocation:getName() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - pushString(L, vocation->getVocName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetDescription(lua_State* L) -{ - // vocation:getDescription() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - pushString(L, vocation->getVocDescription()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetRequiredSkillTries(lua_State* L) -{ - // vocation:getRequiredSkillTries(skillType, skillLevel) - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - skills_t skillType = getNumber(L, 2); - uint16_t skillLevel = getNumber(L, 3); - lua_pushnumber(L, vocation->getReqSkillTries(skillType, skillLevel)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetRequiredManaSpent(lua_State* L) -{ - // vocation:getRequiredManaSpent(magicLevel) - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - uint32_t magicLevel = getNumber(L, 2); - lua_pushnumber(L, vocation->getReqMana(magicLevel)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetCapacityGain(lua_State* L) -{ - // vocation:getCapacityGain() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getCapGain()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetHealthGain(lua_State* L) -{ - // vocation:getHealthGain() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getHPGain()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetHealthGainTicks(lua_State* L) -{ - // vocation:getHealthGainTicks() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getHealthGainTicks()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetHealthGainAmount(lua_State* L) -{ - // vocation:getHealthGainAmount() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getHealthGainAmount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetManaGain(lua_State* L) -{ - // vocation:getManaGain() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getManaGain()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetManaGainTicks(lua_State* L) -{ - // vocation:getManaGainTicks() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getManaGainTicks()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetManaGainAmount(lua_State* L) -{ - // vocation:getManaGainAmount() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getManaGainAmount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetMaxSoul(lua_State* L) -{ - // vocation:getMaxSoul() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getSoulMax()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetSoulGainTicks(lua_State* L) -{ - // vocation:getSoulGainTicks() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getSoulGainTicks()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetAttackSpeed(lua_State* L) -{ - // vocation:getAttackSpeed() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getAttackSpeed()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetBaseSpeed(lua_State* L) -{ - // vocation:getBaseSpeed() - Vocation* vocation = getUserdata(L, 1); - if (vocation) { - lua_pushnumber(L, vocation->getBaseSpeed()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetDemotion(lua_State* L) -{ - // vocation:getDemotion() - Vocation* vocation = getUserdata(L, 1); - if (!vocation) { - lua_pushnil(L); - return 1; - } - - uint16_t fromId = vocation->getFromVocation(); - if (fromId == VOCATION_NONE) { - lua_pushnil(L); - return 1; - } - - Vocation* demotedVocation = g_vocations.getVocation(fromId); - if (demotedVocation && demotedVocation != vocation) { - pushUserdata(L, demotedVocation); - setMetatable(L, -1, "Vocation"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaVocationGetPromotion(lua_State* L) -{ - // vocation:getPromotion() - Vocation* vocation = getUserdata(L, 1); - if (!vocation) { - lua_pushnil(L); - return 1; - } - - uint16_t promotedId = g_vocations.getPromotedVocation(vocation->getId()); - if (promotedId == VOCATION_NONE) { - lua_pushnil(L); - return 1; - } - - Vocation* promotedVocation = g_vocations.getVocation(promotedId); - if (promotedVocation && promotedVocation != vocation) { - pushUserdata(L, promotedVocation); - setMetatable(L, -1, "Vocation"); - } else { - lua_pushnil(L); - } - return 1; -} - -// Town -int LuaScriptInterface::luaTownCreate(lua_State* L) -{ - // Town(id or name) - Town* town; - if (isNumber(L, 2)) { - town = g_game.map.towns.getTown(getNumber(L, 2)); - } else if (isString(L, 2)) { - town = g_game.map.towns.getTown(getString(L, 2)); - } else { - town = nullptr; - } - - if (town) { - pushUserdata(L, town); - setMetatable(L, -1, "Town"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTownGetId(lua_State* L) -{ - // town:getId() - Town* town = getUserdata(L, 1); - if (town) { - lua_pushnumber(L, town->getID()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTownGetName(lua_State* L) -{ - // town:getName() - Town* town = getUserdata(L, 1); - if (town) { - pushString(L, town->getName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaTownGetTemplePosition(lua_State* L) -{ - // town:getTemplePosition() - Town* town = getUserdata(L, 1); - if (town) { - pushPosition(L, town->getTemplePosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -// House -int LuaScriptInterface::luaHouseCreate(lua_State* L) -{ - // House(id) - House* house = g_game.map.houses.getHouse(getNumber(L, 2)); - if (house) { - pushUserdata(L, house); - setMetatable(L, -1, "House"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetId(lua_State* L) -{ - // house:getId() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetName(lua_State* L) -{ - // house:getName() - House* house = getUserdata(L, 1); - if (house) { - pushString(L, house->getName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetTown(lua_State* L) -{ - // house:getTown() - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - Town* town = g_game.map.towns.getTown(house->getTownId()); - if (town) { - pushUserdata(L, town); - setMetatable(L, -1, "Town"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetExitPosition(lua_State* L) -{ - // house:getExitPosition() - House* house = getUserdata(L, 1); - if (house) { - pushPosition(L, house->getEntryPosition()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetRent(lua_State* L) -{ - // house:getRent() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getRent()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetOwnerGuid(lua_State* L) -{ - // house:getOwnerGuid() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getOwner()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseSetOwnerGuid(lua_State* L) -{ - // house:setOwnerGuid(guid[, updateDatabase = true]) - House* house = getUserdata(L, 1); - if (house) { - uint32_t guid = getNumber(L, 2); - bool updateDatabase = getBoolean(L, 3, true); - house->setOwner(guid, updateDatabase); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetBeds(lua_State* L) -{ - // house:getBeds() - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - const auto& beds = house->getBeds(); - lua_createtable(L, beds.size(), 0); - - int index = 0; - for (BedItem* bedItem : beds) { - pushUserdata(L, bedItem); - setItemMetatable(L, -1, bedItem); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetBedCount(lua_State* L) -{ - // house:getBedCount() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getBedCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetDoors(lua_State* L) -{ - // house:getDoors() - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - const auto& doors = house->getDoors(); - lua_createtable(L, doors.size(), 0); - - int index = 0; - for (Door* door : doors) { - pushUserdata(L, door); - setItemMetatable(L, -1, door); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetDoorCount(lua_State* L) -{ - // house:getDoorCount() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getDoors().size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetTiles(lua_State* L) -{ - // house:getTiles() - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - const auto& tiles = house->getTiles(); - lua_createtable(L, tiles.size(), 0); - - int index = 0; - for (Tile* tile : tiles) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetTileCount(lua_State* L) -{ - // house:getTileCount() - House* house = getUserdata(L, 1); - if (house) { - lua_pushnumber(L, house->getTiles().size()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaHouseGetAccessList(lua_State* L) -{ - // house:getAccessList(listId) - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - std::string list; - uint32_t listId = getNumber(L, 2); - if (house->getAccessList(listId, list)) { - pushString(L, list); - } else { - pushBoolean(L, false); - } - return 1; -} - -int LuaScriptInterface::luaHouseSetAccessList(lua_State* L) -{ - // house:setAccessList(listId, list) - House* house = getUserdata(L, 1); - if (!house) { - lua_pushnil(L); - return 1; - } - - uint32_t listId = getNumber(L, 2); - const std::string& list = getString(L, 3); - house->setAccessList(listId, list); - pushBoolean(L, true); - return 1; -} - -// ItemType -int LuaScriptInterface::luaItemTypeCreate(lua_State* L) -{ - // ItemType(id or name) - uint32_t id; - if (isNumber(L, 2)) { - id = getNumber(L, 2); - } else { - id = Item::items.getItemIdByName(getString(L, 2)); - } - - const ItemType& itemType = Item::items[id]; - pushUserdata(L, &itemType); - setMetatable(L, -1, "ItemType"); - return 1; -} - -int LuaScriptInterface::luaItemTypeIsCorpse(lua_State* L) -{ - // itemType:isCorpse() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->corpseType != RACE_NONE); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsDoor(lua_State* L) -{ - // itemType:isDoor() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->isDoor()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsContainer(lua_State* L) -{ - // itemType:isContainer() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->isContainer()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsFluidContainer(lua_State* L) -{ - // itemType:isFluidContainer() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->isFluidContainer()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsMovable(lua_State* L) -{ - // itemType:isMovable() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->moveable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsRune(lua_State* L) -{ - // itemType:isRune() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->isRune()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsStackable(lua_State* L) -{ - // itemType:isStackable() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->stackable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsReadable(lua_State* L) -{ - // itemType:isReadable() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->canReadText); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeIsWritable(lua_State* L) -{ - // itemType:isWritable() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->canWriteText); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetType(lua_State* L) -{ - // itemType:getType() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->type); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetId(lua_State* L) -{ - // itemType:getId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->id); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetClientId(lua_State* L) -{ - // itemType:getClientId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->clientId); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetName(lua_State* L) -{ - // itemType:getName() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushString(L, itemType->name); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetPluralName(lua_State* L) -{ - // itemType:getPluralName() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushString(L, itemType->getPluralName()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetArticle(lua_State* L) -{ - // itemType:getArticle() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushString(L, itemType->article); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDescription(lua_State* L) -{ - // itemType:getDescription() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushString(L, itemType->description); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetSlotPosition(lua_State *L) -{ - // itemType:getSlotPosition() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->slotPosition); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetCharges(lua_State* L) -{ - // itemType:getCharges() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->charges); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetFluidSource(lua_State* L) -{ - // itemType:getFluidSource() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->fluidSource); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetCapacity(lua_State* L) -{ - // itemType:getCapacity() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->maxItems); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetWeight(lua_State* L) -{ - // itemType:getWeight([count = 1]) - uint16_t count = getNumber(L, 2, 1); - - const ItemType* itemType = getUserdata(L, 1); - if (!itemType) { - lua_pushnil(L); - return 1; - } - - uint64_t weight = static_cast(itemType->weight) * std::max(1, count); - lua_pushnumber(L, weight); - return 1; -} - -int LuaScriptInterface::luaItemTypeGetHitChance(lua_State* L) -{ - // itemType:getHitChance() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->hitChance); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetShootRange(lua_State* L) -{ - // itemType:getShootRange() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->shootRange); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetAttack(lua_State* L) -{ - // itemType:getAttack() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->attack); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDefense(lua_State* L) -{ - // itemType:getDefense() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->defense); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetExtraDefense(lua_State* L) -{ - // itemType:getExtraDefense() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->extraDefense); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetArmor(lua_State* L) -{ - // itemType:getArmor() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->armor); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetWeaponType(lua_State* L) -{ - // itemType:getWeaponType() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->weaponType); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetElementType(lua_State* L) -{ - // itemType:getElementType() - const ItemType* itemType = getUserdata(L, 1); - if (!itemType) { - lua_pushnil(L); - return 1; - } - - auto& abilities = itemType->abilities; - if (abilities) { - lua_pushnumber(L, abilities->elementType); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetElementDamage(lua_State* L) -{ - // itemType:getElementDamage() - const ItemType* itemType = getUserdata(L, 1); - if (!itemType) { - lua_pushnil(L); - return 1; - } - - auto& abilities = itemType->abilities; - if (abilities) { - lua_pushnumber(L, abilities->elementDamage); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetTransformEquipId(lua_State* L) -{ - // itemType:getTransformEquipId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->transformEquipTo); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetTransformDeEquipId(lua_State* L) -{ - // itemType:getTransformDeEquipId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->transformDeEquipTo); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDestroyId(lua_State* L) -{ - // itemType:getDestroyId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->destroyTo); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDecayId(lua_State* L) -{ - // itemType:getDecayId() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->decayTo); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetRequiredLevel(lua_State* L) -{ - // itemType:getRequiredLevel() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->minReqLevel); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeHasSubType(lua_State* L) -{ - // itemType:hasSubType() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - pushBoolean(L, itemType->hasSubType()); - } else { - lua_pushnil(L); - } - return 1; -} - -// Combat -int LuaScriptInterface::luaCombatCreate(lua_State* L) -{ - // Combat() - pushUserdata(L, g_luaEnvironment.createCombatObject(getScriptEnv()->getScriptInterface())); - setMetatable(L, -1, "Combat"); - return 1; -} - -int LuaScriptInterface::luaCombatSetParameter(lua_State* L) -{ - // combat:setParameter(key, value) - Combat* combat = getUserdata(L, 1); - if (!combat) { - lua_pushnil(L); - return 1; - } - - CombatParam_t key = getNumber(L, 2); - uint32_t value; - if (isBoolean(L, 3)) { - value = getBoolean(L, 3) ? 1 : 0; - } else { - value = getNumber(L, 3); - } - combat->setParam(key, value); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCombatSetFormula(lua_State* L) -{ - // combat:setFormula(type, mina, minb, maxa, maxb) - Combat* combat = getUserdata(L, 1); - if (!combat) { - lua_pushnil(L); - return 1; - } - - formulaType_t type = getNumber(L, 2); - double mina = getNumber(L, 3); - double minb = getNumber(L, 4); - double maxa = getNumber(L, 5); - double maxb = getNumber(L, 6); - combat->setPlayerCombatValues(type, mina, minb, maxa, maxb); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaCombatSetArea(lua_State* L) -{ - // combat:setArea(area) - if (getScriptEnv()->getScriptId() != EVENT_ID_LOADING) { - reportErrorFunc("This function can only be used while loading the script."); - lua_pushnil(L); - return 1; - } - - const AreaCombat* area = g_luaEnvironment.getAreaObject(getNumber(L, 2)); - if (!area) { - reportErrorFunc(getErrorDesc(LUA_ERROR_AREA_NOT_FOUND)); - lua_pushnil(L); - return 1; - } - - Combat* combat = getUserdata(L, 1); - if (combat) { - combat->setArea(new AreaCombat(*area)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCombatSetCondition(lua_State* L) -{ - // combat:setCondition(condition) - Condition* condition = getUserdata(L, 2); - Combat* combat = getUserdata(L, 1); - if (combat && condition) { - combat->setCondition(condition->clone()); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCombatSetCallback(lua_State* L) -{ - // combat:setCallback(key, function) - Combat* combat = getUserdata(L, 1); - if (!combat) { - lua_pushnil(L); - return 1; - } - - CallBackParam_t key = getNumber(L, 2); - if (!combat->setCallback(key)) { - lua_pushnil(L); - return 1; - } - - CallBack* callback = combat->getCallback(key); - if (!callback) { - lua_pushnil(L); - return 1; - } - - const std::string& function = getString(L, 3); - pushBoolean(L, callback->loadCallBack(getScriptEnv()->getScriptInterface(), function)); - return 1; -} - -int LuaScriptInterface::luaCombatSetOrigin(lua_State* L) -{ - // combat:setOrigin(origin) - Combat* combat = getUserdata(L, 1); - if (combat) { - combat->setOrigin(getNumber(L, 2)); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCombatExecute(lua_State* L) -{ - // combat:execute(creature, variant) - Combat* combat = getUserdata(L, 1); - if (!combat) { - pushBoolean(L, false); - return 1; - } - - Creature* creature = getCreature(L, 2); - - const LuaVariant& variant = getVariant(L, 3); - switch (variant.type) { - case VARIANT_NUMBER: { - Creature* target = g_game.getCreatureByID(variant.number); - if (!target) { - pushBoolean(L, false); - return 1; - } - - if (combat->hasArea()) { - combat->doCombat(creature, target->getPosition()); - } else { - combat->doCombat(creature, target); - } - break; - } - - case VARIANT_POSITION: { - combat->doCombat(creature, variant.pos); - break; - } - - case VARIANT_TARGETPOSITION: { - if (combat->hasArea()) { - combat->doCombat(creature, variant.pos); - } else { - combat->postCombatEffects(creature, variant.pos); - g_game.addMagicEffect(variant.pos, CONST_ME_POFF); - } - break; - } - - case VARIANT_STRING: { - Player* target = g_game.getPlayerByName(variant.text); - if (!target) { - pushBoolean(L, false); - return 1; - } - - combat->doCombat(creature, target); - break; - } - - case VARIANT_NONE: { - reportErrorFunc(getErrorDesc(LUA_ERROR_VARIANT_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - default: { - break; - } - } - - pushBoolean(L, true); - return 1; -} - -// Condition -int LuaScriptInterface::luaConditionCreate(lua_State* L) -{ - // Condition(conditionType[, conditionId = CONDITIONID_COMBAT]) - ConditionType_t conditionType = getNumber(L, 2); - ConditionId_t conditionId = getNumber(L, 3, CONDITIONID_COMBAT); - - Condition* condition = Condition::createCondition(conditionId, conditionType, 0, 0); - if (condition) { - pushUserdata(L, condition); - setMetatable(L, -1, "Condition"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionDelete(lua_State* L) -{ - // condition:delete() - Condition** conditionPtr = getRawUserdata(L, 1); - if (conditionPtr && *conditionPtr) { - delete *conditionPtr; - *conditionPtr = nullptr; - } - return 0; -} - -int LuaScriptInterface::luaConditionGetId(lua_State* L) -{ - // condition:getId() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionGetSubId(lua_State* L) -{ - // condition:getSubId() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getSubId()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionGetType(lua_State* L) -{ - // condition:getType() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getType()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionGetIcons(lua_State* L) -{ - // condition:getIcons() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getIcons()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionGetEndTime(lua_State* L) -{ - // condition:getEndTime() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getEndTime()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionClone(lua_State* L) -{ - // condition:clone() - Condition* condition = getUserdata(L, 1); - if (condition) { - pushUserdata(L, condition->clone()); - setMetatable(L, -1, "Condition"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionGetTicks(lua_State* L) -{ - // condition:getTicks() - Condition* condition = getUserdata(L, 1); - if (condition) { - lua_pushnumber(L, condition->getTicks()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionSetTicks(lua_State* L) -{ - // condition:setTicks(ticks) - int32_t ticks = getNumber(L, 2); - Condition* condition = getUserdata(L, 1); - if (condition) { - condition->setTicks(ticks); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionSetParameter(lua_State* L) -{ - // condition:setParameter(key, value) - Condition* condition = getUserdata(L, 1); - if (!condition) { - lua_pushnil(L); - return 1; - } - - ConditionParam_t key = getNumber(L, 2); - int32_t value; - if (isBoolean(L, 3)) { - value = getBoolean(L, 3) ? 1 : 0; - } else { - value = getNumber(L, 3); - } - condition->setParam(key, value); - pushBoolean(L, true); - return 1; -} - -int LuaScriptInterface::luaConditionSetFormula(lua_State* L) -{ - // condition:setFormula(mina, minb, maxa, maxb) - double maxb = getNumber(L, 5); - double maxa = getNumber(L, 4); - double minb = getNumber(L, 3); - double mina = getNumber(L, 2); - ConditionSpeed* condition = dynamic_cast(getUserdata(L, 1)); - if (condition) { - condition->setFormulaVars(mina, minb, maxa, maxb); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionSetOutfit(lua_State* L) -{ - // condition:setOutfit(outfit) - // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs, lookFeet[, lookAddons[, lookMount]]) - Outfit_t outfit; - if (isTable(L, 2)) { - outfit = getOutfit(L, 2); - } else { - outfit.lookMount = getNumber(L, 9, outfit.lookMount); - outfit.lookAddons = getNumber(L, 8, outfit.lookAddons); - outfit.lookFeet = getNumber(L, 7); - outfit.lookLegs = getNumber(L, 6); - outfit.lookBody = getNumber(L, 5); - outfit.lookHead = getNumber(L, 4); - outfit.lookType = getNumber(L, 3); - outfit.lookTypeEx = getNumber(L, 2); - } - - ConditionOutfit* condition = dynamic_cast(getUserdata(L, 1)); - if (condition) { - condition->setOutfit(outfit); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaConditionAddDamage(lua_State* L) -{ - // condition:addDamage(rounds, time, value) - int32_t value = getNumber(L, 4); - int32_t time = getNumber(L, 3); - int32_t rounds = getNumber(L, 2); - ConditionDamage* condition = dynamic_cast(getUserdata(L, 1)); - if (condition) { - pushBoolean(L, condition->addDamage(rounds, time, value)); - } else { - lua_pushnil(L); - } - return 1; -} - -// MonsterType -int LuaScriptInterface::luaMonsterTypeCreate(lua_State* L) -{ - // MonsterType(name) - MonsterType* monsterType = g_monsters.getMonsterType(getString(L, 2)); - if (monsterType) { - pushUserdata(L, monsterType); - setMetatable(L, -1, "MonsterType"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsAttackable(lua_State* L) -{ - // monsterType:isAttackable() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isAttackable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsConvinceable(lua_State* L) -{ - // monsterType:isConvinceable() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isConvinceable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsSummonable(lua_State* L) -{ - // monsterType:isSummonable() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isSummonable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsIllusionable(lua_State* L) -{ - // monsterType:isIllusionable() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isIllusionable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsHostile(lua_State* L) -{ - // monsterType:isHostile() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isHostile); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsPassive(lua_State* L) -{ - // monsterType:isPassive() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->isPassive); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsPushable(lua_State* L) -{ - // monsterType:isPushable() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->pushable); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeIsHealthShown(lua_State* L) -{ - // monsterType:isHealthShown() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, !monsterType->hiddenHealth); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeCanPushItems(lua_State* L) -{ - // monsterType:canPushItems() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->canPushItems); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeCanPushCreatures(lua_State* L) -{ - // monsterType:canPushCreatures() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushBoolean(L, monsterType->canPushCreatures); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetName(lua_State* L) -{ - // monsterType:getName() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushString(L, monsterType->name); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetNameDescription(lua_State* L) -{ - // monsterType:getNameDescription() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushString(L, monsterType->nameDescription); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetHealth(lua_State* L) -{ - // monsterType:getHealth() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->health); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetMaxHealth(lua_State* L) -{ - // monsterType:getMaxHealth() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->healthMax); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetRunHealth(lua_State* L) -{ - // monsterType:getRunHealth() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->runAwayHealth); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetExperience(lua_State* L) -{ - // monsterType:getExperience() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->experience); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetCombatImmunities(lua_State* L) -{ - // monsterType:getCombatImmunities() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->damageImmunities); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetConditionImmunities(lua_State* L) -{ - // monsterType:getConditionImmunities() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->conditionImmunities); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetAttackList(lua_State* L) -{ - // monsterType:getAttackList() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, monsterType->attackSpells.size(), 0); - - int index = 0; - for (const auto& spellBlock : monsterType->attackSpells) { - lua_createtable(L, 0, 8); - - setField(L, "chance", spellBlock.chance); - setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); - setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); - setField(L, "minCombatValue", spellBlock.minCombatValue); - setField(L, "maxCombatValue", spellBlock.maxCombatValue); - setField(L, "range", spellBlock.range); - setField(L, "speed", spellBlock.speed); - pushUserdata(L, static_cast(spellBlock.spell)); - lua_setfield(L, -2, "spell"); - - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetDefenseList(lua_State* L) -{ - // monsterType:getDefenseList() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, monsterType->defenseSpells.size(), 0); - - - int index = 0; - for (const auto& spellBlock : monsterType->defenseSpells) { - lua_createtable(L, 0, 8); - - setField(L, "chance", spellBlock.chance); - setField(L, "isCombatSpell", spellBlock.combatSpell ? 1 : 0); - setField(L, "isMelee", spellBlock.isMelee ? 1 : 0); - setField(L, "minCombatValue", spellBlock.minCombatValue); - setField(L, "maxCombatValue", spellBlock.maxCombatValue); - setField(L, "range", spellBlock.range); - setField(L, "speed", spellBlock.speed); - pushUserdata(L, static_cast(spellBlock.spell)); - lua_setfield(L, -2, "spell"); - - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetElementList(lua_State* L) -{ - // monsterType:getElementList() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - lua_createtable(L, monsterType->elementMap.size(), 0); - for (const auto& elementEntry : monsterType->elementMap) { - lua_pushnumber(L, elementEntry.second); - lua_rawseti(L, -2, elementEntry.first); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetVoices(lua_State* L) -{ - // monsterType:getVoices() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - int index = 0; - lua_createtable(L, monsterType->voiceVector.size(), 0); - for (const auto& voiceBlock : monsterType->voiceVector) { - lua_createtable(L, 0, 2); - setField(L, "text", voiceBlock.text); - setField(L, "yellText", voiceBlock.yellText); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetLoot(lua_State* L) -{ - // monsterType:getLoot() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - static const std::function&)> parseLoot = [&](const std::vector& lootList) { - lua_createtable(L, lootList.size(), 0); - - int index = 0; - for (const auto& lootBlock : lootList) { - lua_createtable(L, 0, 7); - - setField(L, "itemId", lootBlock.id); - setField(L, "chance", lootBlock.chance); - setField(L, "subType", lootBlock.subType); - setField(L, "maxCount", lootBlock.countmax); - setField(L, "actionId", lootBlock.actionId); - setField(L, "text", lootBlock.text); - - parseLoot(lootBlock.childLoot); - lua_setfield(L, -2, "childLoot"); - - lua_rawseti(L, -2, ++index); - } - }; - parseLoot(monsterType->lootItems); - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetCreatureEvents(lua_State* L) -{ - // monsterType:getCreatureEvents() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - int index = 0; - lua_createtable(L, monsterType->scripts.size(), 0); - for (const std::string& creatureEvent : monsterType->scripts) { - pushString(L, creatureEvent); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetSummonList(lua_State* L) -{ - // monsterType:getSummonList() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - int index = 0; - lua_createtable(L, monsterType->summons.size(), 0); - for (const auto& summonBlock : monsterType->summons) { - lua_createtable(L, 0, 3); - setField(L, "name", summonBlock.name); - setField(L, "speed", summonBlock.speed); - setField(L, "chance", summonBlock.chance); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetMaxSummons(lua_State* L) -{ - // monsterType:getMaxSummons() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->maxSummons); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetArmor(lua_State* L) -{ - // monsterType:getArmor() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->armor); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetDefense(lua_State* L) -{ - // monsterType:getDefense() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->defense); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetOutfit(lua_State* L) -{ - // monsterType:getOutfit() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - pushOutfit(L, monsterType->outfit); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetRace(lua_State* L) -{ - // monsterType:getRace() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->race); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetCorpseId(lua_State* L) -{ - // monsterType:getCorpseId() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->lookcorpse); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetManaCost(lua_State* L) -{ - // monsterType:getManaCost() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->manaCost); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetBaseSpeed(lua_State* L) -{ - // monsterType:getBaseSpeed() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->baseSpeed); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetLight(lua_State* L) -{ - // monsterType:getLight() - MonsterType* monsterType = getUserdata(L, 1); - if (!monsterType) { - lua_pushnil(L); - return 1; - } - - lua_pushnumber(L, monsterType->lightLevel); - lua_pushnumber(L, monsterType->lightColor); - return 2; -} - -int LuaScriptInterface::luaMonsterTypeGetStaticAttackChance(lua_State* L) -{ - // monsterType:getStaticAttackChance() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->staticAttackChance); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetTargetDistance(lua_State* L) -{ - // monsterType:getTargetDistance() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->targetDistance); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetYellChance(lua_State* L) -{ - // monsterType:getYellChance() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->yellChance); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetYellSpeedTicks(lua_State* L) -{ - // monsterType:getYellSpeedTicks() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->yellSpeedTicks); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetChangeTargetChance(lua_State* L) -{ - // monsterType:getChangeTargetChance() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->changeTargetChance); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaMonsterTypeGetChangeTargetSpeed(lua_State* L) -{ - // monsterType:getChangeTargetSpeed() - MonsterType* monsterType = getUserdata(L, 1); - if (monsterType) { - lua_pushnumber(L, monsterType->changeTargetSpeed); - } else { - lua_pushnil(L); - } - return 1; -} - -// Party -int LuaScriptInterface::luaPartyDisband(lua_State* L) -{ - // party:disband() - Party** partyPtr = getRawUserdata(L, 1); - if (partyPtr && *partyPtr) { - Party*& party = *partyPtr; - party->disband(); - party = nullptr; - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyGetLeader(lua_State* L) -{ - // party:getLeader() - Party* party = getUserdata(L, 1); - if (!party) { - lua_pushnil(L); - return 1; - } - - Player* leader = party->getLeader(); - if (leader) { - pushUserdata(L, leader); - setMetatable(L, -1, "Player"); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartySetLeader(lua_State* L) -{ - // party:setLeader(player) - Player* player = getPlayer(L, 2); - Party* party = getUserdata(L, 1); - if (party && player) { - pushBoolean(L, party->passPartyLeadership(player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyGetMembers(lua_State* L) -{ - // party:getMembers() - Party* party = getUserdata(L, 1); - if (!party) { - lua_pushnil(L); - return 1; - } - - int index = 0; - lua_createtable(L, party->getMemberCount(), 0); - for (Player* player : party->getMembers()) { - pushUserdata(L, player); - setMetatable(L, -1, "Player"); - lua_rawseti(L, -2, ++index); - } - return 1; -} - -int LuaScriptInterface::luaPartyGetMemberCount(lua_State* L) -{ - // party:getMemberCount() - Party* party = getUserdata(L, 1); - if (party) { - lua_pushnumber(L, party->getMemberCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyGetInvitees(lua_State* L) -{ - // party:getInvitees() - Party* party = getUserdata(L, 1); - if (party) { - lua_createtable(L, party->getInvitationCount(), 0); - - int index = 0; - for (Player* player : party->getInvitees()) { - pushUserdata(L, player); - setMetatable(L, -1, "Player"); - lua_rawseti(L, -2, ++index); - } - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyGetInviteeCount(lua_State* L) -{ - // party:getInviteeCount() - Party* party = getUserdata(L, 1); - if (party) { - lua_pushnumber(L, party->getInvitationCount()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyAddInvite(lua_State* L) -{ - // party:addInvite(player) - Player* player = getPlayer(L, 2); - Party* party = getUserdata(L, 1); - if (party && player) { - pushBoolean(L, party->invitePlayer(*player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyRemoveInvite(lua_State* L) -{ - // party:removeInvite(player) - Player* player = getPlayer(L, 2); - Party* party = getUserdata(L, 1); - if (party && player) { - pushBoolean(L, party->removeInvite(*player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyAddMember(lua_State* L) -{ - // party:addMember(player) - Player* player = getPlayer(L, 2); - Party* party = getUserdata(L, 1); - if (party && player) { - pushBoolean(L, party->joinParty(*player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyRemoveMember(lua_State* L) -{ - // party:removeMember(player) - Player* player = getPlayer(L, 2); - Party* party = getUserdata(L, 1); - if (party && player) { - pushBoolean(L, party->leaveParty(player)); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyIsSharedExperienceActive(lua_State* L) -{ - // party:isSharedExperienceActive() - Party* party = getUserdata(L, 1); - if (party) { - pushBoolean(L, party->isSharedExperienceActive()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyIsSharedExperienceEnabled(lua_State* L) -{ - // party:isSharedExperienceEnabled() - Party* party = getUserdata(L, 1); - if (party) { - pushBoolean(L, party->isSharedExperienceEnabled()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartyShareExperience(lua_State* L) -{ - // party:shareExperience(experience) - uint64_t experience = getNumber(L, 2); - Party* party = getUserdata(L, 1); - if (party) { - party->shareExperience(experience); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaPartySetSharedExperience(lua_State* L) -{ - // party:setSharedExperience(active) - bool active = getBoolean(L, 2); - Party* party = getUserdata(L, 1); - if (party) { - pushBoolean(L, party->setSharedExperience(party->getLeader(), active)); - } else { - lua_pushnil(L); - } - return 1; -} - -// -LuaEnvironment::LuaEnvironment() : - LuaScriptInterface("Main Interface"), m_testInterface(nullptr), - m_lastEventTimerId(1), m_lastCombatId(0), m_lastAreaId(0) -{ - // -} - -LuaEnvironment::~LuaEnvironment() -{ - delete m_testInterface; - closeState(); -} - -bool LuaEnvironment::initState() -{ - m_luaState = luaL_newstate(); - if (!m_luaState) { - return false; - } - - luaL_openlibs(m_luaState); - registerFunctions(); - - m_runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaEnvironment::reInitState() -{ - // TODO: get children, reload children - closeState(); - return initState(); -} - -bool LuaEnvironment::closeState() -{ - if (!m_luaState) { - return false; - } - - for (const auto& combatEntry : m_combatIdMap) { - clearCombatObjects(combatEntry.first); - } - - for (const auto& areaEntry : m_areaIdMap) { - clearAreaObjects(areaEntry.first); - } - - for (auto& timerEntry : m_timerEvents) { - LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second); - for (int32_t parameter : timerEventDesc.parameters) { - luaL_unref(m_luaState, LUA_REGISTRYINDEX, parameter); - } - luaL_unref(m_luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - } - - m_combatIdMap.clear(); - m_areaIdMap.clear(); - m_timerEvents.clear(); - m_cacheFiles.clear(); - - lua_close(m_luaState); - m_luaState = nullptr; - return true; -} - -LuaScriptInterface* LuaEnvironment::getTestInterface() -{ - if (!m_testInterface) { - m_testInterface = new LuaScriptInterface("Test Interface"); - m_testInterface->initState(); - } - return m_testInterface; -} - -Combat* LuaEnvironment::getCombatObject(uint32_t id) const -{ - auto it = m_combatMap.find(id); - if (it == m_combatMap.end()) { - return nullptr; - } - return it->second; -} - -Combat* LuaEnvironment::createCombatObject(LuaScriptInterface* interface) -{ - Combat* combat = new Combat; - m_combatMap[++m_lastCombatId] = combat; - m_combatIdMap[interface].push_back(m_lastCombatId); - return combat; -} - -void LuaEnvironment::clearCombatObjects(LuaScriptInterface* interface) -{ - auto it = m_combatIdMap.find(interface); - if (it == m_combatIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = m_combatMap.find(id); - if (itt != m_combatMap.end()) { - delete itt->second; - m_combatMap.erase(itt); - } - } - it->second.clear(); -} - -AreaCombat* LuaEnvironment::getAreaObject(uint32_t id) const -{ - auto it = m_areaMap.find(id); - if (it == m_areaMap.end()) { - return nullptr; - } - return it->second; -} - -uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface* interface) -{ - m_areaMap[++m_lastAreaId] = new AreaCombat; - m_areaIdMap[interface].push_back(m_lastAreaId); - return m_lastAreaId; -} - -void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) -{ - auto it = m_areaIdMap.find(interface); - if (it == m_areaIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = m_areaMap.find(id); - if (itt != m_areaMap.end()) { - delete itt->second; - m_areaMap.erase(itt); - } - } - it->second.clear(); -} - -void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) -{ - auto it = m_timerEvents.find(eventIndex); - if (it == m_timerEvents.end()) { - return; - } - - LuaTimerEventDesc timerEventDesc = std::move(it->second); - m_timerEvents.erase(it); - - //push function - lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - - //push parameters - for (auto parameter : boost::adaptors::reverse(timerEventDesc.parameters)) { - lua_rawgeti(m_luaState, LUA_REGISTRYINDEX, parameter); - } - - //call the function - if (reserveScriptEnv()) { - ScriptEnvironment* env = getScriptEnv(); - env->setTimerEvent(); - env->setScriptId(timerEventDesc.scriptId, this); - callFunction(timerEventDesc.parameters.size()); - } else { - std::cout << "[Error - LuaScriptInterface::executeTimerEvent] Call stack overflow" << std::endl; - } - - //free resources - luaL_unref(m_luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - for (auto parameter : timerEventDesc.parameters) { - luaL_unref(m_luaState, LUA_REGISTRYINDEX, parameter); - } -} diff --git a/path_10_8/src/luascript.h b/path_10_8/src/luascript.h deleted file mode 100644 index 5675399a4..000000000 --- a/path_10_8/src/luascript.h +++ /dev/null @@ -1,1322 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_LUASCRIPT_H_5344B2BC907E46E3943EA78574A212D8 -#define FS_LUASCRIPT_H_5344B2BC907E46E3943EA78574A212D8 - -#include - -#if LUA_VERSION_NUM >= 502 -// NOTE: Define LUA_COMPAT_ALL as a workaround if this doesn't work -#ifndef LUA_COMPAT_ALL -#ifndef LUA_COMPAT_MODULE -#define luaL_register(L, libname, l) (luaL_newlib(L, l), lua_pushvalue(L, -1), lua_setglobal(L, libname)) -#endif -#define lua_equal(L, i1, i2) lua_compare(L, (i1), (i2), LUA_OPEQ) -#endif -#endif - -#include "database.h" -#include "enums.h" -#include "position.h" - -class Thing; -class Creature; -class Player; -class Item; -class Container; -class AreaCombat; -class Combat; -class Condition; -class Npc; -class Monster; - -enum LuaVariantType_t { - VARIANT_NONE, - - VARIANT_NUMBER, - VARIANT_POSITION, - VARIANT_TARGETPOSITION, - VARIANT_STRING, -}; - -enum LuaDataType { - LuaData_Unknown, - - LuaData_Item, - LuaData_Container, - LuaData_Teleport, - LuaData_Player, - LuaData_Monster, - LuaData_Npc, - LuaData_Tile, -}; - -struct LuaVariant { - LuaVariant() { - type = VARIANT_NONE; - number = 0; - } - - LuaVariantType_t type; - std::string text; - Position pos; - uint32_t number; -}; - -struct LuaTimerEventDesc { - int32_t scriptId; - int32_t function; - std::list parameters; - uint32_t eventId; - - LuaTimerEventDesc() : - scriptId(-1), function(-1), eventId(0) {} - - LuaTimerEventDesc(LuaTimerEventDesc&& other) : - scriptId(other.scriptId), function(other.function), - parameters(std::move(other.parameters)), eventId(other.eventId) {} -}; - -class LuaScriptInterface; -class Game; -class Npc; - -class ScriptEnvironment -{ - public: - ScriptEnvironment(); - ~ScriptEnvironment(); - - // non-copyable - ScriptEnvironment(const ScriptEnvironment&) = delete; - ScriptEnvironment& operator=(const ScriptEnvironment&) = delete; - - void resetEnv(); - - void setScriptId(int32_t scriptId, LuaScriptInterface* scriptInterface) { - m_scriptId = scriptId; - m_interface = scriptInterface; - } - bool setCallbackId(int32_t callbackId, LuaScriptInterface* scriptInterface); - void setEventDesc(std::string desc) { - m_eventdesc = desc; - } - - std::string getEventDesc() const { - return m_eventdesc; - } - int32_t getScriptId() const { - return m_scriptId; - } - int32_t getCallbackId() const { - return m_callbackId; - } - LuaScriptInterface* getScriptInterface() { - return m_interface; - } - - void setTimerEvent() { - m_timerEvent = true; - } - void resetTimerEvent() { - m_timerEvent = false; - } - - void getEventInfo(int32_t& scriptId, std::string& desc, LuaScriptInterface*& scriptInterface, int32_t& callbackId, bool& timerEvent) const; - - void addTempItem(Item* item); - static void removeTempItem(Item* item); - uint32_t addThing(Thing* thing); - void insertItem(uint32_t uid, Item* item); - - static DBResult_ptr getResultByID(uint32_t id); - static uint32_t addResult(DBResult_ptr res); - static bool removeResult(uint32_t id); - - void setNpc(Npc* npc) { - m_curNpc = npc; - } - Npc* getNpc() const { - return m_curNpc; - } - - Thing* getThingByUID(uint32_t uid); - Item* getItemByUID(uint32_t uid); - Container* getContainerByUID(uint32_t uid); - void removeItemByUID(uint32_t uid); - - private: - typedef std::vector VariantVector; - typedef std::map StorageMap; - typedef std::map DBResultMap; - - //script file id - int32_t m_scriptId; - int32_t m_callbackId; - bool m_timerEvent; - LuaScriptInterface* m_interface; - //script event desc - std::string m_eventdesc; - - //local item map - uint32_t m_lastUID; - std::unordered_map localMap; - - //temporary item list - static std::multimap tempItems; - - //result map - static uint32_t m_lastResultId; - static DBResultMap m_tempResults; - - //for npc scripts - Npc* m_curNpc; -}; - -#define reportErrorFunc(a) reportError(__FUNCTION__, a, true) - -enum ErrorCode_t { - LUA_ERROR_PLAYER_NOT_FOUND, - LUA_ERROR_CREATURE_NOT_FOUND, - LUA_ERROR_ITEM_NOT_FOUND, - LUA_ERROR_THING_NOT_FOUND, - LUA_ERROR_TILE_NOT_FOUND, - LUA_ERROR_HOUSE_NOT_FOUND, - LUA_ERROR_COMBAT_NOT_FOUND, - LUA_ERROR_CONDITION_NOT_FOUND, - LUA_ERROR_AREA_NOT_FOUND, - LUA_ERROR_CONTAINER_NOT_FOUND, - LUA_ERROR_VARIANT_NOT_FOUND, - LUA_ERROR_VARIANT_UNKNOWN, - LUA_ERROR_SPELL_NOT_FOUND, -}; - -class LuaScriptInterface -{ - public: - explicit LuaScriptInterface(std::string interfaceName); - virtual ~LuaScriptInterface(); - - // non-copyable - LuaScriptInterface(const LuaScriptInterface&) = delete; - LuaScriptInterface& operator=(const LuaScriptInterface&) = delete; - - virtual bool initState(); - bool reInitState(); - - int32_t loadFile(const std::string& file, Npc* npc = nullptr); - - const std::string& getFileById(int32_t scriptId); - int32_t getEvent(const std::string& eventName); - int32_t getMetaEvent(const std::string& globalName, const std::string& eventName); - - static ScriptEnvironment* getScriptEnv() { - assert(m_scriptEnvIndex >= 0 && m_scriptEnvIndex < 16); - return m_scriptEnv + m_scriptEnvIndex; - } - - static bool reserveScriptEnv() { - return ++m_scriptEnvIndex < 16; - } - - static void resetScriptEnv() { - assert(m_scriptEnvIndex >= 0); - m_scriptEnv[m_scriptEnvIndex--].resetEnv(); - } - - static void reportError(const char* function, const std::string& error_desc, bool stack_trace = false); - - const std::string& getInterfaceName() const { - return m_interfaceName; - } - const std::string& getLastLuaError() const { - return m_lastLuaError; - } - - lua_State* getLuaState() const { - return m_luaState; - } - - bool pushFunction(int32_t functionId); - - static int luaErrorHandler(lua_State* L); - bool callFunction(int params); - void callVoidFunction(int params); - - //push/pop common structures - static void pushThing(lua_State* L, Thing* thing); - static void pushVariant(lua_State* L, const LuaVariant& var); - static void pushString(lua_State* L, const std::string& value); - static void pushCallback(lua_State* L, int32_t callback); - - static std::string popString(lua_State* L); - static int32_t popCallback(lua_State* L); - - // Userdata - template - static void pushUserdata(lua_State* L, T* value) - { - T** userdata = static_cast(lua_newuserdata(L, sizeof(T*))); - *userdata = value; - } - - // Metatables - static void setMetatable(lua_State* L, int32_t index, const std::string& name); - static void setWeakMetatable(lua_State* L, int32_t index, const std::string& name); - - static void setItemMetatable(lua_State* L, int32_t index, const Item* item); - static void setCreatureMetatable(lua_State* L, int32_t index, const Creature* creature); - - // Get - template - inline static typename std::enable_if::value, T>::type - getNumber(lua_State* L, int32_t arg) - { - return static_cast(static_cast(lua_tonumber(L, arg))); - } - template - inline static typename std::enable_if::value || std::is_floating_point::value, T>::type - getNumber(lua_State* L, int32_t arg) - { - return static_cast(lua_tonumber(L, arg)); - } - template - static T getNumber(lua_State *L, int32_t arg, T defaultValue) - { - const auto parameters = lua_gettop(L); - if (parameters == 0 || arg > parameters) { - return defaultValue; - } - return getNumber(L, arg); - } - template - static T* getUserdata(lua_State* L, int32_t arg) - { - T** userdata = getRawUserdata(L, arg); - if (!userdata) { - return nullptr; - } - return *userdata; - } - template - inline static T** getRawUserdata(lua_State* L, int32_t arg) - { - return static_cast(lua_touserdata(L, arg)); - } - - inline static bool getBoolean(lua_State* L, int32_t arg) - { - return lua_toboolean(L, arg) != 0; - } - inline static bool getBoolean(lua_State* L, int32_t arg, bool defaultValue) - { - const auto parameters = lua_gettop(L); - if (parameters == 0 || arg > parameters) { - return defaultValue; - } - return lua_toboolean(L, arg) != 0; - } - - static std::string getString(lua_State* L, int32_t arg); - static Position getPosition(lua_State* L, int32_t arg, int32_t& stackpos); - static Position getPosition(lua_State* L, int32_t arg); - static Outfit_t getOutfit(lua_State* L, int32_t arg); - static LuaVariant getVariant(lua_State* L, int32_t arg); - - static Thing* getThing(lua_State* L, int32_t arg); - static Creature* getCreature(lua_State* L, int32_t arg); - static Player* getPlayer(lua_State* L, int32_t arg); - - template - static T getField(lua_State* L, int32_t arg, const std::string& key) - { - lua_getfield(L, arg, key.c_str()); - return getNumber(L, -1); - } - - static std::string getFieldString(lua_State* L, int32_t arg, const std::string& key); - - static LuaDataType getUserdataType(lua_State* L, int32_t arg); - - // Is - inline static bool isNumber(lua_State* L, int32_t arg) - { - return lua_isnumber(L, arg) != 0; - } - inline static bool isString(lua_State* L, int32_t arg) - { - return lua_isstring(L, arg) != 0; - } - inline static bool isBoolean(lua_State* L, int32_t arg) - { - return lua_isboolean(L, arg); - } - inline static bool isTable(lua_State* L, int32_t arg) - { - return lua_istable(L, arg); - } - inline static bool isFunction(lua_State* L, int32_t arg) - { - return lua_isfunction(L, arg); - } - inline static bool isUserdata(lua_State* L, int32_t arg) - { - return lua_isuserdata(L, arg) != 0; - } - - // Push - static void pushBoolean(lua_State* L, bool value); - static void pushPosition(lua_State* L, const Position& position, int32_t stackpos = 0); - static void pushOutfit(lua_State* L, const Outfit_t& outfit); - - // - inline static void setField(lua_State* L, const char* index, lua_Number value) - { - lua_pushnumber(L, value); - lua_setfield(L, -2, index); - } - - inline static void setField(lua_State* L, const char* index, const std::string& value) - { - pushString(L, value); - lua_setfield(L, -2, index); - } - - static std::string escapeString(const std::string& string); - -#ifndef LUAJIT_VERSION - static const luaL_Reg luaBitReg[7]; -#endif - static const luaL_Reg luaConfigManagerTable[4]; - static const luaL_Reg luaDatabaseTable[9]; - static const luaL_Reg luaResultTable[6]; - - static int protectedCall(lua_State* L, int nargs, int nresults); - - protected: - virtual bool closeState(); - - void registerFunctions(); - - void registerClass(const std::string& className, const std::string& baseClass, lua_CFunction newFunction = nullptr); - void registerTable(const std::string& tableName); - void registerMethod(const std::string& className, const std::string& methodName, lua_CFunction func); - void registerMetaMethod(const std::string& className, const std::string& methodName, lua_CFunction func); - void registerGlobalMethod(const std::string& functionName, lua_CFunction func); - void registerVariable(const std::string& tableName, const std::string& name, lua_Number value); - void registerGlobalVariable(const std::string& name, lua_Number value); - void registerGlobalBoolean(const std::string& name, bool value); - - std::string getStackTrace(const std::string& error_desc); - - static std::string getErrorDesc(ErrorCode_t code); - static bool getArea(lua_State* L, std::list& list, uint32_t& rows); - - //lua functions - static int luaDoCreateItem(lua_State* L); - static int luaDoCreateItemEx(lua_State* L); - static int luaDoMoveCreature(lua_State* L); - - static int luaDoPlayerAddItem(lua_State* L); - static int luaDoTileAddItemEx(lua_State* L); - static int luaDoSetCreatureLight(lua_State* L); - - //get item info - static int luaGetDepotId(lua_State* L); - - //get creature info functions - static int luaGetPlayerFlagValue(lua_State* L); - static int luaGetCreatureCondition(lua_State* L); - - static int luaGetPlayerInstantSpellInfo(lua_State* L); - static int luaGetPlayerInstantSpellCount(lua_State* L); - - static int luaGetWorldTime(lua_State* L); - static int luaGetWorldLight(lua_State* L); - static int luaGetWorldUpTime(lua_State* L); - - //type validation - static int luaIsDepot(lua_State* L); - static int luaIsMoveable(lua_State* L); - static int luaIsValidUID(lua_State* L); - - //container - static int luaDoAddContainerItem(lua_State* L); - - // - static int luaCreateCombatArea(lua_State* L); - - static int luaDoAreaCombatHealth(lua_State* L); - static int luaDoTargetCombatHealth(lua_State* L); - - // - static int luaDoAreaCombatMana(lua_State* L); - static int luaDoTargetCombatMana(lua_State* L); - - static int luaDoAreaCombatCondition(lua_State* L); - static int luaDoTargetCombatCondition(lua_State* L); - - static int luaDoAreaCombatDispel(lua_State* L); - static int luaDoTargetCombatDispel(lua_State* L); - - static int luaDoChallengeCreature(lua_State* L); - - static int luaSetCreatureOutfit(lua_State* L); - static int luaSetMonsterOutfit(lua_State* L); - static int luaSetItemOutfit(lua_State* L); - - static int luaDebugPrint(lua_State* L); - static int luaIsInArray(lua_State* L); - static int luaAddEvent(lua_State* L); - static int luaStopEvent(lua_State* L); - - static int luaSaveServer(lua_State* L); - static int luaCleanMap(lua_State* L); - - static int luaIsInWar(lua_State* L); - - static int luaGetWaypointPositionByName(lua_State* L); - - static int luaSendChannelMessage(lua_State* L); - static int luaSendGuildChannelMessage(lua_State* L); - -#ifndef LUAJIT_VERSION - static int luaBitNot(lua_State* L); - static int luaBitAnd(lua_State* L); - static int luaBitOr(lua_State* L); - static int luaBitXor(lua_State* L); - static int luaBitLeftShift(lua_State* L); - static int luaBitRightShift(lua_State* L); -#endif - - static int luaConfigManagerGetString(lua_State* L); - static int luaConfigManagerGetNumber(lua_State* L); - static int luaConfigManagerGetBoolean(lua_State* L); - - static int luaDatabaseExecute(lua_State* L); - static int luaDatabaseAsyncExecute(lua_State* L); - static int luaDatabaseStoreQuery(lua_State* L); - static int luaDatabaseAsyncStoreQuery(lua_State* L); - static int luaDatabaseEscapeString(lua_State* L); - static int luaDatabaseEscapeBlob(lua_State* L); - static int luaDatabaseLastInsertId(lua_State* L); - static int luaDatabaseConnected(lua_State* L); - static int luaDatabaseTableExists(lua_State* L); - - static int luaResultGetNumber(lua_State* L); - static int luaResultGetString(lua_State* L); - static int luaResultGetStream(lua_State* L); - static int luaResultNext(lua_State* L); - static int luaResultFree(lua_State* L); - - // Userdata - static int luaUserdataCompare(lua_State* L); - - // _G - static int luaIsType(lua_State* L); - static int luaRawGetMetatable(lua_State* L); - - // os - static int luaSystemTime(lua_State* L); - - // table - static int luaTableCreate(lua_State* L); - - // Game - static int luaGameGetSpectators(lua_State* L); - static int luaGameGetPlayers(lua_State* L); - static int luaGameLoadMap(lua_State* L); - - static int luaGameGetExperienceStage(lua_State* L); - static int luaGameGetMonsterCount(lua_State* L); - static int luaGameGetPlayerCount(lua_State* L); - static int luaGameGetNpcCount(lua_State* L); - - static int luaGameGetTowns(lua_State* L); - static int luaGameGetHouses(lua_State* L); - - static int luaGameGetGameState(lua_State* L); - static int luaGameSetGameState(lua_State* L); - - static int luaGameGetWorldType(lua_State* L); - static int luaGameSetWorldType(lua_State* L); - - static int luaGameGetReturnMessage(lua_State* L); - - static int luaGameCreateItem(lua_State* L); - static int luaGameCreateContainer(lua_State* L); - static int luaGameCreateMonster(lua_State* L); - static int luaGameCreateNpc(lua_State* L); - static int luaGameCreateTile(lua_State* L); - - static int luaGameStartRaid(lua_State* L); - - static int luaGameHasEffect(lua_State* L); - static int luaGameHasDistanceEffect(lua_State* L); - - // Variant - static int luaVariantCreate(lua_State* L); - - static int luaVariantGetNumber(lua_State* L); - static int luaVariantGetString(lua_State* L); - static int luaVariantGetPosition(lua_State* L); - - // Position - static int luaPositionCreate(lua_State* L); - static int luaPositionAdd(lua_State* L); - static int luaPositionSub(lua_State* L); - static int luaPositionCompare(lua_State* L); - - static int luaPositionGetDistance(lua_State* L); - static int luaPositionIsSightClear(lua_State* L); - - static int luaPositionSendMagicEffect(lua_State* L); - static int luaPositionSendDistanceEffect(lua_State* L); - - // Tile - static int luaTileCreate(lua_State* L); - - static int luaTileGetPosition(lua_State* L); - static int luaTileGetGround(lua_State* L); - static int luaTileGetThing(lua_State* L); - static int luaTileGetThingCount(lua_State* L); - static int luaTileGetTopVisibleThing(lua_State* L); - - static int luaTileGetTopTopItem(lua_State* L); - static int luaTileGetTopDownItem(lua_State* L); - static int luaTileGetFieldItem(lua_State* L); - - static int luaTileGetItemById(lua_State* L); - static int luaTileGetItemByType(lua_State* L); - static int luaTileGetItemByTopOrder(lua_State* L); - static int luaTileGetItemCountById(lua_State* L); - - static int luaTileGetBottomCreature(lua_State* L); - static int luaTileGetTopCreature(lua_State* L); - static int luaTileGetBottomVisibleCreature(lua_State* L); - static int luaTileGetTopVisibleCreature(lua_State* L); - - static int luaTileGetItems(lua_State* L); - static int luaTileGetItemCount(lua_State* L); - static int luaTileGetDownItemCount(lua_State* L); - static int luaTileGetTopItemCount(lua_State* L); - - static int luaTileGetCreatures(lua_State* L); - static int luaTileGetCreatureCount(lua_State* L); - - static int luaTileHasProperty(lua_State* L); - static int luaTileHasFlag(lua_State* L); - - static int luaTileGetThingIndex(lua_State* L); - - static int luaTileQueryAdd(lua_State* L); - - static int luaTileGetHouse(lua_State* L); - - // NetworkMessage - static int luaNetworkMessageCreate(lua_State* L); - static int luaNetworkMessageDelete(lua_State* L); - - static int luaNetworkMessageGetByte(lua_State* L); - static int luaNetworkMessageGetU16(lua_State* L); - static int luaNetworkMessageGetU32(lua_State* L); - static int luaNetworkMessageGetU64(lua_State* L); - static int luaNetworkMessageGetString(lua_State* L); - static int luaNetworkMessageGetPosition(lua_State* L); - - static int luaNetworkMessageAddByte(lua_State* L); - static int luaNetworkMessageAddU16(lua_State* L); - static int luaNetworkMessageAddU32(lua_State* L); - static int luaNetworkMessageAddU64(lua_State* L); - static int luaNetworkMessageAddString(lua_State* L); - static int luaNetworkMessageAddPosition(lua_State* L); - static int luaNetworkMessageAddDouble(lua_State* L); - static int luaNetworkMessageAddItem(lua_State* L); - static int luaNetworkMessageAddItemId(lua_State* L); - - static int luaNetworkMessageReset(lua_State* L); - static int luaNetworkMessageSkipBytes(lua_State* L); - static int luaNetworkMessageSendToPlayer(lua_State* L); - - // ModalWindow - static int luaModalWindowCreate(lua_State* L); - static int luaModalWindowDelete(lua_State* L); - - static int luaModalWindowGetId(lua_State* L); - static int luaModalWindowGetTitle(lua_State* L); - static int luaModalWindowGetMessage(lua_State* L); - - static int luaModalWindowSetTitle(lua_State* L); - static int luaModalWindowSetMessage(lua_State* L); - - static int luaModalWindowGetButtonCount(lua_State* L); - static int luaModalWindowGetChoiceCount(lua_State* L); - - static int luaModalWindowAddButton(lua_State* L); - static int luaModalWindowAddChoice(lua_State* L); - - static int luaModalWindowGetDefaultEnterButton(lua_State* L); - static int luaModalWindowSetDefaultEnterButton(lua_State* L); - - static int luaModalWindowGetDefaultEscapeButton(lua_State* L); - static int luaModalWindowSetDefaultEscapeButton(lua_State* L); - - static int luaModalWindowHasPriority(lua_State* L); - static int luaModalWindowSetPriority(lua_State* L); - - static int luaModalWindowSendToPlayer(lua_State* L); - - // Item - static int luaItemCreate(lua_State* L); - - static int luaItemIsItem(lua_State* L); - - static int luaItemGetParent(lua_State* L); - static int luaItemGetTopParent(lua_State* L); - - static int luaItemGetId(lua_State* L); - - static int luaItemClone(lua_State* L); - static int luaItemSplit(lua_State* L); - static int luaItemRemove(lua_State* L); - - static int luaItemGetUniqueId(lua_State* L); - static int luaItemGetActionId(lua_State* L); - static int luaItemSetActionId(lua_State* L); - - static int luaItemGetCount(lua_State* L); - static int luaItemGetCharges(lua_State* L); - static int luaItemGetFluidType(lua_State* L); - static int luaItemGetWeight(lua_State* L); - - static int luaItemGetSubType(lua_State* L); - - static int luaItemGetName(lua_State* L); - static int luaItemGetPluralName(lua_State* L); - static int luaItemGetArticle(lua_State* L); - - static int luaItemGetPosition(lua_State* L); - static int luaItemGetTile(lua_State* L); - - static int luaItemHasAttribute(lua_State* L); - static int luaItemGetAttribute(lua_State* L); - static int luaItemSetAttribute(lua_State* L); - static int luaItemRemoveAttribute(lua_State* L); - static int luaItemSerializeAttributes(lua_State* L); - - static int luaItemMoveTo(lua_State* L); - static int luaItemTransform(lua_State* L); - static int luaItemDecay(lua_State* L); - - static int luaItemGetDescription(lua_State* L); - - static int luaItemHasProperty(lua_State* L); - - // Container - static int luaContainerCreate(lua_State* L); - - static int luaContainerGetSize(lua_State* L); - static int luaContainerGetCapacity(lua_State* L); - static int luaContainerGetEmptySlots(lua_State* L); - - static int luaContainerGetItemHoldingCount(lua_State* L); - static int luaContainerGetItemCountById(lua_State* L); - - static int luaContainerGetItem(lua_State* L); - static int luaContainerHasItem(lua_State* L); - static int luaContainerAddItem(lua_State* L); - static int luaContainerAddItemEx(lua_State* L); - - // Teleport - static int luaTeleportCreate(lua_State* L); - - static int luaTeleportGetDestination(lua_State* L); - static int luaTeleportSetDestination(lua_State* L); - - // Creature - static int luaCreatureCreate(lua_State* L); - - static int luaCreatureRegisterEvent(lua_State* L); - static int luaCreatureUnregisterEvent(lua_State* L); - - static int luaCreatureIsRemoved(lua_State* L); - static int luaCreatureIsCreature(lua_State* L); - static int luaCreatureIsInGhostMode(lua_State* L); - static int luaCreatureIsHealthHidden(lua_State* L); - - static int luaCreatureCanSee(lua_State* L); - static int luaCreatureCanSeeCreature(lua_State* L); - - static int luaCreatureGetParent(lua_State* L); - - static int luaCreatureGetId(lua_State* L); - static int luaCreatureGetName(lua_State* L); - - static int luaCreatureGetTarget(lua_State* L); - static int luaCreatureSetTarget(lua_State* L); - - static int luaCreatureGetFollowCreature(lua_State* L); - static int luaCreatureSetFollowCreature(lua_State* L); - - static int luaCreatureGetMaster(lua_State* L); - static int luaCreatureSetMaster(lua_State* L); - - static int luaCreatureGetLight(lua_State* L); - static int luaCreatureSetLight(lua_State* L); - - static int luaCreatureGetSpeed(lua_State* L); - static int luaCreatureGetBaseSpeed(lua_State* L); - static int luaCreatureChangeSpeed(lua_State* L); - - static int luaCreatureSetDropLoot(lua_State* L); - - static int luaCreatureGetPosition(lua_State* L); - static int luaCreatureGetTile(lua_State* L); - static int luaCreatureGetDirection(lua_State* L); - static int luaCreatureSetDirection(lua_State* L); - - static int luaCreatureGetHealth(lua_State* L); - static int luaCreatureAddHealth(lua_State* L); - static int luaCreatureGetMaxHealth(lua_State* L); - static int luaCreatureSetMaxHealth(lua_State* L); - static int luaCreatureSetHiddenHealth(lua_State* L); - - static int luaCreatureGetMana(lua_State* L); - static int luaCreatureAddMana(lua_State* L); - static int luaCreatureGetMaxMana(lua_State* L); - - static int luaCreatureGetSkull(lua_State* L); - static int luaCreatureSetSkull(lua_State* L); - - static int luaCreatureGetOutfit(lua_State* L); - static int luaCreatureSetOutfit(lua_State* L); - - static int luaCreatureGetCondition(lua_State* L); - static int luaCreatureAddCondition(lua_State* L); - static int luaCreatureRemoveCondition(lua_State* L); - - static int luaCreatureRemove(lua_State* L); - static int luaCreatureTeleportTo(lua_State* L); - static int luaCreatureSay(lua_State* L); - - static int luaCreatureGetDamageMap(lua_State* L); - - static int luaCreatureGetSummons(lua_State* L); - - static int luaCreatureGetDescription(lua_State* L); - - static int luaCreatureGetPathTo(lua_State* L); - - // Player - static int luaPlayerCreate(lua_State* L); - - static int luaPlayerIsPlayer(lua_State* L); - - static int luaPlayerGetGuid(lua_State* L); - static int luaPlayerGetIp(lua_State* L); - static int luaPlayerGetAccountId(lua_State* L); - static int luaPlayerGetLastLoginSaved(lua_State* L); - static int luaPlayerGetLastLogout(lua_State* L); - - static int luaPlayerGetAccountType(lua_State* L); - static int luaPlayerSetAccountType(lua_State* L); - - static int luaPlayerGetCapacity(lua_State* L); - static int luaPlayerSetCapacity(lua_State* L); - - static int luaPlayerGetFreeCapacity(lua_State* L); - - static int luaPlayerGetDepotChest(lua_State* L); - static int luaPlayerGetInbox(lua_State* L); - - static int luaPlayerGetSkullTime(lua_State* L); - static int luaPlayerSetSkullTime(lua_State* L); - static int luaPlayerGetDeathPenalty(lua_State* L); - - static int luaPlayerGetExperience(lua_State* L); - static int luaPlayerAddExperience(lua_State* L); - static int luaPlayerRemoveExperience(lua_State* L); - static int luaPlayerGetLevel(lua_State* L); - - static int luaPlayerGetMagicLevel(lua_State* L); - static int luaPlayerGetBaseMagicLevel(lua_State* L); - static int luaPlayerSetMaxMana(lua_State* L); - static int luaPlayerGetManaSpent(lua_State* L); - static int luaPlayerAddManaSpent(lua_State* L); - - static int luaPlayerGetSkillLevel(lua_State* L); - static int luaPlayerGetEffectiveSkillLevel(lua_State* L); - static int luaPlayerGetSkillPercent(lua_State* L); - static int luaPlayerGetSkillTries(lua_State* L); - static int luaPlayerAddSkillTries(lua_State* L); - - static int luaPlayerAddOfflineTrainingTime(lua_State* L); - static int luaPlayerGetOfflineTrainingTime(lua_State* L); - static int luaPlayerRemoveOfflineTrainingTime(lua_State* L); - - static int luaPlayerAddOfflineTrainingTries(lua_State* L); - - static int luaPlayerGetOfflineTrainingSkill(lua_State* L); - static int luaPlayerSetOfflineTrainingSkill(lua_State* L); - - static int luaPlayerGetItemCount(lua_State* L); - static int luaPlayerGetItemById(lua_State* L); - - static int luaPlayerGetVocation(lua_State* L); - static int luaPlayerSetVocation(lua_State* L); - - static int luaPlayerGetSex(lua_State* L); - static int luaPlayerSetSex(lua_State* L); - - static int luaPlayerGetTown(lua_State* L); - static int luaPlayerSetTown(lua_State* L); - - static int luaPlayerGetGuild(lua_State* L); - static int luaPlayerSetGuild(lua_State* L); - - static int luaPlayerGetGuildLevel(lua_State* L); - static int luaPlayerSetGuildLevel(lua_State* L); - - static int luaPlayerGetGuildNick(lua_State* L); - static int luaPlayerSetGuildNick(lua_State* L); - - static int luaPlayerGetGroup(lua_State* L); - static int luaPlayerSetGroup(lua_State* L); - - static int luaPlayerGetStamina(lua_State* L); - static int luaPlayerSetStamina(lua_State* L); - - static int luaPlayerGetSoul(lua_State* L); - static int luaPlayerAddSoul(lua_State* L); - static int luaPlayerGetMaxSoul(lua_State* L); - - static int luaPlayerGetBankBalance(lua_State* L); - static int luaPlayerSetBankBalance(lua_State* L); - - static int luaPlayerGetStorageValue(lua_State* L); - static int luaPlayerSetStorageValue(lua_State* L); - - static int luaPlayerAddItem(lua_State* L); - static int luaPlayerAddItemEx(lua_State* L); - static int luaPlayerRemoveItem(lua_State* L); - - static int luaPlayerGetMoney(lua_State* L); - static int luaPlayerAddMoney(lua_State* L); - static int luaPlayerRemoveMoney(lua_State* L); - - static int luaPlayerShowTextDialog(lua_State* L); - - static int luaPlayerSendTextMessage(lua_State* L); - static int luaPlayerSendChannelMessage(lua_State* L); - static int luaPlayerSendPrivateMessage(lua_State* L); - - static int luaPlayerChannelSay(lua_State* L); - static int luaPlayerOpenChannel(lua_State* L); - - static int luaPlayerGetSlotItem(lua_State* L); - - static int luaPlayerGetParty(lua_State* L); - - static int luaPlayerAddOutfit(lua_State* L); - static int luaPlayerAddOutfitAddon(lua_State* L); - static int luaPlayerRemoveOutfit(lua_State* L); - static int luaPlayerRemoveOutfitAddon(lua_State* L); - static int luaPlayerHasOutfit(lua_State* L); - static int luaPlayerSendOutfitWindow(lua_State* L); - - static int luaPlayerAddMount(lua_State* L); - static int luaPlayerRemoveMount(lua_State* L); - static int luaPlayerHasMount(lua_State* L); - - static int luaPlayerGetPremiumDays(lua_State* L); - static int luaPlayerAddPremiumDays(lua_State* L); - static int luaPlayerRemovePremiumDays(lua_State* L); - - static int luaPlayerHasBlessing(lua_State* L); - static int luaPlayerAddBlessing(lua_State* L); - static int luaPlayerRemoveBlessing(lua_State* L); - - static int luaPlayerCanLearnSpell(lua_State* L); - static int luaPlayerLearnSpell(lua_State* L); - static int luaPlayerForgetSpell(lua_State* L); - static int luaPlayerHasLearnedSpell(lua_State* L); - - static int luaPlayerSendTutorial(lua_State* L); - static int luaPlayerAddMapMark(lua_State* L); - - static int luaPlayerSave(lua_State* L); - static int luaPlayerPopupFYI(lua_State* L); - - static int luaPlayerIsPzLocked(lua_State* L); - - static int luaPlayerGetClient(lua_State* L); - static int luaPlayerGetHouse(lua_State* L); - - static int luaPlayerSetGhostMode(lua_State* L); - - static int luaPlayerGetContainerId(lua_State* L); - static int luaPlayerGetContainerById(lua_State* L); - static int luaPlayerGetContainerIndex(lua_State* L); - - // Monster - static int luaMonsterCreate(lua_State* L); - - static int luaMonsterIsMonster(lua_State* L); - - static int luaMonsterGetType(lua_State* L); - - static int luaMonsterGetSpawnPosition(lua_State* L); - static int luaMonsterIsInSpawnRange(lua_State* L); - - static int luaMonsterIsIdle(lua_State* L); - static int luaMonsterSetIdle(lua_State* L); - - static int luaMonsterIsTarget(lua_State* L); - static int luaMonsterIsOpponent(lua_State* L); - static int luaMonsterIsFriend(lua_State* L); - - static int luaMonsterAddFriend(lua_State* L); - static int luaMonsterRemoveFriend(lua_State* L); - static int luaMonsterGetFriendList(lua_State* L); - static int luaMonsterGetFriendCount(lua_State* L); - - static int luaMonsterAddTarget(lua_State* L); - static int luaMonsterRemoveTarget(lua_State* L); - static int luaMonsterGetTargetList(lua_State* L); - static int luaMonsterGetTargetCount(lua_State* L); - - static int luaMonsterSelectTarget(lua_State* L); - static int luaMonsterSearchTarget(lua_State* L); - - // Npc - static int luaNpcCreate(lua_State* L); - - static int luaNpcIsNpc(lua_State* L); - - static int luaNpcSetMasterPos(lua_State* L); - - static int luaNpcGetSpeechBubble(lua_State* L); - static int luaNpcSetSpeechBubble(lua_State* L); - - // Guild - static int luaGuildCreate(lua_State* L); - - static int luaGuildGetId(lua_State* L); - static int luaGuildGetName(lua_State* L); - static int luaGuildGetMembersOnline(lua_State* L); - - static int luaGuildAddRank(lua_State* L); - static int luaGuildGetRankById(lua_State* L); - static int luaGuildGetRankByLevel(lua_State* L); - - static int luaGuildGetMotd(lua_State* L); - static int luaGuildSetMotd(lua_State* L); - - // Group - static int luaGroupCreate(lua_State* L); - - static int luaGroupGetId(lua_State* L); - static int luaGroupGetName(lua_State* L); - static int luaGroupGetFlags(lua_State* L); - static int luaGroupGetAccess(lua_State* L); - static int luaGroupGetMaxDepotItems(lua_State* L); - static int luaGroupGetMaxVipEntries(lua_State* L); - - // Vocation - static int luaVocationCreate(lua_State* L); - - static int luaVocationGetId(lua_State* L); - static int luaVocationGetClientId(lua_State* L); - static int luaVocationGetName(lua_State* L); - static int luaVocationGetDescription(lua_State* L); - - static int luaVocationGetRequiredSkillTries(lua_State* L); - static int luaVocationGetRequiredManaSpent(lua_State* L); - - static int luaVocationGetCapacityGain(lua_State* L); - - static int luaVocationGetHealthGain(lua_State* L); - static int luaVocationGetHealthGainTicks(lua_State* L); - static int luaVocationGetHealthGainAmount(lua_State* L); - - static int luaVocationGetManaGain(lua_State* L); - static int luaVocationGetManaGainTicks(lua_State* L); - static int luaVocationGetManaGainAmount(lua_State* L); - - static int luaVocationGetMaxSoul(lua_State* L); - static int luaVocationGetSoulGainTicks(lua_State* L); - - static int luaVocationGetAttackSpeed(lua_State* L); - static int luaVocationGetBaseSpeed(lua_State* L); - - static int luaVocationGetDemotion(lua_State* L); - static int luaVocationGetPromotion(lua_State* L); - - // Town - static int luaTownCreate(lua_State* L); - - static int luaTownGetId(lua_State* L); - static int luaTownGetName(lua_State* L); - static int luaTownGetTemplePosition(lua_State* L); - - // House - static int luaHouseCreate(lua_State* L); - - static int luaHouseGetId(lua_State* L); - static int luaHouseGetName(lua_State* L); - static int luaHouseGetTown(lua_State* L); - static int luaHouseGetExitPosition(lua_State* L); - static int luaHouseGetRent(lua_State* L); - - static int luaHouseGetOwnerGuid(lua_State* L); - static int luaHouseSetOwnerGuid(lua_State* L); - - static int luaHouseGetBeds(lua_State* L); - static int luaHouseGetBedCount(lua_State* L); - - static int luaHouseGetDoors(lua_State* L); - static int luaHouseGetDoorCount(lua_State* L); - - static int luaHouseGetTiles(lua_State* L); - static int luaHouseGetTileCount(lua_State* L); - - static int luaHouseGetAccessList(lua_State* L); - static int luaHouseSetAccessList(lua_State* L); - - // ItemType - static int luaItemTypeCreate(lua_State* L); - - static int luaItemTypeIsCorpse(lua_State* L); - static int luaItemTypeIsDoor(lua_State* L); - static int luaItemTypeIsContainer(lua_State* L); - static int luaItemTypeIsFluidContainer(lua_State* L); - static int luaItemTypeIsMovable(lua_State* L); - static int luaItemTypeIsRune(lua_State* L); - static int luaItemTypeIsStackable(lua_State* L); - static int luaItemTypeIsReadable(lua_State* L); - static int luaItemTypeIsWritable(lua_State* L); - - static int luaItemTypeGetType(lua_State* L); - static int luaItemTypeGetId(lua_State* L); - static int luaItemTypeGetClientId(lua_State* L); - static int luaItemTypeGetName(lua_State* L); - static int luaItemTypeGetPluralName(lua_State* L); - static int luaItemTypeGetArticle(lua_State* L); - static int luaItemTypeGetDescription(lua_State* L); - static int luaItemTypeGetSlotPosition(lua_State *L); - - static int luaItemTypeGetCharges(lua_State* L); - static int luaItemTypeGetFluidSource(lua_State* L); - static int luaItemTypeGetCapacity(lua_State* L); - static int luaItemTypeGetWeight(lua_State* L); - - static int luaItemTypeGetHitChance(lua_State* L); - static int luaItemTypeGetShootRange(lua_State* L); - static int luaItemTypeGetAttack(lua_State* L); - static int luaItemTypeGetDefense(lua_State* L); - static int luaItemTypeGetExtraDefense(lua_State* L); - static int luaItemTypeGetArmor(lua_State* L); - static int luaItemTypeGetWeaponType(lua_State* L); - - static int luaItemTypeGetElementType(lua_State* L); - static int luaItemTypeGetElementDamage(lua_State* L); - - static int luaItemTypeGetTransformEquipId(lua_State* L); - static int luaItemTypeGetTransformDeEquipId(lua_State* L); - static int luaItemTypeGetDestroyId(lua_State* L); - static int luaItemTypeGetDecayId(lua_State* L); - static int luaItemTypeGetRequiredLevel(lua_State* L); - - static int luaItemTypeHasSubType(lua_State* L); - - // Combat - static int luaCombatCreate(lua_State* L); - - static int luaCombatSetParameter(lua_State* L); - static int luaCombatSetFormula(lua_State* L); - - static int luaCombatSetArea(lua_State* L); - static int luaCombatSetCondition(lua_State* L); - static int luaCombatSetCallback(lua_State* L); - static int luaCombatSetOrigin(lua_State* L); - - static int luaCombatExecute(lua_State* L); - - // Condition - static int luaConditionCreate(lua_State* L); - static int luaConditionDelete(lua_State* L); - - static int luaConditionGetId(lua_State* L); - static int luaConditionGetSubId(lua_State* L); - static int luaConditionGetType(lua_State* L); - static int luaConditionGetIcons(lua_State* L); - static int luaConditionGetEndTime(lua_State* L); - - static int luaConditionClone(lua_State* L); - - static int luaConditionGetTicks(lua_State* L); - static int luaConditionSetTicks(lua_State* L); - - static int luaConditionSetParameter(lua_State* L); - static int luaConditionSetFormula(lua_State* L); - static int luaConditionSetOutfit(lua_State* L); - - static int luaConditionAddDamage(lua_State* L); - - // MonsterType - static int luaMonsterTypeCreate(lua_State* L); - - static int luaMonsterTypeIsAttackable(lua_State* L); - static int luaMonsterTypeIsConvinceable(lua_State* L); - static int luaMonsterTypeIsSummonable(lua_State* L); - static int luaMonsterTypeIsIllusionable(lua_State* L); - static int luaMonsterTypeIsHostile(lua_State* L); - static int luaMonsterTypeIsPassive(lua_State* L); - static int luaMonsterTypeIsPushable(lua_State* L); - static int luaMonsterTypeIsHealthShown(lua_State* L); - - static int luaMonsterTypeCanPushItems(lua_State* L); - static int luaMonsterTypeCanPushCreatures(lua_State* L); - - static int luaMonsterTypeGetName(lua_State* L); - static int luaMonsterTypeGetNameDescription(lua_State* L); - - static int luaMonsterTypeGetHealth(lua_State* L); - static int luaMonsterTypeGetMaxHealth(lua_State* L); - static int luaMonsterTypeGetRunHealth(lua_State* L); - static int luaMonsterTypeGetExperience(lua_State* L); - - static int luaMonsterTypeGetCombatImmunities(lua_State* L); - static int luaMonsterTypeGetConditionImmunities(lua_State* L); - - static int luaMonsterTypeGetAttackList(lua_State* L); - static int luaMonsterTypeGetDefenseList(lua_State* L); - static int luaMonsterTypeGetElementList(lua_State* L); - - static int luaMonsterTypeGetVoices(lua_State* L); - static int luaMonsterTypeGetLoot(lua_State* L); - static int luaMonsterTypeGetCreatureEvents(lua_State* L); - - static int luaMonsterTypeGetSummonList(lua_State* L); - static int luaMonsterTypeGetMaxSummons(lua_State* L); - - static int luaMonsterTypeGetArmor(lua_State* L); - static int luaMonsterTypeGetDefense(lua_State* L); - static int luaMonsterTypeGetOutfit(lua_State* L); - static int luaMonsterTypeGetRace(lua_State* L); - static int luaMonsterTypeGetCorpseId(lua_State* L); - static int luaMonsterTypeGetManaCost(lua_State* L); - static int luaMonsterTypeGetBaseSpeed(lua_State* L); - static int luaMonsterTypeGetLight(lua_State* L); - - static int luaMonsterTypeGetStaticAttackChance(lua_State* L); - static int luaMonsterTypeGetTargetDistance(lua_State* L); - static int luaMonsterTypeGetYellChance(lua_State* L); - static int luaMonsterTypeGetYellSpeedTicks(lua_State* L); - static int luaMonsterTypeGetChangeTargetChance(lua_State* L); - static int luaMonsterTypeGetChangeTargetSpeed(lua_State* L); - - // Party - static int luaPartyDisband(lua_State* L); - - static int luaPartyGetLeader(lua_State* L); - static int luaPartySetLeader(lua_State* L); - - static int luaPartyGetMembers(lua_State* L); - static int luaPartyGetMemberCount(lua_State* L); - - static int luaPartyGetInvitees(lua_State* L); - static int luaPartyGetInviteeCount(lua_State* L); - - static int luaPartyAddInvite(lua_State* L); - static int luaPartyRemoveInvite(lua_State* L); - - static int luaPartyAddMember(lua_State* L); - static int luaPartyRemoveMember(lua_State* L); - - static int luaPartyIsSharedExperienceActive(lua_State* L); - static int luaPartyIsSharedExperienceEnabled(lua_State* L); - static int luaPartyShareExperience(lua_State* L); - static int luaPartySetSharedExperience(lua_State* L); - - // - lua_State* m_luaState; - std::string m_lastLuaError; - - std::string m_interfaceName; - int32_t m_eventTableRef; - - static ScriptEnvironment m_scriptEnv[16]; - static int32_t m_scriptEnvIndex; - - int32_t m_runningEventId; - std::string m_loadingFile; - - //script file cache - std::map m_cacheFiles; -}; - -class LuaEnvironment : public LuaScriptInterface -{ - public: - LuaEnvironment(); - ~LuaEnvironment(); - - // non-copyable - LuaEnvironment(const LuaEnvironment&) = delete; - LuaEnvironment& operator=(const LuaEnvironment&) = delete; - - bool initState(); - bool reInitState(); - bool closeState(); - - LuaScriptInterface* getTestInterface(); - - Combat* getCombatObject(uint32_t id) const; - Combat* createCombatObject(LuaScriptInterface* interface); - void clearCombatObjects(LuaScriptInterface* interface); - - AreaCombat* getAreaObject(uint32_t id) const; - uint32_t createAreaObject(LuaScriptInterface* interface); - void clearAreaObjects(LuaScriptInterface* interface); - - private: - void executeTimerEvent(uint32_t eventIndex); - - // - std::unordered_map m_timerEvents; - std::unordered_map m_combatMap; - std::unordered_map m_areaMap; - - std::unordered_map> m_combatIdMap; - std::unordered_map> m_areaIdMap; - - LuaScriptInterface* m_testInterface; - - uint32_t m_lastEventTimerId; - uint32_t m_lastCombatId; - uint32_t m_lastAreaId; - - // - friend class LuaScriptInterface; - friend class CombatSpell; -}; - -#endif diff --git a/path_10_8/src/mailbox.cpp b/path_10_8/src/mailbox.cpp deleted file mode 100644 index c9553a50c..000000000 --- a/path_10_8/src/mailbox.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "mailbox.h" -#include "game.h" -#include "iologindata.h" - -extern Game g_game; - -ReturnValue Mailbox::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t, Creature*) const -{ - const Item* item = thing.getItem(); - if (item && Mailbox::canSend(item)) { - return RETURNVALUE_NOERROR; - } - return RETURNVALUE_NOTPOSSIBLE; -} - -ReturnValue Mailbox::queryMaxCount(int32_t, const Thing&, uint32_t count, uint32_t& maxQueryCount, uint32_t) const -{ - maxQueryCount = std::max(1, count); - return RETURNVALUE_NOERROR; -} - -ReturnValue Mailbox::queryRemove(const Thing&, uint32_t, uint32_t) const -{ - return RETURNVALUE_NOTPOSSIBLE; -} - -Cylinder* Mailbox::queryDestination(int32_t&, const Thing&, Item**, uint32_t&) -{ - return this; -} - -void Mailbox::addThing(Thing* thing) -{ - return addThing(0, thing); -} - -void Mailbox::addThing(int32_t, Thing* thing) -{ - Item* item = thing->getItem(); - if (item && Mailbox::canSend(item)) { - sendItem(item); - } -} - -void Mailbox::updateThing(Thing*, uint16_t, uint32_t) -{ - // -} - -void Mailbox::replaceThing(uint32_t, Thing*) -{ - // -} - -void Mailbox::removeThing(Thing*, uint32_t) -{ - // -} - -void Mailbox::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); -} - -void Mailbox::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); -} - -bool Mailbox::sendItem(Item* item) const -{ - std::string receiver; - if (!getReceiver(item, receiver)) { - return false; - } - - /**No need to continue if its still empty**/ - if (receiver.empty()) { - return false; - } - - Player* player = g_game.getPlayerByName(receiver); - if (player) { - if (g_game.internalMoveItem(item->getParent(), player->getInbox(), INDEX_WHEREEVER, - item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) { - g_game.transformItem(item, item->getID() + 1); - player->onReceiveMail(); - return true; - } - } else { - Player tmpPlayer(nullptr); - if (!IOLoginData::loadPlayerByName(&tmpPlayer, receiver)) { - return false; - } - - if (g_game.internalMoveItem(item->getParent(), tmpPlayer.getInbox(), INDEX_WHEREEVER, - item, item->getItemCount(), nullptr, FLAG_NOLIMIT) == RETURNVALUE_NOERROR) { - g_game.transformItem(item, item->getID() + 1); - IOLoginData::savePlayer(&tmpPlayer); - return true; - } - } - return false; -} - -bool Mailbox::getReceiver(Item* item, std::string& name) const -{ - const Container* container = item->getContainer(); - if (container) { - for (Item* containerItem : container->getItemList()) { - if (containerItem->getID() == ITEM_LABEL && getReceiver(containerItem, name)) { - return true; - } - } - return false; - } - - const std::string& text = item->getText(); - if (text.empty()) { - return false; - } - - name = getFirstLine(text); - trimString(name); - return true; -} - -bool Mailbox::canSend(const Item* item) -{ - return item->getID() == ITEM_PARCEL || item->getID() == ITEM_LETTER; -} diff --git a/path_10_8/src/mailbox.h b/path_10_8/src/mailbox.h deleted file mode 100644 index c4b70f5dc..000000000 --- a/path_10_8/src/mailbox.h +++ /dev/null @@ -1,66 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MAILBOX_H_D231C6BE8D384CAAA3AE410C1323F9DB -#define FS_MAILBOX_H_D231C6BE8D384CAAA3AE410C1323F9DB - -#include "item.h" -#include "cylinder.h" -#include "const.h" - -class Mailbox final : public Item, public Cylinder -{ - public: - explicit Mailbox(uint16_t itemId) : Item(itemId) {} - - Mailbox* getMailbox() final { - return this; - } - const Mailbox* getMailbox() const final { - return this; - } - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, - uint32_t& maxQueryCount, uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) final; - - void addThing(Thing* thing) final; - void addThing(int32_t index, Thing* thing) final; - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - private: - bool getReceiver(Item* item, std::string& name) const; - bool sendItem(Item* item) const; - - static bool canSend(const Item* item); -}; - -#endif diff --git a/path_10_8/src/map.cpp b/path_10_8/src/map.cpp deleted file mode 100644 index 502e18c4a..000000000 --- a/path_10_8/src/map.cpp +++ /dev/null @@ -1,1042 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "iomap.h" -#include "iomapserialize.h" -#include "combat.h" -#include "creature.h" -#include "game.h" - -extern Game g_game; - -bool Map::loadMap(const std::string& identifier, bool loadHouses) -{ - IOMap loader; - if (!loader.loadMap(this, identifier)) { - std::cout << "[Fatal - Map::loadMap] " << loader.getLastErrorString() << std::endl; - return false; - } - - if (!IOMap::loadSpawns(this)) { - std::cout << "[Warning - Map::loadMap] Failed to load spawn data." << std::endl; - } - - if (loadHouses) { - if (!IOMap::loadHouses(this)) { - std::cout << "[Warning - Map::loadMap] Failed to load house data." << std::endl; - } - - IOMapSerialize::loadHouseInfo(); - IOMapSerialize::loadHouseItems(this); - } - return true; -} - -bool Map::save() -{ - bool saved = false; - for (uint32_t tries = 0; tries < 3; tries++) { - if (IOMapSerialize::saveHouseInfo()) { - saved = true; - break; - } - } - - if (!saved) { - return false; - } - - saved = false; - for (uint32_t tries = 0; tries < 3; tries++) { - if (IOMapSerialize::saveHouseItems()) { - saved = true; - break; - } - } - return saved; -} - -Tile* Map::getTile(uint16_t x, uint16_t y, uint8_t z) const -{ - if (z >= MAP_MAX_LAYERS) { - return nullptr; - } - - const QTreeLeafNode* leaf = QTreeNode::getLeafStatic(&root, x, y); - if (!leaf) { - return nullptr; - } - - const Floor* floor = leaf->getFloor(z); - if (!floor) { - return nullptr; - } - return floor->tiles[x & FLOOR_MASK][y & FLOOR_MASK]; -} - -void Map::setTile(uint16_t x, uint16_t y, uint8_t z, Tile* newTile) -{ - if (z >= MAP_MAX_LAYERS) { - std::cout << "ERROR: Attempt to set tile on invalid coordinate " << Position(x, y, z) << "!" << std::endl; - return; - } - - QTreeLeafNode::newLeaf = false; - QTreeLeafNode* leaf = root.createLeaf(x, y, 15); - - if (QTreeLeafNode::newLeaf) { - //update north - QTreeLeafNode* northLeaf = root.getLeaf(x, y - FLOOR_SIZE); - if (northLeaf) { - northLeaf->m_leafS = leaf; - } - - //update west leaf - QTreeLeafNode* westLeaf = root.getLeaf(x - FLOOR_SIZE, y); - if (westLeaf) { - westLeaf->m_leafE = leaf; - } - - //update south - QTreeLeafNode* southLeaf = root.getLeaf(x, y + FLOOR_SIZE); - if (southLeaf) { - leaf->m_leafS = southLeaf; - } - - //update east - QTreeLeafNode* eastLeaf = root.getLeaf(x + FLOOR_SIZE, y); - if (eastLeaf) { - leaf->m_leafE = eastLeaf; - } - } - - Floor* floor = leaf->createFloor(z); - uint32_t offsetX = x & FLOOR_MASK; - uint32_t offsetY = y & FLOOR_MASK; - - Tile*& tile = floor->tiles[offsetX][offsetY]; - if (tile) { - TileItemVector* items = newTile->getItemList(); - if (items) { - for (auto it = items->rbegin(), end = items->rend(); it != end; ++it) { - tile->addThing(*it); - } - items->clear(); - } - - Item* ground = newTile->getGround(); - if (ground) { - tile->addThing(ground); - newTile->setGround(nullptr); - } - delete newTile; - } else { - tile = newTile; - } -} - -bool Map::placeCreature(const Position& centerPos, Creature* creature, bool extendedPos/* = false*/, bool forceLogin/* = false*/) -{ - bool foundTile; - bool placeInPZ; - - Tile* tile = getTile(centerPos.x, centerPos.y, centerPos.z); - if (tile) { - placeInPZ = tile->hasFlag(TILESTATE_PROTECTIONZONE); - ReturnValue ret = tile->queryAdd(0, *creature, 1, FLAG_IGNOREBLOCKITEM); - foundTile = forceLogin || ret == RETURNVALUE_NOERROR || ret == RETURNVALUE_PLAYERISNOTINVITED; - } else { - placeInPZ = false; - foundTile = false; - } - - if (!foundTile) { - static std::vector> extendedRelList { - {0, -2}, - {-1, -1}, {0, -1}, {1, -1}, - {-2, 0}, {-1, 0}, {1, 0}, {2, 0}, - {-1, 1}, {0, 1}, {1, 1}, - {0, 2} - }; - - static std::vector> normalRelList { - {-1, -1}, {0, -1}, {1, -1}, - {-1, 0}, {1, 0}, - {-1, 1}, {0, 1}, {1, 1} - }; - - std::vector>& relList = (extendedPos ? extendedRelList : normalRelList); - - if (extendedPos) { - std::shuffle(relList.begin(), relList.begin() + 4, getRandomGenerator()); - std::shuffle(relList.begin() + 4, relList.end(), getRandomGenerator()); - } else { - std::shuffle(relList.begin(), relList.end(), getRandomGenerator()); - } - - for (const auto& it : relList) { - Position tryPos(centerPos.x + it.first, centerPos.y + it.second, centerPos.z); - - tile = getTile(tryPos.x, tryPos.y, tryPos.z); - if (!tile || (placeInPZ && !tile->hasFlag(TILESTATE_PROTECTIONZONE))) { - continue; - } - - if (tile->queryAdd(0, *creature, 1, 0) == RETURNVALUE_NOERROR) { - if (!extendedPos || isSightClear(centerPos, tryPos, false)) { - foundTile = true; - break; - } - } - } - - if (!foundTile) { - return false; - } - } - - int32_t index = 0; - uint32_t flags = 0; - Item* toItem = nullptr; - - Cylinder* toCylinder = tile->queryDestination(index, *creature, &toItem, flags); - toCylinder->internalAddThing(creature); - - const Position& dest = toCylinder->getPosition(); - getQTNode(dest.x, dest.y)->addCreature(creature); - return true; -} - -void Map::moveCreature(Creature& creature, Tile& newTile, bool forceTeleport/* = false*/) -{ - Tile& oldTile = *creature.getTile(); - - Position oldPos = oldTile.getPosition(); - Position newPos = newTile.getPosition(); - - bool teleport = forceTeleport || !newTile.getGround() || !Position::areInRange<1, 1, 0>(oldPos, newPos); - - SpectatorVec list; - getSpectators(list, oldPos, true); - getSpectators(list, newPos, true); - - std::vector oldStackPosVector; - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - if (tmpPlayer->canSeeCreature(&creature)) { - oldStackPosVector.push_back(oldTile.getClientIndexOfCreature(tmpPlayer, &creature)); - } else { - oldStackPosVector.push_back(-1); - } - } - } - - //remove the creature - oldTile.removeThing(&creature, 0); - - QTreeLeafNode* leaf = getQTNode(oldPos.x, oldPos.y); - QTreeLeafNode* new_leaf = getQTNode(newPos.x, newPos.y); - - // Switch the node ownership - if (leaf != new_leaf) { - leaf->removeCreature(&creature); - new_leaf->addCreature(&creature); - } - - //add the creature - newTile.addThing(&creature); - - if (!teleport) { - if (oldPos.y > newPos.y) { - creature.setDirection(DIRECTION_NORTH); - } else if (oldPos.y < newPos.y) { - creature.setDirection(DIRECTION_SOUTH); - } - - if (oldPos.x < newPos.x) { - creature.setDirection(DIRECTION_EAST); - } else if (oldPos.x > newPos.x) { - creature.setDirection(DIRECTION_WEST); - } - } - - //send to client - size_t i = 0; - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - //Use the correct stackpos - int32_t stackpos = oldStackPosVector[i++]; - if (stackpos != -1) { - tmpPlayer->sendCreatureMove(&creature, newPos, newTile.getStackposOfCreature(tmpPlayer, &creature), oldPos, stackpos, teleport); - } - } - } - - //event method - for (Creature* spectator : list) { - spectator->onCreatureMove(&creature, &newTile, newPos, &oldTile, oldPos, teleport); - } - - oldTile.postRemoveNotification(&creature, &newTile, 0); - newTile.postAddNotification(&creature, &oldTile, 0); -} - -void Map::getSpectatorsInternal(SpectatorVec& list, const Position& centerPos, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const -{ - int_fast16_t min_y = centerPos.y + minRangeY; - int_fast16_t min_x = centerPos.x + minRangeX; - int_fast16_t max_y = centerPos.y + maxRangeY; - int_fast16_t max_x = centerPos.x + maxRangeX; - - int32_t minoffset = centerPos.getZ() - maxRangeZ; - uint16_t x1 = std::min(0xFFFF, std::max(0, (min_x + minoffset))); - uint16_t y1 = std::min(0xFFFF, std::max(0, (min_y + minoffset))); - - int32_t maxoffset = centerPos.getZ() - minRangeZ; - uint16_t x2 = std::min(0xFFFF, std::max(0, (max_x + maxoffset))); - uint16_t y2 = std::min(0xFFFF, std::max(0, (max_y + maxoffset))); - - int32_t startx1 = x1 - (x1 % FLOOR_SIZE); - int32_t starty1 = y1 - (y1 % FLOOR_SIZE); - int32_t endx2 = x2 - (x2 % FLOOR_SIZE); - int32_t endy2 = y2 - (y2 % FLOOR_SIZE); - - const QTreeLeafNode* startLeaf = QTreeNode::getLeafStatic(&root, startx1, starty1); - const QTreeLeafNode* leafS = startLeaf; - const QTreeLeafNode* leafE; - - for (int_fast32_t ny = starty1; ny <= endy2; ny += FLOOR_SIZE) { - leafE = leafS; - for (int_fast32_t nx = startx1; nx <= endx2; nx += FLOOR_SIZE) { - if (leafE) { - const CreatureVector& node_list = (onlyPlayers ? leafE->player_list : leafE->creature_list); - CreatureVector::const_iterator node_iter = node_list.begin(); - CreatureVector::const_iterator node_end = node_list.end(); - if (node_iter != node_end) { - do { - Creature* creature = *node_iter; - - const Position& cpos = creature->getPosition(); - if (cpos.z < minRangeZ || cpos.z > maxRangeZ) { - continue; - } - - int_fast16_t offsetZ = Position::getOffsetZ(centerPos, cpos); - if (cpos.y < (min_y + offsetZ) || cpos.y > (max_y + offsetZ)) { - continue; - } - - if (cpos.x < (min_x + offsetZ) || cpos.x > (max_x + offsetZ)) { - continue; - } - - list.insert(creature); - } while (++node_iter != node_end); - } - leafE = leafE->m_leafE; - } else { - leafE = QTreeNode::getLeafStatic(&root, nx + FLOOR_SIZE, ny); - } - } - - if (leafS) { - leafS = leafS->m_leafS; - } else { - leafS = QTreeNode::getLeafStatic(&root, startx1, ny + FLOOR_SIZE); - } - } -} - -void Map::getSpectators(SpectatorVec& list, const Position& centerPos, bool multifloor /*= false*/, bool onlyPlayers /*= false*/, int32_t minRangeX /*= 0*/, int32_t maxRangeX /*= 0*/, int32_t minRangeY /*= 0*/, int32_t maxRangeY /*= 0*/) -{ - if (centerPos.z >= MAP_MAX_LAYERS) { - return; - } - - bool foundCache = false; - bool cacheResult = false; - - minRangeX = (minRangeX == 0 ? -maxViewportX : -minRangeX); - maxRangeX = (maxRangeX == 0 ? maxViewportX : maxRangeX); - minRangeY = (minRangeY == 0 ? -maxViewportY : -minRangeY); - maxRangeY = (maxRangeY == 0 ? maxViewportY : maxRangeY); - - if (minRangeX == -maxViewportX && maxRangeX == maxViewportX && minRangeY == -maxViewportY && maxRangeY == maxViewportY && multifloor) { - if (onlyPlayers) { - auto it = playersSpectatorCache.find(centerPos); - if (it != playersSpectatorCache.end()) { - if (!list.empty()) { - const SpectatorVec& cachedList = it->second; - list.insert(cachedList.begin(), cachedList.end()); - } else { - list = it->second; - } - - foundCache = true; - } - } - - if (!foundCache) { - auto it = spectatorCache.find(centerPos); - if (it != spectatorCache.end()) { - if (!onlyPlayers) { - if (!list.empty()) { - const SpectatorVec& cachedList = it->second; - list.insert(cachedList.begin(), cachedList.end()); - } else { - list = it->second; - } - } else { - const SpectatorVec& cachedList = it->second; - for (Creature* spectator : cachedList) { - if (spectator->getPlayer()) { - list.insert(spectator); - } - } - } - - foundCache = true; - } else { - cacheResult = true; - } - } - } - - if (!foundCache) { - int32_t minRangeZ; - int32_t maxRangeZ; - - if (multifloor) { - if (centerPos.z > 7) { - //underground - - //8->15 - minRangeZ = std::max(centerPos.getZ() - 2, 0); - maxRangeZ = std::min(centerPos.getZ() + 2, MAP_MAX_LAYERS - 1); - } else if (centerPos.z == 6) { - minRangeZ = 0; - maxRangeZ = 8; - } else if (centerPos.z == 7) { - minRangeZ = 0; - maxRangeZ = 9; - } else { - minRangeZ = 0; - maxRangeZ = 7; - } - } else { - minRangeZ = centerPos.z; - maxRangeZ = centerPos.z; - } - - getSpectatorsInternal(list, centerPos, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ, onlyPlayers); - - if (cacheResult) { - if (onlyPlayers) { - playersSpectatorCache[centerPos] = list; - } else { - spectatorCache[centerPos] = list; - } - } - } -} - -void Map::clearSpectatorCache() -{ - spectatorCache.clear(); - playersSpectatorCache.clear(); -} - -bool Map::canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight /*= true*/, - int32_t rangex /*= Map::maxClientViewportX*/, int32_t rangey /*= Map::maxClientViewportY*/) const -{ - //z checks - //underground 8->15 - //ground level and above 7->0 - if ((fromPos.z >= 8 && toPos.z < 8) || (toPos.z >= 8 && fromPos.z < 8)) { - return false; - } - - int32_t deltaz = Position::getDistanceZ(fromPos, toPos); - if (deltaz > 2) { - return false; - } - - if ((Position::getDistanceX(fromPos, toPos) - deltaz) > rangex) { - return false; - } - - //distance checks - if ((Position::getDistanceY(fromPos, toPos) - deltaz) > rangey) { - return false; - } - - if (!checkLineOfSight) { - return true; - } - return isSightClear(fromPos, toPos, false); -} - -bool Map::checkSightLine(const Position& fromPos, const Position& toPos) const -{ - if (fromPos == toPos) { - return true; - } - - Position start(fromPos.z > toPos.z ? toPos : fromPos); - Position destination(fromPos.z > toPos.z ? fromPos : toPos); - - const int8_t mx = start.x < destination.x ? 1 : start.x == destination.x ? 0 : -1; - const int8_t my = start.y < destination.y ? 1 : start.y == destination.y ? 0 : -1; - - int32_t A = Position::getOffsetY(destination, start); - int32_t B = Position::getOffsetX(start, destination); - int32_t C = -(A * destination.x + B * destination.y); - - while (start.x != destination.x || start.y != destination.y) { - int32_t move_hor = std::abs(A * (start.x + mx) + B * (start.y) + C); - int32_t move_ver = std::abs(A * (start.x) + B * (start.y + my) + C); - int32_t move_cross = std::abs(A * (start.x + mx) + B * (start.y + my) + C); - - if (start.y != destination.y && (start.x == destination.x || move_hor > move_ver || move_hor > move_cross)) { - start.y += my; - } - - if (start.x != destination.x && (start.y == destination.y || move_ver > move_hor || move_ver > move_cross)) { - start.x += mx; - } - - const Tile* tile = getTile(start.x, start.y, start.z); - if (tile && tile->hasProperty(CONST_PROP_BLOCKPROJECTILE)) { - return false; - } - } - - // now we need to perform a jump between floors to see if everything is clear (literally) - while (start.z != destination.z) { - const Tile* tile = getTile(start.x, start.y, start.z); - if (tile && tile->getThingCount() > 0) { - return false; - } - - start.z++; - } - - return true; -} - -bool Map::isSightClear(const Position& fromPos, const Position& toPos, bool floorCheck) const -{ - if (floorCheck && fromPos.z != toPos.z) { - return false; - } - - // Cast two converging rays and see if either yields a result. - return checkSightLine(fromPos, toPos) || checkSightLine(toPos, fromPos); -} - -const Tile* Map::canWalkTo(const Creature& creature, const Position& pos) const -{ - int32_t walkCache = creature.getWalkCache(pos); - if (walkCache == 0) { - return nullptr; - } else if (walkCache == 1) { - return getTile(pos.x, pos.y, pos.z); - } - - //used for non-cached tiles - Tile* tile = getTile(pos.x, pos.y, pos.z); - if (creature.getTile() != tile) { - if (!tile || tile->queryAdd(0, creature, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) != RETURNVALUE_NOERROR) { - return nullptr; - } - } - return tile; -} - -bool Map::getPathMatching(const Creature& creature, std::forward_list& dirList, const FrozenPathingConditionCall& pathCondition, const FindPathParams& fpp) const -{ - Position pos = creature.getPosition(); - Position endPos; - - AStarNodes nodes(pos.x, pos.y); - - int32_t bestMatch = 0; - - static int_fast32_t dirNeighbors[8][5][2] = { - {{-1, 0}, {0, 1}, {1, 0}, {1, 1}, {-1, 1}}, - {{-1, 0}, {0, 1}, {0, -1}, {-1, -1}, {-1, 1}}, - {{-1, 0}, {1, 0}, {0, -1}, {-1, -1}, {1, -1}}, - {{0, 1}, {1, 0}, {0, -1}, {1, -1}, {1, 1}}, - {{1, 0}, {0, -1}, {-1, -1}, {1, -1}, {1, 1}}, - {{-1, 0}, {0, -1}, {-1, -1}, {1, -1}, {-1, 1}}, - {{0, 1}, {1, 0}, {1, -1}, {1, 1}, {-1, 1}}, - {{-1, 0}, {0, 1}, {-1, -1}, {1, 1}, {-1, 1}} - }; - static int_fast32_t allNeighbors[8][2] = { - {-1, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, -1}, {1, -1}, {1, 1}, {-1, 1} - }; - - const Position startPos = pos; - - AStarNode* found = nullptr; - while (fpp.maxSearchDist != 0 || nodes.getClosedNodes() < 100) { - AStarNode* n = nodes.getBestNode(); - if (!n) { - if (found) { - break; - } - return false; - } - - const int_fast32_t x = n->x; - const int_fast32_t y = n->y; - pos.x = x; - pos.y = y; - if (pathCondition(startPos, pos, fpp, bestMatch)) { - found = n; - endPos = pos; - if (bestMatch == 0) { - break; - } - } - - uint_fast32_t dirCount; - int_fast32_t* neighbors; - if (n->parent) { - const int_fast32_t offset_x = n->parent->x - x; - const int_fast32_t offset_y = n->parent->y - y; - if (offset_y == 0) { - if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_WEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_EAST]; - } - } else if (!fpp.allowDiagonal || offset_x == 0) { - if (offset_y == -1) { - neighbors = *dirNeighbors[DIRECTION_NORTH]; - } else { - neighbors = *dirNeighbors[DIRECTION_SOUTH]; - } - } else if (offset_y == -1) { - if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_NORTHWEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_NORTHEAST]; - } - } else if (offset_x == -1) { - neighbors = *dirNeighbors[DIRECTION_SOUTHWEST]; - } else { - neighbors = *dirNeighbors[DIRECTION_SOUTHEAST]; - } - dirCount = fpp.allowDiagonal ? 5 : 3; - } else { - dirCount = 8; - neighbors = *allNeighbors; - } - - const int_fast32_t f = n->f; - for (uint_fast32_t i = 0; i < dirCount; ++i) { - pos.x = x + *neighbors++; - pos.y = y + *neighbors++; - - if (fpp.maxSearchDist != 0 && (Position::getDistanceX(startPos, pos) > fpp.maxSearchDist || Position::getDistanceY(startPos, pos) > fpp.maxSearchDist)) { - continue; - } - - if (fpp.keepDistance && !pathCondition.isInRange(startPos, pos, fpp)) { - continue; - } - - const Tile* tile; - AStarNode* neighborNode = nodes.getNodeByPosition(pos.x, pos.y); - if (neighborNode) { - tile = getTile(pos.x, pos.y, pos.z); - } else { - tile = canWalkTo(creature, pos); - if (!tile) { - continue; - } - } - - //The cost (g) for this neighbor - const int_fast32_t cost = AStarNodes::getMapWalkCost(n, pos); - const int_fast32_t extraCost = AStarNodes::getTileWalkCost(creature, tile); - const int_fast32_t newf = f + cost + extraCost; - - if (neighborNode) { - if (neighborNode->f <= newf) { - //The node on the closed/open list is cheaper than this one - continue; - } - - neighborNode->f = newf; - neighborNode->parent = n; - nodes.openNode(neighborNode); - } else { - //Does not exist in the open/closed list, create a new node - neighborNode = nodes.createOpenNode(n, pos.x, pos.y, newf); - if (!neighborNode) { - if (found) { - break; - } - return false; - } - } - } - - nodes.closeNode(n); - } - - if (!found) { - return false; - } - - int_fast32_t prevx = endPos.x; - int_fast32_t prevy = endPos.y; - - found = found->parent; - while (found) { - pos.x = found->x; - pos.y = found->y; - - int_fast32_t dx = pos.getX() - prevx; - int_fast32_t dy = pos.getY() - prevy; - - prevx = pos.x; - prevy = pos.y; - - if (dx == 1 && dy == 1) { - dirList.push_front(DIRECTION_NORTHWEST); - } else if (dx == -1 && dy == 1) { - dirList.push_front(DIRECTION_NORTHEAST); - } else if (dx == 1 && dy == -1) { - dirList.push_front(DIRECTION_SOUTHWEST); - } else if (dx == -1 && dy == -1) { - dirList.push_front(DIRECTION_SOUTHEAST); - } else if (dx == 1) { - dirList.push_front(DIRECTION_WEST); - } else if (dx == -1) { - dirList.push_front(DIRECTION_EAST); - } else if (dy == 1) { - dirList.push_front(DIRECTION_NORTH); - } else if (dy == -1) { - dirList.push_front(DIRECTION_SOUTH); - } - - found = found->parent; - } - return true; -} - -// AStarNodes - -AStarNodes::AStarNodes(uint32_t x, uint32_t y) - : nodes(), openNodes() -{ - curNode = 1; - closedNodes = 0; - openNodes[0] = true; - - AStarNode& startNode = nodes[0]; - startNode.parent = nullptr; - startNode.x = x; - startNode.y = y; - startNode.f = 0; - nodeTable[(x << 16) | y] = nodes; -} - -AStarNode* AStarNodes::createOpenNode(AStarNode* parent, uint32_t x, uint32_t y, int_fast32_t f) -{ - if (curNode >= MAX_NODES) { - return nullptr; - } - - size_t retNode = curNode++; - openNodes[retNode] = true; - - AStarNode* node = nodes + retNode; - nodeTable[(x << 16) | y] = node; - node->parent = parent; - node->x = x; - node->y = y; - node->f = f; - return node; -} - -AStarNode* AStarNodes::getBestNode() -{ - if (curNode == 0) { - return nullptr; - } - - int32_t best_node_f = std::numeric_limits::max(); - int32_t best_node = -1; - for (size_t i = 0; i < curNode; i++) { - if (openNodes[i] && nodes[i].f < best_node_f) { - best_node_f = nodes[i].f; - best_node = i; - } - } - - if (best_node >= 0) { - return nodes + best_node; - } - return nullptr; -} - -void AStarNodes::closeNode(AStarNode* node) -{ - size_t index = node - nodes; - assert(index < MAX_NODES); - openNodes[index] = false; - ++closedNodes; -} - -void AStarNodes::openNode(AStarNode* node) -{ - size_t index = node - nodes; - assert(index < MAX_NODES); - if (!openNodes[index]) { - openNodes[index] = true; - --closedNodes; - } -} - -int_fast32_t AStarNodes::getClosedNodes() const -{ - return closedNodes; -} - -AStarNode* AStarNodes::getNodeByPosition(uint32_t x, uint32_t y) -{ - auto it = nodeTable.find((x << 16) | y); - if (it == nodeTable.end()) { - return nullptr; - } - return it->second; -} - -int_fast32_t AStarNodes::getMapWalkCost(AStarNode* node, const Position& neighborPos) -{ - if (std::abs(node->x - neighborPos.x) == std::abs(node->y - neighborPos.y)) { - //diagonal movement extra cost - return MAP_DIAGONALWALKCOST; - } - return MAP_NORMALWALKCOST; -} - -int_fast32_t AStarNodes::getTileWalkCost(const Creature& creature, const Tile* tile) -{ - int_fast32_t cost = 0; - if (tile->getTopVisibleCreature(&creature) != nullptr) { - //destroy creature cost - cost += MAP_NORMALWALKCOST * 3; - } - - if (const MagicField* field = tile->getFieldItem()) { - CombatType_t combatType = field->getCombatType(); - if (!creature.isImmune(combatType) && !creature.hasCondition(Combat::DamageToConditionType(combatType))) { - cost += MAP_NORMALWALKCOST * 18; - } - } - return cost; -} - -// Floor -Floor::~Floor() -{ - for (uint32_t i = 0; i < FLOOR_SIZE; ++i) { - for (uint32_t j = 0; j < FLOOR_SIZE; ++j) { - delete tiles[i][j]; - } - } -} - -// QTreeNode -QTreeNode::QTreeNode() -{ - m_isLeaf = false; - m_child[0] = nullptr; - m_child[1] = nullptr; - m_child[2] = nullptr; - m_child[3] = nullptr; -} - -QTreeNode::~QTreeNode() -{ - delete m_child[0]; - delete m_child[1]; - delete m_child[2]; - delete m_child[3]; -} - -QTreeLeafNode* QTreeNode::getLeaf(uint32_t x, uint32_t y) -{ - if (m_isLeaf) { - return static_cast(this); - } - - QTreeNode* node = m_child[((x & 0x8000) >> 15) | ((y & 0x8000) >> 14)]; - if (!node) { - return nullptr; - } - return node->getLeaf(x << 1, y << 1); -} - -QTreeLeafNode* QTreeNode::createLeaf(uint32_t x, uint32_t y, uint32_t level) -{ - if (!isLeaf()) { - uint32_t index = ((x & 0x8000) >> 15) | ((y & 0x8000) >> 14); - if (!m_child[index]) { - if (level != FLOOR_BITS) { - m_child[index] = new QTreeNode(); - } else { - m_child[index] = new QTreeLeafNode(); - QTreeLeafNode::newLeaf = true; - } - } - return m_child[index]->createLeaf(x * 2, y * 2, level - 1); - } - return static_cast(this); -} - -// QTreeLeafNode -bool QTreeLeafNode::newLeaf = false; -QTreeLeafNode::QTreeLeafNode() -{ - for (uint32_t i = 0; i < MAP_MAX_LAYERS; ++i) { - m_array[i] = nullptr; - } - - m_isLeaf = true; - m_leafS = nullptr; - m_leafE = nullptr; -} - -QTreeLeafNode::~QTreeLeafNode() -{ - for (uint32_t i = 0; i < MAP_MAX_LAYERS; ++i) { - delete m_array[i]; - } -} - -Floor* QTreeLeafNode::createFloor(uint32_t z) -{ - if (!m_array[z]) { - m_array[z] = new Floor(); - } - return m_array[z]; -} - -void QTreeLeafNode::addCreature(Creature* c) -{ - creature_list.push_back(c); - - if (c->getPlayer()) { - player_list.push_back(c); - } -} - -void QTreeLeafNode::removeCreature(Creature* c) -{ - CreatureVector::iterator iter = std::find(creature_list.begin(), creature_list.end(), c); - assert(iter != creature_list.end()); - *iter = creature_list.back(); - creature_list.pop_back(); - - if (c->getPlayer()) { - iter = std::find(player_list.begin(), player_list.end(), c); - assert(iter != player_list.end()); - *iter = player_list.back(); - player_list.pop_back(); - } -} - -uint32_t Map::clean() const -{ - uint64_t start = OTSYS_TIME(); - size_t count = 0, tiles = 0; - - if (g_game.getGameState() == GAME_STATE_NORMAL) { - g_game.setGameState(GAME_STATE_MAINTAIN); - } - - std::vector nodes { - &root - }; - std::vector toRemove; - do { - const QTreeNode* node = nodes.back(); - nodes.pop_back(); - if (node->isLeaf()) { - const QTreeLeafNode* leafNode = static_cast(node); - for (uint8_t z = 0; z < MAP_MAX_LAYERS; ++z) { - Floor* floor = leafNode->getFloor(z); - if (!floor) { - continue; - } - - for (size_t x = 0; x < FLOOR_SIZE; ++x) { - for (size_t y = 0; y < FLOOR_SIZE; ++y) { - Tile* tile = floor->tiles[x][y]; - if (!tile || tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - continue; - } - - TileItemVector* itemList = tile->getItemList(); - if (!itemList) { - continue; - } - - ++tiles; - for (Item* item : *itemList) { - if (item->isCleanable()) { - toRemove.push_back(item); - } - } - - for (Item* item : toRemove) { - g_game.internalRemoveItem(item, -1); - } - count += toRemove.size(); - toRemove.clear(); - } - } - } - } else { - for (size_t i = 0; i < 4; ++i) { - QTreeNode* childNode = node->m_child[i]; - if (childNode) { - nodes.push_back(childNode); - } - } - } - } while (!nodes.empty()); - - if (g_game.getGameState() == GAME_STATE_MAINTAIN) { - g_game.setGameState(GAME_STATE_NORMAL); - } - - std::cout << "> CLEAN: Removed " << count << " item" << (count != 1 ? "s" : "") - << " from " << tiles << " tile" << (tiles != 1 ? "s" : "") << " in " - << (OTSYS_TIME() - start) / (1000.) << " seconds." << std::endl; - return count; -} diff --git a/path_10_8/src/map.h b/path_10_8/src/map.h deleted file mode 100644 index 34593a45e..000000000 --- a/path_10_8/src/map.h +++ /dev/null @@ -1,294 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MAP_H_E3953D57C058461F856F5221D359DAFA -#define FS_MAP_H_E3953D57C058461F856F5221D359DAFA - -#include "position.h" -#include "item.h" -#include "fileloader.h" - -#include "tools.h" -#include "tile.h" -#include "town.h" -#include "house.h" -#include "spawn.h" - -class Creature; -class Player; -class Game; -class Tile; -class Map; - -#define MAP_MAX_LAYERS 16 - -struct FindPathParams; -struct AStarNode { - AStarNode* parent; - int_fast32_t f; - uint16_t x, y; -}; - -#define MAX_NODES 512 - -#define MAP_NORMALWALKCOST 10 -#define MAP_DIAGONALWALKCOST 25 - -class AStarNodes -{ - public: - AStarNodes(uint32_t x, uint32_t y); - - AStarNode* createOpenNode(AStarNode* parent, uint32_t x, uint32_t y, int_fast32_t f); - AStarNode* getBestNode(); - void closeNode(AStarNode* node); - void openNode(AStarNode* node); - int_fast32_t getClosedNodes() const; - AStarNode* getNodeByPosition(uint32_t x, uint32_t y); - - static int_fast32_t getMapWalkCost(AStarNode* node, const Position& neighborPos); - static int_fast32_t getTileWalkCost(const Creature& creature, const Tile* tile); - - private: - AStarNode nodes[MAX_NODES]; - bool openNodes[MAX_NODES]; - std::unordered_map nodeTable; - size_t curNode; - int_fast32_t closedNodes; -}; - -typedef std::map SpectatorCache; - -#define FLOOR_BITS 3 -#define FLOOR_SIZE (1 << FLOOR_BITS) -#define FLOOR_MASK (FLOOR_SIZE - 1) - -struct Floor { - Floor() : tiles() {} - ~Floor(); - - // non-copyable - Floor(const Floor&) = delete; - Floor& operator=(const Floor&) = delete; - - Tile* tiles[FLOOR_SIZE][FLOOR_SIZE]; -}; - -class FrozenPathingConditionCall; -class QTreeLeafNode; - -class QTreeNode -{ - public: - QTreeNode(); - virtual ~QTreeNode(); - - // non-copyable - QTreeNode(const QTreeNode&) = delete; - QTreeNode& operator=(const QTreeNode&) = delete; - - bool isLeaf() const { - return m_isLeaf; - } - - QTreeLeafNode* getLeaf(uint32_t x, uint32_t y); - - template - inline static Leaf getLeafStatic(Node node, uint32_t x, uint32_t y) - { - do { - node = node->m_child[((x & 0x8000) >> 15) | ((y & 0x8000) >> 14)]; - if (!node) { - return nullptr; - } - - x <<= 1; - y <<= 1; - } while (!node->m_isLeaf); - return static_cast(node); - } - - QTreeLeafNode* createLeaf(uint32_t x, uint32_t y, uint32_t level); - - protected: - QTreeNode* m_child[4]; - - bool m_isLeaf; - - friend class Map; -}; - -class QTreeLeafNode final : public QTreeNode -{ - public: - QTreeLeafNode(); - ~QTreeLeafNode(); - - // non-copyable - QTreeLeafNode(const QTreeLeafNode&) = delete; - QTreeLeafNode& operator=(const QTreeLeafNode&) = delete; - - Floor* createFloor(uint32_t z); - Floor* getFloor(uint8_t z) const { - return m_array[z]; - } - - void addCreature(Creature* c); - void removeCreature(Creature* c); - - protected: - static bool newLeaf; - QTreeLeafNode* m_leafS; - QTreeLeafNode* m_leafE; - Floor* m_array[MAP_MAX_LAYERS]; - CreatureVector creature_list; - CreatureVector player_list; - - friend class Map; - friend class QTreeNode; -}; - -/** - * Map class. - * Holds all the actual map-data - */ - -class Map -{ - public: - Map() : width(0), height(0) {} - - static const int32_t maxViewportX = 11; //min value: maxClientViewportX + 1 - static const int32_t maxViewportY = 11; //min value: maxClientViewportY + 1 - static const int32_t maxClientViewportX = 8; - static const int32_t maxClientViewportY = 6; - - uint32_t clean() const; - - /** - * Load a map. - * \returns true if the map was loaded successfully - */ - bool loadMap(const std::string& identifier, bool loadHouses); - - /** - * Save a map. - * \returns true if the map was saved successfully - */ - static bool save(); - - /** - * Get a single tile. - * \returns A pointer to that tile. - */ - Tile* getTile(uint16_t x, uint16_t y, uint8_t z) const; - inline Tile* getTile(const Position& pos) const { - return getTile(pos.x, pos.y, pos.z); - } - - /** - * Set a single tile. - */ - void setTile(uint16_t x, uint16_t y, uint8_t z, Tile* newTile); - void setTile(const Position& pos, Tile* newTile) { - setTile(pos.x, pos.y, pos.z, newTile); - } - - /** - * Place a creature on the map - * \param centerPos The position to place the creature - * \param creature Creature to place on the map - * \param extendedPos If true, the creature will in first-hand be placed 2 tiles away - * \param forceLogin If true, placing the creature will not fail becase of obstacles (creatures/chests) - */ - bool placeCreature(const Position& centerPos, Creature* creature, bool extendedPos = false, bool forceLogin = false); - - void moveCreature(Creature& creature, Tile& newTile, bool forceTeleport = false); - - /** - * Remove a creature from the map. - * \param c Creature pointer to the creature to remove - */ - bool removeCreature(Creature* c); - - void getSpectators(SpectatorVec& list, const Position& centerPos, bool multifloor = false, bool onlyPlayers = false, - int32_t minRangeX = 0, int32_t maxRangeX = 0, - int32_t minRangeY = 0, int32_t maxRangeY = 0); - - void clearSpectatorCache(); - - /** - * Checks if you can throw an object to that position - * \param fromPos from Source point - * \param toPos Destination point - * \param rangex maximum allowed range horizontially - * \param rangey maximum allowed range vertically - * \param checkLineOfSight checks if there is any blocking objects in the way - * \returns The result if you can throw there or not - */ - bool canThrowObjectTo(const Position& fromPos, const Position& toPos, bool checkLineOfSight = true, - int32_t rangex = Map::maxClientViewportX, int32_t rangey = Map::maxClientViewportY) const; - - /** - * Checks if path is clear from fromPos to toPos - * Notice: This only checks a straight line if the path is clear, for path finding use getPathTo. - * \param fromPos from Source point - * \param toPos Destination point - * \param floorCheck if true then view is not clear if fromPos.z is not the same as toPos.z - * \returns The result if there is no obstacles - */ - bool isSightClear(const Position& fromPos, const Position& toPos, bool floorCheck) const; - bool checkSightLine(const Position& fromPos, const Position& toPos) const; - - const Tile* canWalkTo(const Creature& creature, const Position& pos) const; - - bool getPathMatching(const Creature& creature, std::forward_list& dirList, - const FrozenPathingConditionCall& pathCondition, const FindPathParams& fpp) const; - - std::map waypoints; - - QTreeLeafNode* getQTNode(uint16_t x, uint16_t y) { - return QTreeNode::getLeafStatic(&root, x, y); - } - - Spawns spawns; - Towns towns; - Houses houses; - protected: - SpectatorCache spectatorCache; - SpectatorCache playersSpectatorCache; - - QTreeNode root; - - std::string spawnfile; - std::string housefile; - - uint32_t width, height; - - // Actually scans the map for spectators - void getSpectatorsInternal(SpectatorVec& list, const Position& centerPos, - int32_t minRangeX, int32_t maxRangeX, - int32_t minRangeY, int32_t maxRangeY, - int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const; - - friend class Game; - friend class IOMap; -}; - -#endif diff --git a/path_10_8/src/monster.cpp b/path_10_8/src/monster.cpp deleted file mode 100644 index ae603cb34..000000000 --- a/path_10_8/src/monster.cpp +++ /dev/null @@ -1,2031 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "monster.h" -#include "game.h" -#include "spells.h" - -extern Game g_game; -extern Monsters g_monsters; - -int32_t Monster::despawnRange; -int32_t Monster::despawnRadius; - -uint32_t Monster::monsterAutoID = 0x40000000; - -Monster* Monster::createMonster(const std::string& name) -{ - MonsterType* mType = g_monsters.getMonsterType(name); - if (!mType) { - return nullptr; - } - return new Monster(mType); -} - -Monster::Monster(MonsterType* _mtype) : - Creature() -{ - isIdle = true; - isMasterInRange = false; - mType = _mtype; - spawn = nullptr; - defaultOutfit = mType->outfit; - currentOutfit = mType->outfit; - - skull = mType->skull; - - health = mType->health; - healthMax = mType->healthMax; - baseSpeed = mType->baseSpeed; - internalLight.level = mType->lightLevel; - internalLight.color = mType->lightColor; - - hiddenHealth = mType->hiddenHealth; - - minCombatValue = 0; - maxCombatValue = 0; - - targetTicks = 0; - targetChangeTicks = 0; - targetChangeCooldown = 0; - attackTicks = 0; - defenseTicks = 0; - yellTicks = 0; - extraMeleeAttack = false; - - strDescription = mType->nameDescription; - toLowerCaseString(strDescription); - - stepDuration = 0; - - lastMeleeAttack = 0; - - // register creature events - for (const std::string& scriptName : mType->scripts) { - if (!registerCreatureEvent(scriptName)) { - std::cout << "[Warning - Monster::Monster] Unknown event name: " << scriptName << std::endl; - } - } -} - -Monster::~Monster() -{ - clearTargetList(); - clearFriendList(); -} - -void Monster::addList() -{ - g_game.addMonster(this); -} - -void Monster::removeList() -{ - g_game.removeMonster(this); -} - -bool Monster::canSee(const Position& pos) const -{ - return Creature::canSee(getPosition(), pos, 9, 9); -} - -void Monster::onAttackedCreatureDisappear(bool) -{ - attackTicks = 0; - extraMeleeAttack = true; -} - -void Monster::onCreatureAppear(Creature* creature, bool isLogin) -{ - Creature::onCreatureAppear(creature, isLogin); - - if (mType->creatureAppearEvent != -1) { - // onCreatureAppear(self, creature) - LuaScriptInterface* scriptInterface = mType->scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Monster::onCreatureAppear] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(mType->creatureAppearEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(mType->creatureAppearEvent); - - LuaScriptInterface::pushUserdata(L, this); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - if (scriptInterface->callFunction(2)) { - return; - } - } - - if (creature == this) { - //We just spawned lets look around to see who is there. - if (isSummon()) { - isMasterInRange = canSee(getMaster()->getPosition()); - } - - updateTargetList(); - updateIdleStatus(); - } else { - onCreatureEnter(creature); - } -} - -void Monster::onRemoveCreature(Creature* creature, bool isLogout) -{ - Creature::onRemoveCreature(creature, isLogout); - - if (mType->creatureDisappearEvent != -1) { - // onCreatureDisappear(self, creature) - LuaScriptInterface* scriptInterface = mType->scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Monster::onCreatureDisappear] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(mType->creatureDisappearEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(mType->creatureDisappearEvent); - - LuaScriptInterface::pushUserdata(L, this); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - if (scriptInterface->callFunction(2)) { - return; - } - } - - if (creature == this) { - if (spawn) { - spawn->startSpawnCheck(); - } - - setIdle(true); - } else { - onCreatureLeave(creature); - } -} - -void Monster::onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) -{ - Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - - if (mType->creatureMoveEvent != -1) { - // onCreatureMove(self, creature, oldPosition, newPosition) - LuaScriptInterface* scriptInterface = mType->scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Monster::onCreatureMove] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(mType->creatureMoveEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(mType->creatureMoveEvent); - - LuaScriptInterface::pushUserdata(L, this); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushPosition(L, oldPos); - LuaScriptInterface::pushPosition(L, newPos); - - if (scriptInterface->callFunction(4)) { - return; - } - } - - if (creature == this) { - if (isSummon()) { - isMasterInRange = canSee(getMaster()->getPosition()); - } - - updateTargetList(); - updateIdleStatus(); - } else { - bool canSeeNewPos = canSee(newPos); - bool canSeeOldPos = canSee(oldPos); - - if (canSeeNewPos && !canSeeOldPos) { - onCreatureEnter(creature); - } else if (!canSeeNewPos && canSeeOldPos) { - onCreatureLeave(creature); - } - - if (canSeeNewPos && isSummon() && getMaster() == creature) { - isMasterInRange = true; //Turn the summon on again - } - - updateIdleStatus(); - - if (!isSummon()) { - if (followCreature) { - const Position& followPosition = followCreature->getPosition(); - const Position& position = getPosition(); - - int32_t offset_x = Position::getDistanceX(followPosition, position); - int32_t offset_y = Position::getDistanceY(followPosition, position); - if ((offset_x > 1 || offset_y > 1) && mType->changeTargetChance > 0) { - Direction dir = getDirectionTo(position, followPosition); - const Position& checkPosition = getNextPosition(dir, position); - - Tile* tile = g_game.map.getTile(checkPosition); - if (tile) { - Creature* topCreature = tile->getTopCreature(); - if (topCreature && followCreature != topCreature && isOpponent(topCreature)) { - selectTarget(topCreature); - } - } - } - } else if (isOpponent(creature)) { - //we have no target lets try pick this one - selectTarget(creature); - } - } - } -} - -void Monster::onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) -{ - Creature::onCreatureSay(creature, type, text); - - if (mType->creatureSayEvent != -1) { - // onCreatureSay(self, creature, type, message) - LuaScriptInterface* scriptInterface = mType->scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Monster::onCreatureSay] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(mType->creatureSayEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(mType->creatureSayEvent); - - LuaScriptInterface::pushUserdata(L, this); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - lua_pushnumber(L, type); - LuaScriptInterface::pushString(L, text); - - scriptInterface->callVoidFunction(4); - } -} - -void Monster::addFriend(Creature* creature) -{ - assert(creature != this); - auto result = friendList.insert(creature); - if (result.second) { - creature->incrementReferenceCounter(); - } -} - -void Monster::removeFriend(Creature* creature) -{ - auto it = friendList.find(creature); - if (it != friendList.end()) { - creature->decrementReferenceCounter(); - friendList.erase(it); - } -} - -void Monster::addTarget(Creature* creature, bool pushFront/* = false*/) -{ - assert(creature != this); - if (std::find(targetList.begin(), targetList.end(), creature) == targetList.end()) { - creature->incrementReferenceCounter(); - if (pushFront) { - targetList.push_front(creature); - } else { - targetList.push_back(creature); - } - } -} - -void Monster::removeTarget(Creature* creature) -{ - auto it = std::find(targetList.begin(), targetList.end(), creature); - if (it != targetList.end()) { - creature->decrementReferenceCounter(); - targetList.erase(it); - } -} - -void Monster::updateTargetList() -{ - auto friendIterator = friendList.begin(); - while (friendIterator != friendList.end()) { - Creature* creature = *friendIterator; - if (creature->getHealth() <= 0 || !canSee(creature->getPosition())) { - creature->decrementReferenceCounter(); - friendIterator = friendList.erase(friendIterator); - } else { - ++friendIterator; - } - } - - auto targetIterator = targetList.begin(); - while (targetIterator != targetList.end()) { - Creature* creature = *targetIterator; - if (creature->getHealth() <= 0 || !canSee(creature->getPosition())) { - creature->decrementReferenceCounter(); - targetIterator = targetList.erase(targetIterator); - } else { - ++targetIterator; - } - } - - SpectatorVec list; - g_game.map.getSpectators(list, _position, true); - list.erase(this); - for (Creature* spectator : list) { - if (canSee(spectator->getPosition())) { - onCreatureFound(spectator); - } - } -} - -void Monster::clearTargetList() -{ - for (Creature* creature : targetList) { - creature->decrementReferenceCounter(); - } - targetList.clear(); -} - -void Monster::clearFriendList() -{ - for (Creature* creature : friendList) { - creature->decrementReferenceCounter(); - } - friendList.clear(); -} - -void Monster::onCreatureFound(Creature* creature, bool pushFront/* = false*/) -{ - if (isFriend(creature)) { - addFriend(creature); - } - - if (isOpponent(creature)) { - addTarget(creature, pushFront); - } - - updateIdleStatus(); -} - -void Monster::onCreatureEnter(Creature* creature) -{ - // std::cout << "onCreatureEnter - " << creature->getName() << std::endl; - - if (getMaster() == creature) { - //Turn the summon on again - isMasterInRange = true; - updateIdleStatus(); - } - - onCreatureFound(creature, true); -} - -bool Monster::isFriend(const Creature* creature) const -{ - if (isSummon() && getMaster()->getPlayer()) { - const Player* masterPlayer = getMaster()->getPlayer(); - const Player* tmpPlayer = nullptr; - - if (creature->getPlayer()) { - tmpPlayer = creature->getPlayer(); - } else { - const Creature* creatureMaster = creature->getMaster(); - - if (creatureMaster && creatureMaster->getPlayer()) { - tmpPlayer = creatureMaster->getPlayer(); - } - } - - if (tmpPlayer && (tmpPlayer == getMaster() || masterPlayer->isPartner(tmpPlayer))) { - return true; - } - } else if (creature->getMonster() && !creature->isSummon()) { - return true; - } - - return false; -} - -bool Monster::isOpponent(const Creature* creature) const -{ - if (isSummon() && getMaster()->getPlayer()) { - if (creature != getMaster()) { - return true; - } - } else { - if ((creature->getPlayer() && !creature->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) || - (creature->getMaster() && creature->getMaster()->getPlayer())) { - return true; - } - } - - return false; -} - -void Monster::onCreatureLeave(Creature* creature) -{ - // std::cout << "onCreatureLeave - " << creature->getName() << std::endl; - - if (getMaster() == creature) { - //Turn the monster off until its master comes back - isMasterInRange = false; - updateIdleStatus(); - } - - //update friendList - if (isFriend(creature)) { - removeFriend(creature); - } - - //update targetList - if (isOpponent(creature)) { - removeTarget(creature); - if (targetList.empty()) { - updateIdleStatus(); - } - } -} - -bool Monster::searchTarget(TargetSearchType_t searchType /*= TARGETSEARCH_DEFAULT*/) -{ - std::list resultList; - const Position& myPos = getPosition(); - - for (Creature* creature : targetList) { - if (followCreature != creature && isTarget(creature)) { - if (searchType == TARGETSEARCH_RANDOM || canUseAttack(myPos, creature)) { - resultList.push_back(creature); - } - } - } - - switch (searchType) { - case TARGETSEARCH_NEAREST: { - Creature* target = nullptr; - if (!resultList.empty()) { - auto it = resultList.begin(); - target = *it; - - if (++it != resultList.end()) { - const Position& targetPosition = target->getPosition(); - int32_t minRange = Position::getDistanceX(myPos, targetPosition) + Position::getDistanceY(myPos, targetPosition); - do { - const Position& pos = (*it)->getPosition(); - - int32_t distance = Position::getDistanceX(myPos, pos) + Position::getDistanceY(myPos, pos); - if (distance < minRange) { - target = *it; - minRange = distance; - } - } while (++it != resultList.end()); - } - } else { - int32_t minRange = std::numeric_limits::max(); - for (Creature* creature : targetList) { - if (!isTarget(creature)) { - continue; - } - - const Position& pos = creature->getPosition(); - int32_t distance = Position::getDistanceX(myPos, pos) + Position::getDistanceY(myPos, pos); - if (distance < minRange) { - target = creature; - minRange = distance; - } - } - } - - if (target && selectTarget(target)) { - return true; - } - break; - } - - case TARGETSEARCH_DEFAULT: - case TARGETSEARCH_ATTACKRANGE: - case TARGETSEARCH_RANDOM: - default: { - if (!resultList.empty()) { - auto it = resultList.begin(); - std::advance(it, uniform_random(0, resultList.size() - 1)); - return selectTarget(*it); - } - - if (searchType == TARGETSEARCH_ATTACKRANGE) { - return false; - } - - break; - } - } - - //lets just pick the first target in the list - for (Creature* target : targetList) { - if (followCreature != target && selectTarget(target)) { - return true; - } - } - return false; -} - -void Monster::onFollowCreatureComplete(const Creature* creature) -{ - if (creature) { - auto it = std::find(targetList.begin(), targetList.end(), creature); - if (it != targetList.end()) { - Creature* target = (*it); - targetList.erase(it); - - if (hasFollowPath) { - targetList.push_front(target); - } else if (!isSummon()) { - targetList.push_back(target); - } else { - target->decrementReferenceCounter(); - } - } - } -} - -BlockType_t Monster::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense /* = false*/, bool checkArmor /* = false*/, bool /* field = false */) -{ - BlockType_t blockType = Creature::blockHit(attacker, combatType, damage, checkDefense, checkArmor); - - if (damage != 0) { - int32_t elementMod = 0; - auto it = mType->elementMap.find(combatType); - if (it != mType->elementMap.end()) { - elementMod = it->second; - } - - if (elementMod != 0) { - damage = static_cast(std::ceil(damage * ((100 - elementMod) / 100.))); - if (damage <= 0) { - damage = 0; - blockType = BLOCK_ARMOR; - } - } - } - - return blockType; -} - - -bool Monster::isTarget(const Creature* creature) const -{ - if (creature->isRemoved() || !creature->isAttackable() || - creature->getZone() == ZONE_PROTECTION || !canSeeCreature(creature)) { - return false; - } - - if (creature->getPosition().z != getPosition().z) { - return false; - } - return true; -} - -bool Monster::selectTarget(Creature* creature) -{ - if (!isTarget(creature)) { - return false; - } - - if (isPassive() && !hasBeenAttacked(creature->getID())) { - return false; - } - - auto it = std::find(targetList.begin(), targetList.end(), creature); - if (it == targetList.end()) { - //Target not found in our target list. - return false; - } - - if (isHostile() || isSummon()) { - if (setAttackedCreature(creature) && !isSummon()) { - g_dispatcher.addTask(createTask(std::bind(&Game::checkCreatureAttack, &g_game, getID()))); - } - } - return setFollowCreature(creature); -} - -void Monster::setIdle(bool _idle) -{ - if (isRemoved() || getHealth() <= 0) { - return; - } - - isIdle = _idle; - - if (!isIdle) { - g_game.addCreatureCheck(this); - } else { - onIdleStatus(); - clearTargetList(); - clearFriendList(); - Game::removeCreatureCheck(this); - } -} - -void Monster::updateIdleStatus() -{ - bool idle = false; - - if (conditions.empty()) { - if (isSummon()) { - if (!isMasterInRange || (getMaster()->getMonster() && getMaster()->getMonster()->getIdleStatus())) { - idle = true; - } - } else if (targetList.empty()) { - idle = true; - } - } - - setIdle(idle); -} - -void Monster::onAddCondition(ConditionType_t type) -{ - if (type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON) { - updateMapCache(); - } - - updateIdleStatus(); -} - -void Monster::onEndCondition(ConditionType_t type) -{ - if (type == CONDITION_FIRE || type == CONDITION_ENERGY || type == CONDITION_POISON) { - updateMapCache(); - } - - updateIdleStatus(); -} - -void Monster::onThink(uint32_t interval) -{ - Creature::onThink(interval); - - if (mType->thinkEvent != -1) { - // onThink(self, interval) - LuaScriptInterface* scriptInterface = mType->scriptInterface; - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Monster::onThink] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(mType->thinkEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(mType->thinkEvent); - - LuaScriptInterface::pushUserdata(L, this); - LuaScriptInterface::setMetatable(L, -1, "Monster"); - - lua_pushnumber(L, interval); - - if (scriptInterface->callFunction(2)) { - return; - } - } - - if (!isInSpawnRange(_position)) { - g_game.internalTeleport(this, masterPos); - setIdle(true); - } else { - updateIdleStatus(); - - if (!isIdle) { - addEventWalk(); - - if (isSummon()) { - if (!attackedCreature) { - if (getMaster() && getMaster()->getAttackedCreature()) { - //This happens if the monster is summoned during combat - selectTarget(getMaster()->getAttackedCreature()); - } else if (getMaster() != followCreature) { - //Our master has not ordered us to attack anything, lets follow him around instead. - setFollowCreature(getMaster()); - } - } else if (attackedCreature == this) { - setFollowCreature(nullptr); - } else if (followCreature != attackedCreature) { - //This happens just after a master orders an attack, so lets follow it aswell. - setFollowCreature(attackedCreature); - } - } else if (!targetList.empty()) { - if (!followCreature || !hasFollowPath) { - searchTarget(); - } else if (isFleeing()) { - if (attackedCreature && !canUseAttack(getPosition(), attackedCreature)) { - searchTarget(TARGETSEARCH_ATTACKRANGE); - } - } - } - - onThinkTarget(interval); - onThinkYell(interval); - onThinkDefense(interval); - } - } -} - -void Monster::doAttacking(uint32_t interval) -{ - if (!attackedCreature || (isSummon() && attackedCreature == this)) { - return; - } - - bool updateLook = true; - bool resetTicks = interval != 0; - attackTicks += interval; - - const Position& myPos = getPosition(); - const Position& targetPos = attackedCreature->getPosition(); - - for (const spellBlock_t& spellBlock : mType->attackSpells) { - bool inRange = false; - - if (canUseSpell(myPos, targetPos, spellBlock, interval, inRange, resetTicks)) { - if (spellBlock.chance >= static_cast(uniform_random(1, 100))) { - if (updateLook) { - updateLookDirection(); - updateLook = false; - } - - minCombatValue = spellBlock.minCombatValue; - maxCombatValue = spellBlock.maxCombatValue; - spellBlock.spell->castSpell(this, attackedCreature); - if (!attackedCreature) { - break; - } - - if (spellBlock.isMelee) { - extraMeleeAttack = false; - } - } - } - - if (!inRange && spellBlock.isMelee) { - //melee swing out of reach - extraMeleeAttack = true; - } - } - - if (updateLook) { - updateLookDirection(); - } - - if (resetTicks) { - attackTicks = 0; - } -} - -bool Monster::canUseAttack(const Position& pos, const Creature* target) const -{ - if (isHostile()) { - const Position& targetPos = target->getPosition(); - uint32_t distance = std::max(Position::getDistanceX(pos, targetPos), Position::getDistanceY(pos, targetPos)); - for (const spellBlock_t& spellBlock : mType->attackSpells) { - if (spellBlock.range != 0 && distance <= spellBlock.range) { - return g_game.isSightClear(pos, targetPos, true); - } - } - return false; - } - return true; -} - -bool Monster::canUseSpell(const Position& pos, const Position& targetPos, - const spellBlock_t& sb, uint32_t interval, bool& inRange, bool& resetTicks) -{ - inRange = true; - - if (sb.isMelee && isFleeing()) { - return false; - } - - if (extraMeleeAttack) { - lastMeleeAttack = OTSYS_TIME(); - } else if (sb.isMelee && (OTSYS_TIME() - lastMeleeAttack) < 1500) { - return false; - } - - if (!sb.isMelee || !extraMeleeAttack) { - if (sb.speed > attackTicks) { - resetTicks = false; - return false; - } - - if (attackTicks % sb.speed >= interval) { - //already used this spell for this round - return false; - } - } - - if (sb.range != 0 && std::max(Position::getDistanceX(pos, targetPos), Position::getDistanceY(pos, targetPos)) > sb.range) { - inRange = false; - return false; - } - return true; -} - -void Monster::onThinkTarget(uint32_t interval) -{ - if (!isSummon()) { - if (mType->changeTargetSpeed != 0) { - bool canChangeTarget = true; - - if (targetChangeCooldown > 0) { - targetChangeCooldown -= interval; - - if (targetChangeCooldown <= 0) { - targetChangeCooldown = 0; - targetChangeTicks = mType->changeTargetSpeed; - } else { - canChangeTarget = false; - } - } - - if (canChangeTarget) { - targetChangeTicks += interval; - - if (targetChangeTicks >= mType->changeTargetSpeed) { - targetChangeTicks = 0; - targetChangeCooldown = mType->changeTargetSpeed; - - if (mType->changeTargetChance >= uniform_random(1, 100)) { - if (mType->targetDistance <= 1) { - searchTarget(TARGETSEARCH_RANDOM); - } else { - searchTarget(TARGETSEARCH_NEAREST); - } - } - } - } - } - } -} - -void Monster::onThinkDefense(uint32_t interval) -{ - bool resetTicks = true; - defenseTicks += interval; - - for (const spellBlock_t& spellBlock : mType->defenseSpells) { - if (spellBlock.speed > defenseTicks) { - resetTicks = false; - continue; - } - - if (defenseTicks % spellBlock.speed >= interval) { - //already used this spell for this round - continue; - } - - if ((spellBlock.chance >= static_cast(uniform_random(1, 100)))) { - minCombatValue = spellBlock.minCombatValue; - maxCombatValue = spellBlock.maxCombatValue; - spellBlock.spell->castSpell(this, this); - } - } - - if (!isSummon() && summons.size() < mType->maxSummons) { - for (const summonBlock_t& summonBlock : mType->summons) { - if (summonBlock.speed > defenseTicks) { - resetTicks = false; - continue; - } - - if (summons.size() >= mType->maxSummons) { - continue; - } - - if (defenseTicks % summonBlock.speed >= interval) { - //already used this spell for this round - continue; - } - - if (summonBlock.chance < static_cast(uniform_random(1, 100))) { - continue; - } - - Monster* summon = Monster::createMonster(summonBlock.name); - if (summon) { - const Position& summonPos = getPosition(); - - addSummon(summon); - - if (!g_game.placeCreature(summon, summonPos)) { - removeSummon(summon); - } else { - g_game.addMagicEffect(getPosition(), CONST_ME_MAGIC_BLUE); - g_game.addMagicEffect(summon->getPosition(), CONST_ME_TELEPORT); - } - } - } - } - - if (resetTicks) { - defenseTicks = 0; - } -} - -void Monster::onThinkYell(uint32_t interval) -{ - if (mType->yellSpeedTicks == 0) { - return; - } - - yellTicks += interval; - if (yellTicks >= mType->yellSpeedTicks) { - yellTicks = 0; - - if (!mType->voiceVector.empty() && (mType->yellChance >= static_cast(uniform_random(1, 100)))) { - uint32_t index = uniform_random(0, mType->voiceVector.size() - 1); - const voiceBlock_t& vb = mType->voiceVector[index]; - - if (vb.yellText) { - g_game.internalCreatureSay(this, TALKTYPE_MONSTER_YELL, vb.text, false); - } else { - g_game.internalCreatureSay(this, TALKTYPE_MONSTER_SAY, vb.text, false); - } - } - } -} - -void Monster::onWalk() -{ - Creature::onWalk(); -} - -bool Monster::pushItem(Item* item) -{ - const Position& centerPos = item->getPosition(); - - static std::vector> relList { - {-1, -1}, {0, -1}, {1, -1}, - {-1, 0}, {1, 0}, - {-1, 1}, {0, 1}, {1, 1} - }; - - std::shuffle(relList.begin(), relList.end(), getRandomGenerator()); - - for (const auto& it : relList) { - Position tryPos(centerPos.x + it.first, centerPos.y + it.second, centerPos.z); - Tile* tile = g_game.map.getTile(tryPos); - if (tile && g_game.canThrowObjectTo(centerPos, tryPos)) { - if (g_game.internalMoveItem(item->getParent(), tile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr) == RETURNVALUE_NOERROR) { - return true; - } - } - } - return false; -} - -void Monster::pushItems(Tile* tile) -{ - //We can not use iterators here since we can push the item to another tile - //which will invalidate the iterator. - //start from the end to minimize the amount of traffic - if (TileItemVector* items = tile->getItemList()) { - uint32_t moveCount = 0; - uint32_t removeCount = 0; - - int32_t downItemSize = tile->getDownItemCount(); - for (int32_t i = downItemSize; --i >= 0;) { - Item* item = items->at(i); - if (item && item->hasProperty(CONST_PROP_MOVEABLE) && (item->hasProperty(CONST_PROP_BLOCKPATH) - || item->hasProperty(CONST_PROP_BLOCKSOLID))) { - if (moveCount < 20 && Monster::pushItem(item)) { - ++moveCount; - } else if (g_game.internalRemoveItem(item) == RETURNVALUE_NOERROR) { - ++removeCount; - } - } - } - - if (removeCount > 0) { - g_game.addMagicEffect(tile->getPosition(), CONST_ME_POFF); - } - } -} - -bool Monster::pushCreature(Creature* creature) -{ - static std::vector dirList { - DIRECTION_NORTH, - DIRECTION_WEST, DIRECTION_EAST, - DIRECTION_SOUTH - }; - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); - - for (Direction dir : dirList) { - const Position& tryPos = Spells::getCasterPosition(creature, dir); - Tile* toTile = g_game.map.getTile(tryPos); - if (toTile && !toTile->hasProperty(CONST_PROP_BLOCKPATH)) { - if (g_game.internalMoveCreature(creature, dir) == RETURNVALUE_NOERROR) { - return true; - } - } - } - return false; -} - -void Monster::pushCreatures(Tile* tile) -{ - //We can not use iterators here since we can push a creature to another tile - //which will invalidate the iterator. - if (CreatureVector* creatures = tile->getCreatures()) { - uint32_t removeCount = 0; - Monster* lastPushedMonster = nullptr; - - for (size_t i = 0; i < creatures->size();) { - Monster* monster = creatures->at(i)->getMonster(); - if (monster && monster->isPushable()) { - if (monster != lastPushedMonster && Monster::pushCreature(monster)) { - lastPushedMonster = monster; - continue; - } - - monster->changeHealth(-monster->getHealth()); - monster->setDropLoot(false); - removeCount++; - } - - ++i; - } - - if (removeCount > 0) { - g_game.addMagicEffect(tile->getPosition(), CONST_ME_BLOCKHIT); - } - } -} - -bool Monster::getNextStep(Direction& dir, uint32_t& flags) -{ - if (isIdle || getHealth() <= 0) { - //we dont have anyone watching might aswell stop walking - eventWalk = 0; - return false; - } - - bool result = false; - if ((!followCreature || !hasFollowPath) && !isSummon()) { - if (followCreature || getTimeSinceLastMove() > 1000) { - //choose a random direction - result = getRandomStep(getPosition(), dir); - } - } else if (isSummon() || followCreature) { - result = Creature::getNextStep(dir, flags); - if (result) { - flags |= FLAG_PATHFINDING; - } else { - //target dancing - if (attackedCreature && attackedCreature == followCreature) { - if (isFleeing()) { - result = getDanceStep(getPosition(), dir, false, false); - } else if (mType->staticAttackChance < static_cast(uniform_random(1, 100))) { - result = getDanceStep(getPosition(), dir); - } - } - } - } - - if (result && (canPushItems() || canPushCreatures())) { - const Position& pos = Spells::getCasterPosition(this, dir); - Tile* tile = g_game.map.getTile(pos); - if (tile) { - if (canPushItems()) { - Monster::pushItems(tile); - } - - if (canPushCreatures()) { - Monster::pushCreatures(tile); - } - } - } - - return result; -} - -bool Monster::getRandomStep(const Position& creaturePos, Direction& dir) const -{ - static std::vector dirList{ - DIRECTION_NORTH, - DIRECTION_WEST, DIRECTION_EAST, - DIRECTION_SOUTH - }; - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); - - for (Direction _dir : dirList) { - if (canWalkTo(creaturePos, _dir)) { - dir = _dir; - return true; - } - } - return false; -} - -bool Monster::getDanceStep(const Position& creaturePos, Direction& dir, - bool keepAttack /*= true*/, bool keepDistance /*= true*/) -{ - bool canDoAttackNow = canUseAttack(creaturePos, attackedCreature); - - assert(attackedCreature != nullptr); - const Position& centerPos = attackedCreature->getPosition(); - - int_fast32_t offset_x = Position::getOffsetX(creaturePos, centerPos); - int_fast32_t offset_y = Position::getOffsetY(creaturePos, centerPos); - - int_fast32_t distance_x = std::abs(offset_x); - int_fast32_t distance_y = std::abs(offset_y); - - uint32_t centerToDist = std::max(distance_x, distance_y); - - std::vector dirList; - - if (!keepDistance || offset_y >= 0) { - uint32_t tmpDist = std::max(distance_x, std::abs((creaturePos.getY() - 1) - centerPos.getY())); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_NORTH)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y - 1, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_NORTH); - } - } - } - - if (!keepDistance || offset_y <= 0) { - uint32_t tmpDist = std::max(distance_x, std::abs((creaturePos.getY() + 1) - centerPos.getY())); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_SOUTH)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x, creaturePos.y + 1, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_SOUTH); - } - } - } - - if (!keepDistance || offset_x <= 0) { - uint32_t tmpDist = std::max(std::abs((creaturePos.getX() + 1) - centerPos.getX()), distance_y); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_EAST)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x + 1, creaturePos.y, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_EAST); - } - } - } - - if (!keepDistance || offset_x >= 0) { - uint32_t tmpDist = std::max(std::abs((creaturePos.getX() - 1) - centerPos.getX()), distance_y); - if (tmpDist == centerToDist && canWalkTo(creaturePos, DIRECTION_WEST)) { - bool result = true; - - if (keepAttack) { - result = (!canDoAttackNow || canUseAttack(Position(creaturePos.x - 1, creaturePos.y, creaturePos.z), attackedCreature)); - } - - if (result) { - dirList.push_back(DIRECTION_WEST); - } - } - } - - if (!dirList.empty()) { - std::shuffle(dirList.begin(), dirList.end(), getRandomGenerator()); - dir = dirList[uniform_random(0, dirList.size() - 1)]; - return true; - } - return false; -} - -bool Monster::getDistanceStep(const Position& targetPos, Direction& dir, bool flee /* = false */) -{ - const Position& creaturePos = getPosition(); - - int_fast32_t dx = Position::getDistanceX(creaturePos, targetPos); - int_fast32_t dy = Position::getDistanceY(creaturePos, targetPos); - - int32_t distance = std::max(dx, dy); - - if (!flee && (distance > mType->targetDistance || !g_game.isSightClear(creaturePos, targetPos, true))) { - return false; // let the A* calculate it - } else if (!flee && distance == mType->targetDistance) { - return true; // we don't really care here, since it's what we wanted to reach (a dancestep will take of dancing in that position) - } - - int_fast32_t offsetx = Position::getOffsetX(creaturePos, targetPos); - int_fast32_t offsety = Position::getOffsetY(creaturePos, targetPos); - - if (dx <= 1 && dy <= 1) { - //seems like a target is near, it this case we need to slow down our movements (as a monster) - if (stepDuration < 2) { - stepDuration++; - } - } else if (stepDuration > 0) { - stepDuration--; - } - - if (offsetx == 0 && offsety == 0) { - return getRandomStep(creaturePos, dir); // player is "on" the monster so let's get some random step and rest will be taken care later. - } - - if (dx == dy) { - //player is diagonal to the monster - if (offsetx >= 1 && offsety >= 1) { - // player is NW - //escape to SE, S or E [and some extra] - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - - if (s && e) { - dir = boolean_random() ? DIRECTION_SOUTH : DIRECTION_EAST; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } else if (canWalkTo(creaturePos, DIRECTION_SOUTHEAST)) { - dir = DIRECTION_SOUTHEAST; - return true; - } - - /* fleeing */ - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - - if (flee) { - if (n && w) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_WEST; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } - } - - /* end of fleeing */ - - if (w && canWalkTo(creaturePos, DIRECTION_SOUTHWEST)) { - dir = DIRECTION_WEST; - } else if (n && canWalkTo(creaturePos, DIRECTION_NORTHEAST)) { - dir = DIRECTION_NORTH; - } - - return true; - } else if (offsetx <= -1 && offsety <= -1) { - //player is SE - //escape to NW , W or N [and some extra] - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - - if (w && n) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_NORTH; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } - - if (canWalkTo(creaturePos, DIRECTION_NORTHWEST)) { - dir = DIRECTION_NORTHWEST; - return true; - } - - /* fleeing */ - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - - if (flee) { - if (s && e) { - dir = boolean_random() ? DIRECTION_SOUTH : DIRECTION_EAST; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } - } - - /* end of fleeing */ - - if (s && canWalkTo(creaturePos, DIRECTION_SOUTHWEST)) { - dir = DIRECTION_SOUTH; - } else if (e && canWalkTo(creaturePos, DIRECTION_NORTHEAST)) { - dir = DIRECTION_EAST; - } - - return true; - } else if (offsetx >= 1 && offsety <= -1) { - //player is SW - //escape to NE, N, E [and some extra] - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - if (n && e) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_EAST; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } - - if (canWalkTo(creaturePos, DIRECTION_NORTHEAST)) { - dir = DIRECTION_NORTHEAST; - return true; - } - - /* fleeing */ - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - - if (flee) { - if (s && w) { - dir = boolean_random() ? DIRECTION_SOUTH : DIRECTION_WEST; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } - } - - /* end of fleeing */ - - if (w && canWalkTo(creaturePos, DIRECTION_NORTHWEST)) { - dir = DIRECTION_WEST; - } else if (s && canWalkTo(creaturePos, DIRECTION_SOUTHEAST)) { - dir = DIRECTION_SOUTH; - } - - return true; - } else if (offsetx <= -1 && offsety >= 1) { - // player is NE - //escape to SW, S, W [and some extra] - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - if (w && s) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_SOUTH; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } else if (canWalkTo(creaturePos, DIRECTION_SOUTHWEST)) { - dir = DIRECTION_SOUTHWEST; - return true; - } - - /* fleeing */ - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - - if (flee) { - if (n && e) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_EAST; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } - } - - /* end of fleeing */ - - if (e && canWalkTo(creaturePos, DIRECTION_SOUTHEAST)) { - dir = DIRECTION_EAST; - } else if (n && canWalkTo(creaturePos, DIRECTION_NORTHWEST)) { - dir = DIRECTION_NORTH; - } - - return true; - } - } - - //Now let's decide where the player is located to the monster (what direction) so we can decide where to escape. - if (dy > dx) { - Direction playerDir = offsety < 0 ? DIRECTION_SOUTH : DIRECTION_NORTH; - switch (playerDir) { - case DIRECTION_NORTH: { - // Player is to the NORTH, so obviously we need to check if we can go SOUTH, if not then let's choose WEST or EAST and again if we can't we need to decide about some diagonal movements. - if (canWalkTo(creaturePos, DIRECTION_SOUTH)) { - dir = DIRECTION_SOUTH; - return true; - } - - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - if (w && e && offsetx == 0) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_EAST; - return true; - } else if (w && offsetx <= 0) { - dir = DIRECTION_WEST; - return true; - } else if (e && offsetx >= 0) { - dir = DIRECTION_EAST; - return true; - } - - /* fleeing */ - if (flee) { - if (w && e) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_EAST; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } - } - - /* end of fleeing */ - - bool sw = canWalkTo(creaturePos, DIRECTION_SOUTHWEST); - bool se = canWalkTo(creaturePos, DIRECTION_SOUTHEAST); - if (sw || se) { - // we can move both dirs - if (sw && se) { - dir = boolean_random() ? DIRECTION_SOUTHWEST : DIRECTION_SOUTHEAST; - } else if (w) { - dir = DIRECTION_WEST; - } else if (sw) { - dir = DIRECTION_SOUTHWEST; - } else if (e) { - dir = DIRECTION_EAST; - } else if (se) { - dir = DIRECTION_SOUTHEAST; - } - return true; - } - - /* fleeing */ - if (flee && canWalkTo(creaturePos, DIRECTION_NORTH)) { - // towards player, yea - dir = DIRECTION_NORTH; - return true; - } - - /* end of fleeing */ - break; - } - - case DIRECTION_SOUTH: { - if (canWalkTo(creaturePos, DIRECTION_NORTH)) { - dir = DIRECTION_NORTH; - return true; - } - - bool w = canWalkTo(creaturePos, DIRECTION_WEST); - bool e = canWalkTo(creaturePos, DIRECTION_EAST); - if (w && e && offsetx == 0) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_EAST; - return true; - } else if (w && offsetx <= 0) { - dir = DIRECTION_WEST; - return true; - } else if (e && offsetx >= 0) { - dir = DIRECTION_EAST; - return true; - } - - /* fleeing */ - if (flee) { - if (w && e) { - dir = boolean_random() ? DIRECTION_WEST : DIRECTION_EAST; - return true; - } else if (w) { - dir = DIRECTION_WEST; - return true; - } else if (e) { - dir = DIRECTION_EAST; - return true; - } - } - - /* end of fleeing */ - - bool nw = canWalkTo(creaturePos, DIRECTION_NORTHWEST); - bool ne = canWalkTo(creaturePos, DIRECTION_NORTHEAST); - if (nw || ne) { - // we can move both dirs - if (nw && ne) { - dir = boolean_random() ? DIRECTION_NORTHWEST : DIRECTION_NORTHEAST; - } else if (w) { - dir = DIRECTION_WEST; - } else if (nw) { - dir = DIRECTION_NORTHWEST; - } else if (e) { - dir = DIRECTION_EAST; - } else if (ne) { - dir = DIRECTION_NORTHEAST; - } - return true; - } - - /* fleeing */ - if (flee && canWalkTo(creaturePos, DIRECTION_SOUTH)) { - // towards player, yea - dir = DIRECTION_SOUTH; - return true; - } - - /* end of fleeing */ - break; - } - - default: - break; - } - } else { - Direction playerDir = offsetx < 0 ? DIRECTION_EAST : DIRECTION_WEST; - switch (playerDir) { - case DIRECTION_WEST: { - if (canWalkTo(creaturePos, DIRECTION_EAST)) { - dir = DIRECTION_EAST; - return true; - } - - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - if (n && s && offsety == 0) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_SOUTH; - return true; - } else if (n && offsety <= 0) { - dir = DIRECTION_NORTH; - return true; - } else if (s && offsety >= 0) { - dir = DIRECTION_SOUTH; - return true; - } - - /* fleeing */ - if (flee) { - if (n && s) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_SOUTH; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } - } - - /* end of fleeing */ - - bool se = canWalkTo(creaturePos, DIRECTION_SOUTHEAST); - bool ne = canWalkTo(creaturePos, DIRECTION_NORTHEAST); - if (se || ne) { - if (se && ne) { - dir = boolean_random() ? DIRECTION_SOUTHEAST : DIRECTION_NORTHEAST; - } else if (s) { - dir = DIRECTION_SOUTH; - } else if (se) { - dir = DIRECTION_SOUTHEAST; - } else if (n) { - dir = DIRECTION_NORTH; - } else if (ne) { - dir = DIRECTION_NORTHEAST; - } - return true; - } - - /* fleeing */ - if (flee && canWalkTo(creaturePos, DIRECTION_WEST)) { - // towards player, yea - dir = DIRECTION_WEST; - return true; - } - - /* end of fleeing */ - break; - } - - case DIRECTION_EAST: { - if (canWalkTo(creaturePos, DIRECTION_WEST)) { - dir = DIRECTION_WEST; - return true; - } - - bool n = canWalkTo(creaturePos, DIRECTION_NORTH); - bool s = canWalkTo(creaturePos, DIRECTION_SOUTH); - if (n && s && offsety == 0) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_SOUTH; - return true; - } else if (n && offsety <= 0) { - dir = DIRECTION_NORTH; - return true; - } else if (s && offsety >= 0) { - dir = DIRECTION_SOUTH; - return true; - } - - /* fleeing */ - if (flee) { - if (n && s) { - dir = boolean_random() ? DIRECTION_NORTH : DIRECTION_SOUTH; - return true; - } else if (n) { - dir = DIRECTION_NORTH; - return true; - } else if (s) { - dir = DIRECTION_SOUTH; - return true; - } - } - - /* end of fleeing */ - - bool nw = canWalkTo(creaturePos, DIRECTION_NORTHWEST); - bool sw = canWalkTo(creaturePos, DIRECTION_SOUTHWEST); - if (nw || sw) { - if (nw && sw) { - dir = boolean_random() ? DIRECTION_NORTHWEST : DIRECTION_SOUTHWEST; - } else if (n) { - dir = DIRECTION_NORTH; - } else if (nw) { - dir = DIRECTION_NORTHWEST; - } else if (s) { - dir = DIRECTION_SOUTH; - } else if (sw) { - dir = DIRECTION_SOUTHWEST; - } - return true; - } - - /* fleeing */ - if (flee && canWalkTo(creaturePos, DIRECTION_EAST)) { - // towards player, yea - dir = DIRECTION_EAST; - return true; - } - - /* end of fleeing */ - break; - } - - default: - break; - } - } - - return true; -} - -bool Monster::canWalkTo(Position pos, Direction dir) const -{ - pos = getNextPosition(dir, pos); - if (isInSpawnRange(pos)) { - if (getWalkCache(pos) == 0) { - return false; - } - - Tile* tile = g_game.map.getTile(pos); - if (tile && tile->getTopVisibleCreature(this) == nullptr && tile->queryAdd(0, *this, 1, FLAG_PATHFINDING) == RETURNVALUE_NOERROR) { - return true; - } - } - return false; -} - -void Monster::death(Creature*) -{ - setAttackedCreature(nullptr); - - for (Creature* summon : summons) { - summon->changeHealth(-summon->getHealth()); - summon->setMaster(nullptr); - summon->decrementReferenceCounter(); - } - summons.clear(); - - clearTargetList(); - clearFriendList(); - onIdleStatus(); -} - -Item* Monster::getCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature) -{ - Item* corpse = Creature::getCorpse(_lastHitCreature, mostDamageCreature); - if (corpse) { - if (mostDamageCreature) { - if (mostDamageCreature->getPlayer()) { - corpse->setCorpseOwner(mostDamageCreature->getID()); - } else { - const Creature* mostDamageCreatureMaster = mostDamageCreature->getMaster(); - if (mostDamageCreatureMaster && mostDamageCreatureMaster->getPlayer()) { - corpse->setCorpseOwner(mostDamageCreatureMaster->getID()); - } - } - } - } - return corpse; -} - -bool Monster::isInSpawnRange(const Position& pos) const -{ - if (!spawn) { - return true; - } - - if (Monster::despawnRadius == 0) { - return true; - } - - if (!Spawns::isInZone(masterPos, Monster::despawnRadius, pos)) { - return false; - } - - if (Monster::despawnRange == 0) { - return true; - } - - if (Position::getDistanceZ(pos, masterPos) > Monster::despawnRange) { - return false; - } - - return true; -} - -bool Monster::getCombatValues(int32_t& min, int32_t& max) -{ - if (minCombatValue == 0 && maxCombatValue == 0) { - return false; - } - - min = minCombatValue; - max = maxCombatValue; - return true; -} - -void Monster::updateLookDirection() -{ - Direction newDir = getDirection(); - - if (attackedCreature) { - const Position& pos = getPosition(); - const Position& attackedCreaturePos = attackedCreature->getPosition(); - int_fast32_t offsetx = Position::getOffsetX(attackedCreaturePos, pos); - int_fast32_t offsety = Position::getOffsetY(attackedCreaturePos, pos); - - int32_t dx = std::abs(offsetx); - int32_t dy = std::abs(offsety); - if (dx > dy) { - //look EAST/WEST - if (offsetx < 0) { - newDir = DIRECTION_WEST; - } else { - newDir = DIRECTION_EAST; - } - } else if (dx < dy) { - //look NORTH/SOUTH - if (offsety < 0) { - newDir = DIRECTION_NORTH; - } else { - newDir = DIRECTION_SOUTH; - } - } else { - Direction dir = getDirection(); - if (offsetx < 0 && offsety < 0) { - if (dir == DIRECTION_SOUTH) { - newDir = DIRECTION_WEST; - } else if (dir == DIRECTION_EAST) { - newDir = DIRECTION_NORTH; - } - } else if (offsetx < 0 && offsety > 0) { - if (dir == DIRECTION_NORTH) { - newDir = DIRECTION_WEST; - } else if (dir == DIRECTION_EAST) { - newDir = DIRECTION_SOUTH; - } - } else if (offsetx > 0 && offsety < 0) { - if (dir == DIRECTION_SOUTH) { - newDir = DIRECTION_EAST; - } else if (dir == DIRECTION_WEST) { - newDir = DIRECTION_NORTH; - } - } else { - if (dir == DIRECTION_NORTH) { - newDir = DIRECTION_EAST; - } else if (dir == DIRECTION_WEST) { - newDir = DIRECTION_SOUTH; - } - } - } - } - - g_game.internalCreatureTurn(this, newDir); -} - -void Monster::dropLoot(Container* corpse, Creature*) -{ - if (corpse && lootDrop) { - mType->createLoot(corpse); - } -} - -void Monster::setNormalCreatureLight() -{ - internalLight.level = mType->lightLevel; - internalLight.color = mType->lightColor; -} - -void Monster::drainHealth(Creature* attacker, int32_t damage) -{ - Creature::drainHealth(attacker, damage); - if (isInvisible()) { - removeCondition(CONDITION_INVISIBLE); - } -} - -void Monster::changeHealth(int32_t healthChange, bool sendHealthChange/* = true*/) -{ - //In case a player with ignore flag set attacks the monster - setIdle(false); - Creature::changeHealth(healthChange, sendHealthChange); -} - -bool Monster::challengeCreature(Creature* creature) -{ - if (isSummon()) { - return false; - } - - bool result = selectTarget(creature); - if (result) { - targetChangeCooldown = 8000; - targetChangeTicks = 0; - } - return result; -} - -bool Monster::convinceCreature(Creature* creature) -{ - Player* player = creature->getPlayer(); - if (player && !player->hasFlag(PlayerFlag_CanConvinceAll)) { - if (!mType->isConvinceable) { - return false; - } - } - - if (isSummon()) { - if (getMaster()->getPlayer()) { - return false; - } else if (getMaster() == creature) { - return false; - } - - Creature* oldMaster = getMaster(); - oldMaster->removeSummon(this); - } - - creature->addSummon(this); - - setFollowCreature(nullptr); - setAttackedCreature(nullptr); - - //destroy summons - for (Creature* summon : summons) { - summon->changeHealth(-summon->getHealth()); - summon->setMaster(nullptr); - summon->decrementReferenceCounter(); - } - summons.clear(); - - isMasterInRange = true; - updateTargetList(); - updateIdleStatus(); - - //Notify surrounding about the change - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true); - g_game.map.getSpectators(list, creature->getPosition(), true); - for (Creature* spectator : list) { - spectator->onCreatureConvinced(creature, this); - } - - if (spawn) { - spawn->removeMonster(this); - spawn = nullptr; - } - return true; -} - -void Monster::onCreatureConvinced(const Creature* convincer, const Creature* creature) -{ - if (convincer != this && (isFriend(creature) || isOpponent(creature))) { - updateTargetList(); - updateIdleStatus(); - } -} - -void Monster::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const -{ - Creature::getPathSearchParams(creature, fpp); - - fpp.minTargetDist = 1; - fpp.maxTargetDist = mType->targetDistance; - - if (isSummon()) { - if (getMaster() == creature) { - fpp.maxTargetDist = 2; - fpp.fullPathSearch = true; - } else if (mType->targetDistance <= 1) { - fpp.fullPathSearch = true; - } else { - fpp.fullPathSearch = !canUseAttack(getPosition(), creature); - } - } else if (isFleeing()) { - //Distance should be higher than the client view range (Map::maxClientViewportX/Map::maxClientViewportY) - fpp.maxTargetDist = Map::maxViewportX; - fpp.clearSight = false; - fpp.keepDistance = true; - fpp.fullPathSearch = false; - } else if (mType->targetDistance <= 1) { - fpp.fullPathSearch = true; - } else { - fpp.fullPathSearch = !canUseAttack(getPosition(), creature); - } -} diff --git a/path_10_8/src/monster.h b/path_10_8/src/monster.h deleted file mode 100644 index 824573026..000000000 --- a/path_10_8/src/monster.h +++ /dev/null @@ -1,278 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MONSTER_H_9F5EEFE64314418CA7DA41D1B9409DD0 -#define FS_MONSTER_H_9F5EEFE64314418CA7DA41D1B9409DD0 - -#include "tile.h" -#include "monsters.h" - -class Creature; -class Game; -class Spawn; - -typedef std::unordered_set CreatureHashSet; -typedef std::list CreatureList; - -enum TargetSearchType_t { - TARGETSEARCH_DEFAULT, - TARGETSEARCH_RANDOM, - TARGETSEARCH_ATTACKRANGE, - TARGETSEARCH_NEAREST, -}; - -class Monster final : public Creature -{ - public: - static Monster* createMonster(const std::string& name); - static int32_t despawnRange; - static int32_t despawnRadius; - - explicit Monster(MonsterType* mtype); - ~Monster(); - - // non-copyable - Monster(const Monster&) = delete; - Monster& operator=(const Monster&) = delete; - - Monster* getMonster() final { - return this; - } - const Monster* getMonster() const final { - return this; - } - - void setID() final { - if (id == 0) { - id = monsterAutoID++; - } - } - - void removeList() final; - void addList() final; - - const std::string& getName() const final { - return mType->name; - } - const std::string& getNameDescription() const final { - return mType->nameDescription; - } - std::string getDescription(int32_t) const final { - return strDescription + '.'; - } - - CreatureType_t getType() const final { - return CREATURETYPE_MONSTER; - } - - const Position& getMasterPos() const { - return masterPos; - } - void setMasterPos(Position pos) { - masterPos = pos; - } - - RaceType_t getRace() const final { - return mType->race; - } - int32_t getArmor() const final { - return mType->armor; - } - int32_t getDefense() const final { - return mType->defense; - } - bool isPushable() const final { - return mType->pushable && baseSpeed != 0; - } - bool isAttackable() const final { - return mType->isAttackable; - } - - bool canPushItems() const { - return mType->canPushItems; - } - bool canPushCreatures() const { - return mType->canPushCreatures; - } - bool isHostile() const { - return mType->isHostile; - } - bool isPassive() const { - return mType->isPassive; - } - bool canSee(const Position& pos) const final; - bool canSeeInvisibility() const final { - return isImmune(CONDITION_INVISIBLE); - } - uint32_t getManaCost() const { - return mType->manaCost; - } - void setSpawn(Spawn* _spawn) { - spawn = _spawn; - } - - void onAttackedCreatureDisappear(bool isLogout) final; - - void onCreatureAppear(Creature* creature, bool isLogin) final; - void onRemoveCreature(Creature* creature, bool isLogout) final; - void onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, const Tile* oldTile, const Position& oldPos, bool teleport) final; - void onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) final; - - void drainHealth(Creature* attacker, int32_t damage) final; - void changeHealth(int32_t healthChange, bool sendHealthChange = true) final; - void onWalk() final; - bool getNextStep(Direction& dir, uint32_t& flags) final; - void onFollowCreatureComplete(const Creature* creature) final; - - void onThink(uint32_t interval) final; - - bool challengeCreature(Creature* creature) final; - bool convinceCreature(Creature* creature) final; - - void setNormalCreatureLight() final; - bool getCombatValues(int32_t& min, int32_t& max) final; - - void doAttacking(uint32_t interval) final; - bool hasExtraSwing() final { - return extraMeleeAttack; - } - - bool searchTarget(TargetSearchType_t searchType = TARGETSEARCH_DEFAULT); - bool selectTarget(Creature* creature); - - const CreatureList& getTargetList() const { - return targetList; - } - const CreatureHashSet& getFriendList() const { - return friendList; - } - - bool isTarget(const Creature* creature) const; - bool isFleeing() const { - return getHealth() <= mType->runAwayHealth; - } - - bool getDistanceStep(const Position& targetPos, Direction& dir, bool flee = false); - bool isTargetNearby() const { - return stepDuration >= 1; - } - - BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense = false, bool checkArmor = false, bool field = false); - - static uint32_t monsterAutoID; - - private: - CreatureHashSet friendList; - CreatureList targetList; - - std::string strDescription; - - MonsterType* mType; - Spawn* spawn; - - int64_t lastMeleeAttack; - - uint32_t attackTicks; - uint32_t targetTicks; - uint32_t targetChangeTicks; - uint32_t defenseTicks; - uint32_t yellTicks; - int32_t minCombatValue; - int32_t maxCombatValue; - int32_t targetChangeCooldown; - int32_t stepDuration; - - Position masterPos; - - bool isIdle; - bool extraMeleeAttack; - bool isMasterInRange; - - void onCreatureEnter(Creature* creature); - void onCreatureLeave(Creature* creature); - void onCreatureFound(Creature* creature, bool pushFront = false); - - void updateLookDirection(); - - void addFriend(Creature* creature); - void removeFriend(Creature* creature); - void addTarget(Creature* creature, bool pushFront = false); - void removeTarget(Creature* creature); - - void updateTargetList(); - void clearTargetList(); - void clearFriendList(); - - void death(Creature* _lastHitCreature) final; - Item* getCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature) final; - - void setIdle(bool _idle); - void updateIdleStatus(); - bool getIdleStatus() const { - return isIdle; - } - - void onAddCondition(ConditionType_t type) final; - void onEndCondition(ConditionType_t type) final; - void onCreatureConvinced(const Creature* convincer, const Creature* creature) final; - - bool canUseAttack(const Position& pos, const Creature* target) const; - bool canUseSpell(const Position& pos, const Position& targetPos, - const spellBlock_t& sb, uint32_t interval, bool& inRange, bool& resetTicks); - bool getRandomStep(const Position& creaturePos, Direction& dir) const; - bool getDanceStep(const Position& creaturePos, Direction& dir, - bool keepAttack = true, bool keepDistance = true); - bool isInSpawnRange(const Position& pos) const; - bool canWalkTo(Position pos, Direction dir) const; - - static bool pushItem(Item* item); - static void pushItems(Tile* tile); - static bool pushCreature(Creature* creature); - static void pushCreatures(Tile* tile); - - void onThinkTarget(uint32_t interval); - void onThinkYell(uint32_t interval); - void onThinkDefense(uint32_t interval); - - bool isFriend(const Creature* creature) const; - bool isOpponent(const Creature* creature) const; - - uint64_t getLostExperience() const final { - return skillLoss ? mType->experience : 0; - } - uint16_t getLookCorpse() const final { - return mType->lookcorpse; - } - void dropLoot(Container* corpse, Creature* _lastHitCreature) final; - uint32_t getDamageImmunities() const final { - return mType->damageImmunities; - } - uint32_t getConditionImmunities() const final { - return mType->conditionImmunities; - } - void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const final; - bool useCacheMap() const final { - return true; - } - - friend class LuaScriptInterface; -}; - -#endif diff --git a/path_10_8/src/monsters.cpp b/path_10_8/src/monsters.cpp deleted file mode 100644 index 1bc843c26..000000000 --- a/path_10_8/src/monsters.cpp +++ /dev/null @@ -1,1302 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "monsters.h" -#include "monster.h" -#include "spells.h" -#include "combat.h" -#include "weapons.h" -#include "configmanager.h" -#include "game.h" - -#include "pugicast.h" - -extern Game g_game; -extern Spells* g_spells; -extern Monsters g_monsters; -extern ConfigManager g_config; - -spellBlock_t::~spellBlock_t() -{ - if (combatSpell) { - delete spell; - } -} - -MonsterType::MonsterType() -{ - reset(); -} - -void MonsterType::reset() -{ - experience = 0; - - defense = 0; - armor = 0; - - hiddenHealth = false; - - canPushItems = false; - canPushCreatures = false; - staticAttackChance = 95; - maxSummons = 0; - targetDistance = 1; - runAwayHealth = 0; - pushable = true; - baseSpeed = 200; - health = 100; - healthMax = 100; - - outfit.reset(); - lookcorpse = 0; - - skull = SKULL_NONE; - - conditionImmunities = 0; - damageImmunities = 0; - race = RACE_BLOOD; - isSummonable = false; - isIllusionable = false; - isConvinceable = false; - isAttackable = true; - isHostile = true; - isPassive = false; - - lightLevel = 0; - lightColor = 0; - - manaCost = 0; - summons.clear(); - lootItems.clear(); - elementMap.clear(); - - attackSpells.clear(); - defenseSpells.clear(); - - yellSpeedTicks = 0; - yellChance = 0; - voiceVector.clear(); - - changeTargetSpeed = 0; - changeTargetChance = 0; - - scriptInterface = nullptr; - creatureAppearEvent = -1; - creatureDisappearEvent = -1; - creatureMoveEvent = -1; - creatureSayEvent = -1; - thinkEvent = -1; - - scripts.clear(); -} - -uint32_t Monsters::getLootRandom() -{ - return uniform_random(0, MAX_LOOTCHANCE) / g_config.getNumber(ConfigManager::RATE_LOOT); -} - -void MonsterType::createLoot(Container* corpse) -{ - if (g_config.getNumber(ConfigManager::RATE_LOOT) == 0) { - corpse->startDecaying(); - return; - } - - Player* owner = g_game.getPlayerByID(corpse->getCorpseOwner()); - if (!owner || owner->getStaminaMinutes() > 840) { - for (auto it = lootItems.rbegin(), end = lootItems.rend(); it != end; ++it) { - auto itemList = createLootItem(*it); - if (itemList.empty()) { - continue; - } - - for (Item* item : itemList) { - //check containers - if (Container* container = item->getContainer()) { - if (!createLootContainer(container, *it)) { - delete container; - continue; - } - } - - if (g_game.internalAddItem(corpse, item) != RETURNVALUE_NOERROR) { - corpse->internalAddThing(item); - } - } - } - - if (owner) { - std::ostringstream ss; - ss << "Loot of " << nameDescription << ": " << corpse->getContentDescription(); - - if (owner->getParty()) { - owner->getParty()->broadcastPartyLoot(ss.str()); - } else { - owner->sendTextMessage(MESSAGE_LOOT, ss.str()); - } - } - } else { - std::ostringstream ss; - ss << "Loot of " << nameDescription << ": nothing (due to low stamina)"; - - if (owner->getParty()) { - owner->getParty()->broadcastPartyLoot(ss.str()); - } else { - owner->sendTextMessage(MESSAGE_LOOT, ss.str()); - } - } - - corpse->startDecaying(); -} - -std::vector MonsterType::createLootItem(const LootBlock& lootBlock) -{ - int32_t itemCount = 0; - - uint32_t randvalue = Monsters::getLootRandom(); - if (randvalue < lootBlock.chance) { - if (Item::items[lootBlock.id].stackable) { - itemCount = randvalue % lootBlock.countmax + 1; - } else { - itemCount = 1; - } - } - - std::vector itemList; - while (itemCount > 0) { - uint16_t n = static_cast(std::min(itemCount, 100)); - Item* tmpItem = Item::CreateItem(lootBlock.id, n); - if (!tmpItem) { - break; - } - - itemCount -= n; - - if (lootBlock.subType != -1) { - tmpItem->setSubType(lootBlock.subType); - } - - if (lootBlock.actionId != -1) { - tmpItem->setActionId(lootBlock.actionId); - } - - if (!lootBlock.text.empty()) { - tmpItem->setText(lootBlock.text); - } - - if (!lootBlock.name.empty()) { - tmpItem->setStrAttr(ITEM_ATTRIBUTE_NAME, lootBlock.name); - } - - if (!lootBlock.article.empty()) { - tmpItem->setStrAttr(ITEM_ATTRIBUTE_ARTICLE, lootBlock.article); - } - - if (lootBlock.attack != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_ATTACK, lootBlock.attack); - } - - if (lootBlock.defense != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_DEFENSE, lootBlock.defense); - } - - if (lootBlock.extraDefense != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_EXTRADEFENSE, lootBlock.extraDefense); - } - - if (lootBlock.armor != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_ARMOR, lootBlock.armor); - } - - if (lootBlock.shootRange != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_SHOOTRANGE, lootBlock.shootRange); - } - - if (lootBlock.hitChance != -1) { - tmpItem->setIntAttr(ITEM_ATTRIBUTE_HITCHANCE, lootBlock.hitChance); - } - - itemList.push_back(tmpItem); - } - return itemList; -} - -bool MonsterType::createLootContainer(Container* parent, const LootBlock& lootblock) -{ - auto it = lootblock.childLoot.begin(), end = lootblock.childLoot.end(); - if (it == end) { - return true; - } - - for (; it != end && parent->size() < parent->capacity(); ++it) { - auto itemList = createLootItem(*it); - for (Item* tmpItem : itemList) { - if (Container* container = tmpItem->getContainer()) { - if (!createLootContainer(container, *it)) { - delete container; - } else { - parent->internalAddThing(container); - } - } else { - parent->internalAddThing(tmpItem); - } - } - } - return !parent->empty(); -} - -Monsters::Monsters() -{ - loaded = false; -} - -bool Monsters::loadFromXml(bool reloading /*= false*/) -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/monster/monsters.xml"); - if (!result) { - printXMLError("Error - Monsters::loadFromXml", "data/monster/monsters.xml", result); - return false; - } - - loaded = true; - - std::list> monsterScriptList; - for (auto monsterNode : doc.child("monsters").children()) { - loadMonster("data/monster/" + std::string(monsterNode.attribute("file").as_string()), monsterNode.attribute("name").as_string(), monsterScriptList, reloading); - } - - if (!monsterScriptList.empty()) { - if (!scriptInterface) { - scriptInterface.reset(new LuaScriptInterface("Monster Interface")); - scriptInterface->initState(); - } - - for (const auto& scriptEntry : monsterScriptList) { - MonsterType* mType = scriptEntry.first; - if (scriptInterface->loadFile("data/monster/scripts/" + scriptEntry.second) == 0) { - mType->scriptInterface = scriptInterface.get(); - mType->creatureAppearEvent = scriptInterface->getEvent("onCreatureAppear"); - mType->creatureDisappearEvent = scriptInterface->getEvent("onCreatureDisappear"); - mType->creatureMoveEvent = scriptInterface->getEvent("onCreatureMove"); - mType->creatureSayEvent = scriptInterface->getEvent("onCreatureSay"); - mType->thinkEvent = scriptInterface->getEvent("onThink"); - } else { - std::cout << "[Warning - Monsters::loadMonster] Can not load script: " << scriptEntry.second << std::endl; - std::cout << scriptInterface->getLastLuaError() << std::endl; - } - } - } - return true; -} - -bool Monsters::reload() -{ - loaded = false; - - scriptInterface.reset(); - - return loadFromXml(true); -} - -ConditionDamage* Monsters::getDamageCondition(ConditionType_t conditionType, - int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval) -{ - ConditionDamage* condition = static_cast(Condition::createCondition(CONDITIONID_COMBAT, conditionType, 0, 0)); - condition->setParam(CONDITION_PARAM_TICKINTERVAL, tickInterval); - condition->setParam(CONDITION_PARAM_MINVALUE, minDamage); - condition->setParam(CONDITION_PARAM_MAXVALUE, maxDamage); - condition->setParam(CONDITION_PARAM_STARTVALUE, startDamage); - condition->setParam(CONDITION_PARAM_DELAYED, 1); - return condition; -} - -bool Monsters::deserializeSpell(const pugi::xml_node& node, spellBlock_t& sb, const std::string& description) -{ - std::string name; - std::string scriptName; - bool isScripted; - - pugi::xml_attribute attr; - if ((attr = node.attribute("script"))) { - scriptName = attr.as_string(); - isScripted = true; - } else if ((attr = node.attribute("name"))) { - name = attr.as_string(); - isScripted = false; - } else { - return false; - } - - if ((attr = node.attribute("speed")) || (attr = node.attribute("interval"))) { - sb.speed = std::max(1, pugi::cast(attr.value())); - } - - if ((attr = node.attribute("chance"))) { - uint32_t chance = pugi::cast(attr.value()); - if (chance > 100) { - chance = 100; - } - sb.chance = chance; - } - - if ((attr = node.attribute("range"))) { - uint32_t range = pugi::cast(attr.value()); - if (range > (Map::maxViewportX * 2)) { - range = Map::maxViewportX * 2; - } - sb.range = range; - } - - if ((attr = node.attribute("min"))) { - sb.minCombatValue = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("max"))) { - sb.maxCombatValue = pugi::cast(attr.value()); - - //normalize values - if (std::abs(sb.minCombatValue) > std::abs(sb.maxCombatValue)) { - int32_t value = sb.maxCombatValue; - sb.maxCombatValue = sb.minCombatValue; - sb.minCombatValue = value; - } - } - - if (auto spell = g_spells->getSpellByName(name)) { - sb.spell = spell; - return true; - } - - CombatSpell* combatSpell = nullptr; - bool needTarget = false; - bool needDirection = false; - - if (isScripted) { - if ((attr = node.attribute("direction"))) { - needDirection = attr.as_bool(); - } - - if ((attr = node.attribute("target"))) { - needTarget = attr.as_bool(); - } - - std::unique_ptr combatSpellPtr(new CombatSpell(nullptr, needTarget, needDirection)); - if (!combatSpellPtr->loadScript("data/" + g_spells->getScriptBaseName() + "/scripts/" + scriptName)) { - return false; - } - - if (!combatSpellPtr->loadScriptCombat()) { - return false; - } - - combatSpell = combatSpellPtr.release(); - combatSpell->getCombat()->setPlayerCombatValues(COMBAT_FORMULA_DAMAGE, sb.minCombatValue, 0, sb.maxCombatValue, 0); - } else { - Combat* combat = new Combat; - if ((attr = node.attribute("length"))) { - int32_t length = pugi::cast(attr.value()); - if (length > 0) { - int32_t spread = 3; - - //need direction spell - if ((attr = node.attribute("spread"))) { - spread = std::max(0, pugi::cast(attr.value())); - } - - AreaCombat* area = new AreaCombat(); - area->setupArea(length, spread); - combat->setArea(area); - - needDirection = true; - } - } - - if ((attr = node.attribute("radius"))) { - int32_t radius = pugi::cast(attr.value()); - - //target spell - if ((attr = node.attribute("target"))) { - needTarget = attr.as_bool(); - } - - AreaCombat* area = new AreaCombat(); - area->setupArea(radius); - combat->setArea(area); - } - - std::string tmpName = asLowerCaseString(name); - - if (tmpName == "melee") { - sb.isMelee = true; - - pugi::xml_attribute attackAttribute, skillAttribute; - if ((attackAttribute = node.attribute("attack")) && (skillAttribute = node.attribute("skill"))) { - sb.minCombatValue = 0; - sb.maxCombatValue = -Weapons::getMaxMeleeDamage(pugi::cast(skillAttribute.value()), pugi::cast(attackAttribute.value())); - } - - ConditionType_t conditionType = CONDITION_NONE; - int32_t minDamage = 0; - int32_t maxDamage = 0; - uint32_t tickInterval = 2000; - - if ((attr = node.attribute("fire"))) { - conditionType = CONDITION_FIRE; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 9000; - } else if ((attr = node.attribute("poison"))) { - conditionType = CONDITION_POISON; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 5000; - } else if ((attr = node.attribute("energy"))) { - conditionType = CONDITION_ENERGY; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 10000; - } else if ((attr = node.attribute("drown"))) { - conditionType = CONDITION_DROWN; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 5000; - } else if ((attr = node.attribute("freeze"))) { - conditionType = CONDITION_FREEZING; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 8000; - } else if ((attr = node.attribute("dazzle"))) { - conditionType = CONDITION_DAZZLED; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 10000; - } else if ((attr = node.attribute("curse"))) { - conditionType = CONDITION_CURSED; - - minDamage = pugi::cast(attr.value()); - maxDamage = minDamage; - tickInterval = 4000; - } else if ((attr = node.attribute("bleed")) || (attr = node.attribute("physical"))) { - conditionType = CONDITION_BLEEDING; - tickInterval = 5000; - } - - if ((attr = node.attribute("tick"))) { - int32_t value = pugi::cast(attr.value()); - if (value > 0) { - tickInterval = value; - } - } - - if (conditionType != CONDITION_NONE) { - Condition* condition = getDamageCondition(conditionType, maxDamage, minDamage, 0, tickInterval); - combat->setCondition(condition); - } - - sb.range = 1; - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE); - combat->setParam(COMBAT_PARAM_BLOCKARMOR, 1); - combat->setParam(COMBAT_PARAM_BLOCKSHIELD, 1); - combat->setOrigin(ORIGIN_MELEE); - } else if (tmpName == "physical") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE); - combat->setParam(COMBAT_PARAM_BLOCKARMOR, 1); - combat->setOrigin(ORIGIN_RANGED); - } else if (tmpName == "bleed") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE); - } else if (tmpName == "poison" || tmpName == "earth") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE); - } else if (tmpName == "fire") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_FIREDAMAGE); - } else if (tmpName == "energy") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE); - } else if (tmpName == "drown") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_DROWNDAMAGE); - } else if (tmpName == "ice") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE); - } else if (tmpName == "holy") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_HOLYDAMAGE); - } else if (tmpName == "death") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE); - } else if (tmpName == "lifedrain") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_LIFEDRAIN); - } else if (tmpName == "manadrain") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_MANADRAIN); - } else if (tmpName == "healing") { - combat->setParam(COMBAT_PARAM_TYPE, COMBAT_HEALING); - combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); - } else if (tmpName == "speed") { - int32_t speedChange = 0; - int32_t duration = 10000; - - if ((attr = node.attribute("duration"))) { - duration = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("speedchange"))) { - speedChange = pugi::cast(attr.value()); - if (speedChange < -1000) { - //cant be slower than 100% - speedChange = -1000; - } - } - - ConditionType_t conditionType; - if (speedChange > 0) { - conditionType = CONDITION_HASTE; - combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); - } else { - conditionType = CONDITION_PARALYZE; - } - - ConditionSpeed* condition = static_cast(Condition::createCondition(CONDITIONID_COMBAT, conditionType, duration, 0)); - condition->setFormulaVars(speedChange / 1000.0, 0, speedChange / 1000.0, 0); - combat->setCondition(condition); - } else if (tmpName == "outfit") { - int32_t duration = 10000; - - if ((attr = node.attribute("duration"))) { - duration = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("monster"))) { - MonsterType* mType = g_monsters.getMonsterType(attr.as_string()); - if (mType) { - ConditionOutfit* condition = static_cast(Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)); - condition->setOutfit(mType->outfit); - combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); - combat->setCondition(condition); - } - } else if ((attr = node.attribute("item"))) { - Outfit_t outfit; - outfit.lookTypeEx = pugi::cast(attr.value()); - - ConditionOutfit* condition = static_cast(Condition::createCondition(CONDITIONID_COMBAT, CONDITION_OUTFIT, duration, 0)); - condition->setOutfit(outfit); - combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); - combat->setCondition(condition); - } - } else if (tmpName == "invisible") { - int32_t duration = 10000; - - if ((attr = node.attribute("duration"))) { - duration = pugi::cast(attr.value()); - } - - Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_INVISIBLE, duration, 0); - combat->setParam(COMBAT_PARAM_AGGRESSIVE, 0); - combat->setCondition(condition); - } else if (tmpName == "drunk") { - int32_t duration = 10000; - - if ((attr = node.attribute("duration"))) { - duration = pugi::cast(attr.value()); - } - - Condition* condition = Condition::createCondition(CONDITIONID_COMBAT, CONDITION_DRUNK, duration, 0); - combat->setCondition(condition); - } else if (tmpName == "firefield") { - combat->setParam(COMBAT_PARAM_CREATEITEM, ITEM_FIREFIELD_PVP_FULL); - } else if (tmpName == "poisonfield") { - combat->setParam(COMBAT_PARAM_CREATEITEM, ITEM_POISONFIELD_PVP); - } else if (tmpName == "energyfield") { - combat->setParam(COMBAT_PARAM_CREATEITEM, ITEM_ENERGYFIELD_PVP); - } else if (tmpName == "firecondition" || tmpName == "energycondition" || - tmpName == "earthcondition" || tmpName == "poisoncondition" || - tmpName == "icecondition" || tmpName == "freezecondition" || - tmpName == "deathcondition" || tmpName == "cursecondition" || - tmpName == "holycondition" || tmpName == "dazzlecondition" || - tmpName == "drowncondition" || tmpName == "bleedcondition" || - tmpName == "physicalcondition") { - ConditionType_t conditionType = CONDITION_NONE; - uint32_t tickInterval = 2000; - - if (tmpName == "firecondition") { - conditionType = CONDITION_FIRE; - tickInterval = 10000; - } else if (tmpName == "poisoncondition" || tmpName == "earthcondition") { - conditionType = CONDITION_POISON; - tickInterval = 5000; - } else if (tmpName == "energycondition") { - conditionType = CONDITION_ENERGY; - tickInterval = 10000; - } else if (tmpName == "drowncondition") { - conditionType = CONDITION_DROWN; - tickInterval = 5000; - } else if (tmpName == "freezecondition" || tmpName == "icecondition") { - conditionType = CONDITION_FREEZING; - tickInterval = 10000; - } else if (tmpName == "cursecondition" || tmpName == "deathcondition") { - conditionType = CONDITION_CURSED; - tickInterval = 4000; - } else if (tmpName == "dazzlecondition" || tmpName == "holycondition") { - conditionType = CONDITION_DAZZLED; - tickInterval = 10000; - } else if (tmpName == "physicalcondition" || tmpName == "bleedcondition") { - conditionType = CONDITION_BLEEDING; - tickInterval = 5000; - } - - if ((attr = node.attribute("tick"))) { - int32_t value = pugi::cast(attr.value()); - if (value > 0) { - tickInterval = value; - } - } - - int32_t minDamage = std::abs(sb.minCombatValue); - int32_t maxDamage = std::abs(sb.maxCombatValue); - int32_t startDamage = 0; - - if ((attr = node.attribute("start"))) { - int32_t value = std::abs(pugi::cast(attr.value())); - if (value <= minDamage) { - startDamage = value; - } - } - - Condition* condition = getDamageCondition(conditionType, maxDamage, minDamage, startDamage, tickInterval); - combat->setCondition(condition); - } else if (tmpName == "strength") { - // - } else if (tmpName == "effect") { - // - } else { - std::cout << "[Error - Monsters::deserializeSpell] - " << description << " - Unknown spell name: " << name << std::endl; - delete combat; - return false; - } - - combat->setPlayerCombatValues(COMBAT_FORMULA_DAMAGE, sb.minCombatValue, 0, sb.maxCombatValue, 0); - combatSpell = new CombatSpell(combat, needTarget, needDirection); - - for (auto attributeNode : node.children()) { - if ((attr = attributeNode.attribute("key"))) { - const char* value = attr.value(); - if (strcasecmp(value, "shooteffect") == 0) { - if ((attr = attributeNode.attribute("value"))) { - ShootType_t shoot = getShootType(attr.as_string()); - if (shoot != CONST_ANI_NONE) { - combat->setParam(COMBAT_PARAM_DISTANCEEFFECT, shoot); - } else { - std::cout << "[Warning - Monsters::deserializeSpell] " << description << " - Unknown shootEffect: " << attr.as_string() << std::endl; - } - } - } else if (strcasecmp(value, "areaeffect") == 0) { - if ((attr = attributeNode.attribute("value"))) { - MagicEffectClasses effect = getMagicEffect(attr.as_string()); - if (effect != CONST_ME_NONE) { - combat->setParam(COMBAT_PARAM_EFFECT, effect); - } else { - std::cout << "[Warning - Monsters::deserializeSpell] " << description << " - Unknown areaEffect: " << attr.as_string() << std::endl; - } - } - } else { - std::cout << "[Warning - Monsters::deserializeSpells] Effect type \"" << attr.as_string() << "\" does not exist." << std::endl; - } - } - } - } - - sb.spell = combatSpell; - if (combatSpell) { - sb.combatSpell = true; - } - return true; -} - -bool Monsters::loadMonster(const std::string& file, const std::string& monsterName, std::list>& monsterScriptList, bool reloading /*= false*/) -{ - MonsterType* mType = nullptr; - bool new_mType = true; - - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(file.c_str()); - if (!result) { - printXMLError("Error - Monsters::loadMonster", file, result); - return false; - } - - pugi::xml_node monsterNode = doc.child("monster"); - if (!monsterNode) { - std::cout << "[Error - Monsters::loadMonster] Missing monster node in: " << file << std::endl; - return false; - } - - pugi::xml_attribute attr; - if (!(attr = monsterNode.attribute("name"))) { - std::cout << "[Error - Monsters::loadMonster] Missing name in: " << file << std::endl; - return false; - } - - if (reloading) { - mType = getMonsterType(monsterName); - if (mType != nullptr) { - new_mType = false; - mType->reset(); - } - } - - if (new_mType) { - mType = &monsters[asLowerCaseString(monsterName)]; - } - - mType->name = attr.as_string(); - - if ((attr = monsterNode.attribute("nameDescription"))) { - mType->nameDescription = attr.as_string(); - } else { - mType->nameDescription = "a " + mType->name; - toLowerCaseString(mType->nameDescription); - } - - if ((attr = monsterNode.attribute("race"))) { - std::string tmpStrValue = asLowerCaseString(attr.as_string()); - uint16_t tmpInt = pugi::cast(attr.value()); - if (tmpStrValue == "venom" || tmpInt == 1) { - mType->race = RACE_VENOM; - } else if (tmpStrValue == "blood" || tmpInt == 2) { - mType->race = RACE_BLOOD; - } else if (tmpStrValue == "undead" || tmpInt == 3) { - mType->race = RACE_UNDEAD; - } else if (tmpStrValue == "fire" || tmpInt == 4) { - mType->race = RACE_FIRE; - } else if (tmpStrValue == "energy" || tmpInt == 5) { - mType->race = RACE_ENERGY; - } else { - std::cout << "[Warning - Monsters::loadMonster] Unknown race type " << attr.as_string() << ". " << file << std::endl; - } - } - - if ((attr = monsterNode.attribute("experience"))) { - mType->experience = pugi::cast(attr.value()); - } - - if ((attr = monsterNode.attribute("speed"))) { - mType->baseSpeed = pugi::cast(attr.value()); - } - - if ((attr = monsterNode.attribute("manacost"))) { - mType->manaCost = pugi::cast(attr.value()); - } - - if ((attr = monsterNode.attribute("skull"))) { - mType->skull = getSkullType(attr.as_string()); - } - - if ((attr = monsterNode.attribute("script"))) { - monsterScriptList.emplace_back(mType, attr.as_string()); - } - - pugi::xml_node node; - if ((node = monsterNode.child("health"))) { - if ((attr = node.attribute("now"))) { - mType->health = pugi::cast(attr.value()); - } else { - std::cout << "[Error - Monsters::loadMonster] Missing health now. " << file << std::endl; - } - - if ((attr = node.attribute("max"))) { - mType->healthMax = pugi::cast(attr.value()); - } else { - std::cout << "[Error - Monsters::loadMonster] Missing health max. " << file << std::endl; - } - } - - if ((node = monsterNode.child("flags"))) { - for (auto flagNode : node.children()) { - attr = flagNode.first_attribute(); - const char* attrName = attr.name(); - if (strcasecmp(attrName, "summonable") == 0) { - mType->isSummonable = attr.as_bool(); - } else if (strcasecmp(attrName, "attackable") == 0) { - mType->isAttackable = attr.as_bool(); - } else if (strcasecmp(attrName, "hostile") == 0) { - mType->isHostile = attr.as_bool(); - } else if (strcasecmp(attrName, "passive") == 0) { - mType->isPassive = attr.as_bool(); - } else if (strcasecmp(attrName, "illusionable") == 0) { - mType->isIllusionable = attr.as_bool(); - } else if (strcasecmp(attrName, "convinceable") == 0) { - mType->isConvinceable = attr.as_bool(); - } else if (strcasecmp(attrName, "pushable") == 0) { - mType->pushable = attr.as_bool(); - } else if (strcasecmp(attrName, "canpushitems") == 0) { - mType->canPushItems = attr.as_bool(); - } else if (strcasecmp(attrName, "canpushcreatures") == 0) { - mType->canPushCreatures = attr.as_bool(); - } else if (strcasecmp(attrName, "staticattack") == 0) { - uint32_t staticAttack = pugi::cast(attr.value()); - if (staticAttack > 100) { - std::cout << "[Warning - Monsters::loadMonster] staticattack greater than 100. " << file << std::endl; - staticAttack = 100; - } - - mType->staticAttackChance = staticAttack; - } else if (strcasecmp(attrName, "lightlevel") == 0) { - mType->lightLevel = pugi::cast(attr.value()); - } else if (strcasecmp(attrName, "lightcolor") == 0) { - mType->lightColor = pugi::cast(attr.value()); - } else if (strcasecmp(attrName, "targetdistance") == 0) { - mType->targetDistance = std::max(1, pugi::cast(attr.value())); - } else if (strcasecmp(attrName, "runonhealth") == 0) { - mType->runAwayHealth = pugi::cast(attr.value()); - } else if (strcasecmp(attrName, "hidehealth") == 0) { - mType->hiddenHealth = attr.as_bool(); - } else { - std::cout << "[Warning - Monsters::loadMonster] Unknown flag attribute: " << attrName << ". " << file << std::endl; - } - } - - //if a monster can push creatures, - // it should not be pushable - if (mType->canPushCreatures && mType->pushable) { - mType->pushable = false; - } - } - - if ((node = monsterNode.child("targetchange"))) { - if ((attr = node.attribute("speed")) || (attr = node.attribute("interval"))) { - mType->changeTargetSpeed = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing targetchange speed. " << file << std::endl; - } - - if ((attr = node.attribute("chance"))) { - mType->changeTargetChance = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing targetchange chance. " << file << std::endl; - } - } - - if ((node = monsterNode.child("look"))) { - if ((attr = node.attribute("type"))) { - mType->outfit.lookType = pugi::cast(attr.value()); - - if ((attr = node.attribute("head"))) { - mType->outfit.lookHead = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("body"))) { - mType->outfit.lookBody = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("legs"))) { - mType->outfit.lookLegs = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("feet"))) { - mType->outfit.lookFeet = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("addons"))) { - mType->outfit.lookAddons = pugi::cast(attr.value()); - } - } else if ((attr = node.attribute("typeex"))) { - mType->outfit.lookTypeEx = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing look type/typeex. " << file << std::endl; - } - - if ((attr = node.attribute("mount"))) { - mType->outfit.lookMount = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("corpse"))) { - mType->lookcorpse = pugi::cast(attr.value()); - } - } - - if ((node = monsterNode.child("attacks"))) { - for (auto attackNode : node.children()) { - spellBlock_t sb; - if (deserializeSpell(attackNode, sb, monsterName)) { - mType->attackSpells.emplace_back(std::move(sb)); - } else { - std::cout << "[Warning - Monsters::loadMonster] Cant load spell. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("defenses"))) { - if ((attr = node.attribute("defense"))) { - mType->defense = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("armor"))) { - mType->armor = pugi::cast(attr.value()); - } - - for (auto defenseNode : node.children()) { - spellBlock_t sb; - if (deserializeSpell(defenseNode, sb, monsterName)) { - mType->defenseSpells.emplace_back(std::move(sb)); - } else { - std::cout << "[Warning - Monsters::loadMonster] Cant load spell. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("immunities"))) { - for (auto immunityNode : node.children()) { - if ((attr = immunityNode.attribute("name"))) { - std::string tmpStrValue = asLowerCaseString(attr.as_string()); - if (tmpStrValue == "physical") { - mType->damageImmunities |= COMBAT_PHYSICALDAMAGE; - mType->conditionImmunities |= CONDITION_BLEEDING; - } else if (tmpStrValue == "energy") { - mType->damageImmunities |= COMBAT_ENERGYDAMAGE; - mType->conditionImmunities |= CONDITION_ENERGY; - } else if (tmpStrValue == "fire") { - mType->damageImmunities |= COMBAT_FIREDAMAGE; - mType->conditionImmunities |= CONDITION_FIRE; - } else if (tmpStrValue == "poison" || - tmpStrValue == "earth") { - mType->damageImmunities |= COMBAT_EARTHDAMAGE; - mType->conditionImmunities |= CONDITION_POISON; - } else if (tmpStrValue == "drown") { - mType->damageImmunities |= COMBAT_DROWNDAMAGE; - mType->conditionImmunities |= CONDITION_DROWN; - } else if (tmpStrValue == "ice") { - mType->damageImmunities |= COMBAT_ICEDAMAGE; - mType->conditionImmunities |= CONDITION_FREEZING; - } else if (tmpStrValue == "holy") { - mType->damageImmunities |= COMBAT_HOLYDAMAGE; - mType->conditionImmunities |= CONDITION_DAZZLED; - } else if (tmpStrValue == "death") { - mType->damageImmunities |= COMBAT_DEATHDAMAGE; - mType->conditionImmunities |= CONDITION_CURSED; - } else if (tmpStrValue == "lifedrain") { - mType->damageImmunities |= COMBAT_LIFEDRAIN; - } else if (tmpStrValue == "manadrain") { - mType->damageImmunities |= COMBAT_MANADRAIN; - } else if (tmpStrValue == "paralyze") { - mType->conditionImmunities |= CONDITION_PARALYZE; - } else if (tmpStrValue == "outfit") { - mType->conditionImmunities |= CONDITION_OUTFIT; - } else if (tmpStrValue == "drunk") { - mType->conditionImmunities |= CONDITION_DRUNK; - } else if (tmpStrValue == "invisible" || tmpStrValue == "invisibility") { - mType->conditionImmunities |= CONDITION_INVISIBLE; - } else if (tmpStrValue == "bleed") { - mType->conditionImmunities |= CONDITION_BLEEDING; - } else { - std::cout << "[Warning - Monsters::loadMonster] Unknown immunity name " << attr.as_string() << ". " << file << std::endl; - } - } else if ((attr = immunityNode.attribute("physical"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_PHYSICALDAMAGE; - mType->conditionImmunities |= CONDITION_BLEEDING; - } - } else if ((attr = immunityNode.attribute("energy"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_ENERGYDAMAGE; - mType->conditionImmunities |= CONDITION_ENERGY; - } - } else if ((attr = immunityNode.attribute("fire"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_FIREDAMAGE; - mType->conditionImmunities |= CONDITION_FIRE; - } - } else if ((attr = immunityNode.attribute("poison")) || (attr = immunityNode.attribute("earth"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_EARTHDAMAGE; - mType->conditionImmunities |= CONDITION_POISON; - } - } else if ((attr = immunityNode.attribute("drown"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_DROWNDAMAGE; - mType->conditionImmunities |= CONDITION_DROWN; - } - } else if ((attr = immunityNode.attribute("ice"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_ICEDAMAGE; - mType->conditionImmunities |= CONDITION_FREEZING; - } - } else if ((attr = immunityNode.attribute("holy"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_HOLYDAMAGE; - mType->conditionImmunities |= CONDITION_DAZZLED; - } - } else if ((attr = immunityNode.attribute("death"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_DEATHDAMAGE; - mType->conditionImmunities |= CONDITION_CURSED; - } - } else if ((attr = immunityNode.attribute("lifedrain"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_LIFEDRAIN; - } - } else if ((attr = immunityNode.attribute("manadrain"))) { - if (attr.as_bool()) { - mType->damageImmunities |= COMBAT_MANADRAIN; - } - } else if ((attr = immunityNode.attribute("paralyze"))) { - if (attr.as_bool()) { - mType->conditionImmunities |= CONDITION_PARALYZE; - } - } else if ((attr = immunityNode.attribute("outfit"))) { - if (attr.as_bool()) { - mType->conditionImmunities |= CONDITION_OUTFIT; - } - } else if ((attr = immunityNode.attribute("bleed"))) { - if (attr.as_bool()) { - mType->conditionImmunities |= CONDITION_BLEEDING; - } - } else if ((attr = immunityNode.attribute("drunk"))) { - if (attr.as_bool()) { - mType->conditionImmunities |= CONDITION_DRUNK; - } - } else if ((attr = immunityNode.attribute("invisible")) || (attr = immunityNode.attribute("invisibility"))) { - if (attr.as_bool()) { - mType->conditionImmunities |= CONDITION_INVISIBLE; - } - } else { - std::cout << "[Warning - Monsters::loadMonster] Unknown immunity. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("voices"))) { - if ((attr = node.attribute("speed")) || (attr = node.attribute("interval"))) { - mType->yellSpeedTicks = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing voices speed. " << file << std::endl; - } - - if ((attr = node.attribute("chance"))) { - mType->yellChance = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing voices chance. " << file << std::endl; - } - - for (auto voiceNode : node.children()) { - voiceBlock_t vb; - if ((attr = voiceNode.attribute("sentence"))) { - vb.text = attr.as_string(); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing voice sentence. " << file << std::endl; - } - - if ((attr = voiceNode.attribute("yell"))) { - vb.yellText = attr.as_bool(); - } else { - vb.yellText = false; - } - mType->voiceVector.emplace_back(vb); - } - } - - if ((node = monsterNode.child("loot"))) { - for (auto lootNode : node.children()) { - LootBlock lootBlock; - if (loadLootItem(lootNode, lootBlock)) { - mType->lootItems.emplace_back(std::move(lootBlock)); - } else { - std::cout << "[Warning - Monsters::loadMonster] Cant load loot. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("elements"))) { - for (auto elementNode : node.children()) { - if ((attr = elementNode.attribute("physicalPercent"))) { - mType->elementMap[COMBAT_PHYSICALDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("icePercent"))) { - mType->elementMap[COMBAT_ICEDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("poisonPercent")) || (attr = elementNode.attribute("earthPercent"))) { - mType->elementMap[COMBAT_EARTHDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("firePercent"))) { - mType->elementMap[COMBAT_FIREDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("energyPercent"))) { - mType->elementMap[COMBAT_ENERGYDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("holyPercent"))) { - mType->elementMap[COMBAT_HOLYDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("deathPercent"))) { - mType->elementMap[COMBAT_DEATHDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("drownPercent"))) { - mType->elementMap[COMBAT_DROWNDAMAGE] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("lifedrainPercent"))) { - mType->elementMap[COMBAT_LIFEDRAIN] = pugi::cast(attr.value()); - } else if ((attr = elementNode.attribute("manadrainPercent"))) { - mType->elementMap[COMBAT_MANADRAIN] = pugi::cast(attr.value()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Unknown element percent. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("summons"))) { - if ((attr = node.attribute("maxSummons"))) { - mType->maxSummons = std::min(pugi::cast(attr.value()), 100); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing summons maxSummons. " << file << std::endl; - } - - for (auto summonNode : node.children()) { - int32_t chance = 100; - int32_t speed = 1000; - - if ((attr = summonNode.attribute("speed")) || (attr = summonNode.attribute("interval"))) { - speed = pugi::cast(attr.value()); - } - - if ((attr = summonNode.attribute("chance"))) { - chance = pugi::cast(attr.value()); - } - - if ((attr = summonNode.attribute("name"))) { - summonBlock_t sb; - sb.name = attr.as_string(); - sb.speed = speed; - sb.chance = chance; - mType->summons.emplace_back(sb); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing summon name. " << file << std::endl; - } - } - } - - if ((node = monsterNode.child("script"))) { - for (auto eventNode : node.children()) { - if ((attr = eventNode.attribute("name"))) { - mType->scripts.emplace_back(attr.as_string()); - } else { - std::cout << "[Warning - Monsters::loadMonster] Missing name for script event. " << file << std::endl; - } - } - } - - mType->summons.shrink_to_fit(); - mType->lootItems.shrink_to_fit(); - mType->attackSpells.shrink_to_fit(); - mType->defenseSpells.shrink_to_fit(); - mType->voiceVector.shrink_to_fit(); - mType->scripts.shrink_to_fit(); - return true; -} - -bool Monsters::loadLootItem(const pugi::xml_node& node, LootBlock& lootBlock) -{ - pugi::xml_attribute attr; - if ((attr = node.attribute("id"))) { - lootBlock.id = pugi::cast(attr.value()); - } - - if (lootBlock.id == 0) { - return false; - } - - if ((attr = node.attribute("countmax"))) { - lootBlock.countmax = std::max(1, pugi::cast(attr.value())); - } else { - lootBlock.countmax = 1; - } - - if ((attr = node.attribute("chance")) || (attr = node.attribute("chance1"))) { - lootBlock.chance = std::min(MAX_LOOTCHANCE, pugi::cast(attr.value())); - } else { - lootBlock.chance = MAX_LOOTCHANCE; - } - - if (Item::items[lootBlock.id].isContainer()) { - loadLootContainer(node, lootBlock); - } - - //optional - if ((attr = node.attribute("subtype"))) { - lootBlock.subType = pugi::cast(attr.value()); - } else { - uint32_t charges = Item::items[lootBlock.id].charges; - if (charges != 0) { - lootBlock.subType = charges; - } - } - - if ((attr = node.attribute("actionId"))) { - lootBlock.actionId = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("text"))) { - lootBlock.text = attr.as_string(); - } - - if ((attr = node.attribute("name"))) { - lootBlock.name = attr.as_string(); - } - - if ((attr = node.attribute("article"))) { - lootBlock.article = attr.as_string(); - } - - if ((attr = node.attribute("attack"))) { - lootBlock.attack = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("defense"))) { - lootBlock.defense = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("extradefense"))) { - lootBlock.extraDefense = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("armor"))) { - lootBlock.armor = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("shootrange"))) { - lootBlock.shootRange = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("hitchance"))) { - lootBlock.hitChance = pugi::cast(attr.value()); - } - return true; -} - -void Monsters::loadLootContainer(const pugi::xml_node& node, LootBlock& lBlock) -{ - for (auto subNode : node.children()) { - LootBlock lootBlock; - if (loadLootItem(subNode, lootBlock)) { - lBlock.childLoot.emplace_back(std::move(lootBlock)); - } - } -} - -MonsterType* Monsters::getMonsterType(const std::string& name) -{ - auto it = monsters.find(asLowerCaseString(name)); - - if (it == monsters.end()) { - return nullptr; - } - return &it->second; -} diff --git a/path_10_8/src/monsters.h b/path_10_8/src/monsters.h deleted file mode 100644 index 01e81a40b..000000000 --- a/path_10_8/src/monsters.h +++ /dev/null @@ -1,217 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D -#define FS_MONSTERS_H_776E8327BCE2450EB7C4A260785E6C0D - -#include "creature.h" - - -const uint32_t MAX_LOOTCHANCE = 100000; -const uint32_t MAX_STATICWALK = 100; - -struct LootBlock { - uint16_t id; - uint32_t countmax; - uint32_t chance; - - //optional - int32_t subType; - int32_t actionId; - std::string text; - std::string name; - std::string article; - int32_t attack; - int32_t defense; - int32_t extraDefense; - int32_t armor; - int32_t shootRange; - int32_t hitChance; - - std::vector childLoot; - LootBlock() { - id = 0; - countmax = 0; - chance = 0; - - subType = -1; - actionId = -1; - attack = -1; - defense = -1; - extraDefense = -1; - armor = -1; - shootRange = -1; - hitChance = -1; - } -}; - -struct summonBlock_t { - std::string name; - uint32_t chance; - uint32_t speed; -}; - -class BaseSpell; -struct spellBlock_t { - spellBlock_t() = default; - ~spellBlock_t(); - spellBlock_t(const spellBlock_t& other) = delete; - spellBlock_t& operator=(const spellBlock_t& other) = delete; - spellBlock_t(spellBlock_t&& other): - spell(other.spell), - chance(other.chance), - speed(other.speed), - range(other.range), - minCombatValue(other.minCombatValue), - maxCombatValue(other.maxCombatValue), - combatSpell(other.combatSpell), - isMelee(other.isMelee) { - other.spell = nullptr; - } - - BaseSpell* spell = nullptr; - uint32_t chance = 100; - uint32_t speed = 2000; - uint32_t range = 0; - int32_t minCombatValue = 0; - int32_t maxCombatValue = 0; - bool combatSpell = false; - bool isMelee = false; -}; - -struct voiceBlock_t { - std::string text; - bool yellText; -}; - -class MonsterType -{ - public: - MonsterType(); - ~MonsterType() = default; - - // non-copyable - MonsterType(const MonsterType&) = delete; - MonsterType& operator=(const MonsterType&) = delete; - - void reset(); - - std::map elementMap; - - std::vector voiceVector; - - std::vector lootItems; - std::vector scripts; - std::vector attackSpells; - std::vector defenseSpells; - std::vector summons; - - std::string name; - std::string nameDescription; - - LuaScriptInterface* scriptInterface; - - uint64_t experience; - - Outfit_t outfit; - - uint32_t manaCost; - uint32_t yellChance; - uint32_t yellSpeedTicks; - uint32_t staticAttackChance; - uint32_t maxSummons; - uint32_t changeTargetSpeed; - uint32_t conditionImmunities; - uint32_t damageImmunities; - uint32_t baseSpeed; - - int32_t creatureAppearEvent; - int32_t creatureDisappearEvent; - int32_t creatureMoveEvent; - int32_t creatureSayEvent; - int32_t thinkEvent; - int32_t targetDistance; - int32_t runAwayHealth; - int32_t health; - int32_t healthMax; - int32_t changeTargetChance; - int32_t defense; - int32_t armor; - - RaceType_t race; - - uint16_t lookcorpse; - - Skulls_t skull; - uint8_t lightLevel; - uint8_t lightColor; - - bool canPushItems; - bool canPushCreatures; - bool pushable; - bool isSummonable; - bool isIllusionable; - bool isConvinceable; - bool isAttackable; - bool isHostile; - bool isPassive; - bool hiddenHealth; - - void createLoot(Container* corpse); - bool createLootContainer(Container* parent, const LootBlock& lootblock); - std::vector createLootItem(const LootBlock& lootBlock); -}; - -class Monsters -{ - public: - Monsters(); - ~Monsters() = default; - // non-copyable - Monsters(const Monsters&) = delete; - Monsters& operator=(const Monsters&) = delete; - - bool loadFromXml(bool reloading = false); - bool isLoaded() const { - return loaded; - } - bool reload(); - - MonsterType* getMonsterType(const std::string& name); - uint32_t getIdByName(const std::string& name); - - static uint32_t getLootRandom(); - - private: - ConditionDamage* getDamageCondition(ConditionType_t conditionType, - int32_t maxDamage, int32_t minDamage, int32_t startDamage, uint32_t tickInterval); - bool deserializeSpell(const pugi::xml_node& node, spellBlock_t& sb, const std::string& description = ""); - - bool loadMonster(const std::string& file, const std::string& monsterName, std::list>& monsterScriptList, bool reloading = false); - - void loadLootContainer(const pugi::xml_node& node, LootBlock&); - bool loadLootItem(const pugi::xml_node& node, LootBlock&); - - std::map monsters; - std::unique_ptr scriptInterface; - - bool loaded; -}; - -#endif diff --git a/path_10_8/src/mounts.cpp b/path_10_8/src/mounts.cpp deleted file mode 100644 index 15c89abff..000000000 --- a/path_10_8/src/mounts.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "mounts.h" - -#include "pugicast.h" -#include "tools.h" - -bool Mounts::reload() -{ - mounts.clear(); - return loadFromXml(); -} - -bool Mounts::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/mounts.xml"); - if (!result) { - printXMLError("Error - Mounts::loadFromXml", "data/XML/mounts.xml", result); - return false; - } - - for (auto mountNode : doc.child("mounts").children()) { - mounts.emplace_back( - static_cast(pugi::cast(mountNode.attribute("id").value())), - pugi::cast(mountNode.attribute("clientid").value()), - mountNode.attribute("name").as_string(), - pugi::cast(mountNode.attribute("speed").value()), - mountNode.attribute("premium").as_bool() - ); - } - mounts.shrink_to_fit(); - return true; -} - -Mount* Mounts::getMountByID(uint8_t id) -{ - auto it = std::find_if(mounts.begin(), mounts.end(), [id](const Mount& mount) { - return mount.id == id; - }); - - return it != mounts.end() ? &*it : nullptr; -} - -Mount* Mounts::getMountByClientID(uint16_t clientId) -{ - auto it = std::find_if(mounts.begin(), mounts.end(), [clientId](const Mount& mount) { - return mount.clientId == clientId; - }); - - return it != mounts.end() ? &*it : nullptr; -} diff --git a/path_10_8/src/mounts.h b/path_10_8/src/mounts.h deleted file mode 100644 index 77c9b2642..000000000 --- a/path_10_8/src/mounts.h +++ /dev/null @@ -1,51 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MOUNTS_H_73716D11906A4C5C9F4A7B68D34C9BA6 -#define FS_MOUNTS_H_73716D11906A4C5C9F4A7B68D34C9BA6 - -struct Mount -{ - Mount(uint8_t id, uint16_t clientId, std::string name, int32_t speed, bool premium) - : name(name), speed(speed), clientId(clientId), id(id), premium(premium) {} - - std::string name; - int32_t speed; - uint16_t clientId; - uint8_t id; - bool premium; -}; - -class Mounts -{ - public: - bool reload(); - bool loadFromXml(); - Mount* getMountByID(uint8_t id); - Mount* getMountByClientID(uint16_t clientId); - - const std::vector& getMounts() const { - return mounts; - } - - private: - std::vector mounts; -}; - -#endif diff --git a/path_10_8/src/movement.cpp b/path_10_8/src/movement.cpp deleted file mode 100644 index 45414c017..000000000 --- a/path_10_8/src/movement.cpp +++ /dev/null @@ -1,908 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "game.h" - -#include "pugicast.h" - -#include "movement.h" - -extern Game g_game; -extern Vocations g_vocations; - -MoveEvents::MoveEvents() : - m_scriptInterface("MoveEvents Interface") -{ - m_scriptInterface.initState(); -} - -MoveEvents::~MoveEvents() -{ - clear(); -} - -void MoveEvents::clearMap(MoveListMap& map) -{ - std::unordered_set set; - for (const auto& it : map) { - const MoveEventList& moveEventList = it.second; - for (int32_t i = 0; i < MOVE_EVENT_LAST; ++i) { - for (MoveEvent* moveEvent : moveEventList.moveEvent[i]) { - set.insert(moveEvent); - } - } - } - map.clear(); - - for (MoveEvent* moveEvent : set) { - delete moveEvent; - } -} - -void MoveEvents::clear() -{ - clearMap(m_itemIdMap); - clearMap(m_actionIdMap); - clearMap(m_uniqueIdMap); - - for (const auto& it : m_positionMap) { - const MoveEventList& moveEventList = it.second; - for (int32_t i = 0; i < MOVE_EVENT_LAST; ++i) { - for (MoveEvent* moveEvent : moveEventList.moveEvent[i]) { - delete moveEvent; - } - } - } - m_positionMap.clear(); - - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& MoveEvents::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string MoveEvents::getScriptBaseName() const -{ - return "movements"; -} - -Event* MoveEvents::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "movevent") != 0) { - return nullptr; - } - return new MoveEvent(&m_scriptInterface); -} - -bool MoveEvents::registerEvent(Event* event, const pugi::xml_node& node) -{ - MoveEvent* moveEvent = static_cast(event); //event is guaranteed to be a MoveEvent - - const MoveEvent_t eventType = moveEvent->getEventType(); - if (eventType == MOVE_EVENT_ADD_ITEM || eventType == MOVE_EVENT_REMOVE_ITEM) { - pugi::xml_attribute tileItemAttribute = node.attribute("tileitem"); - if (tileItemAttribute && pugi::cast(tileItemAttribute.value()) == 1) { - switch (eventType) { - case MOVE_EVENT_ADD_ITEM: - moveEvent->setEventType(MOVE_EVENT_ADD_ITEM_ITEMTILE); - break; - case MOVE_EVENT_REMOVE_ITEM: - moveEvent->setEventType(MOVE_EVENT_REMOVE_ITEM_ITEMTILE); - break; - default: - break; - } - } - } - - pugi::xml_attribute attr; - if ((attr = node.attribute("itemid"))) { - int32_t id = pugi::cast(attr.value()); - addEvent(moveEvent, id, m_itemIdMap); - if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { - ItemType& it = Item::items.getItemType(id); - it.wieldInfo = moveEvent->getWieldInfo(); - it.minReqLevel = moveEvent->getReqLevel(); - it.minReqMagicLevel = moveEvent->getReqMagLv(); - it.vocationString = moveEvent->getVocationString(); - } - } else if ((attr = node.attribute("fromid"))) { - uint32_t id = pugi::cast(attr.value()); - uint32_t endId = pugi::cast(node.attribute("toid").value()); - - addEvent(moveEvent, id, m_itemIdMap); - - if (moveEvent->getEventType() == MOVE_EVENT_EQUIP) { - ItemType& it = Item::items.getItemType(id); - it.wieldInfo = moveEvent->getWieldInfo(); - it.minReqLevel = moveEvent->getReqLevel(); - it.minReqMagicLevel = moveEvent->getReqMagLv(); - it.vocationString = moveEvent->getVocationString(); - - while (++id <= endId) { - addEvent(moveEvent, id, m_itemIdMap); - - ItemType& tit = Item::items.getItemType(id); - tit.wieldInfo = moveEvent->getWieldInfo(); - tit.minReqLevel = moveEvent->getReqLevel(); - tit.minReqMagicLevel = moveEvent->getReqMagLv(); - tit.vocationString = moveEvent->getVocationString(); - } - } else { - while (++id <= endId) { - addEvent(moveEvent, id, m_itemIdMap); - } - } - } else if ((attr = node.attribute("uniqueid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), m_uniqueIdMap); - } else if ((attr = node.attribute("fromuid"))) { - uint32_t id = pugi::cast(attr.value()); - uint32_t endId = pugi::cast(node.attribute("touid").value()); - addEvent(moveEvent, id, m_uniqueIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, m_uniqueIdMap); - } - } else if ((attr = node.attribute("actionid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), m_actionIdMap); - } else if ((attr = node.attribute("fromaid"))) { - uint32_t id = pugi::cast(attr.value()); - uint32_t endId = pugi::cast(node.attribute("toaid").value()); - addEvent(moveEvent, id, m_actionIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, m_actionIdMap); - } - } else if ((attr = node.attribute("pos"))) { - std::vector posList = vectorAtoi(explodeString(attr.as_string(), ";")); - if (posList.size() < 3) { - return false; - } - - Position pos(posList[0], posList[1], posList[2]); - addEvent(moveEvent, pos, m_positionMap); - } else { - return false; - } - return true; -} - -void MoveEvents::addEvent(MoveEvent* moveEvent, int32_t id, MoveListMap& map) -{ - auto it = map.find(id); - if (it == map.end()) { - MoveEventList moveEventList; - moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); - map[id] = moveEventList; - } else { - std::list& moveEventList = it->second.moveEvent[moveEvent->getEventType()]; - for (MoveEvent* existingMoveEvent : moveEventList) { - if (existingMoveEvent->getSlot() == moveEvent->getSlot()) { - std::cout << "[Warning - MoveEvents::addEvent] Duplicate move event found: " << id << std::endl; - } - } - moveEventList.push_back(moveEvent); - } -} - -MoveEvent* MoveEvents::getEvent(Item* item, MoveEvent_t eventType, slots_t slot) -{ - uint32_t slotp; - switch (slot) { - case CONST_SLOT_HEAD: slotp = SLOTP_HEAD; break; - case CONST_SLOT_NECKLACE: slotp = SLOTP_NECKLACE; break; - case CONST_SLOT_BACKPACK: slotp = SLOTP_BACKPACK; break; - case CONST_SLOT_ARMOR: slotp = SLOTP_ARMOR; break; - case CONST_SLOT_RIGHT: slotp = SLOTP_RIGHT; break; - case CONST_SLOT_LEFT: slotp = SLOTP_LEFT; break; - case CONST_SLOT_LEGS: slotp = SLOTP_LEGS; break; - case CONST_SLOT_FEET: slotp = SLOTP_FEET; break; - case CONST_SLOT_AMMO: slotp = SLOTP_AMMO; break; - case CONST_SLOT_RING: slotp = SLOTP_RING; break; - default: slotp = 0; break; - } - - auto it = m_itemIdMap.find(item->getID()); - if (it != m_itemIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - for (MoveEvent* moveEvent : moveEventList) { - if ((moveEvent->getSlot() & slotp) != 0) { - return moveEvent; - } - } - } - return nullptr; -} - -MoveEvent* MoveEvents::getEvent(Item* item, MoveEvent_t eventType) -{ - MoveListMap::iterator it; - - if (item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID)) { - it = m_uniqueIdMap.find(item->getUniqueId()); - if (it != m_uniqueIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - if (item->hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) { - it = m_actionIdMap.find(item->getActionId()); - if (it != m_actionIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - it = m_itemIdMap.find(item->getID()); - if (it != m_itemIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - return nullptr; -} - -void MoveEvents::addEvent(MoveEvent* moveEvent, const Position& pos, MovePosListMap& map) -{ - auto it = map.find(pos); - if (it == map.end()) { - MoveEventList moveEventList; - moveEventList.moveEvent[moveEvent->getEventType()].push_back(moveEvent); - map[pos] = moveEventList; - } else { - std::list& moveEventList = it->second.moveEvent[moveEvent->getEventType()]; - if (!moveEventList.empty()) { - std::cout << "[Warning - MoveEvents::addEvent] Duplicate move event found: " << pos << std::endl; - } - - moveEventList.push_back(moveEvent); - } -} - -MoveEvent* MoveEvents::getEvent(const Tile* tile, MoveEvent_t eventType) -{ - MovePosListMap::iterator it = m_positionMap.find(tile->getPosition()); - if (it != m_positionMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - return nullptr; -} - -uint32_t MoveEvents::onCreatureMove(Creature* creature, const Tile* tile, const Position& fromPos, MoveEvent_t eventType) -{ - const Position& pos = tile->getPosition(); - - uint32_t ret = 1; - - MoveEvent* moveEvent = getEvent(tile, eventType); - if (moveEvent) { - ret &= moveEvent->fireStepEvent(creature, nullptr, pos, fromPos); - } - - for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) { - Thing* thing = tile->getThing(i); - if (!thing) { - continue; - } - - Item* tileItem = thing->getItem(); - if (!tileItem) { - continue; - } - - moveEvent = getEvent(tileItem, eventType); - if (moveEvent) { - ret &= moveEvent->fireStepEvent(creature, tileItem, pos, fromPos); - } - } - return ret; -} - -uint32_t MoveEvents::onPlayerEquip(Player* player, Item* item, slots_t slot, bool isCheck) -{ - MoveEvent* moveEvent = getEvent(item, MOVE_EVENT_EQUIP, slot); - if (!moveEvent) { - return 1; - } - return moveEvent->fireEquip(player, item, slot, isCheck); -} - -uint32_t MoveEvents::onPlayerDeEquip(Player* player, Item* item, slots_t slot) -{ - MoveEvent* moveEvent = getEvent(item, MOVE_EVENT_DEEQUIP, slot); - if (!moveEvent) { - return 1; - } - return moveEvent->fireEquip(player, item, slot, true); -} - -uint32_t MoveEvents::onItemMove(Item* item, Tile* tile, bool isAdd) -{ - MoveEvent_t eventType1, eventType2; - if (isAdd) { - eventType1 = MOVE_EVENT_ADD_ITEM; - eventType2 = MOVE_EVENT_ADD_ITEM_ITEMTILE; - } else { - eventType1 = MOVE_EVENT_REMOVE_ITEM; - eventType2 = MOVE_EVENT_REMOVE_ITEM_ITEMTILE; - } - - uint32_t ret = 1; - MoveEvent* moveEvent = getEvent(tile, eventType1); - if (moveEvent) { - ret &= moveEvent->fireAddRemItem(item, nullptr, tile->getPosition()); - } - - moveEvent = getEvent(item, eventType1); - if (moveEvent) { - ret &= moveEvent->fireAddRemItem(item, nullptr, tile->getPosition()); - } - - for (size_t i = tile->getFirstIndex(), j = tile->getLastIndex(); i < j; ++i) { - Thing* thing = tile->getThing(i); - if (!thing) { - continue; - } - - Item* tileItem = thing->getItem(); - if (!tileItem || tileItem == item) { - continue; - } - - moveEvent = getEvent(tileItem, eventType2); - if (moveEvent) { - ret &= moveEvent->fireAddRemItem(item, tileItem, tile->getPosition()); - } - } - return ret; -} - -MoveEvent::MoveEvent(LuaScriptInterface* _interface) : - Event(_interface) -{ - m_eventType = MOVE_EVENT_NONE; - stepFunction = nullptr; - moveFunction = nullptr; - equipFunction = nullptr; - slot = SLOTP_WHEREEVER; - wieldInfo = 0; - reqLevel = 0; - reqMagLevel = 0; - premium = false; -} - -MoveEvent::MoveEvent(const MoveEvent* copy) : - Event(copy) -{ - m_eventType = copy->m_eventType; - stepFunction = copy->stepFunction; - moveFunction = copy->moveFunction; - equipFunction = copy->equipFunction; - slot = copy->slot; - - if (copy->m_eventType == MOVE_EVENT_EQUIP) { - wieldInfo = copy->wieldInfo; - reqLevel = copy->reqLevel; - reqMagLevel = copy->reqMagLevel; - vocationString = copy->vocationString; - premium = copy->premium; - vocEquipMap = copy->vocEquipMap; - } -} - -std::string MoveEvent::getScriptEventName() const -{ - switch (m_eventType) { - case MOVE_EVENT_STEP_IN: return "onStepIn"; - case MOVE_EVENT_STEP_OUT: return "onStepOut"; - case MOVE_EVENT_EQUIP: return "onEquip"; - case MOVE_EVENT_DEEQUIP: return "onDeEquip"; - case MOVE_EVENT_ADD_ITEM: return "onAddItem"; - case MOVE_EVENT_REMOVE_ITEM: return "onRemoveItem"; - default: - std::cout << "[Error - MoveEvent::getScriptEventName] Invalid event type" << std::endl; - return std::string(); - } -} - -bool MoveEvent::configureEvent(const pugi::xml_node& node) -{ - pugi::xml_attribute eventAttr = node.attribute("event"); - if (!eventAttr) { - std::cout << "[Error - MoveEvent::configureMoveEvent] Missing event" << std::endl; - return false; - } - - std::string tmpStr = asLowerCaseString(eventAttr.as_string()); - if (tmpStr == "stepin") { - m_eventType = MOVE_EVENT_STEP_IN; - } else if (tmpStr == "stepout") { - m_eventType = MOVE_EVENT_STEP_OUT; - } else if (tmpStr == "equip") { - m_eventType = MOVE_EVENT_EQUIP; - } else if (tmpStr == "deequip") { - m_eventType = MOVE_EVENT_DEEQUIP; - } else if (tmpStr == "additem") { - m_eventType = MOVE_EVENT_ADD_ITEM; - } else if (tmpStr == "removeitem") { - m_eventType = MOVE_EVENT_REMOVE_ITEM; - } else { - std::cout << "Error: [MoveEvent::configureMoveEvent] No valid event name " << eventAttr.as_string() << std::endl; - return false; - } - - if (m_eventType == MOVE_EVENT_EQUIP || m_eventType == MOVE_EVENT_DEEQUIP) { - pugi::xml_attribute slotAttribute = node.attribute("slot"); - if (slotAttribute) { - tmpStr = asLowerCaseString(slotAttribute.as_string()); - if (tmpStr == "head") { - slot = SLOTP_HEAD; - } else if (tmpStr == "necklace") { - slot = SLOTP_NECKLACE; - } else if (tmpStr == "backpack") { - slot = SLOTP_BACKPACK; - } else if (tmpStr == "armor") { - slot = SLOTP_ARMOR; - } else if (tmpStr == "right-hand") { - slot = SLOTP_RIGHT; - } else if (tmpStr == "left-hand") { - slot = SLOTP_LEFT; - } else if (tmpStr == "hand" || tmpStr == "shield") { - slot = SLOTP_RIGHT | SLOTP_LEFT; - } else if (tmpStr == "legs") { - slot = SLOTP_LEGS; - } else if (tmpStr == "feet") { - slot = SLOTP_FEET; - } else if (tmpStr == "ring") { - slot = SLOTP_RING; - } else if (tmpStr == "ammo") { - slot = SLOTP_AMMO; - } else { - std::cout << "[Warning - MoveEvent::configureMoveEvent] Unknown slot type: " << slotAttribute.as_string() << std::endl; - } - } - - wieldInfo = 0; - - pugi::xml_attribute levelAttribute = node.attribute("level"); - if (levelAttribute) { - reqLevel = pugi::cast(levelAttribute.value()); - if (reqLevel > 0) { - wieldInfo |= WIELDINFO_LEVEL; - } - } - - pugi::xml_attribute magLevelAttribute = node.attribute("maglevel"); - if (magLevelAttribute) { - reqMagLevel = pugi::cast(magLevelAttribute.value()); - if (reqMagLevel > 0) { - wieldInfo |= WIELDINFO_MAGLV; - } - } - - pugi::xml_attribute premiumAttribute = node.attribute("premium"); - if (premiumAttribute) { - premium = premiumAttribute.as_bool(); - if (premium) { - wieldInfo |= WIELDINFO_PREMIUM; - } - } - - //Gather vocation information - std::list vocStringList; - for (auto vocationNode : node.children()) { - pugi::xml_attribute vocationNameAttribute = vocationNode.attribute("name"); - if (!vocationNameAttribute) { - continue; - } - - int32_t vocationId = g_vocations.getVocationId(vocationNameAttribute.as_string()); - if (vocationId != -1) { - vocEquipMap[vocationId] = true; - if (vocationNode.attribute("showInDescription").as_bool(true)) { - vocStringList.push_back(asLowerCaseString(vocationNameAttribute.as_string())); - } - } - } - - if (!vocEquipMap.empty()) { - wieldInfo |= WIELDINFO_VOCREQ; - } - - for (const std::string& str : vocStringList) { - if (!vocationString.empty()) { - if (str != vocStringList.back()) { - vocationString.push_back(','); - vocationString.push_back(' '); - } else { - vocationString += " and "; - } - } - - vocationString += str; - vocationString.push_back('s'); - } - } - return true; -} - -bool MoveEvent::loadFunction(const pugi::xml_attribute& attr) -{ - const char* functionName = attr.as_string(); - if (strcasecmp(functionName, "onstepinfield") == 0) { - stepFunction = StepInField; - } else if (strcasecmp(functionName, "onstepoutfield") == 0) { - stepFunction = StepOutField; - } else if (strcasecmp(functionName, "onaddfield") == 0) { - moveFunction = AddItemField; - } else if (strcasecmp(functionName, "onremovefield") == 0) { - moveFunction = RemoveItemField; - } else if (strcasecmp(functionName, "onequipitem") == 0) { - equipFunction = EquipItem; - } else if (strcasecmp(functionName, "ondeequipitem") == 0) { - equipFunction = DeEquipItem; - } else { - std::cout << "[Warning - MoveEvent::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - m_scripted = false; - return true; -} - -MoveEvent_t MoveEvent::getEventType() const -{ - return m_eventType; -} - -void MoveEvent::setEventType(MoveEvent_t type) -{ - m_eventType = type; -} - -uint32_t MoveEvent::StepInField(Creature* creature, Item* item, const Position&, const Position&) -{ - MagicField* field = item->getMagicField(); - if (field) { - field->onStepInField(creature); - return 1; - } - - return LUA_ERROR_ITEM_NOT_FOUND; -} - -uint32_t MoveEvent::StepOutField(Creature*, Item*, const Position&, const Position&) -{ - return 1; -} - -uint32_t MoveEvent::AddItemField(Item* item, Item*, const Position&) -{ - if (MagicField* field = item->getMagicField()) { - Tile* tile = item->getTile(); - if (CreatureVector* creatures = tile->getCreatures()) { - for (Creature* creature : *creatures) { - field->onStepInField(creature); - } - } - return 1; - } - return LUA_ERROR_ITEM_NOT_FOUND; -} - -uint32_t MoveEvent::RemoveItemField(Item*, Item*, const Position&) -{ - return 1; -} - -uint32_t MoveEvent::EquipItem(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool isCheck) -{ - if (player->isItemAbilityEnabled(slot)) { - return 1; - } - - if (!player->hasFlag(PlayerFlag_IgnoreWeaponCheck) && moveEvent->getWieldInfo() != 0) { - if (player->getLevel() < moveEvent->getReqLevel() || player->getMagicLevel() < moveEvent->getReqMagLv()) { - return 0; - } - - if (moveEvent->isPremium() && !player->isPremium()) { - return 0; - } - - const VocEquipMap& vocEquipMap = moveEvent->getVocEquipMap(); - if (!vocEquipMap.empty() && vocEquipMap.find(player->getVocationId()) == vocEquipMap.end()) { - return 0; - } - } - - if (isCheck) { - return 1; - } - - const ItemType& it = Item::items[item->getID()]; - if (it.transformEquipTo != 0) { - Item* newItem = g_game.transformItem(item, it.transformEquipTo); - g_game.startDecay(newItem); - } else { - player->setItemAbility(slot, true); - } - - if (!it.abilities) { - return 1; - } - - if (it.abilities->invisible) { - Condition* condition = Condition::createCondition(static_cast(slot), CONDITION_INVISIBLE, -1, 0); - player->addCondition(condition); - } - - if (it.abilities->manaShield) { - Condition* condition = Condition::createCondition(static_cast(slot), CONDITION_MANASHIELD, -1, 0); - player->addCondition(condition); - } - - if (it.abilities->speed != 0) { - g_game.changeSpeed(player, it.abilities->speed); - } - - if (it.abilities->conditionSuppressions != 0) { - player->addConditionSuppressions(it.abilities->conditionSuppressions); - player->sendIcons(); - } - - if (it.abilities->regeneration) { - Condition* condition = Condition::createCondition(static_cast(slot), CONDITION_REGENERATION, -1, 0); - - if (it.abilities->healthGain != 0) { - condition->setParam(CONDITION_PARAM_HEALTHGAIN, it.abilities->healthGain); - } - - if (it.abilities->healthTicks != 0) { - condition->setParam(CONDITION_PARAM_HEALTHTICKS, it.abilities->healthTicks); - } - - if (it.abilities->manaGain != 0) { - condition->setParam(CONDITION_PARAM_MANAGAIN, it.abilities->manaGain); - } - - if (it.abilities->manaTicks != 0) { - condition->setParam(CONDITION_PARAM_MANATICKS, it.abilities->manaTicks); - } - - player->addCondition(condition); - } - - //skill modifiers - bool needUpdateSkills = false; - - for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - if (it.abilities->skills[i]) { - needUpdateSkills = true; - player->setVarSkill(static_cast(i), it.abilities->skills[i]); - } - } - - if (needUpdateSkills) { - player->sendSkills(); - } - - //stat modifiers - bool needUpdateStats = false; - - for (int32_t s = STAT_FIRST; s <= STAT_LAST; ++s) { - if (it.abilities->stats[s]) { - needUpdateStats = true; - player->setVarStats(static_cast(s), it.abilities->stats[s]); - } - - if (it.abilities->statsPercent[s]) { - needUpdateStats = true; - player->setVarStats(static_cast(s), static_cast(player->getDefaultStats(static_cast(s)) * ((it.abilities->statsPercent[s] - 100) / 100.f))); - } - } - - if (needUpdateStats) { - player->sendStats(); - } - - return 1; -} - -uint32_t MoveEvent::DeEquipItem(MoveEvent*, Player* player, Item* item, slots_t slot, bool) -{ - if (!player->isItemAbilityEnabled(slot)) { - return 1; - } - - player->setItemAbility(slot, false); - - const ItemType& it = Item::items[item->getID()]; - if (it.transformDeEquipTo != 0) { - g_game.transformItem(item, it.transformDeEquipTo); - g_game.startDecay(item); - } - - if (!it.abilities) { - return 1; - } - - if (it.abilities->invisible) { - player->removeCondition(CONDITION_INVISIBLE, static_cast(slot)); - } - - if (it.abilities->manaShield) { - player->removeCondition(CONDITION_MANASHIELD, static_cast(slot)); - } - - if (it.abilities->speed != 0) { - g_game.changeSpeed(player, -it.abilities->speed); - } - - if (it.abilities->conditionSuppressions != 0) { - player->removeConditionSuppressions(it.abilities->conditionSuppressions); - player->sendIcons(); - } - - if (it.abilities->regeneration) { - player->removeCondition(CONDITION_REGENERATION, static_cast(slot)); - } - - //skill modifiers - bool needUpdateSkills = false; - - for (int32_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - if (it.abilities->skills[i] != 0) { - needUpdateSkills = true; - player->setVarSkill(static_cast(i), -it.abilities->skills[i]); - } - } - - if (needUpdateSkills) { - player->sendSkills(); - } - - //stat modifiers - bool needUpdateStats = false; - - for (int32_t s = STAT_FIRST; s <= STAT_LAST; ++s) { - if (it.abilities->stats[s]) { - needUpdateStats = true; - player->setVarStats(static_cast(s), -it.abilities->stats[s]); - } - - if (it.abilities->statsPercent[s]) { - needUpdateStats = true; - player->setVarStats(static_cast(s), -static_cast(player->getDefaultStats(static_cast(s)) * ((it.abilities->statsPercent[s] - 100) / 100.f))); - } - } - - if (needUpdateStats) { - player->sendStats(); - } - - return 1; -} - -uint32_t MoveEvent::fireStepEvent(Creature* creature, Item* item, const Position& pos, const Position& fromPos) -{ - if (m_scripted) { - return executeStep(creature, item, pos, fromPos); - } else { - return stepFunction(creature, item, pos, fromPos); - } -} - -bool MoveEvent::executeStep(Creature* creature, Item* item, const Position& pos, const Position& /*fromPos*/) -{ - //onStepIn(creature, item, pos, fromPosition) - //onStepOut(creature, item, pos, fromPosition) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeStep] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushPosition(L, pos); - LuaScriptInterface::pushPosition(L, creature->getLastPosition()); - - return m_scriptInterface->callFunction(4); -} - -uint32_t MoveEvent::fireEquip(Player* player, Item* item, slots_t slot, bool boolean) -{ - if (m_scripted) { - return executeEquip(player, item, slot); - } else { - return equipFunction(this, player, item, slot, boolean); - } -} - -bool MoveEvent::executeEquip(Player* player, Item* item, slots_t slot) -{ - //onEquip(player, item, slot) - //onDeEquip(player, item, slot) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeEquip] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - LuaScriptInterface::pushThing(L, item); - lua_pushnumber(L, slot); - - return m_scriptInterface->callFunction(3); -} - -uint32_t MoveEvent::fireAddRemItem(Item* item, Item* tileItem, const Position& pos) -{ - if (m_scripted) { - return executeAddRemItem(item, tileItem, pos); - } else { - return moveFunction(item, tileItem, pos); - } -} - -bool MoveEvent::executeAddRemItem(Item* item, Item* tileItem, const Position& pos) -{ - //onaddItem(moveitem, tileitem, pos) - //onRemoveItem(moveitem, tileitem, pos) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeAddRemItem] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushThing(L, tileItem); - LuaScriptInterface::pushPosition(L, pos); - - return m_scriptInterface->callFunction(3); -} diff --git a/path_10_8/src/movement.h b/path_10_8/src/movement.h deleted file mode 100644 index f7821f478..000000000 --- a/path_10_8/src/movement.h +++ /dev/null @@ -1,172 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_MOVEMENT_H_5E0D2626D4634ACA83AC6509518E5F49 -#define FS_MOVEMENT_H_5E0D2626D4634ACA83AC6509518E5F49 - -#include "baseevents.h" -#include "item.h" -#include "luascript.h" - -enum MoveEvent_t { - MOVE_EVENT_STEP_IN, - MOVE_EVENT_STEP_OUT, - MOVE_EVENT_EQUIP, - MOVE_EVENT_DEEQUIP, - MOVE_EVENT_ADD_ITEM, - MOVE_EVENT_REMOVE_ITEM, - MOVE_EVENT_ADD_ITEM_ITEMTILE, - MOVE_EVENT_REMOVE_ITEM_ITEMTILE, - - MOVE_EVENT_LAST, - MOVE_EVENT_NONE -}; - -class MoveEvent; - -struct MoveEventList { - std::list moveEvent[MOVE_EVENT_LAST]; -}; - -typedef std::map VocEquipMap; - -class MoveEvents final : public BaseEvents -{ - public: - MoveEvents(); - ~MoveEvents(); - - // non-copyable - MoveEvents(const MoveEvents&) = delete; - MoveEvents& operator=(const MoveEvents&) = delete; - - uint32_t onCreatureMove(Creature* creature, const Tile* tile, const Position& fromPos, MoveEvent_t eventType); - uint32_t onPlayerEquip(Player* player, Item* item, slots_t slot, bool isCheck); - uint32_t onPlayerDeEquip(Player* player, Item* item, slots_t slot); - uint32_t onItemMove(Item* item, Tile* tile, bool isAdd); - - MoveEvent* getEvent(Item* item, MoveEvent_t eventType); - - protected: - typedef std::map MoveListMap; - void clearMap(MoveListMap& map); - - typedef std::map MovePosListMap; - void clear() final; - LuaScriptInterface& getScriptInterface() final; - std::string getScriptBaseName() const final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - - void registerItemID(int32_t itemId, MoveEvent_t eventType); - void registerActionID(int32_t actionId, MoveEvent_t eventType); - void registerUniqueID(int32_t uniqueId, MoveEvent_t eventType); - - void addEvent(MoveEvent* moveEvent, int32_t id, MoveListMap& map); - - void addEvent(MoveEvent* moveEvent, const Position& pos, MovePosListMap& map); - MoveEvent* getEvent(const Tile* tile, MoveEvent_t eventType); - - MoveEvent* getEvent(Item* item, MoveEvent_t eventType, slots_t slot); - - MoveListMap m_uniqueIdMap; - MoveListMap m_actionIdMap; - MoveListMap m_itemIdMap; - MovePosListMap m_positionMap; - - LuaScriptInterface m_scriptInterface; -}; - -typedef uint32_t (StepFunction)(Creature* creature, Item* item, const Position& pos, const Position& fromPos); -typedef uint32_t (MoveFunction)(Item* item, Item* tileItem, const Position& pos); -typedef uint32_t (EquipFunction)(MoveEvent* moveEvent, Player* player, Item* item, slots_t slot, bool boolean); - -class MoveEvent final : public Event -{ - public: - explicit MoveEvent(LuaScriptInterface* _interface); - explicit MoveEvent(const MoveEvent* copy); - - MoveEvent_t getEventType() const; - void setEventType(MoveEvent_t type); - - bool configureEvent(const pugi::xml_node& node) final; - bool loadFunction(const pugi::xml_attribute& attr) final; - - uint32_t fireStepEvent(Creature* creature, Item* item, const Position& pos, const Position& fromPos); - uint32_t fireAddRemItem(Item* item, Item* tileItem, const Position& pos); - uint32_t fireEquip(Player* player, Item* item, slots_t slot, bool boolean); - - uint32_t getSlot() const { - return slot; - } - - //scripting - bool executeStep(Creature* creature, Item* item, const Position& pos, const Position& fromPos); - bool executeEquip(Player* player, Item* item, slots_t slot); - bool executeAddRemItem(Item* item, Item* tileItem, const Position& pos); - // - - //onEquip information - uint32_t getReqLevel() const { - return reqLevel; - } - uint32_t getReqMagLv() const { - return reqMagLevel; - } - bool isPremium() const { - return premium; - } - const std::string& getVocationString() const { - return vocationString; - } - uint32_t getWieldInfo() const { - return wieldInfo; - } - const VocEquipMap& getVocEquipMap() const { - return vocEquipMap; - } - - protected: - std::string getScriptEventName() const final; - - static StepFunction StepInField; - static StepFunction StepOutField; - - static MoveFunction AddItemField; - static MoveFunction RemoveItemField; - static EquipFunction EquipItem; - static EquipFunction DeEquipItem; - - MoveEvent_t m_eventType; - StepFunction* stepFunction; - MoveFunction* moveFunction; - EquipFunction* equipFunction; - uint32_t slot; - - //onEquip information - uint32_t reqLevel; - uint32_t reqMagLevel; - bool premium; - std::string vocationString; - uint32_t wieldInfo; - VocEquipMap vocEquipMap; -}; - -#endif diff --git a/path_10_8/src/networkmessage.cpp b/path_10_8/src/networkmessage.cpp deleted file mode 100644 index fb6fb2219..000000000 --- a/path_10_8/src/networkmessage.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "networkmessage.h" - -#include "container.h" -#include "creature.h" -#include "player.h" - -#include "position.h" -#include "rsa.h" - -int32_t NetworkMessage::decodeHeader() -{ - int32_t newSize = static_cast(buffer[0] | buffer[1] << 8); - length = newSize; - return length; -} - -/******************************************************************************/ -std::string NetworkMessage::getString(uint16_t stringLen/* = 0*/) -{ - if (stringLen == 0) { - stringLen = get(); - } - - if (!canRead(stringLen)) { - return std::string(); - } - - char* v = reinterpret_cast(buffer) + position; //does not break strict aliasing - position += stringLen; - return std::string(v, stringLen); -} - -Position NetworkMessage::getPosition() -{ - Position pos; - pos.x = get(); - pos.y = get(); - pos.z = getByte(); - return pos; -} -/******************************************************************************/ - -void NetworkMessage::addString(const std::string& value) -{ - size_t stringLen = value.length(); - if (!canAdd(stringLen + 2) || stringLen > 8192) { - return; - } - - add(stringLen); - memcpy(buffer + position, value.c_str(), stringLen); - position += stringLen; - length += stringLen; -} - -void NetworkMessage::addDouble(double value, uint8_t precision/* = 2*/) -{ - addByte(precision); - add((value * std::pow(static_cast(10), precision)) + std::numeric_limits::max()); -} - -void NetworkMessage::addBytes(const char* bytes, size_t size) -{ - if (!canAdd(size) || size > 8192) { - return; - } - - memcpy(buffer + position, bytes, size); - position += size; - length += size; -} - -void NetworkMessage::addPaddingBytes(size_t n) -{ - if (!canAdd(n)) { - return; - } - - memset(buffer + position, 0x33, n); - length += n; -} - -void NetworkMessage::addPosition(const Position& pos) -{ - add(pos.x); - add(pos.y); - addByte(pos.z); -} - -void NetworkMessage::addItem(uint16_t id, uint8_t count) -{ - const ItemType& it = Item::items[id]; - - add(it.clientId); - - addByte(0xFF); // MARK_UNMARKED - - if (it.stackable) { - addByte(count); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[count & 7]); - } - - if (it.isAnimation) { - addByte(0xFE); // random phase (0xFF for async) - } -} - -void NetworkMessage::addItem(const Item* item) -{ - const ItemType& it = Item::items[item->getID()]; - - add(it.clientId); - addByte(0xFF); // MARK_UNMARKED - - if (it.stackable) { - addByte(std::min(0xFF, item->getItemCount())); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[item->getFluidType() & 7]); - } - - if (it.isAnimation) { - addByte(0xFE); // random phase (0xFF for async) - } -} - -void NetworkMessage::addItemId(uint16_t itemId) -{ - add(Item::items[itemId].clientId); -} diff --git a/path_10_8/src/networkmessage.h b/path_10_8/src/networkmessage.h deleted file mode 100644 index 5147a54b5..000000000 --- a/path_10_8/src/networkmessage.h +++ /dev/null @@ -1,178 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_NETWORKMESSAGE_H_B853CFED58D1413A87ACED07B2926E03 -#define FS_NETWORKMESSAGE_H_B853CFED58D1413A87ACED07B2926E03 - -#include "const.h" - -class Item; -class Creature; -class Player; -struct Position; -class RSA; - -class NetworkMessage -{ - public: - typedef uint16_t MsgSize_t; - // Headers: - // 2 bytes for unencrypted message size - // 4 bytes for checksum - // 2 bytes for encrypted message size - static const MsgSize_t INITIAL_BUFFER_POSITION = 8; - enum { HEADER_LENGTH = 2 }; - enum { CHECKSUM_LENGTH = 4 }; - enum { XTEA_MULTIPLE = 8 }; - enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - CHECKSUM_LENGTH - XTEA_MULTIPLE }; - enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 }; - - NetworkMessage() { - reset(); - } - - void reset() { - overrun = false; - length = 0; - position = INITIAL_BUFFER_POSITION; - } - - // simply read functions for incoming message - uint8_t getByte() { - if (!canRead(1)) { - return 0; - } - - return buffer[position++]; - } - - uint8_t getPreviousByte() { - return buffer[--position]; - } - - template - T get() { - if (!canRead(sizeof(T))) { - return 0; - } - - T v; - memcpy(&v, buffer + position, sizeof(T)); - position += sizeof(T); - return v; - } - - std::string getString(uint16_t stringLen = 0); - Position getPosition(); - - // skips count unknown/unused bytes in an incoming message - void skipBytes(int16_t count) { - position += count; - } - - // simply write functions for outgoing message - void addByte(uint8_t value) { - if (!canAdd(1)) { - return; - } - - buffer[position++] = value; - length++; - } - - template - void add(T value) { - if (!canAdd(sizeof(T))) { - return; - } - - memcpy(buffer + position, &value, sizeof(T)); - position += sizeof(T); - length += sizeof(T); - } - - void addBytes(const char* bytes, size_t size); - void addPaddingBytes(size_t n); - - void addString(const std::string& value); - - void addDouble(double value, uint8_t precision = 2); - - // write functions for complex types - void addPosition(const Position& pos); - void addItem(uint16_t id, uint8_t count); - void addItem(const Item* item); - void addItemId(uint16_t itemId); - - MsgSize_t getLength() const { - return length; - } - - void setLength(MsgSize_t newLength) { - length = newLength; - } - - MsgSize_t getBufferPosition() const { - return position; - } - - void setBufferPosition(MsgSize_t pos) { - position = pos; - } - - int32_t decodeHeader(); - - bool isOverrun() const { - return overrun; - } - - uint8_t* getBuffer() { - return buffer; - } - - const uint8_t* getBuffer() const { - return buffer; - } - - uint8_t* getBodyBuffer() { - position = 2; - return buffer + HEADER_LENGTH; - } - - protected: - inline bool canAdd(size_t size) const { - return (size + position) < MAX_BODY_LENGTH; - } - - inline bool canRead(int32_t size) { - if ((position + size) > (length + 8) || size >= (NETWORKMESSAGE_MAXSIZE - position)) { - overrun = true; - return false; - } - return true; - } - - MsgSize_t length; - MsgSize_t position; - bool overrun; - - uint8_t buffer[NETWORKMESSAGE_MAXSIZE]; -}; - -#endif // #ifndef __NETWORK_MESSAGE_H__ diff --git a/path_10_8/src/npc.cpp b/path_10_8/src/npc.cpp deleted file mode 100644 index 61bb65f5c..000000000 --- a/path_10_8/src/npc.cpp +++ /dev/null @@ -1,1275 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "npc.h" -#include "game.h" -#include "tools.h" -#include "position.h" -#include "player.h" -#include "spawn.h" -#include "pugicast.h" -#include "luascript.h" - -extern Game g_game; -extern LuaEnvironment g_luaEnvironment; - -enum { - EVENT_ID_LOADING = 1, - EVENT_ID_USER = 1000, -}; - -uint32_t Npc::npcAutoID = 0x80000000; -NpcScriptInterface* Npc::m_scriptInterface = nullptr; - -void Npcs::reload() -{ - const std::map& npcs = g_game.getNpcs(); - for (const auto& it : npcs) { - it.second->closeAllShopWindows(); - } - - delete Npc::m_scriptInterface; - Npc::m_scriptInterface = nullptr; - - for (const auto& it : npcs) { - it.second->reload(); - } -} - -Npc* Npc::createNpc(const std::string& name) -{ - std::unique_ptr npc(new Npc(name)); - if (!npc->load()) { - return nullptr; - } - return npc.release(); -} - -Npc::Npc(const std::string& _name) : - Creature(), m_filename("data/npc/" + _name + ".xml") -{ - loaded = false; - - masterRadius = -1; - - m_npcEventHandler = nullptr; - reset(); -} - -Npc::~Npc() -{ - reset(); -} - -void Npc::addList() -{ - g_game.addNpc(this); -} - -void Npc::removeList() -{ - g_game.removeNpc(this); -} - -bool Npc::load() -{ - if (loaded) { - return true; - } - - reset(); - - if (!m_scriptInterface) { - m_scriptInterface = new NpcScriptInterface(); - m_scriptInterface->loadNpcLib("data/npc/lib/npc.lua"); - } - - loaded = loadFromXml(m_filename); - return loaded; -} - -void Npc::reset() -{ - loaded = false; - walkTicks = 1500; - floorChange = false; - attackable = false; - ignoreHeight = true; - focusCreature = 0; - speechBubble = SPEECHBUBBLE_NONE; - - delete m_npcEventHandler; - m_npcEventHandler = nullptr; - - m_parameters.clear(); - shopPlayerSet.clear(); -} - -void Npc::reload() -{ - reset(); - load(); - - // Simulate that the creature is placed on the map again. - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureAppear(this); - } - - if (walkTicks > 0) { - addEventWalk(); - } -} - -bool Npc::loadFromXml(const std::string& filename) -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(filename.c_str()); - if (!result) { - printXMLError("Error - Npc::loadFromXml", filename, result); - return false; - } - - pugi::xml_node npcNode = doc.child("npc"); - if (!npcNode) { - std::cout << "[Error - Npc::loadFromXml] Missing npc tag in " << filename << std::endl; - return false; - } - - name = npcNode.attribute("name").as_string(); - attackable = npcNode.attribute("attackable").as_bool(); - floorChange = npcNode.attribute("floorchange").as_bool(); - - pugi::xml_attribute attr; - if ((attr = npcNode.attribute("speed"))) { - baseSpeed = pugi::cast(attr.value()); - } else { - baseSpeed = 100; - } - - if ((attr = npcNode.attribute("walkinterval"))) { - walkTicks = pugi::cast(attr.value()); - } - - if ((attr = npcNode.attribute("walkradius"))) { - masterRadius = pugi::cast(attr.value()); - } - - if ((attr = npcNode.attribute("ignoreheight"))) { - ignoreHeight = attr.as_bool(); - } - - if ((attr = npcNode.attribute("speechbubble"))) { - speechBubble = pugi::cast(attr.value()); - } - - if ((attr = npcNode.attribute("skull"))) { - setSkull(getSkullType(attr.as_string())); - } - - pugi::xml_node healthNode = npcNode.child("health"); - if (healthNode) { - if ((attr = healthNode.attribute("now"))) { - health = pugi::cast(attr.value()); - } else { - health = 100; - } - - if ((attr = healthNode.attribute("max"))) { - healthMax = pugi::cast(attr.value()); - } else { - healthMax = 100; - } - } - - pugi::xml_node lookNode = npcNode.child("look"); - if (lookNode) { - pugi::xml_attribute lookTypeAttribute = lookNode.attribute("type"); - if (lookTypeAttribute) { - defaultOutfit.lookType = pugi::cast(lookTypeAttribute.value()); - defaultOutfit.lookHead = pugi::cast(lookNode.attribute("head").value()); - defaultOutfit.lookBody = pugi::cast(lookNode.attribute("body").value()); - defaultOutfit.lookLegs = pugi::cast(lookNode.attribute("legs").value()); - defaultOutfit.lookFeet = pugi::cast(lookNode.attribute("feet").value()); - defaultOutfit.lookAddons = pugi::cast(lookNode.attribute("addons").value()); - } else if ((attr = lookNode.attribute("typeex"))) { - defaultOutfit.lookTypeEx = pugi::cast(attr.value()); - } - defaultOutfit.lookMount = pugi::cast(lookNode.attribute("mount").value()); - - currentOutfit = defaultOutfit; - } - - for (auto parameterNode : npcNode.child("parameters").children()) { - m_parameters[parameterNode.attribute("key").as_string()] = parameterNode.attribute("value").as_string(); - } - - pugi::xml_attribute scriptFile = npcNode.attribute("script"); - if (scriptFile) { - m_npcEventHandler = new NpcEventsHandler(scriptFile.as_string(), this); - if (!m_npcEventHandler->isLoaded()) { - delete m_npcEventHandler; - m_npcEventHandler = nullptr; - return false; - } - } - return true; -} - -bool Npc::canSee(const Position& pos) const -{ - if (pos.z != getPosition().z) { - return false; - } - return Creature::canSee(getPosition(), pos, 3, 3); -} - -std::string Npc::getDescription(int32_t) const -{ - std::string descr; - descr.reserve(name.length() + 1); - descr.assign(name); - descr.push_back('.'); - return descr; -} - -void Npc::onCreatureAppear(Creature* creature, bool isLogin) -{ - Creature::onCreatureAppear(creature, isLogin); - - if (creature == this) { - if (walkTicks > 0) { - addEventWalk(); - } - - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureAppear(creature); - } - } else if (creature->getPlayer()) { - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureAppear(creature); - } - } -} - -void Npc::onRemoveCreature(Creature* creature, bool isLogout) -{ - Creature::onRemoveCreature(creature, isLogout); - - if (creature == this) { - closeAllShopWindows(); - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureDisappear(creature); - } - } else if (creature->getPlayer()) { - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureDisappear(creature); - } - } -} - -void Npc::onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) -{ - Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - - if (creature == this || creature->getPlayer()) { - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureMove(creature, oldPos, newPos); - } - } -} - -void Npc::onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) -{ - if (creature->getID() == id) { - return; - } - - //only players for script events - Player* player = creature->getPlayer(); - if (player) { - if (m_npcEventHandler) { - m_npcEventHandler->onCreatureSay(player, type, text); - } - } -} - -void Npc::onPlayerCloseChannel(Player* player) -{ - if (m_npcEventHandler) { - m_npcEventHandler->onPlayerCloseChannel(player); - } -} - -void Npc::onThink(uint32_t interval) -{ - Creature::onThink(interval); - - if (m_npcEventHandler) { - m_npcEventHandler->onThink(); - } - - if (getTimeSinceLastMove() >= walkTicks) { - addEventWalk(); - } -} - -void Npc::doSay(const std::string& text) -{ - g_game.internalCreatureSay(this, TALKTYPE_SAY, text, false); -} - -void Npc::doSayToPlayer(Player* player, const std::string& text) -{ - if (player) { - player->sendCreatureSay(this, TALKTYPE_PRIVATE_NP, text); - player->onCreatureSay(this, TALKTYPE_PRIVATE_NP, text); - } -} - -void Npc::onPlayerTrade(Player* player, int32_t callback, uint16_t itemId, uint8_t count, - uint8_t amount, bool ignore/* = false*/, bool inBackpacks/* = false*/) -{ - if (m_npcEventHandler) { - m_npcEventHandler->onPlayerTrade(player, callback, itemId, count, amount, ignore, inBackpacks); - } - player->sendSaleItemList(); -} - -void Npc::onPlayerEndTrade(Player* player, int32_t buyCallback, int32_t sellCallback) -{ - lua_State* L = getScriptInterface()->getLuaState(); - - if (buyCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); - } - - if (sellCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); - } - - removeShopPlayer(player); - - if (m_npcEventHandler) { - m_npcEventHandler->onPlayerEndTrade(player); - } -} - -bool Npc::getNextStep(Direction& dir, uint32_t& flags) -{ - if (Creature::getNextStep(dir, flags)) { - return true; - } - - if (walkTicks <= 0) { - return false; - } - - if (focusCreature != 0) { - return false; - } - - if (getTimeSinceLastMove() < walkTicks) { - return false; - } - - return getRandomStep(dir); -} - -bool Npc::canWalkTo(const Position& fromPos, Direction dir) const -{ - if (masterRadius == 0) { - return false; - } - - Position toPos = getNextPosition(dir, fromPos); - if (!Spawns::isInZone(masterPos, masterRadius, toPos)) { - return false; - } - - Tile* tile = g_game.map.getTile(toPos); - if (!tile || tile->queryAdd(0, *this, 1, 0) != RETURNVALUE_NOERROR) { - return false; - } - - if (!floorChange && (tile->floorChange() || tile->getTeleportItem())) { - return false; - } - - if (!ignoreHeight && tile->hasHeight(1)) { - return false; - } - - return true; -} - -bool Npc::getRandomStep(Direction& dir) const -{ - std::vector dirList; - const Position& creaturePos = getPosition(); - - if (canWalkTo(creaturePos, DIRECTION_NORTH)) { - dirList.push_back(DIRECTION_NORTH); - } - - if (canWalkTo(creaturePos, DIRECTION_SOUTH)) { - dirList.push_back(DIRECTION_SOUTH); - } - - if (canWalkTo(creaturePos, DIRECTION_EAST)) { - dirList.push_back(DIRECTION_EAST); - } - - if (canWalkTo(creaturePos, DIRECTION_WEST)) { - dirList.push_back(DIRECTION_WEST); - } - - if (dirList.empty()) { - return false; - } - - dir = dirList[uniform_random(0, dirList.size() - 1)]; - return true; -} - -void Npc::doMoveTo(const Position& target) -{ - std::forward_list listDir; - if (getPathTo(target, listDir, 1, 1, true, true)) { - startAutoWalk(listDir); - } -} - -void Npc::turnToCreature(Creature* creature) -{ - const Position& creaturePos = creature->getPosition(); - const Position& myPos = getPosition(); - const auto dx = Position::getOffsetX(myPos, creaturePos); - const auto dy = Position::getOffsetY(myPos, creaturePos); - - float tan; - if (dx != 0) { - tan = static_cast(dy) / dx; - } else { - tan = 10; - } - - Direction dir; - if (std::abs(tan) < 1) { - if (dx > 0) { - dir = DIRECTION_WEST; - } else { - dir = DIRECTION_EAST; - } - } else { - if (dy > 0) { - dir = DIRECTION_NORTH; - } else { - dir = DIRECTION_SOUTH; - } - } - g_game.internalCreatureTurn(this, dir); -} - -void Npc::setCreatureFocus(Creature* creature) -{ - if (creature) { - focusCreature = creature->getID(); - turnToCreature(creature); - } else { - focusCreature = 0; - } -} - -void Npc::addShopPlayer(Player* player) -{ - shopPlayerSet.insert(player); -} - -void Npc::removeShopPlayer(Player* player) -{ - shopPlayerSet.erase(player); -} - -void Npc::closeAllShopWindows() -{ - while (!shopPlayerSet.empty()) { - Player* player = *shopPlayerSet.begin(); - if (!player->closeShopWindow()) { - removeShopPlayer(player); - } - } -} - -NpcScriptInterface* Npc::getScriptInterface() -{ - return m_scriptInterface; -} - -NpcScriptInterface::NpcScriptInterface() : - LuaScriptInterface("Npc interface") -{ - m_libLoaded = false; - initState(); -} - -bool NpcScriptInterface::initState() -{ - m_luaState = g_luaEnvironment.getLuaState(); - if (!m_luaState) { - return false; - } - - registerFunctions(); - - lua_newtable(m_luaState); - m_eventTableRef = luaL_ref(m_luaState, LUA_REGISTRYINDEX); - m_runningEventId = EVENT_ID_USER; - return true; -} - -bool NpcScriptInterface::closeState() -{ - m_libLoaded = false; - LuaScriptInterface::closeState(); - return true; -} - -bool NpcScriptInterface::loadNpcLib(const std::string& file) -{ - if (m_libLoaded) { - return true; - } - - if (loadFile(file) == -1) { - std::cout << "[Warning - NpcScriptInterface::loadNpcLib] Can not load " << file << std::endl; - return false; - } - - m_libLoaded = true; - return true; -} - -void NpcScriptInterface::registerFunctions() -{ - //npc exclusive functions - lua_register(m_luaState, "selfSay", NpcScriptInterface::luaActionSay); - lua_register(m_luaState, "selfMove", NpcScriptInterface::luaActionMove); - lua_register(m_luaState, "selfMoveTo", NpcScriptInterface::luaActionMoveTo); - lua_register(m_luaState, "selfTurn", NpcScriptInterface::luaActionTurn); - lua_register(m_luaState, "selfFollow", NpcScriptInterface::luaActionFollow); - lua_register(m_luaState, "getDistanceTo", NpcScriptInterface::luagetDistanceTo); - lua_register(m_luaState, "doNpcSetCreatureFocus", NpcScriptInterface::luaSetNpcFocus); - lua_register(m_luaState, "getNpcCid", NpcScriptInterface::luaGetNpcCid); - lua_register(m_luaState, "getNpcParameter", NpcScriptInterface::luaGetNpcParameter); - lua_register(m_luaState, "openShopWindow", NpcScriptInterface::luaOpenShopWindow); - lua_register(m_luaState, "closeShopWindow", NpcScriptInterface::luaCloseShopWindow); - lua_register(m_luaState, "doSellItem", NpcScriptInterface::luaDoSellItem); - - // metatable - registerMethod("Npc", "getParameter", NpcScriptInterface::luaNpcGetParameter); - registerMethod("Npc", "setFocus", NpcScriptInterface::luaNpcSetFocus); - - registerMethod("Npc", "openShopWindow", NpcScriptInterface::luaNpcOpenShopWindow); - registerMethod("Npc", "closeShopWindow", NpcScriptInterface::luaNpcCloseShopWindow); -} - -int NpcScriptInterface::luaActionSay(lua_State* L) -{ - //selfSay(words[, target]) - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - return 0; - } - - const std::string& text = getString(L, 1); - if (lua_gettop(L) >= 2) { - Player* target = getPlayer(L, 2); - if (target) { - npc->doSayToPlayer(target, text); - return 0; - } - } - - npc->doSay(text); - return 0; -} - -int NpcScriptInterface::luaActionMove(lua_State* L) -{ - //selfMove(direction) - Npc* npc = getScriptEnv()->getNpc(); - if (npc) { - g_game.internalMoveCreature(npc, getNumber(L, 1)); - } - return 0; -} - -int NpcScriptInterface::luaActionMoveTo(lua_State* L) -{ - //selfMoveTo(x,y,z) - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - return 0; - } - - npc->doMoveTo(Position( - getNumber(L, 1), - getNumber(L, 2), - getNumber(L, 3) - )); - return 0; -} - -int NpcScriptInterface::luaActionTurn(lua_State* L) -{ - //selfTurn(direction) - Npc* npc = getScriptEnv()->getNpc(); - if (npc) { - g_game.internalCreatureTurn(npc, getNumber(L, 1)); - } - return 0; -} - -int NpcScriptInterface::luaActionFollow(lua_State* L) -{ - //selfFollow(player) - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - pushBoolean(L, false); - return 1; - } - - pushBoolean(L, npc->setFollowCreature(getPlayer(L, 1))); - return 1; -} - -int NpcScriptInterface::luagetDistanceTo(lua_State* L) -{ - //getDistanceTo(uid) - ScriptEnvironment* env = getScriptEnv(); - - Npc* npc = env->getNpc(); - if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); - lua_pushnil(L); - return 1; - } - - uint32_t uid = getNumber(L, -1); - - Thing* thing = env->getThingByUID(uid); - if (!thing) { - reportErrorFunc(getErrorDesc(LUA_ERROR_THING_NOT_FOUND)); - lua_pushnil(L); - return 1; - } - - const Position& thingPos = thing->getPosition(); - const Position& npcPos = npc->getPosition(); - if (npcPos.z != thingPos.z) { - lua_pushnumber(L, -1); - } else { - int32_t dist = std::max(Position::getDistanceX(npcPos, thingPos), Position::getDistanceY(npcPos, thingPos)); - lua_pushnumber(L, dist); - } - return 1; -} - -int NpcScriptInterface::luaSetNpcFocus(lua_State* L) -{ - //doNpcSetCreatureFocus(cid) - Npc* npc = getScriptEnv()->getNpc(); - if (npc) { - npc->setCreatureFocus(getCreature(L, -1)); - } - return 0; -} - -int NpcScriptInterface::luaGetNpcCid(lua_State* L) -{ - //getNpcCid() - Npc* npc = getScriptEnv()->getNpc(); - if (npc) { - lua_pushnumber(L, npc->getID()); - } else { - lua_pushnil(L); - } - return 1; -} - -int NpcScriptInterface::luaGetNpcParameter(lua_State* L) -{ - //getNpcParameter(paramKey) - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - lua_pushnil(L); - return 1; - } - - std::string paramKey = getString(L, -1); - - auto it = npc->m_parameters.find(paramKey); - if (it != npc->m_parameters.end()) { - LuaScriptInterface::pushString(L, it->second); - } else { - lua_pushnil(L); - } - return 1; -} - -int NpcScriptInterface::luaOpenShopWindow(lua_State* L) -{ - //openShopWindow(cid, items, onBuy callback, onSell callback) - int32_t sellCallback; - if (lua_isfunction(L, -1) == 0) { - sellCallback = -1; - lua_pop(L, 1); // skip it - use default value - } else { - sellCallback = popCallback(L); - } - - int32_t buyCallback; - if (lua_isfunction(L, -1) == 0) { - buyCallback = -1; - lua_pop(L, 1); // skip it - use default value - } else { - buyCallback = popCallback(L); - } - - if (lua_istable(L, -1) == 0) { - reportError(__FUNCTION__, "item list is not a table."); - pushBoolean(L, false); - return 1; - } - - std::list items; - lua_pushnil(L); - while (lua_next(L, -2) != 0) { - const auto tableIndex = lua_gettop(L); - ShopInfo item; - - item.itemId = getField(L, tableIndex, "id"); - item.subType = getField(L, tableIndex, "subType"); - if (item.subType == 0) { - item.subType = getField(L, tableIndex, "subtype"); - lua_pop(L, 1); - } - - item.buyPrice = getField(L, tableIndex, "buy"); - item.sellPrice = getField(L, tableIndex, "sell"); - item.realName = getFieldString(L, tableIndex, "name"); - - items.push_back(item); - lua_pop(L, 6); - } - lua_pop(L, 1); - - Player* player = getPlayer(L, -1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - //Close any eventual other shop window currently open. - player->closeShopWindow(false); - - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - npc->addShopPlayer(player); - player->setShopOwner(npc, buyCallback, sellCallback); - player->openShopWindow(npc, items); - - pushBoolean(L, true); - return 1; -} - -int NpcScriptInterface::luaCloseShopWindow(lua_State* L) -{ - //closeShopWindow(cid) - Npc* npc = getScriptEnv()->getNpc(); - if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Player* player = getPlayer(L, 1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - int32_t buyCallback; - int32_t sellCallback; - - Npc* merchant = player->getShopOwner(buyCallback, sellCallback); - - //Check if we actually have a shop window with this player. - if (merchant == npc) { - player->sendCloseShop(); - - if (buyCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); - } - - if (sellCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); - } - - player->setShopOwner(nullptr, -1, -1); - npc->removeShopPlayer(player); - } - - pushBoolean(L, true); - return 1; -} - -int NpcScriptInterface::luaDoSellItem(lua_State* L) -{ - //doSellItem(cid, itemid, amount, subtype, actionid, canDropOnMap) - Player* player = getPlayer(L, 1); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - uint32_t sellCount = 0; - - uint32_t itemId = getNumber(L, 2); - uint32_t amount = getNumber(L, 3); - uint32_t subType; - - int32_t n = getNumber(L, 4, -1); - if (n != -1) { - subType = n; - } else { - subType = 1; - } - - uint32_t actionId = getNumber(L, 5, 0); - bool canDropOnMap = getBoolean(L, 6, true); - - const ItemType& it = Item::items[itemId]; - if (it.stackable) { - while (amount > 0) { - int32_t stackCount = std::min(100, amount); - Item* item = Item::CreateItem(it.id, stackCount); - if (item && actionId != 0) { - item->setActionId(actionId); - } - - if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RETURNVALUE_NOERROR) { - delete item; - lua_pushnumber(L, sellCount); - return 1; - } - - amount -= stackCount; - sellCount += stackCount; - } - } else { - for (uint32_t i = 0; i < amount; ++i) { - Item* item = Item::CreateItem(it.id, subType); - if (item && actionId != 0) { - item->setActionId(actionId); - } - - if (g_game.internalPlayerAddItem(player, item, canDropOnMap) != RETURNVALUE_NOERROR) { - delete item; - lua_pushnumber(L, sellCount); - return 1; - } - - ++sellCount; - } - } - - lua_pushnumber(L, sellCount); - return 1; -} - -int NpcScriptInterface::luaNpcGetParameter(lua_State* L) -{ - // npc:getParameter(key) - const std::string& key = getString(L, 2); - Npc* npc = getUserdata(L, 1); - if (npc) { - auto it = npc->m_parameters.find(key); - if (it != npc->m_parameters.end()) { - pushString(L, it->second); - } else { - lua_pushnil(L); - } - } else { - lua_pushnil(L); - } - return 1; -} - -int NpcScriptInterface::luaNpcSetFocus(lua_State* L) -{ - // npc:setFocus(creature) - Creature* creature = getCreature(L, 2); - Npc* npc = getUserdata(L, 1); - if (npc) { - npc->setCreatureFocus(creature); - pushBoolean(L, true); - } else { - lua_pushnil(L); - } - return 1; -} - -int NpcScriptInterface::luaNpcOpenShopWindow(lua_State* L) -{ - // npc:openShopWindow(cid, items, buyCallback, sellCallback) - if (!isTable(L, 3)) { - reportErrorFunc("item list is not a table."); - pushBoolean(L, false); - return 1; - } - - Player* player = getPlayer(L, 2); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Npc* npc = getUserdata(L, 1); - if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - int32_t sellCallback = -1; - if (LuaScriptInterface::isFunction(L, 5)) { - sellCallback = luaL_ref(L, LUA_REGISTRYINDEX); - } - - int32_t buyCallback = -1; - if (LuaScriptInterface::isFunction(L, 4)) { - buyCallback = luaL_ref(L, LUA_REGISTRYINDEX); - } - - std::list items; - - lua_pushnil(L); - while (lua_next(L, 3) != 0) { - const auto tableIndex = lua_gettop(L); - ShopInfo item; - - item.itemId = getField(L, tableIndex, "id"); - item.subType = getField(L, tableIndex, "subType"); - if (item.subType == 0) { - item.subType = getField(L, tableIndex, "subtype"); - lua_pop(L, 1); - } - - item.buyPrice = getField(L, tableIndex, "buy"); - item.sellPrice = getField(L, tableIndex, "sell"); - item.realName = getFieldString(L, tableIndex, "name"); - - items.push_back(item); - lua_pop(L, 6); - } - lua_pop(L, 1); - - player->closeShopWindow(false); - npc->addShopPlayer(player); - - player->setShopOwner(npc, buyCallback, sellCallback); - player->openShopWindow(npc, items); - - pushBoolean(L, true); - return 1; -} - -int NpcScriptInterface::luaNpcCloseShopWindow(lua_State* L) -{ - // npc:closeShopWindow(player) - Player* player = getPlayer(L, 2); - if (!player) { - reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - Npc* npc = getUserdata(L, 1); - if (!npc) { - reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND)); - pushBoolean(L, false); - return 1; - } - - int32_t buyCallback; - int32_t sellCallback; - - Npc* merchant = player->getShopOwner(buyCallback, sellCallback); - if (merchant == npc) { - player->sendCloseShop(); - if (buyCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, buyCallback); - } - - if (sellCallback != -1) { - luaL_unref(L, LUA_REGISTRYINDEX, sellCallback); - } - - player->setShopOwner(nullptr, -1, -1); - npc->removeShopPlayer(player); - } - - pushBoolean(L, true); - return 1; -} - -NpcEventsHandler::NpcEventsHandler(const std::string& file, Npc* npc) -{ - m_npc = npc; - m_scriptInterface = npc->getScriptInterface(); - m_loaded = m_scriptInterface->loadFile("data/npc/scripts/" + file, npc) == 0; - if (!m_loaded) { - std::cout << "[Warning - NpcScript::NpcScript] Can not load script: " << file << std::endl; - std::cout << m_scriptInterface->getLastLuaError() << std::endl; - m_onCreatureSay = -1; - m_onCreatureDisappear = -1; - m_onCreatureAppear = -1; - m_onCreatureMove = -1; - m_onPlayerCloseChannel = -1; - m_onPlayerEndTrade = -1; - m_onThink = -1; - } else { - m_onCreatureSay = m_scriptInterface->getEvent("onCreatureSay"); - m_onCreatureDisappear = m_scriptInterface->getEvent("onCreatureDisappear"); - m_onCreatureAppear = m_scriptInterface->getEvent("onCreatureAppear"); - m_onCreatureMove = m_scriptInterface->getEvent("onCreatureMove"); - m_onPlayerCloseChannel = m_scriptInterface->getEvent("onPlayerCloseChannel"); - m_onPlayerEndTrade = m_scriptInterface->getEvent("onPlayerEndTrade"); - m_onThink = m_scriptInterface->getEvent("onThink"); - } -} - -bool NpcEventsHandler::isLoaded() const -{ - return m_loaded; -} - -void NpcEventsHandler::onCreatureAppear(Creature* creature) -{ - if (m_onCreatureAppear == -1) { - return; - } - - //onCreatureAppear(creature) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreature] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onCreatureAppear, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onCreatureAppear); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - m_scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureDisappear(Creature* creature) -{ - if (m_onCreatureDisappear == -1) { - return; - } - - //onCreatureDisappear(creature) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureDisappear] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onCreatureDisappear, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onCreatureDisappear); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - m_scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureMove(Creature* creature, const Position& oldPos, const Position& newPos) -{ - if (m_onCreatureMove == -1) { - return; - } - - //onCreatureMove(creature, oldPos, newPos) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureMove] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onCreatureMove, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onCreatureMove); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushPosition(L, oldPos); - LuaScriptInterface::pushPosition(L, newPos); - m_scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) -{ - if (m_onCreatureSay == -1) { - return; - } - - //onCreatureSay(creature, type, msg) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureSay] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onCreatureSay, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onCreatureSay); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, type); - LuaScriptInterface::pushString(L, text); - m_scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onPlayerTrade(Player* player, int32_t callback, uint16_t itemid, - uint8_t count, uint8_t amount, bool ignore, bool inBackpacks) -{ - if (callback == -1) { - return; - } - - //onBuy(player, itemid, count, amount, ignore, inbackpacks) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onPlayerTrade] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(-1, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - LuaScriptInterface::pushCallback(L, callback); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - lua_pushnumber(L, itemid); - lua_pushnumber(L, count); - lua_pushnumber(L, amount); - LuaScriptInterface::pushBoolean(L, ignore); - LuaScriptInterface::pushBoolean(L, inBackpacks); - m_scriptInterface->callFunction(6); -} - -void NpcEventsHandler::onPlayerCloseChannel(Player* player) -{ - if (m_onPlayerCloseChannel == -1) { - return; - } - - //onPlayerCloseChannel(player) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onPlayerCloseChannel] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onPlayerCloseChannel, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onPlayerCloseChannel); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - m_scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onPlayerEndTrade(Player* player) -{ - if (m_onPlayerEndTrade == -1) { - return; - } - - //onPlayerEndTrade(player) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onPlayerEndTrade] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onPlayerEndTrade, m_scriptInterface); - env->setNpc(m_npc); - - lua_State* L = m_scriptInterface->getLuaState(); - m_scriptInterface->pushFunction(m_onPlayerEndTrade); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - m_scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onThink() -{ - if (m_onThink == -1) { - return; - } - - //onThink() - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onThink] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_onThink, m_scriptInterface); - env->setNpc(m_npc); - - m_scriptInterface->pushFunction(m_onThink); - m_scriptInterface->callFunction(0); -} diff --git a/path_10_8/src/npc.h b/path_10_8/src/npc.h deleted file mode 100644 index bd81f307e..000000000 --- a/path_10_8/src/npc.h +++ /dev/null @@ -1,249 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_NPC_H_B090D0CB549D4435AFA03647195D156F -#define FS_NPC_H_B090D0CB549D4435AFA03647195D156F - -#include "creature.h" -#include "luascript.h" - -#include - -class Npc; -class Player; - -class Npcs -{ - public: - static void reload(); -}; - -class NpcScriptInterface final : public LuaScriptInterface -{ - public: - NpcScriptInterface(); - - bool loadNpcLib(const std::string& file); - - protected: - void registerFunctions(); - - static int luaActionSay(lua_State* L); - static int luaActionMove(lua_State* L); - static int luaActionMoveTo(lua_State* L); - static int luaActionTurn(lua_State* L); - static int luaActionFollow(lua_State* L); - static int luagetDistanceTo(lua_State* L); - static int luaSetNpcFocus(lua_State* L); - static int luaGetNpcCid(lua_State* L); - static int luaGetNpcParameter(lua_State* L); - static int luaOpenShopWindow(lua_State* L); - static int luaCloseShopWindow(lua_State* L); - static int luaDoSellItem(lua_State* L); - - // metatable - static int luaNpcGetParameter(lua_State* L); - static int luaNpcSetFocus(lua_State* L); - - static int luaNpcOpenShopWindow(lua_State* L); - static int luaNpcCloseShopWindow(lua_State* L); - - private: - bool initState() final; - bool closeState() final; - - bool m_libLoaded; -}; - -class NpcEventsHandler -{ - public: - NpcEventsHandler(const std::string& file, Npc* npc); - - void onCreatureAppear(Creature* creature); - void onCreatureDisappear(Creature* creature); - void onCreatureMove(Creature* creature, const Position& oldPos, const Position& newPos); - void onCreatureSay(Creature* creature, SpeakClasses, const std::string& text); - void onPlayerTrade(Player* player, int32_t callback, uint16_t itemId, uint8_t count, uint8_t amount, bool ignore = false, bool inBackpacks = false); - void onPlayerCloseChannel(Player* player); - void onPlayerEndTrade(Player* player); - void onThink(); - - bool isLoaded() const; - - protected: - Npc* m_npc; - NpcScriptInterface* m_scriptInterface; - - int32_t m_onCreatureAppear; - int32_t m_onCreatureDisappear; - int32_t m_onCreatureMove; - int32_t m_onCreatureSay; - int32_t m_onPlayerCloseChannel; - int32_t m_onPlayerEndTrade; - int32_t m_onThink; - bool m_loaded; -}; - -class Npc final : public Creature -{ - public: - ~Npc(); - - // non-copyable - Npc(const Npc&) = delete; - Npc& operator=(const Npc&) = delete; - - Npc* getNpc() final { - return this; - } - const Npc* getNpc() const final { - return this; - } - - bool isPushable() const final { - return walkTicks > 0; - } - - void setID() final { - if (id == 0) { - id = npcAutoID++; - } - } - - void removeList() final; - void addList() final; - - static Npc* createNpc(const std::string& name); - - bool canSee(const Position& pos) const final; - - bool load(); - void reload(); - - const std::string& getName() const final { - return name; - } - const std::string& getNameDescription() const final { - return name; - } - - CreatureType_t getType() const final { - return CREATURETYPE_NPC; - } - - uint8_t getSpeechBubble() const final { - return speechBubble; - } - void setSpeechBubble(const uint8_t bubble) { - speechBubble = bubble; - } - - void doSay(const std::string& text); - void doSayToPlayer(Player* player, const std::string& text); - - void doMoveTo(const Position& pos); - - int32_t getMasterRadius() const { - return masterRadius; - } - const Position& getMasterPos() const { - return masterPos; - } - void setMasterPos(Position pos, int32_t radius = 1) { - masterPos = pos; - if (masterRadius == -1) { - masterRadius = radius; - } - } - - void onPlayerCloseChannel(Player* player); - void onPlayerTrade(Player* player, int32_t callback, uint16_t itemId, uint8_t count, - uint8_t amount, bool ignore = false, bool inBackpacks = false); - void onPlayerEndTrade(Player* player, int32_t buyCallback, int32_t sellCallback); - - void turnToCreature(Creature* creature); - void setCreatureFocus(Creature* creature); - - NpcScriptInterface* getScriptInterface(); - - static uint32_t npcAutoID; - - protected: - explicit Npc(const std::string& _name); - - void onCreatureAppear(Creature* creature, bool isLogin) final; - void onRemoveCreature(Creature* creature, bool isLogout) final; - void onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) final; - - void onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) final; - void onThink(uint32_t interval) final; - std::string getDescription(int32_t lookDistance) const final; - - bool isImmune(CombatType_t) const final { - return !attackable; - } - bool isImmune(ConditionType_t) const final { - return !attackable; - } - bool isAttackable() const final { - return attackable; - } - bool getNextStep(Direction& dir, uint32_t& flags) final; - - bool canWalkTo(const Position& fromPos, Direction dir) const; - bool getRandomStep(Direction& dir) const; - - void reset(); - bool loadFromXml(const std::string& name); - - void addShopPlayer(Player* player); - void removeShopPlayer(Player* player); - void closeAllShopWindows(); - - std::map m_parameters; - - std::set shopPlayerSet; - - std::string name; - std::string m_filename; - - NpcEventsHandler* m_npcEventHandler; - - Position masterPos; - - uint32_t walkTicks; - int32_t focusCreature; - int32_t masterRadius; - - uint8_t speechBubble; - - bool floorChange; - bool attackable; - bool ignoreHeight; - bool loaded; - - static NpcScriptInterface* m_scriptInterface; - - friend class Npcs; - friend class NpcScriptInterface; -}; - -#endif diff --git a/path_10_8/src/otpch.cpp b/path_10_8/src/otpch.cpp deleted file mode 100644 index b8314c168..000000000 --- a/path_10_8/src/otpch.cpp +++ /dev/null @@ -1,20 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" \ No newline at end of file diff --git a/path_10_8/src/otpch.h b/path_10_8/src/otpch.h deleted file mode 100644 index 75f0a8284..000000000 --- a/path_10_8/src/otpch.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#define FS_OTPCH_H_F00C737DA6CA4C8D90F57430C614367F - -// Definitions should be global. -#include "definitions.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ext/pugixml.hpp" diff --git a/path_10_8/src/otserv.cpp b/path_10_8/src/otserv.cpp deleted file mode 100644 index 94ff8112d..000000000 --- a/path_10_8/src/otserv.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "server.h" - -#include "game.h" - -#include "iomarket.h" - -#ifndef _WIN32 -#include // for sigemptyset() -#endif - -#include "configmanager.h" -#include "scriptmanager.h" -#include "rsa.h" -#include "protocolold.h" -#include "protocollogin.h" -#include "protocolstatus.h" -#include "databasemanager.h" -#include "scheduler.h" -#include "databasetasks.h" - -DatabaseTasks g_databaseTasks; -Dispatcher g_dispatcher; -Scheduler g_scheduler; - -Game g_game; -ConfigManager g_config; -Monsters g_monsters; -Vocations g_vocations; -RSA g_RSA; - -std::mutex g_loaderLock; -std::condition_variable g_loaderSignal; -std::unique_lock g_loaderUniqueLock(g_loaderLock); - -void startupErrorMessage(const std::string& errorStr) -{ - std::cout << "> ERROR: " << errorStr << std::endl; - g_loaderSignal.notify_all(); -} - -void mainLoader(int argc, char* argv[], ServiceManager* servicer); - -void badAllocationHandler() -{ - // Use functions that only use stack allocation - puts("Allocation failed, server out of memory.\nDecrease the size of your map or compile in 64 bits mode.\n"); - getchar(); - exit(-1); -} - -int main(int argc, char* argv[]) -{ - // Setup bad allocation handler - std::set_new_handler(badAllocationHandler); - -#ifndef _WIN32 - // ignore sigpipe... - struct sigaction sigh; - sigh.sa_handler = SIG_IGN; - sigh.sa_flags = 0; - sigemptyset(&sigh.sa_mask); - sigaction(SIGPIPE, &sigh, nullptr); -#endif - - ServiceManager serviceManager; - - g_dispatcher.start(); - g_scheduler.start(); - - g_dispatcher.addTask(createTask(std::bind(mainLoader, argc, argv, &serviceManager))); - - g_loaderSignal.wait(g_loaderUniqueLock); - - if (serviceManager.is_running()) { - std::cout << ">> " << g_config.getString(ConfigManager::SERVER_NAME) << " Server Online!" << std::endl << std::endl; -#ifdef _WIN32 - SetConsoleCtrlHandler([](DWORD) -> BOOL { - g_dispatcher.addTask(createTask([]() { - g_dispatcher.addTask(createTask( - std::bind(&Game::shutdown, &g_game) - )); - g_scheduler.stop(); - g_databaseTasks.stop(); - g_dispatcher.stop(); - })); - ExitThread(0); - }, 1); -#endif - serviceManager.run(); - } else { - std::cout << ">> No services running. The server is NOT online." << std::endl; - g_scheduler.shutdown(); - g_databaseTasks.shutdown(); - g_dispatcher.shutdown(); - } - - g_scheduler.join(); - g_databaseTasks.join(); - g_dispatcher.join(); - return 0; -} - -void mainLoader(int, char*[], ServiceManager* services) -{ - //dispatcher thread - g_game.setGameState(GAME_STATE_STARTUP); - - srand(static_cast(OTSYS_TIME())); -#ifdef _WIN32 - SetConsoleTitle(STATUS_SERVER_NAME); -#endif - std::cout << "The " << STATUS_SERVER_NAME << " Version: (" << STATUS_SERVER_VERSION << "." << MINOR_VERSION << "." << REVISION_VERSION << ") - Codename: (" << SOFTWARE_CODENAME << ")" << std::endl; - std::cout << "Compiled with: " << BOOST_COMPILER << std::endl; - std::cout << "Compiled on " << __DATE__ << ' ' << __TIME__ << " for platform "; - -#if defined(__amd64__) || defined(_M_X64) - std::cout << "x64" << std::endl; -#elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) - std::cout << "x86" << std::endl; -#elif defined(__arm__) - std::cout << "ARM" << std::endl; -#else - std::cout << "unknown" << std::endl; -#endif - std::cout << std::endl; - - std::cout << "A server developed by " << STATUS_SERVER_DEVELOPERS << "." << std::endl; - std::cout << "Visit our forum for updates, support, and resources: " << GIT_REPO <<"." << std::endl; - std::cout << std::endl; - - // read global config - std::cout << ">> Loading config" << std::endl; - if (!g_config.load()) { - startupErrorMessage("Unable to load config.lua!"); - return; - } - -#ifdef _WIN32 - const std::string& defaultPriority = g_config.getString(ConfigManager::DEFAULT_PRIORITY); - if (strcasecmp(defaultPriority.c_str(), "high") == 0) { - SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); - } else if (strcasecmp(defaultPriority.c_str(), "above-normal") == 0) { - SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); - } -#endif - - //set RSA key - const char* p("14299623962416399520070177382898895550795403345466153217470516082934737582776038882967213386204600674145392845853859217990626450972452084065728686565928113"); - const char* q("7630979195970404721891201847792002125535401292779123937207447574596692788513647179235335529307251350570728407373705564708871762033017096809910315212884101"); - g_RSA.setKey(p, q); - - std::cout << ">> Establishing database connection..." << std::flush; - - Database* db = Database::getInstance(); - if (!db->connect()) { - startupErrorMessage("Failed to connect to database."); - return; - } - - std::cout << " MySQL " << Database::getClientVersion() << std::endl; - - // run database manager - std::cout << ">> Running database manager" << std::endl; - - if (!DatabaseManager::isDatabaseSetup()) { - startupErrorMessage("The database you have specified in config.lua is empty, please import the schema.sql to your database."); - return; - } - g_databaseTasks.start(); - - DatabaseManager::updateDatabase(); - - if (g_config.getBoolean(ConfigManager::OPTIMIZE_DATABASE) && !DatabaseManager::optimizeTables()) { - std::cout << "> No tables were optimized." << std::endl; - } - - //load vocations - std::cout << ">> Loading vocations" << std::endl; - if (!g_vocations.loadFromXml()) { - startupErrorMessage("Unable to load vocations!"); - return; - } - - // load item data - std::cout << ">> Loading items" << std::endl; - if (Item::items.loadFromOtb("data/items/items.otb") != ERROR_NONE) { - startupErrorMessage("Unable to load items (OTB)!"); - return; - } - - if (!Item::items.loadFromXml()) { - startupErrorMessage("Unable to load items (XML)!"); - return; - } - - std::cout << ">> Loading script systems" << std::endl; - if (!ScriptingManager::getInstance()->loadScriptSystems()) { - startupErrorMessage("Failed to load script systems"); - return; - } - - std::cout << ">> Loading monsters" << std::endl; - if (!g_monsters.loadFromXml()) { - startupErrorMessage("Unable to load monsters!"); - return; - } - - std::cout << ">> Loading outfits" << std::endl; - Outfits* outfits = Outfits::getInstance(); - if (!outfits->loadFromXml()) { - startupErrorMessage("Unable to load outfits!"); - return; - } - - std::cout << ">> Checking world type... " << std::flush; - std::string worldType = asLowerCaseString(g_config.getString(ConfigManager::WORLD_TYPE)); - if (worldType == "pvp") { - g_game.setWorldType(WORLD_TYPE_PVP); - } else if (worldType == "no-pvp") { - g_game.setWorldType(WORLD_TYPE_NO_PVP); - } else if (worldType == "pvp-enforced") { - g_game.setWorldType(WORLD_TYPE_PVP_ENFORCED); - } else { - std::cout << std::endl; - - std::ostringstream ss; - ss << "> ERROR: Unknown world type: " << g_config.getString(ConfigManager::WORLD_TYPE) << ", valid world types are: pvp, no-pvp and pvp-enforced."; - startupErrorMessage(ss.str()); - return; - } - std::cout << asUpperCaseString(worldType) << std::endl; - - std::cout << ">> Loading map" << std::endl; - if (!g_game.loadMainMap(g_config.getString(ConfigManager::MAP_NAME))) { - startupErrorMessage("Failed to load map"); - return; - } - - std::cout << ">> Initializing gamestate" << std::endl; - g_game.setGameState(GAME_STATE_INIT); - - // Game client protocols - services->add(g_config.getNumber(ConfigManager::GAME_PORT)); - services->add(g_config.getNumber(ConfigManager::LOGIN_PORT)); - - // OT protocols - services->add(g_config.getNumber(ConfigManager::STATUS_PORT)); - - // Legacy login protocol - services->add(g_config.getNumber(ConfigManager::LOGIN_PORT)); - - RentPeriod_t rentPeriod; - std::string strRentPeriod = asLowerCaseString(g_config.getString(ConfigManager::HOUSE_RENT_PERIOD)); - - if (strRentPeriod == "yearly") { - rentPeriod = RENTPERIOD_YEARLY; - } else if (strRentPeriod == "weekly") { - rentPeriod = RENTPERIOD_WEEKLY; - } else if (strRentPeriod == "monthly") { - rentPeriod = RENTPERIOD_MONTHLY; - } else if (strRentPeriod == "daily") { - rentPeriod = RENTPERIOD_DAILY; - } else { - rentPeriod = RENTPERIOD_NEVER; - } - - g_game.map.houses.payHouses(rentPeriod); - - IOMarket::checkExpiredOffers(); - IOMarket::getInstance()->updateStatistics(); - - std::cout << ">> Loaded all modules, server starting up..." << std::endl; - -#ifndef _WIN32 - if (getuid() == 0 || geteuid() == 0) { - std::cout << "> Warning: " << STATUS_SERVER_NAME << " has been executed as root user, please consider running it as a normal user." << std::endl; - } -#endif - - g_game.start(services); - g_game.setGameState(GAME_STATE_NORMAL); - g_loaderSignal.notify_all(); -} diff --git a/path_10_8/src/outfit.cpp b/path_10_8/src/outfit.cpp deleted file mode 100644 index 2ad61e01b..000000000 --- a/path_10_8/src/outfit.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "outfit.h" - -#include "pugicast.h" -#include "tools.h" - -bool Outfits::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/outfits.xml"); - if (!result) { - printXMLError("Error - Outfits::loadFromXml", "data/XML/outfits.xml", result); - return false; - } - - for (auto outfitNode : doc.child("outfits").children()) { - pugi::xml_attribute attr; - if ((attr = outfitNode.attribute("enabled")) && !attr.as_bool()) { - continue; - } - - if (!(attr = outfitNode.attribute("type"))) { - std::cout << "[Warning - Outfits::loadFromXml] Missing outfit type." << std::endl; - continue; - } - - uint16_t type = pugi::cast(attr.value()); - if (type > PLAYERSEX_LAST) { - std::cout << "[Warning - Outfits::loadFromXml] Invalid outfit type " << type << "." << std::endl; - continue; - } - - pugi::xml_attribute lookTypeAttribute = outfitNode.attribute("looktype"); - if (!lookTypeAttribute) { - std::cout << "[Warning - Outfits::loadFromXml] Missing looktype on outfit." << std::endl; - continue; - } - - outfits[type].emplace_back( - outfitNode.attribute("name").as_string(), - pugi::cast(lookTypeAttribute.value()), - outfitNode.attribute("premium").as_bool(), - outfitNode.attribute("unlocked").as_bool(true) - ); - } - return true; -} - -const Outfit* Outfits::getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) const -{ - for (const Outfit& outfit : outfits[sex]) { - if (outfit.lookType == lookType) { - return &outfit; - } - } - return nullptr; -} diff --git a/path_10_8/src/outfit.h b/path_10_8/src/outfit.h deleted file mode 100644 index 01385e159..000000000 --- a/path_10_8/src/outfit.h +++ /dev/null @@ -1,61 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_OUTFIT_H_C56E7A707E3F422C8C93D9BE09916AA3 -#define FS_OUTFIT_H_C56E7A707E3F422C8C93D9BE09916AA3 - -#include "enums.h" - -struct Outfit { - Outfit(std::string name, uint16_t lookType, bool premium, bool unlocked) : name(name), lookType(lookType), premium(premium), unlocked(unlocked) {} - - std::string name; - uint16_t lookType; - bool premium; - bool unlocked; -}; - -struct ProtocolOutfit { - ProtocolOutfit(const std::string* name, uint16_t lookType, uint8_t addons) : name(name), lookType(lookType), addons(addons) {} - - const std::string* name; - uint16_t lookType; - uint8_t addons; -}; - -class Outfits -{ - public: - static Outfits* getInstance() { - static Outfits instance; - return &instance; - } - - bool loadFromXml(); - - const Outfit* getOutfitByLookType(PlayerSex_t sex, uint16_t lookType) const; - const std::vector& getOutfits(PlayerSex_t sex) const { - return outfits[sex]; - } - - private: - std::vector outfits[PLAYERSEX_LAST + 1]; -}; - -#endif diff --git a/path_10_8/src/outputmessage.cpp b/path_10_8/src/outputmessage.cpp deleted file mode 100644 index 81a6d97f6..000000000 --- a/path_10_8/src/outputmessage.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "outputmessage.h" -#include "protocol.h" -#include "lockfree.h" -#include "scheduler.h" - -extern Scheduler g_scheduler; - -const uint16_t OUTPUTMESSAGE_FREE_LIST_CAPACITY = 2048; -const std::chrono::milliseconds OUTPUTMESSAGE_AUTOSEND_DELAY {10}; - -class OutputMessageAllocator -{ - public: - typedef OutputMessage value_type; - template - struct rebind {typedef LockfreePoolingAllocator other;}; -}; - -void OutputMessagePool::scheduleSendAll() -{ - auto functor = std::bind(&OutputMessagePool::sendAll, this); - g_scheduler.addEvent(createSchedulerTask(OUTPUTMESSAGE_AUTOSEND_DELAY.count(), functor)); -} - -void OutputMessagePool::sendAll() -{ - //dispatcher thread - for (auto& protocol : bufferedProtocols) { - auto& msg = protocol->getCurrentBuffer(); - if (msg) { - protocol->send(std::move(msg)); - } - } - - if (!bufferedProtocols.empty()) { - scheduleSendAll(); - } -} - -void OutputMessagePool::addProtocolToAutosend(Protocol_ptr protocol) -{ - //dispatcher thread - if (bufferedProtocols.empty()) { - scheduleSendAll(); - } - bufferedProtocols.emplace_back(protocol); -} - -void OutputMessagePool::removeProtocolFromAutosend(const Protocol_ptr& protocol) -{ - //dispatcher thread - auto it = std::find(bufferedProtocols.begin(), bufferedProtocols.end(), protocol); - if (it != bufferedProtocols.end()) { - bufferedProtocols.erase(it); - } -} - -OutputMessage_ptr OutputMessagePool::getOutputMessage() -{ - return std::allocate_shared(OutputMessageAllocator()); -} diff --git a/path_10_8/src/outputmessage.h b/path_10_8/src/outputmessage.h deleted file mode 100644 index f58a313a5..000000000 --- a/path_10_8/src/outputmessage.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_OUTPUTMESSAGE_H_C06AAED85C7A43939F22D229297C0CC1 -#define FS_OUTPUTMESSAGE_H_C06AAED85C7A43939F22D229297C0CC1 - -#include "networkmessage.h" -#include "connection.h" -#include "tools.h" - -class Protocol; - -class OutputMessage : public NetworkMessage -{ - public: - OutputMessage(): - outputBufferStart(INITIAL_BUFFER_POSITION) {} - - // non-copyable - OutputMessage(const OutputMessage&) = delete; - OutputMessage& operator=(const OutputMessage&) = delete; - - uint8_t* getOutputBuffer() { - return buffer + outputBufferStart; - } - - void writeMessageLength() { - add_header(length); - } - - void addCryptoHeader(bool addChecksum) { - if (addChecksum) { - add_header(adlerChecksum(buffer + outputBufferStart, length)); - } - - writeMessageLength(); - } - - inline void append(const NetworkMessage& msg) { - auto msgLen = msg.getLength(); - memcpy(buffer + position, msg.getBuffer() + 8, msgLen); - length += msgLen; - position += msgLen; - } - - inline void append(const OutputMessage_ptr& msg) { - auto msgLen = msg->getLength(); - memcpy(buffer + position, msg->getBuffer() + 8, msgLen); - length += msgLen; - position += msgLen; - } - - protected: - template - inline void add_header(T add) { - assert(outputBufferStart >= sizeof(T)); - outputBufferStart -= sizeof(T); - memcpy(buffer + outputBufferStart, &add, sizeof(T)); - //added header size to the message size - length += sizeof(T); - } - - MsgSize_t outputBufferStart; -}; - -class OutputMessagePool -{ - public: - // non-copyable - OutputMessagePool(const OutputMessagePool&) = delete; - OutputMessagePool& operator=(const OutputMessagePool&) = delete; - - static OutputMessagePool& getInstance() { - static OutputMessagePool instance; - return instance; - } - - void sendAll(); - void scheduleSendAll(); - - static OutputMessage_ptr getOutputMessage(); - - void addProtocolToAutosend(Protocol_ptr protocol); - void removeProtocolFromAutosend(const Protocol_ptr& protocol); - private: - OutputMessagePool() = default; - //NOTE: A vector is used here because this container is mostly read - //and relatively rarely modified (only when a client connects/disconnects) - std::vector bufferedProtocols; -}; - - -#endif diff --git a/path_10_8/src/party.cpp b/path_10_8/src/party.cpp deleted file mode 100644 index 75e9de73e..000000000 --- a/path_10_8/src/party.cpp +++ /dev/null @@ -1,502 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "party.h" -#include "game.h" -#include "configmanager.h" -#include "events.h" - -extern Game g_game; -extern ConfigManager g_config; -extern Events* g_events; - -Party::Party(Player* leader) -{ - extraExpRate = 0.20f; - - sharedExpActive = false; - sharedExpEnabled = false; - - this->leader = leader; - leader->setParty(this); -} - -void Party::disband() -{ - if (!g_events->eventPartyOnDisband(this)) { - return; - } - - Player* currentLeader = leader; - leader = nullptr; - - currentLeader->setParty(nullptr); - currentLeader->sendClosePrivate(CHANNEL_PARTY); - g_game.updatePlayerShield(currentLeader); - g_game.updatePlayerHelpers(*currentLeader); - currentLeader->sendCreatureSkull(currentLeader); - currentLeader->sendTextMessage(MESSAGE_INFO_DESCR, "Your party has been disbanded."); - - for (Player* invitee : inviteList) { - invitee->removePartyInvitation(this); - currentLeader->sendCreatureShield(invitee); - } - inviteList.clear(); - - for (Player* member : memberList) { - member->setParty(nullptr); - member->sendClosePrivate(CHANNEL_PARTY); - member->sendTextMessage(MESSAGE_INFO_DESCR, "Your party has been disbanded."); - } - - for (Player* member : memberList) { - g_game.updatePlayerShield(member); - - for (Player* otherMember : memberList) { - otherMember->sendCreatureSkull(member); - } - - member->sendCreatureSkull(currentLeader); - currentLeader->sendCreatureSkull(member); - g_game.updatePlayerHelpers(*member); - } - memberList.clear(); - delete this; -} - -bool Party::leaveParty(Player* player) -{ - if (!player) { - return false; - } - - if (player->getParty() != this && leader != player) { - return false; - } - - if (!g_events->eventPartyOnLeave(this, player)) { - return false; - } - - bool missingLeader = false; - if (leader == player) { - if (!memberList.empty()) { - if (memberList.size() == 1 && inviteList.empty()) { - missingLeader = true; - } else { - passPartyLeadership(memberList.front()); - } - } else { - missingLeader = true; - } - } - - //since we already passed the leadership, we remove the player from the list - auto it = std::find(memberList.begin(), memberList.end(), player); - if (it != memberList.end()) { - memberList.erase(it); - } - - player->setParty(nullptr); - player->sendClosePrivate(CHANNEL_PARTY); - g_game.updatePlayerShield(player); - g_game.updatePlayerHelpers(*player); - - for (Player* member : memberList) { - member->sendCreatureSkull(player); - player->sendPlayerPartyIcons(member); - g_game.updatePlayerHelpers(*member); - } - - leader->sendCreatureSkull(player); - player->sendCreatureSkull(player); - player->sendPlayerPartyIcons(leader); - - player->sendTextMessage(MESSAGE_INFO_DESCR, "You have left the party."); - - updateSharedExperience(); - updateVocationsList(); - - clearPlayerPoints(player); - - std::ostringstream ss; - ss << player->getName() << " has left the party."; - broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str()); - - if (missingLeader || empty()) { - disband(); - } - - return true; -} - -bool Party::passPartyLeadership(Player* player) -{ - if (!player || leader == player || player->getParty() != this) { - return false; - } - - //Remove it before to broadcast the message correctly - auto it = std::find(memberList.begin(), memberList.end(), player); - if (it != memberList.end()) { - memberList.erase(it); - } - - std::ostringstream ss; - ss << player->getName() << " is now the leader of the party."; - broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str(), true); - - Player* oldLeader = leader; - leader = player; - - memberList.insert(memberList.begin(), oldLeader); - - updateSharedExperience(); - - for (Player* member : memberList) { - member->sendCreatureShield(oldLeader); - member->sendCreatureShield(leader); - } - - for (Player* invitee : inviteList) { - invitee->sendCreatureShield(oldLeader); - invitee->sendCreatureShield(leader); - } - - leader->sendCreatureShield(oldLeader); - leader->sendCreatureShield(leader); - - player->sendTextMessage(MESSAGE_INFO_DESCR, "You are now the leader of the party."); - return true; -} - -bool Party::joinParty(Player& player) -{ - if (!g_events->eventPartyOnJoin(this, &player)) { - return false; - } - - auto it = std::find(inviteList.begin(), inviteList.end(), &player); - if (it == inviteList.end()) { - return false; - } - - inviteList.erase(it); - - std::ostringstream ss; - ss << player.getName() << " has joined the party."; - broadcastPartyMessage(MESSAGE_INFO_DESCR, ss.str()); - - player.setParty(this); - - g_game.updatePlayerShield(&player); - - for (Player* member : memberList) { - member->sendCreatureSkull(&player); - player.sendPlayerPartyIcons(member); - } - - player.sendCreatureSkull(&player); - leader->sendCreatureSkull(&player); - player.sendPlayerPartyIcons(leader); - - memberList.push_back(&player); - - g_game.updatePlayerHelpers(player); - - player.removePartyInvitation(this); - updateSharedExperience(); - updateVocationsList(); - - const std::string& leaderName = leader->getName(); - ss.str(std::string()); - ss << "You have joined " << leaderName << "'" << (leaderName.back() == 's' ? "" : "s") << - " party. Open the party channel to communicate with your companions."; - player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - return true; -} - -bool Party::removeInvite(Player& player, bool removeFromPlayer/* = true*/) -{ - auto it = std::find(inviteList.begin(), inviteList.end(), &player); - if (it == inviteList.end()) { - return false; - } - - inviteList.erase(it); - - leader->sendCreatureShield(&player); - player.sendCreatureShield(leader); - - if (removeFromPlayer) { - player.removePartyInvitation(this); - } - - if (empty()) { - disband(); - } else { - for (Player* member : memberList) { - g_game.updatePlayerHelpers(*member); - } - - g_game.updatePlayerHelpers(*leader); - } - - return true; -} - -void Party::revokeInvitation(Player& player) -{ - std::ostringstream ss; - ss << leader->getName() << " has revoked " << (leader->getSex() == PLAYERSEX_FEMALE ? "her" : "his") << " invitation."; - player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - ss.str(std::string()); - ss << "Invitation for " << player.getName() << " has been revoked."; - leader->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - removeInvite(player); -} - -bool Party::invitePlayer(Player& player) -{ - if (isPlayerInvited(&player)) { - return false; - } - - std::ostringstream ss; - ss << player.getName() << " has been invited."; - - if (memberList.empty() && inviteList.empty()) { - ss << " Open the party channel to communicate with your members."; - g_game.updatePlayerShield(leader); - leader->sendCreatureSkull(leader); - } - - leader->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - - inviteList.push_back(&player); - - for (Player* member : memberList) { - g_game.updatePlayerHelpers(*member); - } - g_game.updatePlayerHelpers(*leader); - - leader->sendCreatureShield(&player); - player.sendCreatureShield(leader); - - player.addPartyInvitation(this); - - ss.str(std::string()); - ss << leader->getName() << " has invited you to " << (leader->getSex() == PLAYERSEX_FEMALE ? "her" : "his") << " party."; - player.sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - return true; -} - -bool Party::isPlayerInvited(const Player* player) const -{ - return std::find(inviteList.begin(), inviteList.end(), player) != inviteList.end(); -} - -void Party::updateAllPartyIcons() -{ - for (Player* member : memberList) { - for (Player* otherMember : memberList) { - member->sendCreatureShield(otherMember); - } - - member->sendCreatureShield(leader); - leader->sendCreatureShield(member); - } - leader->sendCreatureShield(leader); -} - -void Party::broadcastPartyMessage(MessageClasses msgClass, const std::string& msg, bool sendToInvitations /*= false*/) -{ - for (Player* member : memberList) { - member->sendTextMessage(msgClass, msg); - } - - leader->sendTextMessage(msgClass, msg); - - if (sendToInvitations) { - for (Player* invitee : inviteList) { - invitee->sendTextMessage(msgClass, msg); - } - } -} - -void Party::broadcastPartyLoot(const std::string& loot) -{ - leader->sendTextMessage(MESSAGE_INFO_DESCR, loot); - - for (Player* member : memberList) { - member->sendTextMessage(MESSAGE_INFO_DESCR, loot); - } -} - -void Party::updateSharedExperience() -{ - if (sharedExpActive) { - bool result = canEnableSharedExperience(); - if (result != sharedExpEnabled) { - sharedExpEnabled = result; - updateAllPartyIcons(); - } - } -} - -void Party::updateVocationsList() -{ - std::set vocationIds; - - uint32_t vocationId = leader->getVocation()->getFromVocation(); - if (vocationId != VOCATION_NONE) { - vocationIds.insert(vocationId); - } - - for (const Player* member : memberList) { - vocationId = member->getVocation()->getFromVocation(); - if (vocationId != VOCATION_NONE) { - vocationIds.insert(vocationId); - } - } - - size_t size = vocationIds.size(); - if (size > 1) { - extraExpRate = static_cast(size * (10 + (size - 1) * 5)) / 100.f; - } else { - extraExpRate = 0.20f; - } -} - -bool Party::setSharedExperience(Player* player, bool _sharedExpActive) -{ - if (!player || leader != player) { - return false; - } - - if (sharedExpActive == _sharedExpActive) { - return true; - } - - sharedExpActive = _sharedExpActive; - - if (sharedExpActive) { - sharedExpEnabled = canEnableSharedExperience(); - - if (sharedExpEnabled) { - leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience is now active."); - } else { - leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience has been activated, but some members of your party are inactive."); - } - } else { - leader->sendTextMessage(MESSAGE_INFO_DESCR, "Shared Experience has been deactivated."); - } - - updateAllPartyIcons(); - return true; -} - -void Party::shareExperience(uint64_t experience, Creature* source/* = nullptr*/) -{ - uint32_t shareExperience = static_cast(std::ceil(((static_cast(experience) / (memberList.size() + 1)) + (static_cast(experience) * extraExpRate)))); - for (Player* member : memberList) { - member->onGainSharedExperience(shareExperience, source); - } - leader->onGainSharedExperience(shareExperience, source); -} - -bool Party::canUseSharedExperience(const Player* player) const -{ - if (memberList.empty()) { - return false; - } - - uint32_t highestLevel = leader->getLevel(); - for (Player* member : memberList) { - if (member->getLevel() > highestLevel) { - highestLevel = member->getLevel(); - } - } - - uint32_t minLevel = static_cast(std::ceil((static_cast(highestLevel) * 2) / 3)); - if (player->getLevel() < minLevel) { - return false; - } - - if (!Position::areInRange<30, 30, 1>(leader->getPosition(), player->getPosition())) { - return false; - } - - if (!player->hasFlag(PlayerFlag_NotGainInFight)) { - //check if the player has healed/attacked anything recently - auto it = ticksMap.find(player->getID()); - if (it == ticksMap.end()) { - return false; - } - - uint64_t timeDiff = OTSYS_TIME() - it->second; - if (timeDiff > static_cast(g_config.getNumber(ConfigManager::PZ_LOCKED))) { - return false; - } - } - return true; -} - -bool Party::canEnableSharedExperience() -{ - if (!canUseSharedExperience(leader)) { - return false; - } - - for (Player* member : memberList) { - if (!canUseSharedExperience(member)) { - return false; - } - } - return true; -} - -void Party::updatePlayerTicks(Player* player, uint32_t points) -{ - if (points != 0 && !player->hasFlag(PlayerFlag_NotGainInFight)) { - ticksMap[player->getID()] = OTSYS_TIME(); - updateSharedExperience(); - } -} - -void Party::clearPlayerPoints(Player* player) -{ - auto it = ticksMap.find(player->getID()); - if (it != ticksMap.end()) { - ticksMap.erase(it); - updateSharedExperience(); - } -} - -bool Party::canOpenCorpse(uint32_t ownerId) const -{ - if (Player* player = g_game.getPlayerByID(ownerId)) { - return leader->getID() == ownerId || player->getParty() == this; - } - return false; -} diff --git a/path_10_8/src/party.h b/path_10_8/src/party.h deleted file mode 100644 index 849685317..000000000 --- a/path_10_8/src/party.h +++ /dev/null @@ -1,102 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PARTY_H_41D4D7CF417C4CC99FAE94D552255044 -#define FS_PARTY_H_41D4D7CF417C4CC99FAE94D552255044 - -#include "player.h" -#include "monsters.h" - -class Player; -class Party; - -typedef std::vector PlayerVector; - -class Party -{ - public: - explicit Party(Player* leader); - - Player* getLeader() const { - return leader; - } - PlayerVector& getMembers() { - return memberList; - } - const PlayerVector& getInvitees() const { - return inviteList; - } - size_t getMemberCount() const { - return memberList.size(); - } - size_t getInvitationCount() const { - return inviteList.size(); - } - - void disband(); - bool invitePlayer(Player& player); - bool joinParty(Player& player); - void revokeInvitation(Player& player); - bool passPartyLeadership(Player* player); - bool leaveParty(Player* player); - - bool removeInvite(Player& player, bool removeFromPlayer = true); - - bool isPlayerInvited(const Player* player) const; - void updateAllPartyIcons(); - void broadcastPartyMessage(MessageClasses msgClass, const std::string& msg, bool sendToInvitations = false); - void broadcastPartyLoot(const std::string& loot); - bool empty() const { - return memberList.empty() && inviteList.empty(); - } - bool canOpenCorpse(uint32_t ownerId) const; - - void shareExperience(uint64_t experience, Creature* source = nullptr); - bool setSharedExperience(Player* player, bool _sharedExpActive); - bool isSharedExperienceActive() const { - return sharedExpActive; - } - bool isSharedExperienceEnabled() const { - return sharedExpEnabled; - } - bool canUseSharedExperience(const Player* player) const; - void updateSharedExperience(); - - void updateVocationsList(); - - void updatePlayerTicks(Player* player, uint32_t points); - void clearPlayerPoints(Player* player); - - protected: - bool canEnableSharedExperience(); - - std::map ticksMap; - - PlayerVector memberList; - PlayerVector inviteList; - - Player* leader; - - float extraExpRate; - - bool sharedExpActive; - bool sharedExpEnabled; -}; - -#endif diff --git a/path_10_8/src/player.cpp b/path_10_8/src/player.cpp deleted file mode 100644 index 52553267e..000000000 --- a/path_10_8/src/player.cpp +++ /dev/null @@ -1,4625 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "bed.h" -#include "chat.h" -#include "combat.h" -#include "configmanager.h" -#include "creatureevent.h" -#include "events.h" -#include "game.h" -#include "iologindata.h" -#include "monster.h" -#include "movement.h" -#include "outputmessage.h" -#include "scheduler.h" -#include "weapons.h" - -extern ConfigManager g_config; -extern Game g_game; -extern Chat* g_chat; -extern Vocations g_vocations; -extern MoveEvents* g_moveEvents; -extern Weapons* g_weapons; -extern CreatureEvents* g_creatureEvents; -extern Events* g_events; - -MuteCountMap Player::muteCountMap; - -uint32_t Player::playerAutoID = 0x10000000; - -Player::Player(ProtocolGame_ptr p) : - Creature(), inventory(), varSkills(), varStats(), inventoryAbilities() -{ - client = p; - isConnecting = false; - - accountNumber = 0; - setVocation(0); - capacity = 40000; - mana = 0; - manaMax = 0; - manaSpent = 0; - soul = 0; - guildLevel = 0; - guild = nullptr; - - level = 1; - levelPercent = 0; - magLevelPercent = 0; - magLevel = 0; - experience = 0; - - damageImmunities = 0; - conditionImmunities = 0; - conditionSuppressions = 0; - group = nullptr; - lastLoginSaved = 0; - lastLogout = 0; - lastIP = 0; - lastPing = OTSYS_TIME(); - lastPong = lastPing; - MessageBufferTicks = 0; - MessageBufferCount = 0; - nextAction = 0; - - windowTextId = 0; - writeItem = nullptr; - maxWriteLen = 0; - - editHouse = nullptr; - editListId = 0; - - shopOwner = nullptr; - purchaseCallback = -1; - saleCallback = -1; - - pzLocked = false; - bloodHitCount = 0; - shieldBlockCount = 0; - lastAttackBlockType = BLOCK_NONE; - addAttackSkillPoint = false; - lastAttack = 0; - - blessings = 0; - - inMarket = false; - lastDepotId = -1; - - chaseMode = CHASEMODE_STANDSTILL; - fightMode = FIGHTMODE_ATTACK; - - bedItem = nullptr; - - tradePartner = nullptr; - tradeState = TRADE_NONE; - tradeItem = nullptr; - - walkTask = nullptr; - walkTaskEvent = 0; - actionTaskEvent = 0; - nextStepEvent = 0; - - lastFailedFollow = 0; - lastWalkthroughAttempt = 0; - lastToggleMount = 0; - - wasMounted = false; - - sex = PLAYERSEX_FEMALE; - - town = nullptr; - - accountType = ACCOUNT_TYPE_NORMAL; - premiumDays = 0; - - idleTime = 0; - - skullTicks = 0; - setParty(nullptr); - - bankBalance = 0; - - inbox = new Inbox(ITEM_INBOX); - inbox->incrementReferenceCounter(); - - offlineTrainingSkill = -1; - offlineTrainingTime = 0; - lastStatsTrainingTime = 0; - - ghostMode = false; - - staminaMinutes = 2520; - - lastQuestlogUpdate = 0; - - inventoryWeight = 0; -} - -Player::~Player() -{ - for (Item* item : inventory) { - if (item) { - item->setParent(nullptr); - item->decrementReferenceCounter(); - } - } - - for (const auto& it : depotLockerMap) { - it.second->removeInbox(inbox); - it.second->decrementReferenceCounter(); - } - - inbox->decrementReferenceCounter(); - - setWriteItem(nullptr); - setEditHouse(nullptr); -} - -bool Player::setVocation(uint16_t vocId) -{ - Vocation* voc = g_vocations.getVocation(vocId); - if (!voc) { - return false; - } - vocation = voc; - - Condition* condition = getCondition(CONDITION_REGENERATION, CONDITIONID_DEFAULT); - if (condition) { - condition->setParam(CONDITION_PARAM_HEALTHGAIN, vocation->getHealthGainAmount()); - condition->setParam(CONDITION_PARAM_HEALTHTICKS, vocation->getHealthGainTicks() * 1000); - condition->setParam(CONDITION_PARAM_MANAGAIN, vocation->getManaGainAmount()); - condition->setParam(CONDITION_PARAM_MANATICKS, vocation->getManaGainTicks() * 1000); - } - return true; -} - -bool Player::isPushable() const -{ - if (hasFlag(PlayerFlag_CannotBePushed)) { - return false; - } - return Creature::isPushable(); -} - -std::string Player::getDescription(int32_t lookDistance) const -{ - std::ostringstream s; - - if (lookDistance == -1) { - s << "yourself."; - - if (group->access) { - s << " You are " << group->name << '.'; - } else if (vocation->getId() != VOCATION_NONE) { - s << " You are " << vocation->getVocDescription() << '.'; - } else { - s << " You have no vocation."; - } - } else { - s << name; - if (!group->access) { - s << " (Level " << level << ')'; - } - s << '.'; - - if (sex == PLAYERSEX_FEMALE) { - s << " She"; - } else { - s << " He"; - } - - if (group->access) { - s << " is " << group->name << '.'; - } else if (vocation->getId() != VOCATION_NONE) { - s << " is " << vocation->getVocDescription() << '.'; - } else { - s << " has no vocation."; - } - } - - if (party) { - if (lookDistance == -1) { - s << " Your party has "; - } else if (sex == PLAYERSEX_FEMALE) { - s << " She is in a party with "; - } else { - s << " He is in a party with "; - } - - size_t memberCount = party->getMemberCount() + 1; - if (memberCount == 1) { - s << "1 member and "; - } else { - s << memberCount << " members and "; - } - - size_t invitationCount = party->getInvitationCount(); - if (invitationCount == 1) { - s << "1 pending invitation."; - } else { - s << invitationCount << " pending invitations."; - } - } - - if (guild) { - const GuildRank* rank = guild->getRankByLevel(guildLevel); - if (rank) { - if (lookDistance == -1) { - s << " You are "; - } else if (sex == PLAYERSEX_FEMALE) { - s << " She is "; - } else { - s << " He is "; - } - - s << rank->name << " of the " << guild->getName(); - if (!guildNick.empty()) { - s << " (" << guildNick << ')'; - } - - size_t memberCount = guild->getMemberCount(); - if (memberCount == 1) { - s << ", which has 1 member, " << guild->getMembersOnline().size() << " of them online."; - } else { - s << ", which has " << memberCount << " members, " << guild->getMembersOnline().size() << " of them online."; - } - } - } - return s.str(); -} - -Item* Player::getInventoryItem(slots_t slot) const -{ - if (slot < CONST_SLOT_FIRST || slot > CONST_SLOT_LAST) { - return nullptr; - } - return inventory[slot]; -} - -void Player::addConditionSuppressions(uint32_t conditions) -{ - conditionSuppressions |= conditions; -} - -void Player::removeConditionSuppressions(uint32_t conditions) -{ - conditionSuppressions &= ~conditions; -} - -Item* Player::getWeapon(slots_t slot, bool ignoreAmmo) const -{ - Item* item = inventory[slot]; - if (!item) { - return nullptr; - } - - WeaponType_t weaponType = item->getWeaponType(); - if (weaponType == WEAPON_NONE || weaponType == WEAPON_SHIELD || weaponType == WEAPON_AMMO) { - return nullptr; - } - - if (!ignoreAmmo && weaponType == WEAPON_DISTANCE) { - const ItemType& it = Item::items[item->getID()]; - if (it.ammoType != AMMO_NONE) { - Item* ammoItem = inventory[CONST_SLOT_AMMO]; - if (!ammoItem || ammoItem->getAmmoType() != it.ammoType) { - return nullptr; - } - item = ammoItem; - } - } - return item; -} - -Item* Player::getWeapon(bool ignoreAmmo/* = false*/) const -{ - Item* item = getWeapon(CONST_SLOT_LEFT, ignoreAmmo); - if (item) { - return item; - } - - item = getWeapon(CONST_SLOT_RIGHT, ignoreAmmo); - if (item) { - return item; - } - return nullptr; -} - -WeaponType_t Player::getWeaponType() const -{ - Item* item = getWeapon(); - if (!item) { - return WEAPON_NONE; - } - return item->getWeaponType(); -} - -int32_t Player::getWeaponSkill(const Item* item) const -{ - if (!item) { - return getSkillLevel(SKILL_FIST); - } - - int32_t attackSkill; - - WeaponType_t weaponType = item->getWeaponType(); - switch (weaponType) { - case WEAPON_SWORD: { - attackSkill = getSkillLevel(SKILL_SWORD); - break; - } - - case WEAPON_CLUB: { - attackSkill = getSkillLevel(SKILL_CLUB); - break; - } - - case WEAPON_AXE: { - attackSkill = getSkillLevel(SKILL_AXE); - break; - } - - case WEAPON_DISTANCE: { - attackSkill = getSkillLevel(SKILL_DISTANCE); - break; - } - - default: { - attackSkill = 0; - break; - } - } - return attackSkill; -} - -int32_t Player::getArmor() const -{ - int32_t armor = 0; - - static const slots_t armorSlots[] = {CONST_SLOT_HEAD, CONST_SLOT_NECKLACE, CONST_SLOT_ARMOR, CONST_SLOT_LEGS, CONST_SLOT_FEET, CONST_SLOT_RING}; - for (slots_t slot : armorSlots) { - Item* inventoryItem = inventory[slot]; - if (inventoryItem) { - armor += inventoryItem->getArmor(); - } - } - return static_cast(armor * vocation->armorMultiplier); -} - -void Player::getShieldAndWeapon(const Item*& shield, const Item*& weapon) const -{ - shield = nullptr; - weapon = nullptr; - - for (uint32_t slot = CONST_SLOT_RIGHT; slot <= CONST_SLOT_LEFT; slot++) { - Item* item = inventory[slot]; - if (!item) { - continue; - } - - switch (item->getWeaponType()) { - case WEAPON_NONE: - break; - - case WEAPON_SHIELD: { - if (!shield || (shield && item->getDefense() > shield->getDefense())) { - shield = item; - } - break; - } - - default: { // weapons that are not shields - weapon = item; - break; - } - } - } -} - -int32_t Player::getDefense() const -{ - int32_t baseDefense = 5; - int32_t defenseValue = 0; - int32_t defenseSkill = 0; - int32_t extraDefense = 0; - float defenseFactor = getDefenseFactor(); - const Item* weapon; - const Item* shield; - getShieldAndWeapon(shield, weapon); - - if (weapon) { - defenseValue = baseDefense + weapon->getDefense(); - extraDefense = weapon->getExtraDefense(); - defenseSkill = getWeaponSkill(weapon); - } - - if (shield && shield->getDefense() >= defenseValue) { - defenseValue = baseDefense + shield->getDefense() + extraDefense; - defenseSkill = getSkillLevel(SKILL_SHIELD); - } - - if (defenseSkill == 0) { - return 0; - } - - defenseValue = static_cast(defenseValue * vocation->defenseMultiplier); - return static_cast(std::ceil((static_cast(defenseSkill * (defenseValue * 0.015)) + (defenseValue * 0.1)) * defenseFactor)); -} - -float Player::getAttackFactor() const -{ - switch (fightMode) { - case FIGHTMODE_ATTACK: return 1.0f; - case FIGHTMODE_BALANCED: return 1.2f; - case FIGHTMODE_DEFENSE: return 2.0f; - default: return 1.0f; - } -} - -float Player::getDefenseFactor() const -{ - switch (fightMode) { - case FIGHTMODE_ATTACK: return 1.0f; - case FIGHTMODE_BALANCED: return 1.2f; - case FIGHTMODE_DEFENSE: { - if ((OTSYS_TIME() - lastAttack) < getAttackSpeed()) { - return 1.0f; - } - - return 2.0f; - } - default: return 1.0f; - } -} - -uint16_t Player::getClientIcons() const -{ - uint16_t icons = 0; - for (Condition* condition : conditions) { - if (!isSuppress(condition->getType())) { - icons |= condition->getIcons(); - } - } - - if (pzLocked) { - icons |= ICON_REDSWORDS; - } - - if (_tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - icons |= ICON_PIGEON; - - // Don't show ICON_SWORDS if player is in protection zone. - if (hasBitSet(ICON_SWORDS, icons)) { - icons &= ~ICON_SWORDS; - } - } - - // Game client debugs with 10 or more icons - // so let's prevent that from happening. - std::bitset<20> icon_bitset(static_cast(icons)); - for (size_t pos = 0, bits_set = icon_bitset.count(); bits_set >= 10; ++pos) { - if (icon_bitset[pos]) { - icon_bitset.reset(pos); - --bits_set; - } - } - return icon_bitset.to_ulong(); -} - -void Player::updateInventoryWeight() -{ - if (hasFlag(PlayerFlag_HasInfiniteCapacity)) { - return; - } - - inventoryWeight = 0; - for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - const Item* item = inventory[i]; - if (item) { - inventoryWeight += item->getWeight(); - } - } -} - -int32_t Player::getPlayerInfo(playerinfo_t playerinfo) const -{ - switch (playerinfo) { - case PLAYERINFO_LEVELPERCENT: return levelPercent; - case PLAYERINFO_MAGICLEVEL: return std::max(0, magLevel + varStats[STAT_MAGICPOINTS]); - case PLAYERINFO_MAGICLEVELPERCENT: return magLevelPercent; - case PLAYERINFO_HEALTH: return health; - case PLAYERINFO_MAXHEALTH: return std::max(1, healthMax + varStats[STAT_MAXHITPOINTS]); - case PLAYERINFO_MANA: return mana; - case PLAYERINFO_MAXMANA: return std::max(0, manaMax + varStats[STAT_MAXMANAPOINTS]); - default: return 0; - } -} - -void Player::addSkillAdvance(skills_t skill, uint64_t count) -{ - uint64_t currReqTries = vocation->getReqSkillTries(skill, skills[skill].level); - uint64_t nextReqTries = vocation->getReqSkillTries(skill, skills[skill].level + 1); - if (currReqTries >= nextReqTries) { - //player has reached max skill - return; - } - - g_events->eventPlayerOnGainSkillTries(this, skill, count); - if (count == 0) { - return; - } - - bool sendUpdateSkills = false; - while ((skills[skill].tries + count) >= nextReqTries) { - count -= nextReqTries - skills[skill].tries; - skills[skill].level++; - skills[skill].tries = 0; - skills[skill].percent = 0; - - std::ostringstream ss; - ss << "You advanced to " << getSkillName(skill) << " level " << skills[skill].level << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - - g_creatureEvents->playerAdvance(this, skill, (skills[skill].level - 1), skills[skill].level); - - sendUpdateSkills = true; - currReqTries = nextReqTries; - nextReqTries = vocation->getReqSkillTries(skill, skills[skill].level + 1); - if (currReqTries >= nextReqTries) { - count = 0; - break; - } - } - - skills[skill].tries += count; - - uint32_t newPercent; - if (nextReqTries > currReqTries) { - newPercent = Player::getPercentLevel(skills[skill].tries, nextReqTries); - } else { - newPercent = 0; - } - - if (skills[skill].percent != newPercent) { - skills[skill].percent = newPercent; - sendUpdateSkills = true; - } - - if (sendUpdateSkills) { - sendSkills(); - } -} - -void Player::setVarStats(stats_t stat, int32_t modifier) -{ - varStats[stat] += modifier; - - switch (stat) { - case STAT_MAXHITPOINTS: { - if (getHealth() > getMaxHealth()) { - Creature::changeHealth(getMaxHealth() - getHealth()); - } else { - g_game.addCreatureHealth(this); - } - break; - } - - case STAT_MAXMANAPOINTS: { - if (getMana() > getMaxMana()) { - Creature::changeMana(getMaxMana() - getMana()); - } - break; - } - - default: { - break; - } - } -} - -int32_t Player::getDefaultStats(stats_t stat) const -{ - switch (stat) { - case STAT_MAXHITPOINTS: return healthMax; - case STAT_MAXMANAPOINTS: return manaMax; - case STAT_MAGICPOINTS: return getBaseMagicLevel(); - default: return 0; - } -} - -void Player::addContainer(uint8_t cid, Container* container) -{ - if (cid > 0xF) { - return; - } - - if (container->getID() == ITEM_BROWSEFIELD) { - container->incrementReferenceCounter(); - } - - auto it = openContainers.find(cid); - if (it != openContainers.end()) { - OpenContainer& openContainer = it->second; - Container* oldContainer = openContainer.container; - if (oldContainer->getID() == ITEM_BROWSEFIELD) { - oldContainer->decrementReferenceCounter(); - } - - openContainer.container = container; - openContainer.index = 0; - } else { - OpenContainer openContainer; - openContainer.container = container; - openContainer.index = 0; - openContainers[cid] = openContainer; - } -} - -void Player::closeContainer(uint8_t cid) -{ - auto it = openContainers.find(cid); - if (it == openContainers.end()) { - return; - } - - OpenContainer openContainer = it->second; - Container* container = openContainer.container; - openContainers.erase(it); - - if (container && container->getID() == ITEM_BROWSEFIELD) { - container->decrementReferenceCounter(); - } -} - -void Player::setContainerIndex(uint8_t cid, uint16_t index) -{ - auto it = openContainers.find(cid); - if (it == openContainers.end()) { - return; - } - it->second.index = index; -} - -Container* Player::getContainerByID(uint8_t cid) -{ - auto it = openContainers.find(cid); - if (it == openContainers.end()) { - return nullptr; - } - return it->second.container; -} - -int8_t Player::getContainerID(const Container* container) const -{ - for (const auto& it : openContainers) { - if (it.second.container == container) { - return it.first; - } - } - return -1; -} - -uint16_t Player::getContainerIndex(uint8_t cid) const -{ - auto it = openContainers.find(cid); - if (it == openContainers.end()) { - return 0; - } - return it->second.index; -} - -bool Player::canOpenCorpse(uint32_t ownerId) const -{ - return getID() == ownerId || (party && party->canOpenCorpse(ownerId)); -} - -uint16_t Player::getLookCorpse() const -{ - if (sex == PLAYERSEX_FEMALE) { - return ITEM_FEMALE_CORPSE; - } else { - return ITEM_MALE_CORPSE; - } -} - -void Player::addStorageValue(const uint32_t key, const int32_t value, const bool isLogin/* = false*/) -{ - if (IS_IN_KEYRANGE(key, RESERVED_RANGE)) { - if (IS_IN_KEYRANGE(key, OUTFITS_RANGE)) { - outfits.emplace_back( - value >> 16, - value & 0xFF - ); - return; - } else if (IS_IN_KEYRANGE(key, MOUNTS_RANGE)) { - // do nothing - } else { - std::cout << "Warning: unknown reserved key: " << key << " player: " << getName() << std::endl; - return; - } - } - - if (value != -1) { - int32_t oldValue; - getStorageValue(key, oldValue); - - storageMap[key] = value; - - if (!isLogin) { - auto currentFrameTime = g_dispatcher.getDispatcherCycle(); - if (lastQuestlogUpdate != currentFrameTime && g_game.quests.isQuestStorage(key, value, oldValue)) { - lastQuestlogUpdate = currentFrameTime; - sendTextMessage(MESSAGE_EVENT_ADVANCE, "Your questlog has been updated."); - } - } - } else { - storageMap.erase(key); - } -} - -bool Player::getStorageValue(const uint32_t key, int32_t& value) const -{ - auto it = storageMap.find(key); - if (it == storageMap.end()) { - value = -1; - return false; - } - - value = it->second; - return true; -} - -bool Player::canSee(const Position& pos) const -{ - if (!client) { - return false; - } - return client->canSee(pos); -} - -bool Player::canSeeCreature(const Creature* creature) const -{ - if (creature == this) { - return true; - } - - if (creature->isInGhostMode() && !group->access) { - return false; - } - - if (!creature->getPlayer() && !canSeeInvisibility() && creature->isInvisible()) { - return false; - } - return true; -} - -bool Player::canWalkthrough(const Creature* creature) const -{ - if (group->access || creature->isInGhostMode()) { - return true; - } - - const Player* player = creature->getPlayer(); - if (!player || !g_config.getBoolean(ConfigManager::ALLOW_WALKTHROUGH)) { - return false; - } - - const Tile* playerTile = player->getTile(); - if (!playerTile || !playerTile->hasFlag(TILESTATE_PROTECTIONZONE)) { - return false; - } - - const Item* playerTileGround = playerTile->getGround(); - if (!playerTileGround || !playerTileGround->hasWalkStack()) { - return false; - } - - Player* thisPlayer = const_cast(this); - if ((OTSYS_TIME() - lastWalkthroughAttempt) > 2000) { - thisPlayer->setLastWalkthroughAttempt(OTSYS_TIME()); - return false; - } - - if (creature->getPosition() != lastWalkthroughPosition) { - thisPlayer->setLastWalkthroughPosition(creature->getPosition()); - return false; - } - - thisPlayer->setLastWalkthroughPosition(creature->getPosition()); - return true; -} - -bool Player::canWalkthroughEx(const Creature* creature) const -{ - if (group->access) { - return true; - } - - const Player* player = creature->getPlayer(); - if (!player || !g_config.getBoolean(ConfigManager::ALLOW_WALKTHROUGH)) { - return false; - } - - const Tile* playerTile = player->getTile(); - return playerTile && playerTile->hasFlag(TILESTATE_PROTECTIONZONE); -} - -void Player::onReceiveMail() -{ - if (isNearDepotBox()) { - sendTextMessage(MESSAGE_EVENT_ADVANCE, "New mail has arrived."); - } -} - -bool Player::isNearDepotBox() const -{ - const Position& pos = getPosition(); - for (int32_t cx = -1; cx <= 1; ++cx) { - for (int32_t cy = -1; cy <= 1; ++cy) { - Tile* tile = g_game.map.getTile(pos.x + cx, pos.y + cy, pos.z); - if (!tile) { - continue; - } - - if (tile->hasFlag(TILESTATE_DEPOT)) { - return true; - } - } - } - return false; -} - -DepotChest* Player::getDepotChest(uint32_t depotId, bool autoCreate) -{ - auto it = depotChests.find(depotId); - if (it != depotChests.end()) { - return it->second; - } - - if (!autoCreate) { - return nullptr; - } - - DepotChest* depotChest = new DepotChest(ITEM_DEPOT); - depotChest->incrementReferenceCounter(); - depotChest->setMaxDepotItems(getMaxDepotItems()); - depotChests[depotId] = depotChest; - return depotChest; -} - -DepotLocker* Player::getDepotLocker(uint32_t depotId) -{ - auto it = depotLockerMap.find(depotId); - if (it != depotLockerMap.end()) { - inbox->setParent(it->second); - return it->second; - } - - DepotLocker* depotLocker = new DepotLocker(ITEM_LOCKER1); - depotLocker->setDepotId(depotId); - depotLocker->internalAddThing(Item::CreateItem(ITEM_MARKET)); - depotLocker->internalAddThing(inbox); - depotLocker->internalAddThing(getDepotChest(depotId, true)); - depotLockerMap[depotId] = depotLocker; - return depotLocker; -} - -void Player::sendCancelMessage(ReturnValue message) const -{ - sendCancelMessage(getReturnMessage(message)); -} - -void Player::sendStats() -{ - if (client) { - client->sendStats(); - lastStatsTrainingTime = getOfflineTrainingTime() / 60 / 1000; - } -} - -void Player::sendPing() -{ - int64_t timeNow = OTSYS_TIME(); - - bool hasLostConnection = false; - if ((timeNow - lastPing) >= 5000) { - lastPing = timeNow; - if (client) { - client->sendPing(); - } else { - hasLostConnection = true; - } - } - - int64_t noPongTime = timeNow - lastPong; - if ((hasLostConnection || noPongTime >= 7000) && attackedCreature && attackedCreature->getPlayer()) { - setAttackedCreature(nullptr); - } - - if (noPongTime >= 60000 && canLogout()) { - if (g_creatureEvents->playerLogout(this)) { - if (client) { - client->logout(true, true); - } else { - g_game.removeCreature(this, true); - } - } - } -} - -Item* Player::getWriteItem(uint32_t& _windowTextId, uint16_t& _maxWriteLen) -{ - _windowTextId = windowTextId; - _maxWriteLen = maxWriteLen; - return writeItem; -} - -void Player::setWriteItem(Item* item, uint16_t _maxWriteLen /*= 0*/) -{ - windowTextId++; - - if (writeItem) { - writeItem->decrementReferenceCounter(); - } - - if (item) { - writeItem = item; - maxWriteLen = _maxWriteLen; - writeItem->incrementReferenceCounter(); - } else { - writeItem = nullptr; - maxWriteLen = 0; - } -} - -House* Player::getEditHouse(uint32_t& _windowTextId, uint32_t& _listId) -{ - _windowTextId = windowTextId; - _listId = editListId; - return editHouse; -} - -void Player::setEditHouse(House* house, uint32_t listId /*= 0*/) -{ - windowTextId++; - editHouse = house; - editListId = listId; -} - -void Player::sendHouseWindow(House* house, uint32_t listId) const -{ - if (!client) { - return; - } - - std::string text; - if (house->getAccessList(listId, text)) { - client->sendHouseWindow(windowTextId, text); - } -} - -//container -void Player::sendAddContainerItem(const Container* container, const Item* item) -{ - if (!client) { - return; - } - - for (const auto& it : openContainers) { - const OpenContainer& openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - uint16_t slot = openContainer.index; - if (container->getID() == ITEM_BROWSEFIELD) { - uint16_t containerSize = container->size() - 1; - uint16_t pageEnd = openContainer.index + container->capacity() - 1; - if (containerSize > pageEnd) { - slot = pageEnd; - item = container->getItemByIndex(pageEnd); - } else { - slot = containerSize; - } - } else if (openContainer.index >= container->capacity()) { - item = container->getItemByIndex(openContainer.index - 1); - } - client->sendAddContainerItem(it.first, slot, item); - } -} - -void Player::sendUpdateContainerItem(const Container* container, uint16_t slot, const Item* newItem) -{ - if (!client) { - return; - } - - for (const auto& it : openContainers) { - const OpenContainer& openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - if (slot < openContainer.index) { - continue; - } - - uint16_t pageEnd = openContainer.index + container->capacity(); - if (slot >= pageEnd) { - continue; - } - - client->sendUpdateContainerItem(it.first, slot, newItem); - } -} - -void Player::sendRemoveContainerItem(const Container* container, uint16_t slot) -{ - if (!client) { - return; - } - - for (auto& it : openContainers) { - OpenContainer& openContainer = it.second; - if (openContainer.container != container) { - continue; - } - - uint16_t& firstIndex = openContainer.index; - if (firstIndex > 0 && firstIndex >= container->size() - 1) { - firstIndex -= container->capacity(); - sendContainer(it.first, container, false, firstIndex); - } - - client->sendRemoveContainerItem(it.first, std::max(slot, firstIndex), container->getItemByIndex(container->capacity() + firstIndex)); - } -} - -void Player::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, - const ItemType& oldType, const Item* newItem, const ItemType& newType) -{ - Creature::onUpdateTileItem(tile, pos, oldItem, oldType, newItem, newType); - - if (oldItem != newItem) { - onRemoveTileItem(tile, pos, oldType, oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - if (tradeItem && oldItem == tradeItem) { - g_game.internalCloseTrade(this); - } - } -} - -void Player::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, - const Item* item) -{ - Creature::onRemoveTileItem(tile, pos, iType, item); - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - const Container* container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - g_game.internalCloseTrade(this); - } - } - } -} - -void Player::onCreatureAppear(Creature* creature, bool isLogin) -{ - Creature::onCreatureAppear(creature, isLogin); - - if (isLogin && creature == this) { - for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { - Item* item = inventory[slot]; - if (item) { - item->startDecaying(); - g_moveEvents->onPlayerEquip(this, item, static_cast(slot), false); - } - } - - for (Condition* condition : storedConditionList) { - addCondition(condition); - } - storedConditionList.clear(); - - BedItem* bed = g_game.getBedBySleeper(guid); - if (bed) { - bed->wakeUp(this); - } - - std::cout << name << " has logged in." << std::endl; - - if (guild) { - guild->addMember(this); - } - - int32_t offlineTime; - if (getLastLogout() != 0) { - // Not counting more than 21 days to prevent overflow when multiplying with 1000 (for milliseconds). - offlineTime = std::min(time(nullptr) - getLastLogout(), 86400 * 21); - } else { - offlineTime = 0; - } - - for (Condition* condition : getMuteConditions()) { - condition->setTicks(condition->getTicks() - (offlineTime * 1000)); - if (condition->getTicks() <= 0) { - removeCondition(condition); - } - } - - g_game.checkPlayersRecord(); - IOLoginData::updateOnlineStatus(guid, true); - } -} - -void Player::onAttackedCreatureDisappear(bool isLogout) -{ - sendCancelTarget(); - - if (!isLogout) { - sendTextMessage(MESSAGE_STATUS_SMALL, "Target lost."); - } -} - -void Player::onFollowCreatureDisappear(bool isLogout) -{ - sendCancelTarget(); - - if (!isLogout) { - sendTextMessage(MESSAGE_STATUS_SMALL, "Target lost."); - } -} - -void Player::onChangeZone(ZoneType_t zone) -{ - if (zone == ZONE_PROTECTION) { - if (attackedCreature && !hasFlag(PlayerFlag_IgnoreProtectionZone)) { - setAttackedCreature(nullptr); - onAttackedCreatureDisappear(false); - } - - if (!group->access && isMounted()) { - dismount(); - g_game.internalCreatureChangeOutfit(this, defaultOutfit); - wasMounted = true; - } - } else { - if (wasMounted) { - toggleMount(true); - wasMounted = false; - } - } - - g_game.updateCreatureWalkthrough(this); - sendIcons(); -} - -void Player::onAttackedCreatureChangeZone(ZoneType_t zone) -{ - if (zone == ZONE_PROTECTION) { - if (!hasFlag(PlayerFlag_IgnoreProtectionZone)) { - setAttackedCreature(nullptr); - onAttackedCreatureDisappear(false); - } - } else if (zone == ZONE_NOPVP) { - if (attackedCreature->getPlayer()) { - if (!hasFlag(PlayerFlag_IgnoreProtectionZone)) { - setAttackedCreature(nullptr); - onAttackedCreatureDisappear(false); - } - } - } else if (zone == ZONE_NORMAL) { - //attackedCreature can leave a pvp zone if not pzlocked - if (g_game.getWorldType() == WORLD_TYPE_NO_PVP) { - if (attackedCreature->getPlayer()) { - setAttackedCreature(nullptr); - onAttackedCreatureDisappear(false); - } - } - } -} - -void Player::onRemoveCreature(Creature* creature, bool isLogout) -{ - Creature::onRemoveCreature(creature, isLogout); - - if (creature == this) { - if (isLogout) { - loginPosition = getPosition(); - } - - lastLogout = time(nullptr); - - if (eventWalk != 0) { - setFollowCreature(nullptr); - } - - if (tradePartner) { - g_game.internalCloseTrade(this); - } - - closeShopWindow(); - - clearPartyInvitations(); - - if (party) { - party->leaveParty(this); - } - - g_chat->removeUserFromAllChannels(*this); - - std::cout << getName() << " has logged out." << std::endl; - - if (guild) { - guild->removeMember(this); - } - - IOLoginData::updateOnlineStatus(guid, false); - - bool saved = false; - for (uint32_t tries = 0; tries < 3; ++tries) { - if (IOLoginData::savePlayer(this)) { - saved = true; - break; - } - } - - if (!saved) { - std::cout << "Error while saving player: " << getName() << std::endl; - } - } -} - -void Player::openShopWindow(Npc* npc, const std::list& shop) -{ - shopItemList = shop; - sendShop(npc); - sendSaleItemList(); -} - -bool Player::closeShopWindow(bool sendCloseShopWindow /*= true*/) -{ - //unreference callbacks - int32_t onBuy; - int32_t onSell; - - Npc* npc = getShopOwner(onBuy, onSell); - if (!npc) { - shopItemList.clear(); - return false; - } - - setShopOwner(nullptr, -1, -1); - npc->onPlayerEndTrade(this, onBuy, onSell); - - if (sendCloseShopWindow) { - sendCloseShop(); - } - - shopItemList.clear(); - return true; -} - -void Player::onWalk(Direction& dir) -{ - Creature::onWalk(dir); - setNextActionTask(nullptr); - setNextAction(OTSYS_TIME() + getStepDuration(dir)); -} - -void Player::onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) -{ - Creature::onCreatureMove(creature, newTile, newPos, oldTile, oldPos, teleport); - - if (hasFollowPath && (creature == followCreature || (creature == this && followCreature))) { - isUpdatingPath = false; - g_dispatcher.addTask(createTask(std::bind(&Game::updateCreatureWalk, &g_game, getID()))); - } - - if (creature != this) { - return; - } - - if (tradeState != TRADE_TRANSFER) { - //check if we should close trade - if (tradeItem && !Position::areInRange<1, 1, 0>(tradeItem->getPosition(), getPosition())) { - g_game.internalCloseTrade(this); - } - - if (tradePartner && !Position::areInRange<2, 2, 0>(tradePartner->getPosition(), getPosition())) { - g_game.internalCloseTrade(this); - } - } - - // close modal windows - if (!modalWindows.empty()) { - // TODO: This shouldn't be hardcoded - for (uint32_t modalWindowId : modalWindows) { - if (modalWindowId == std::numeric_limits::max()) { - sendTextMessage(MESSAGE_EVENT_ADVANCE, "Offline training aborted."); - break; - } - } - modalWindows.clear(); - } - - // leave market - if (inMarket) { - inMarket = false; - } - - if (party) { - party->updateSharedExperience(); - } - - if (teleport || oldPos.z != newPos.z) { - int32_t ticks = g_config.getNumber(ConfigManager::STAIRHOP_DELAY); - if (ticks > 0) { - if (Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_PACIFIED, ticks, 0)) { - addCondition(condition); - } - } - } - - // unset editing house - if (editHouse && !newTile->hasFlag(TILESTATE_HOUSE)) { - editHouse = nullptr; - } -} - -//container -void Player::onAddContainerItem(const Item* item) -{ - checkTradeState(item); -} - -void Player::onUpdateContainerItem(const Container* container, const Item* oldItem, const Item* newItem) -{ - if (oldItem != newItem) { - onRemoveContainerItem(container, oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(oldItem); - } -} - -void Player::onRemoveContainerItem(const Container* container, const Item* item) -{ - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - if (tradeItem->getParent() != container && container->isHoldingItem(tradeItem)) { - g_game.internalCloseTrade(this); - } - } - } -} - -void Player::onCloseContainer(const Container* container) -{ - if (!client) { - return; - } - - for (const auto& it : openContainers) { - if (it.second.container == container) { - client->sendCloseContainer(it.first); - } - } -} - -void Player::onSendContainer(const Container* container) -{ - if (!client) { - return; - } - - bool hasParent = container->hasParent(); - for (const auto& it : openContainers) { - const OpenContainer& openContainer = it.second; - if (openContainer.container == container) { - client->sendContainer(it.first, container, hasParent, openContainer.index); - } - } -} - -//inventory -void Player::onUpdateInventoryItem(Item* oldItem, Item* newItem) -{ - if (oldItem != newItem) { - onRemoveInventoryItem(oldItem); - } - - if (tradeState != TRADE_TRANSFER) { - checkTradeState(oldItem); - } -} - -void Player::onRemoveInventoryItem(Item* item) -{ - if (tradeState != TRADE_TRANSFER) { - checkTradeState(item); - - if (tradeItem) { - const Container* container = item->getContainer(); - if (container && container->isHoldingItem(tradeItem)) { - g_game.internalCloseTrade(this); - } - } - } -} - -void Player::checkTradeState(const Item* item) -{ - if (!tradeItem || tradeState == TRADE_TRANSFER) { - return; - } - - if (tradeItem == item) { - g_game.internalCloseTrade(this); - } else { - const Container* container = dynamic_cast(item->getParent()); - while (container) { - if (container == tradeItem) { - g_game.internalCloseTrade(this); - break; - } - - container = dynamic_cast(container->getParent()); - } - } -} - -void Player::setNextWalkActionTask(SchedulerTask* task) -{ - if (walkTaskEvent != 0) { - g_scheduler.stopEvent(walkTaskEvent); - walkTaskEvent = 0; - } - - delete walkTask; - walkTask = task; -} - -void Player::setNextWalkTask(SchedulerTask* task) -{ - if (nextStepEvent != 0) { - g_scheduler.stopEvent(nextStepEvent); - nextStepEvent = 0; - } - - if (task) { - nextStepEvent = g_scheduler.addEvent(task); - resetIdleTime(); - } -} - -void Player::setNextActionTask(SchedulerTask* task) -{ - if (actionTaskEvent != 0) { - g_scheduler.stopEvent(actionTaskEvent); - actionTaskEvent = 0; - } - - if (task) { - actionTaskEvent = g_scheduler.addEvent(task); - resetIdleTime(); - } -} - -uint32_t Player::getNextActionTime() const -{ - return std::max(SCHEDULER_MINTICKS, nextAction - OTSYS_TIME()); -} - -void Player::onThink(uint32_t interval) -{ - Creature::onThink(interval); - - sendPing(); - - MessageBufferTicks += interval; - if (MessageBufferTicks >= 1500) { - MessageBufferTicks = 0; - addMessageBuffer(); - } - - if (!getTile()->hasFlag(TILESTATE_NOLOGOUT) && !isAccessPlayer()) { - idleTime += interval; - const int32_t kickAfterMinutes = g_config.getNumber(ConfigManager::KICK_AFTER_MINUTES); - if (idleTime > (kickAfterMinutes * 60000) + 60000) { - kickPlayer(true); - } else if (client && idleTime == 60000 * kickAfterMinutes) { - std::ostringstream ss; - ss << "You have been idle for " << kickAfterMinutes << " minutes. You will be disconnected in one minute if you are still idle then."; - client->sendTextMessage(TextMessage(MESSAGE_STATUS_WARNING, ss.str())); - } - } - - if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) { - checkSkullTicks(interval); - } - - addOfflineTrainingTime(interval); - if (lastStatsTrainingTime != getOfflineTrainingTime() / 60 / 1000) { - sendStats(); - } -} - -uint32_t Player::isMuted() const -{ - if (hasFlag(PlayerFlag_CannotBeMuted)) { - return 0; - } - - int32_t muteTicks = 0; - for (Condition* condition : conditions) { - if (condition->getType() == CONDITION_MUTED && condition->getTicks() > muteTicks) { - muteTicks = condition->getTicks(); - } - } - return static_cast(muteTicks) / 1000; -} - -void Player::addMessageBuffer() -{ - if (MessageBufferCount > 0 && g_config.getNumber(ConfigManager::MAX_MESSAGEBUFFER) != 0 && !hasFlag(PlayerFlag_CannotBeMuted)) { - --MessageBufferCount; - } -} - -void Player::removeMessageBuffer() -{ - if (hasFlag(PlayerFlag_CannotBeMuted)) { - return; - } - - const int32_t maxMessageBuffer = g_config.getNumber(ConfigManager::MAX_MESSAGEBUFFER); - if (maxMessageBuffer != 0 && MessageBufferCount <= maxMessageBuffer + 1) { - if (++MessageBufferCount > maxMessageBuffer) { - uint32_t muteCount = 1; - auto it = muteCountMap.find(guid); - if (it != muteCountMap.end()) { - muteCount = it->second; - } - - uint32_t muteTime = 5 * muteCount * muteCount; - muteCountMap[guid] = muteCount + 1; - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_MUTED, muteTime * 1000, 0); - addCondition(condition); - - std::ostringstream ss; - ss << "You are muted for " << muteTime << " seconds."; - sendTextMessage(MESSAGE_STATUS_SMALL, ss.str()); - } - } -} - -void Player::drainHealth(Creature* attacker, int32_t damage) -{ - Creature::drainHealth(attacker, damage); - sendStats(); -} - -void Player::drainMana(Creature* attacker, int32_t manaLoss) -{ - Creature::drainMana(attacker, manaLoss); - sendStats(); -} - -void Player::addManaSpent(uint64_t amount) -{ - if (hasFlag(PlayerFlag_NotGainMana)) { - return; - } - - uint64_t currReqMana = vocation->getReqMana(magLevel); - uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); - if (currReqMana >= nextReqMana) { - //player has reached max magic level - return; - } - - g_events->eventPlayerOnGainSkillTries(this, SKILL_MAGLEVEL, amount); - if (amount == 0) { - return; - } - - bool sendUpdateStats = false; - while ((manaSpent + amount) >= nextReqMana) { - amount -= nextReqMana - manaSpent; - - magLevel++; - manaSpent = 0; - - std::ostringstream ss; - ss << "You advanced to magic level " << magLevel << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - - g_creatureEvents->playerAdvance(this, SKILL_MAGLEVEL, magLevel - 1, magLevel); - - sendUpdateStats = true; - currReqMana = nextReqMana; - nextReqMana = vocation->getReqMana(magLevel + 1); - if (currReqMana >= nextReqMana) { - return; - } - } - - manaSpent += amount; - - uint8_t oldPercent = magLevelPercent; - if (nextReqMana > currReqMana) { - magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana); - } else { - magLevelPercent = 0; - } - - if (oldPercent != magLevelPercent) { - sendUpdateStats = true; - } - - if (sendUpdateStats) { - sendStats(); - } -} - -void Player::addExperience(Creature* source, uint64_t exp, bool sendText/* = false*/) -{ - uint64_t currLevelExp = Player::getExpForLevel(level); - uint64_t nextLevelExp = Player::getExpForLevel(level + 1); - uint64_t rawExp = exp; - if (currLevelExp >= nextLevelExp) { - //player has reached max level - levelPercent = 0; - sendStats(); - return; - } - - g_events->eventPlayerOnGainExperience(this, source, exp, rawExp); - if (exp == 0) { - return; - } - - experience += exp; - - if (sendText) { - std::string expString = std::to_string(exp) + (exp != 1 ? " experience points." : " experience point."); - - TextMessage message(MESSAGE_EXPERIENCE, "You gained " + expString); - message.position = _position; - message.primary.value = exp; - message.primary.color = TEXTCOLOR_WHITE_EXP; - sendTextMessage(message); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_EXPERIENCE_OTHERS; - message.text = getName() + " gained " + expString; - for (Creature* spectator : list) { - spectator->getPlayer()->sendTextMessage(message); - } - } - } - - uint32_t prevLevel = level; - while (experience >= nextLevelExp) { - ++level; - healthMax += vocation->getHPGain(); - health += vocation->getHPGain(); - manaMax += vocation->getManaGain(); - mana += vocation->getManaGain(); - capacity += vocation->getCapGain(); - - currLevelExp = nextLevelExp; - nextLevelExp = Player::getExpForLevel(level + 1); - if (currLevelExp >= nextLevelExp) { - //player has reached max level - break; - } - } - - if (prevLevel != level) { - health = healthMax; - mana = manaMax; - - updateBaseSpeed(); - setBaseSpeed(getBaseSpeed()); - - g_game.changeSpeed(this, 0); - g_game.addCreatureHealth(this); - - if (party) { - party->updateSharedExperience(); - } - - g_creatureEvents->playerAdvance(this, SKILL_LEVEL, prevLevel, level); - - std::ostringstream ss; - ss << "You advanced from Level " << prevLevel << " to Level " << level << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - } - - if (nextLevelExp > currLevelExp) { - levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp); - } else { - levelPercent = 0; - } - sendStats(); -} - -void Player::removeExperience(uint64_t exp, bool sendText/* = false*/) -{ - if (experience == 0 || exp == 0) { - return; - } - - g_events->eventPlayerOnLoseExperience(this, exp); - if (exp == 0) { - return; - } - - uint64_t lostExp = experience; - experience = std::max(0, experience - exp); - - if (sendText) { - lostExp -= experience; - - std::string expString = std::to_string(lostExp) + (lostExp != 1 ? " experience points." : " experience point."); - - TextMessage message(MESSAGE_EXPERIENCE, "You lost " + expString); - message.position = _position; - message.primary.value = lostExp; - message.primary.color = TEXTCOLOR_RED; - sendTextMessage(message); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_EXPERIENCE_OTHERS; - message.text = getName() + " lost " + expString; - for (Creature* spectator : list) { - spectator->getPlayer()->sendTextMessage(message); - } - } - } - - uint32_t oldLevel = level; - uint64_t currLevelExp = Player::getExpForLevel(level); - - while (level > 1 && experience < currLevelExp) { - --level; - healthMax = std::max(0, healthMax - vocation->getHPGain()); - manaMax = std::max(0, manaMax - vocation->getManaGain()); - capacity = std::max(0, capacity - vocation->getCapGain()); - currLevelExp = Player::getExpForLevel(level); - } - - if (oldLevel != level) { - health = healthMax; - mana = manaMax; - - updateBaseSpeed(); - setBaseSpeed(getBaseSpeed()); - - g_game.changeSpeed(this, 0); - g_game.addCreatureHealth(this); - - if (party) { - party->updateSharedExperience(); - } - - std::ostringstream ss; - ss << "You were downgraded from Level " << oldLevel << " to Level " << level << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - } - - uint64_t nextLevelExp = Player::getExpForLevel(level + 1); - if (nextLevelExp > currLevelExp) { - levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp); - } else { - levelPercent = 0; - } - sendStats(); -} - -uint8_t Player::getPercentLevel(uint64_t count, uint64_t nextLevelCount) -{ - if (nextLevelCount == 0) { - return 0; - } - - uint8_t result = (count * 100) / nextLevelCount; - if (result > 100) { - return 0; - } - return result; -} - -void Player::onBlockHit() -{ - if (shieldBlockCount > 0) { - --shieldBlockCount; - - if (hasShield()) { - addSkillAdvance(SKILL_SHIELD, 1); - } - } -} - -void Player::onAttackedCreatureBlockHit(BlockType_t blockType) -{ - lastAttackBlockType = blockType; - - switch (blockType) { - case BLOCK_NONE: { - addAttackSkillPoint = true; - bloodHitCount = 30; - shieldBlockCount = 30; - break; - } - - case BLOCK_DEFENSE: - case BLOCK_ARMOR: { - //need to draw blood every 30 hits - if (bloodHitCount > 0) { - addAttackSkillPoint = true; - --bloodHitCount; - } else { - addAttackSkillPoint = false; - } - break; - } - - default: { - addAttackSkillPoint = false; - break; - } - } -} - -bool Player::hasShield() const -{ - Item* item = inventory[CONST_SLOT_LEFT]; - if (item && item->getWeaponType() == WEAPON_SHIELD) { - return true; - } - - item = inventory[CONST_SLOT_RIGHT]; - if (item && item->getWeaponType() == WEAPON_SHIELD) { - return true; - } - return false; -} - -BlockType_t Player::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense /* = false*/, bool checkArmor /* = false*/, bool field /* = false*/) -{ - BlockType_t blockType = Creature::blockHit(attacker, combatType, damage, checkDefense, checkArmor, field); - - if (attacker) { - sendCreatureSquare(attacker, SQ_COLOR_BLACK); - } - - if (blockType != BLOCK_NONE) { - return blockType; - } - - if (damage > 0) { - for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { - if (!isItemAbilityEnabled(static_cast(slot))) { - continue; - } - - Item* item = inventory[slot]; - if (!item) { - continue; - } - - const ItemType& it = Item::items[item->getID()]; - if (it.abilities) { - const int16_t& absorbPercent = it.abilities->absorbPercent[combatTypeToIndex(combatType)]; - if (absorbPercent != 0) { - damage -= std::ceil(damage * (absorbPercent / 100.)); - - uint16_t charges = item->getCharges(); - if (charges != 0) { - g_game.transformItem(item, item->getID(), charges - 1); - } - } - - if (field) { - const int16_t& fieldAbsorbPercent = it.abilities->fieldAbsorbPercent[combatTypeToIndex(combatType)]; - if (fieldAbsorbPercent != 0) { - damage -= std::ceil(damage * (fieldAbsorbPercent / 100.)); - - uint16_t charges = item->getCharges(); - if (charges != 0) { - g_game.transformItem(item, item->getID(), charges - 1); - } - } - } - } - } - - if (damage <= 0) { - damage = 0; - blockType = BLOCK_ARMOR; - } - } - return blockType; -} - -uint32_t Player::getIP() const -{ - if (client) { - return client->getIP(); - } - - return 0; -} - -void Player::death(Creature* _lastHitCreature) -{ - loginPosition = town->getTemplePosition(); - - if (skillLoss) { - uint8_t unfairFightReduction = 100; - - if (_lastHitCreature) { - Player* lastHitPlayer = _lastHitCreature->getPlayer(); - if (!lastHitPlayer) { - Creature* lastHitMaster = _lastHitCreature->getMaster(); - if (lastHitMaster) { - lastHitPlayer = lastHitMaster->getPlayer(); - } - } - - if (lastHitPlayer) { - uint32_t sumLevels = 0; - uint32_t inFightTicks = g_config.getNumber(ConfigManager::PZ_LOCKED); - for (const auto& it : damageMap) { - CountBlock_t cb = it.second; - if ((OTSYS_TIME() - cb.ticks) <= inFightTicks) { - Player* damageDealer = g_game.getPlayerByID(it.first); - if (damageDealer) { - sumLevels += damageDealer->getLevel(); - } - } - } - - if (sumLevels > level) { - double reduce = level / static_cast(sumLevels); - unfairFightReduction = std::max(20, std::floor((reduce * 100) + 0.5)); - } - } - } - - //Magic level loss - uint64_t sumMana = 0; - uint64_t lostMana = 0; - - //sum up all the mana - for (uint32_t i = 1; i <= magLevel; ++i) { - sumMana += vocation->getReqMana(i); - } - - sumMana += manaSpent; - - double deathLossPercent = getLostPercent() * (unfairFightReduction / 100.); - - lostMana = static_cast(sumMana * deathLossPercent); - - while (lostMana > manaSpent && magLevel > 0) { - lostMana -= manaSpent; - manaSpent = vocation->getReqMana(magLevel); - magLevel--; - } - - manaSpent -= lostMana; - - uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); - if (nextReqMana > vocation->getReqMana(magLevel)) { - magLevelPercent = Player::getPercentLevel(manaSpent, nextReqMana); - } else { - magLevelPercent = 0; - } - - //Skill loss - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { //for each skill - uint64_t sumSkillTries = 0; - for (uint16_t c = 11; c <= skills[i].level; ++c) { //sum up all required tries for all skill levels - sumSkillTries += vocation->getReqSkillTries(i, c); - } - - sumSkillTries += skills[i].tries; - - uint32_t lostSkillTries = static_cast(sumSkillTries * deathLossPercent); - while (lostSkillTries > skills[i].tries) { - lostSkillTries -= skills[i].tries; - - if (skills[i].level <= 10) { - skills[i].level = 10; - skills[i].tries = 0; - lostSkillTries = 0; - break; - } - - skills[i].tries = vocation->getReqSkillTries(i, skills[i].level); - skills[i].level--; - } - - skills[i].tries = std::max(0, skills[i].tries - lostSkillTries); - skills[i].percent = Player::getPercentLevel(skills[i].tries, vocation->getReqSkillTries(i, skills[i].level)); - } - - //Level loss - uint64_t expLoss = static_cast(experience * deathLossPercent); - g_events->eventPlayerOnLoseExperience(this, expLoss); - - if (expLoss != 0) { - uint32_t oldLevel = level; - - if (vocation->getId() == VOCATION_NONE || level > 7) { - experience -= expLoss; - } - - while (level > 1 && experience < Player::getExpForLevel(level)) { - --level; - healthMax = std::max(0, healthMax - vocation->getHPGain()); - manaMax = std::max(0, manaMax - vocation->getManaGain()); - capacity = std::max(0, capacity - vocation->getCapGain()); - } - - if (oldLevel != level) { - std::ostringstream ss; - ss << "You were downgraded from Level " << oldLevel << " to Level " << level << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - } - - uint64_t currLevelExp = Player::getExpForLevel(level); - uint64_t nextLevelExp = Player::getExpForLevel(level + 1); - if (nextLevelExp > currLevelExp) { - levelPercent = Player::getPercentLevel(experience - currLevelExp, nextLevelExp - currLevelExp); - } else { - levelPercent = 0; - } - } - - std::bitset<6> bitset(blessings); - if (bitset[5]) { - Player* lastHitPlayer; - - if (_lastHitCreature) { - lastHitPlayer = _lastHitCreature->getPlayer(); - if (!lastHitPlayer) { - Creature* lastHitMaster = _lastHitCreature->getMaster(); - if (lastHitMaster) { - lastHitPlayer = lastHitMaster->getPlayer(); - } - } - } else { - lastHitPlayer = nullptr; - } - - if (lastHitPlayer) { - bitset.reset(5); - blessings = bitset.to_ulong(); - } else { - blessings = 32; - } - } else { - blessings = 0; - } - - sendStats(); - sendSkills(); - sendReLoginWindow(unfairFightReduction); - - if (getSkull() == SKULL_BLACK) { - health = 40; - mana = 0; - } else { - health = healthMax; - mana = manaMax; - } - - auto it = conditions.begin(), end = conditions.end(); - while (it != end) { - Condition* condition = *it; - if (condition->isPersistent()) { - it = conditions.erase(it); - - condition->endCondition(this); - onEndCondition(condition->getType()); - delete condition; - } else { - ++it; - } - } - } else { - setLossSkill(true); - - auto it = conditions.begin(), end = conditions.end(); - while (it != end) { - Condition* condition = *it; - if (condition->isPersistent()) { - it = conditions.erase(it); - - condition->endCondition(this); - onEndCondition(condition->getType()); - delete condition; - } else { - ++it; - } - } - - health = healthMax; - g_game.internalTeleport(this, getTemplePosition(), true); - g_game.addCreatureHealth(this); - onThink(EVENT_CREATURE_THINK_INTERVAL); - onIdleStatus(); - sendStats(); - } -} - -bool Player::dropCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) -{ - if (getZone() == ZONE_PVP) { - setDropLoot(true); - return false; - } - return Creature::dropCorpse(_lastHitCreature, mostDamageCreature, lastHitUnjustified, mostDamageUnjustified); -} - -Item* Player::getCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature) -{ - Item* corpse = Creature::getCorpse(_lastHitCreature, mostDamageCreature); - if (corpse && corpse->getContainer()) { - std::ostringstream ss; - if (_lastHitCreature) { - ss << "You recognize " << getNameDescription() << ". " << (getSex() == PLAYERSEX_FEMALE ? "She" : "He") << " was killed by " << _lastHitCreature->getNameDescription() << '.'; - } else { - ss << "You recognize " << getNameDescription() << '.'; - } - - corpse->setSpecialDescription(ss.str()); - } - return corpse; -} - -void Player::addInFightTicks(bool pzlock /*= false*/) -{ - if (hasFlag(PlayerFlag_NotGainInFight)) { - return; - } - - if (pzlock) { - pzLocked = true; - } - - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_config.getNumber(ConfigManager::PZ_LOCKED), 0); - addCondition(condition); -} - -void Player::removeList() -{ - g_game.removePlayer(this); - - for (const auto& it : g_game.getPlayers()) { - it.second->notifyStatusChange(this, VIPSTATUS_OFFLINE); - } -} - -void Player::addList() -{ - for (const auto& it : g_game.getPlayers()) { - it.second->notifyStatusChange(this, VIPSTATUS_ONLINE); - } - - g_game.addPlayer(this); -} - -void Player::kickPlayer(bool displayEffect) -{ - g_creatureEvents->playerLogout(this); - if (client) { - client->logout(displayEffect, true); - } else { - g_game.removeCreature(this); - } -} - -void Player::notifyStatusChange(Player* loginPlayer, VipStatus_t status) -{ - if (!client) { - return; - } - - auto it = VIPList.find(loginPlayer->guid); - if (it == VIPList.end()) { - return; - } - - client->sendUpdatedVIPStatus(loginPlayer->guid, status); - - if (status == VIPSTATUS_ONLINE) { - client->sendTextMessage(TextMessage(MESSAGE_STATUS_SMALL, loginPlayer->getName() + " has logged in.")); - } else if (status == VIPSTATUS_OFFLINE) { - client->sendTextMessage(TextMessage(MESSAGE_STATUS_SMALL, loginPlayer->getName() + " has logged out.")); - } -} - -bool Player::removeVIP(uint32_t vipGuid) -{ - if (VIPList.erase(vipGuid) == 0) { - return false; - } - - IOLoginData::removeVIPEntry(accountNumber, vipGuid); - return true; -} - -bool Player::addVIP(uint32_t vipGuid, const std::string& vipName, VipStatus_t status) -{ - if (guid == vipGuid) { - sendTextMessage(MESSAGE_STATUS_SMALL, "You cannot add yourself."); - return false; - } - - if (VIPList.size() >= getMaxVIPEntries() || VIPList.size() == 200) { // max number of buddies is 200 in 9.53 - sendTextMessage(MESSAGE_STATUS_SMALL, "You cannot add more buddies."); - return false; - } - - auto result = VIPList.insert(vipGuid); - if (!result.second) { - sendTextMessage(MESSAGE_STATUS_SMALL, "This player is already in your list."); - return false; - } - - IOLoginData::addVIPEntry(accountNumber, vipGuid, "", 0, false); - if (client) { - client->sendVIP(vipGuid, vipName, "", 0, false, status); - } - return true; -} - -bool Player::addVIPInternal(uint32_t vipGuid) -{ - if (guid == vipGuid) { - return false; - } - - if (VIPList.size() >= getMaxVIPEntries() || VIPList.size() == 200) { // max number of buddies is 200 in 9.53 - return false; - } - - return VIPList.insert(vipGuid).second; -} - -bool Player::editVIP(uint32_t vipGuid, const std::string& description, uint32_t icon, bool notify) -{ - auto it = VIPList.find(vipGuid); - if (it == VIPList.end()) { - return false; // player is not in VIP - } - - IOLoginData::editVIPEntry(accountNumber, vipGuid, description, icon, notify); - return true; -} - -//close container and its child containers -void Player::autoCloseContainers(const Container* container) -{ - std::vector closeList; - for (const auto& it : openContainers) { - Container* tmpContainer = it.second.container; - while (tmpContainer) { - if (tmpContainer->isRemoved() || tmpContainer == container) { - closeList.push_back(it.first); - break; - } - - tmpContainer = dynamic_cast(tmpContainer->getParent()); - } - } - - for (uint32_t containerId : closeList) { - closeContainer(containerId); - if (client) { - client->sendCloseContainer(containerId); - } - } -} - -bool Player::hasCapacity(const Item* item, uint32_t count) const -{ - if (hasFlag(PlayerFlag_CannotPickupItem)) { - return false; - } - - if (hasFlag(PlayerFlag_HasInfiniteCapacity) || item->getTopParent() == this) { - return true; - } - - uint32_t itemWeight = item->getContainer() != nullptr ? item->getWeight() : item->getBaseWeight(); - if (item->isStackable()) { - itemWeight *= count; - } - return itemWeight <= getFreeCapacity(); -} - -ReturnValue Player::queryAdd(int32_t index, const Thing& thing, uint32_t count, uint32_t flags, Creature*) const -{ - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - bool childIsOwner = hasBitSet(FLAG_CHILDISOWNER, flags); - if (childIsOwner) { - //a child container is querying the player, just check if enough capacity - bool skipLimit = hasBitSet(FLAG_NOLIMIT, flags); - if (skipLimit || hasCapacity(item, count)) { - return RETURNVALUE_NOERROR; - } - return RETURNVALUE_NOTENOUGHCAPACITY; - } - - if (!item->isPickupable()) { - return RETURNVALUE_CANNOTPICKUP; - } - - ReturnValue ret = RETURNVALUE_NOERROR; - - const int32_t& slotPosition = item->getSlotPosition(); - if ((slotPosition & SLOTP_HEAD) || (slotPosition & SLOTP_NECKLACE) || - (slotPosition & SLOTP_BACKPACK) || (slotPosition & SLOTP_ARMOR) || - (slotPosition & SLOTP_LEGS) || (slotPosition & SLOTP_FEET) || - (slotPosition & SLOTP_RING)) { - ret = RETURNVALUE_CANNOTBEDRESSED; - } else if (slotPosition & SLOTP_TWO_HAND) { - ret = RETURNVALUE_PUTTHISOBJECTINBOTHHANDS; - } else if ((slotPosition & SLOTP_RIGHT) || (slotPosition & SLOTP_LEFT)) { - if (!g_config.getBoolean(ConfigManager::CLASSIC_EQUIPMENT_SLOTS)) { - ret = RETURNVALUE_CANNOTBEDRESSED; - } else { - ret = RETURNVALUE_PUTTHISOBJECTINYOURHAND; - } - } - - switch (index) { - case CONST_SLOT_HEAD: { - if (slotPosition & SLOTP_HEAD) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_NECKLACE: { - if (slotPosition & SLOTP_NECKLACE) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_BACKPACK: { - if (slotPosition & SLOTP_BACKPACK) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_ARMOR: { - if (slotPosition & SLOTP_ARMOR) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_RIGHT: { - if (slotPosition & SLOTP_RIGHT) { - if (!g_config.getBoolean(ConfigManager::CLASSIC_EQUIPMENT_SLOTS)) { - if (item->getWeaponType() != WEAPON_SHIELD) { - ret = RETURNVALUE_CANNOTBEDRESSED; - } else { - const Item* leftItem = inventory[CONST_SLOT_LEFT]; - if (leftItem) { - if ((leftItem->getSlotPosition() | slotPosition) & SLOTP_TWO_HAND) { - ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE; - } else { - ret = RETURNVALUE_NOERROR; - } - } else { - ret = RETURNVALUE_NOERROR; - } - } - } else if (slotPosition & SLOTP_TWO_HAND) { - if (inventory[CONST_SLOT_LEFT] && inventory[CONST_SLOT_LEFT] != item) { - ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE; - } else { - ret = RETURNVALUE_NOERROR; - } - } else if (inventory[CONST_SLOT_LEFT]) { - const Item* leftItem = inventory[CONST_SLOT_LEFT]; - WeaponType_t type = item->getWeaponType(), leftType = leftItem->getWeaponType(); - - if (leftItem->getSlotPosition() & SLOTP_TWO_HAND) { - ret = RETURNVALUE_DROPTWOHANDEDITEM; - } else if (item == leftItem && count == item->getItemCount()) { - ret = RETURNVALUE_NOERROR; - } else if (leftType == WEAPON_SHIELD && type == WEAPON_SHIELD) { - ret = RETURNVALUE_CANONLYUSEONESHIELD; - } else if (leftType == WEAPON_NONE || type == WEAPON_NONE || - leftType == WEAPON_SHIELD || leftType == WEAPON_AMMO - || type == WEAPON_SHIELD || type == WEAPON_AMMO) { - ret = RETURNVALUE_NOERROR; - } else { - ret = RETURNVALUE_CANONLYUSEONEWEAPON; - } - } else { - ret = RETURNVALUE_NOERROR; - } - } - break; - } - - case CONST_SLOT_LEFT: { - if (slotPosition & SLOTP_LEFT) { - if (!g_config.getBoolean(ConfigManager::CLASSIC_EQUIPMENT_SLOTS)) { - WeaponType_t type = item->getWeaponType(); - if (type == WEAPON_NONE || type == WEAPON_SHIELD) { - ret = RETURNVALUE_CANNOTBEDRESSED; - } else if (inventory[CONST_SLOT_RIGHT] && (slotPosition & SLOTP_TWO_HAND)) { - ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE; - } else { - ret = RETURNVALUE_NOERROR; - } - } else if (slotPosition & SLOTP_TWO_HAND) { - if (inventory[CONST_SLOT_RIGHT] && inventory[CONST_SLOT_RIGHT] != item) { - ret = RETURNVALUE_BOTHHANDSNEEDTOBEFREE; - } else { - ret = RETURNVALUE_NOERROR; - } - } else if (inventory[CONST_SLOT_RIGHT]) { - const Item* rightItem = inventory[CONST_SLOT_RIGHT]; - WeaponType_t type = item->getWeaponType(), rightType = rightItem->getWeaponType(); - - if (rightItem->getSlotPosition() & SLOTP_TWO_HAND) { - ret = RETURNVALUE_DROPTWOHANDEDITEM; - } else if (item == rightItem && count == item->getItemCount()) { - ret = RETURNVALUE_NOERROR; - } else if (rightType == WEAPON_SHIELD && type == WEAPON_SHIELD) { - ret = RETURNVALUE_CANONLYUSEONESHIELD; - } else if (rightType == WEAPON_NONE || type == WEAPON_NONE || - rightType == WEAPON_SHIELD || rightType == WEAPON_AMMO - || type == WEAPON_SHIELD || type == WEAPON_AMMO) { - ret = RETURNVALUE_NOERROR; - } else { - ret = RETURNVALUE_CANONLYUSEONEWEAPON; - } - } else { - ret = RETURNVALUE_NOERROR; - } - } - break; - } - - case CONST_SLOT_LEGS: { - if (slotPosition & SLOTP_LEGS) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_FEET: { - if (slotPosition & SLOTP_FEET) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_RING: { - if (slotPosition & SLOTP_RING) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_AMMO: { - if ((slotPosition & SLOTP_AMMO) || g_config.getBoolean(ConfigManager::CLASSIC_EQUIPMENT_SLOTS)) { - ret = RETURNVALUE_NOERROR; - } - break; - } - - case CONST_SLOT_WHEREEVER: - case -1: - ret = RETURNVALUE_NOTENOUGHROOM; - break; - - default: - ret = RETURNVALUE_NOTPOSSIBLE; - break; - } - - if (ret == RETURNVALUE_NOERROR || ret == RETURNVALUE_NOTENOUGHROOM) { - //need an exchange with source? - const Item* inventoryItem = getInventoryItem(static_cast(index)); - if (inventoryItem && (!inventoryItem->isStackable() || inventoryItem->getID() != item->getID())) { - return RETURNVALUE_NEEDEXCHANGE; - } - - //check if enough capacity - if (!hasCapacity(item, count)) { - return RETURNVALUE_NOTENOUGHCAPACITY; - } - - if (!g_moveEvents->onPlayerEquip(const_cast(this), const_cast(item), static_cast(index), true)) { - return RETURNVALUE_CANNOTBEDRESSED; - } - } - return ret; -} - -ReturnValue Player::queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount, - uint32_t flags) const -{ - const Item* item = thing.getItem(); - if (item == nullptr) { - maxQueryCount = 0; - return RETURNVALUE_NOTPOSSIBLE; - } - - if (index == INDEX_WHEREEVER) { - uint32_t n = 0; - for (int32_t slotIndex = CONST_SLOT_FIRST; slotIndex <= CONST_SLOT_LAST; ++slotIndex) { - Item* inventoryItem = inventory[slotIndex]; - if (inventoryItem) { - if (Container* subContainer = inventoryItem->getContainer()) { - uint32_t queryCount = 0; - subContainer->queryMaxCount(INDEX_WHEREEVER, *item, item->getItemCount(), queryCount, flags); - n += queryCount; - - //iterate through all items, including sub-containers (deep search) - for (ContainerIterator it = subContainer->iterator(); it.hasNext(); it.advance()) { - if (Container* tmpContainer = (*it)->getContainer()) { - queryCount = 0; - tmpContainer->queryMaxCount(INDEX_WHEREEVER, *item, item->getItemCount(), queryCount, flags); - n += queryCount; - } - } - } else if (inventoryItem->isStackable() && item->equals(inventoryItem) && inventoryItem->getItemCount() < 100) { - uint32_t remainder = (100 - inventoryItem->getItemCount()); - - if (queryAdd(slotIndex, *item, remainder, flags) == RETURNVALUE_NOERROR) { - n += remainder; - } - } - } else if (queryAdd(slotIndex, *item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { //empty slot - if (item->isStackable()) { - n += 100; - } else { - ++n; - } - } - } - - maxQueryCount = n; - } else { - const Item* destItem = nullptr; - - const Thing* destThing = getThing(index); - if (destThing) { - destItem = destThing->getItem(); - } - - if (destItem) { - if (destItem->isStackable() && item->equals(destItem) && destItem->getItemCount() < 100) { - maxQueryCount = 100 - destItem->getItemCount(); - } else { - maxQueryCount = 0; - } - } else if (queryAdd(index, *item, count, flags) == RETURNVALUE_NOERROR) { //empty slot - if (item->isStackable()) { - maxQueryCount = 100; - } else { - maxQueryCount = 1; - } - - return RETURNVALUE_NOERROR; - } - } - - if (maxQueryCount < count) { - return RETURNVALUE_NOTENOUGHROOM; - } else { - return RETURNVALUE_NOERROR; - } -} - -ReturnValue Player::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const -{ - int32_t index = getThingIndex(&thing); - if (index == -1) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (count == 0 || (item->isStackable() && count > item->getItemCount())) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) { - return RETURNVALUE_NOTMOVEABLE; - } - - return RETURNVALUE_NOERROR; -} - -Cylinder* Player::queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) -{ - if (index == 0 /*drop to capacity window*/ || index == INDEX_WHEREEVER) { - *destItem = nullptr; - - const Item* item = thing.getItem(); - if (item == nullptr) { - return this; - } - - bool autoStack = !((flags & FLAG_IGNOREAUTOSTACK) == FLAG_IGNOREAUTOSTACK); - bool isStackable = item->isStackable(); - - std::vector containers; - - for (uint32_t slotIndex = CONST_SLOT_FIRST; slotIndex <= CONST_SLOT_LAST; ++slotIndex) { - Item* inventoryItem = inventory[slotIndex]; - if (inventoryItem) { - if (inventoryItem == tradeItem) { - continue; - } - - if (inventoryItem == item) { - continue; - } - - if (autoStack && isStackable) { - //try find an already existing item to stack with - if (queryAdd(slotIndex, *item, item->getItemCount(), 0) == RETURNVALUE_NOERROR) { - if (inventoryItem->equals(item) && inventoryItem->getItemCount() < 100) { - index = slotIndex; - *destItem = inventoryItem; - return this; - } - } - - if (Container* subContainer = inventoryItem->getContainer()) { - containers.push_back(subContainer); - } - } else if (Container* subContainer = inventoryItem->getContainer()) { - containers.push_back(subContainer); - } - } else if (queryAdd(slotIndex, *item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { //empty slot - index = slotIndex; - *destItem = nullptr; - return this; - } - } - - size_t i = 0; - while (i < containers.size()) { - Container* tmpContainer = containers[i++]; - if (!autoStack || !isStackable) { - //we need to find first empty container as fast as we can for non-stackable items - uint32_t n = tmpContainer->capacity() - tmpContainer->size(); - while (n) { - if (tmpContainer->queryAdd(tmpContainer->capacity() - n, *item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { - index = tmpContainer->capacity() - n; - *destItem = nullptr; - return tmpContainer; - } - - n--; - } - - for (Item* tmpContainerItem : tmpContainer->getItemList()) { - if (Container* subContainer = tmpContainerItem->getContainer()) { - containers.push_back(subContainer); - } - } - - continue; - } - - uint32_t n = 0; - - for (Item* tmpItem : tmpContainer->getItemList()) { - if (tmpItem == tradeItem) { - continue; - } - - if (tmpItem == item) { - continue; - } - - //try find an already existing item to stack with - if (tmpItem->equals(item) && tmpItem->getItemCount() < 100) { - index = n; - *destItem = tmpItem; - return tmpContainer; - } - - if (Container* subContainer = tmpItem->getContainer()) { - containers.push_back(subContainer); - } - - n++; - } - - if (n < tmpContainer->capacity() && tmpContainer->queryAdd(n, *item, item->getItemCount(), flags) == RETURNVALUE_NOERROR) { - index = n; - *destItem = nullptr; - return tmpContainer; - } - } - - return this; - } - - Thing* destThing = getThing(index); - if (destThing) { - *destItem = destThing->getItem(); - } - - Cylinder* subCylinder = dynamic_cast(destThing); - if (subCylinder) { - index = INDEX_WHEREEVER; - *destItem = nullptr; - return subCylinder; - } else { - return this; - } -} - -void Player::addThing(int32_t index, Thing* thing) -{ - if (index < CONST_SLOT_FIRST || index > CONST_SLOT_LAST) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (!item) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - item->setParent(this); - inventory[index] = item; - - //send to client - sendInventoryItem(static_cast(index), item); -} - -void Player::updateThing(Thing* thing, uint16_t itemId, uint32_t count) -{ - int32_t index = getThingIndex(thing); - if (index == -1) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (!item) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - item->setID(itemId); - item->setSubType(count); - - //send to client - sendInventoryItem(static_cast(index), item); - - //event methods - onUpdateInventoryItem(item, item); -} - -void Player::replaceThing(uint32_t index, Thing* thing) -{ - if (index > CONST_SLOT_LAST) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* oldItem = getInventoryItem(static_cast(index)); - if (!oldItem) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (!item) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - //send to client - sendInventoryItem(static_cast(index), item); - - //event methods - onUpdateInventoryItem(oldItem, item); - - item->setParent(this); - - inventory[index] = item; -} - -void Player::removeThing(Thing* thing, uint32_t count) -{ - Item* item = thing->getItem(); - if (!item) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - int32_t index = getThingIndex(thing); - if (index == -1) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - if (item->isStackable()) { - if (count == item->getItemCount()) { - //send change to client - sendInventoryItem(static_cast(index), nullptr); - - //event methods - onRemoveInventoryItem(item); - - item->setParent(nullptr); - inventory[index] = nullptr; - } else { - uint8_t newCount = static_cast(std::max(0, item->getItemCount() - count)); - item->setItemCount(newCount); - - //send change to client - sendInventoryItem(static_cast(index), item); - - //event methods - onUpdateInventoryItem(item, item); - } - } else { - //send change to client - sendInventoryItem(static_cast(index), nullptr); - - //event methods - onRemoveInventoryItem(item); - - item->setParent(nullptr); - inventory[index] = nullptr; - } -} - -int32_t Player::getThingIndex(const Thing* thing) const -{ - for (int i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - if (inventory[i] == thing) { - return i; - } - } - return -1; -} - -size_t Player::getFirstIndex() const -{ - return CONST_SLOT_FIRST; -} - -size_t Player::getLastIndex() const -{ - return CONST_SLOT_LAST + 1; -} - -uint32_t Player::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const -{ - uint32_t count = 0; - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - Item* item = inventory[i]; - if (!item) { - continue; - } - - if (item->getID() == itemId) { - count += Item::countByType(item, subType); - } - - if (Container* container = item->getContainer()) { - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - if ((*it)->getID() == itemId) { - count += Item::countByType(*it, subType); - } - } - } - } - return count; -} - -bool Player::removeItemOfType(uint16_t itemId, uint32_t amount, int32_t subType, bool ignoreEquipped/* = false*/) const -{ - if (amount == 0) { - return true; - } - - std::vector itemList; - - uint32_t count = 0; - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - Item* item = inventory[i]; - if (!item) { - continue; - } - - if (!ignoreEquipped && item->getID() == itemId) { - uint32_t itemCount = Item::countByType(item, subType); - if (itemCount == 0) { - continue; - } - - itemList.push_back(item); - - count += itemCount; - if (count >= amount) { - g_game.internalRemoveItems(std::move(itemList), amount, Item::items[itemId].stackable); - return true; - } - } else if (Container* container = item->getContainer()) { - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - Item* containerItem = *it; - if (containerItem->getID() == itemId) { - uint32_t itemCount = Item::countByType(containerItem, subType); - if (itemCount == 0) { - continue; - } - - itemList.push_back(containerItem); - - count += itemCount; - if (count >= amount) { - g_game.internalRemoveItems(std::move(itemList), amount, Item::items[itemId].stackable); - return true; - } - } - } - } - } - return false; -} - -std::map& Player::getAllItemTypeCount(std::map &countMap) const -{ - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; i++) { - Item* item = inventory[i]; - if (!item) { - continue; - } - - countMap[item->getID()] += Item::countByType(item, -1); - - if (Container* container = item->getContainer()) { - for (ContainerIterator it = container->iterator(); it.hasNext(); it.advance()) { - countMap[(*it)->getID()] += Item::countByType(*it, -1); - } - } - } - return countMap; -} - -Thing* Player::getThing(size_t index) const -{ - if (index >= CONST_SLOT_FIRST && index <= CONST_SLOT_LAST) { - return inventory[index]; - } - return nullptr; -} - -void Player::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link /*= LINK_OWNER*/) -{ - if (link == LINK_OWNER) { - //calling movement scripts - g_moveEvents->onPlayerEquip(this, thing->getItem(), static_cast(index), false); - } - - bool requireListUpdate = true; - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - const Item* i = (oldParent ? oldParent->getItem() : nullptr); - - // Check if we owned the old container too, so we don't need to do anything, - // as the list was updated in postRemoveNotification - assert(i ? i->getContainer() != nullptr : true); - - if (i) { - requireListUpdate = i->getContainer()->getHoldingPlayer() != this; - } else { - requireListUpdate = oldParent != this; - } - - updateInventoryWeight(); - updateItemsLight(); - sendStats(); - } - - if (const Item* item = thing->getItem()) { - if (const Container* container = item->getContainer()) { - onSendContainer(container); - } - - if (shopOwner && requireListUpdate) { - updateSaleShopList(item); - } - } else if (const Creature* creature = thing->getCreature()) { - if (creature == this) { - //check containers - std::vector containers; - - for (const auto& it : openContainers) { - Container* container = it.second.container; - if (!Position::areInRange<1, 1, 0>(container->getPosition(), getPosition())) { - containers.push_back(container); - } - } - - for (const Container* container : containers) { - autoCloseContainers(container); - } - } - } -} - -void Player::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link /*= LINK_OWNER*/) -{ - if (link == LINK_OWNER) { - //calling movement scripts - g_moveEvents->onPlayerDeEquip(this, thing->getItem(), static_cast(index)); - } - - bool requireListUpdate = true; - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - const Item* i = (newParent ? newParent->getItem() : nullptr); - - // Check if we owned the old container too, so we don't need to do anything, - // as the list was updated in postRemoveNotification - assert(i ? i->getContainer() != nullptr : true); - - if (i) { - requireListUpdate = i->getContainer()->getHoldingPlayer() != this; - } else { - requireListUpdate = newParent != this; - } - - updateInventoryWeight(); - updateItemsLight(); - sendStats(); - } - - if (const Item* item = thing->getItem()) { - if (const Container* container = item->getContainer()) { - if (container->isRemoved() || !Position::areInRange<1, 1, 0>(getPosition(), container->getPosition())) { - autoCloseContainers(container); - } else if (container->getTopParent() == this) { - onSendContainer(container); - } else if (const Container* topContainer = dynamic_cast(container->getTopParent())) { - if (const DepotChest* depotChest = dynamic_cast(topContainer)) { - bool isOwner = false; - - for (const auto& it : depotChests) { - if (it.second == depotChest) { - isOwner = true; - onSendContainer(container); - } - } - - if (!isOwner) { - autoCloseContainers(container); - } - } else { - onSendContainer(container); - } - } else { - autoCloseContainers(container); - } - } - - if (shopOwner && requireListUpdate) { - updateSaleShopList(item); - } - } -} - -bool Player::updateSaleShopList(const Item* item) -{ - uint16_t itemId = item->getID(); - if (itemId != ITEM_GOLD_COIN && itemId != ITEM_PLATINUM_COIN && itemId != ITEM_CRYSTAL_COIN) { - auto it = std::find_if(shopItemList.begin(), shopItemList.end(), [itemId](const ShopInfo& shopInfo) { return shopInfo.itemId == itemId && shopInfo.sellPrice != 0; }); - if (it == shopItemList.end()) { - const Container* container = item->getContainer(); - if (!container) { - return false; - } - - const auto& items = container->getItemList(); - return std::any_of(items.begin(), items.end(), [this](const Item* containerItem) { - return updateSaleShopList(containerItem); - }); - } - } - - if (client) { - client->sendSaleItemList(shopItemList); - } - return true; -} - -bool Player::hasShopItemForSale(uint32_t itemId, uint8_t subType) const -{ - const ItemType& itemType = Item::items[itemId]; - return std::any_of(shopItemList.begin(), shopItemList.end(), [&](const ShopInfo& shopInfo) { - return shopInfo.itemId == itemId && shopInfo.buyPrice != 0 && (!itemType.isFluidContainer() || shopInfo.subType == subType); - }); -} - -void Player::internalAddThing(Thing* thing) -{ - internalAddThing(0, thing); -} - -void Player::internalAddThing(uint32_t index, Thing* thing) -{ - Item* item = thing->getItem(); - if (!item) { - return; - } - - //index == 0 means we should equip this item at the most appropiate slot (no action required here) - if (index > 0 && index < 11) { - if (inventory[index]) { - return; - } - - inventory[index] = item; - item->setParent(this); - } -} - -bool Player::setFollowCreature(Creature* creature) -{ - if (!Creature::setFollowCreature(creature)) { - setFollowCreature(nullptr); - setAttackedCreature(nullptr); - - sendCancelMessage(RETURNVALUE_THEREISNOWAY); - sendCancelTarget(); - stopWalk(); - return false; - } - return true; -} - -bool Player::setAttackedCreature(Creature* creature) -{ - if (!Creature::setAttackedCreature(creature)) { - sendCancelTarget(); - return false; - } - - if (chaseMode == CHASEMODE_FOLLOW && creature) { - if (followCreature != creature) { - //chase opponent - setFollowCreature(creature); - } - } else if (followCreature) { - setFollowCreature(nullptr); - } - - if (creature) { - g_dispatcher.addTask(createTask(std::bind(&Game::checkCreatureAttack, &g_game, getID()))); - } - return true; -} - -void Player::goToFollowCreature() -{ - if (!walkTask) { - if ((OTSYS_TIME() - lastFailedFollow) < 2000) { - return; - } - - Creature::goToFollowCreature(); - - if (followCreature && !hasFollowPath) { - lastFailedFollow = OTSYS_TIME(); - } - } -} - -void Player::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const -{ - Creature::getPathSearchParams(creature, fpp); - fpp.fullPathSearch = true; -} - -void Player::doAttacking(uint32_t) -{ - if (lastAttack == 0) { - lastAttack = OTSYS_TIME() - getAttackSpeed() - 1; - } - - if (hasCondition(CONDITION_PACIFIED)) { - return; - } - - if ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()) { - bool result = false; - - Item* tool = getWeapon(); - const Weapon* weapon = g_weapons->getWeapon(tool); - if (weapon) { - if (!weapon->interruptSwing()) { - result = weapon->useWeapon(this, tool, attackedCreature); - } else if (!canDoAction()) { - uint32_t delay = getNextActionTime(); - SchedulerTask* task = createSchedulerTask(delay, std::bind(&Game::checkCreatureAttack, - &g_game, getID())); - setNextActionTask(task); - } else { - result = weapon->useWeapon(this, tool, attackedCreature); - } - } else { - result = Weapon::useFist(this, attackedCreature); - } - - if (result) { - lastAttack = OTSYS_TIME(); - } - } -} - -uint64_t Player::getGainedExperience(Creature* attacker) const -{ - if (g_config.getBoolean(ConfigManager::EXPERIENCE_FROM_PLAYERS)) { - Player* attackerPlayer = attacker->getPlayer(); - if (attackerPlayer && attackerPlayer != this && skillLoss && std::abs(static_cast(attackerPlayer->getLevel() - level)) <= g_config.getNumber(ConfigManager::EXP_FROM_PLAYERS_LEVEL_RANGE)) { - return std::max(0, std::floor(getLostExperience() * getDamageRatio(attacker) * 0.75)); - } - } - return 0; -} - -void Player::onFollowCreature(const Creature* creature) -{ - if (!creature) { - stopWalk(); - } -} - -void Player::setChaseMode(chaseMode_t mode) -{ - chaseMode_t prevChaseMode = chaseMode; - chaseMode = mode; - - if (prevChaseMode != chaseMode) { - if (chaseMode == CHASEMODE_FOLLOW) { - if (!followCreature && attackedCreature) { - //chase opponent - setFollowCreature(attackedCreature); - } - } else if (attackedCreature) { - setFollowCreature(nullptr); - cancelNextWalk = true; - } - } -} - -void Player::onWalkAborted() -{ - setNextWalkActionTask(nullptr); - sendCancelWalk(); -} - -void Player::onWalkComplete() -{ - if (walkTask) { - walkTaskEvent = g_scheduler.addEvent(walkTask); - walkTask = nullptr; - } -} - -void Player::stopWalk() -{ - cancelNextWalk = true; -} - -void Player::getCreatureLight(LightInfo& light) const -{ - if (internalLight.level > itemsLight.level) { - light = internalLight; - } else { - light = itemsLight; - } -} - -void Player::updateItemsLight(bool internal /*=false*/) -{ - LightInfo maxLight; - LightInfo curLight; - - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - Item* item = inventory[i]; - if (item) { - item->getLight(curLight); - - if (curLight.level > maxLight.level) { - maxLight = curLight; - } - } - } - - if (itemsLight.level != maxLight.level || itemsLight.color != maxLight.color) { - itemsLight = maxLight; - - if (!internal) { - g_game.changeLight(this); - } - } -} - -void Player::onAddCondition(ConditionType_t type) -{ - Creature::onAddCondition(type); - - if (type == CONDITION_OUTFIT && isMounted()) { - dismount(); - } - - sendIcons(); -} - -void Player::onAddCombatCondition(ConditionType_t type) -{ - switch (type) { - case CONDITION_POISON: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are poisoned."); - break; - - case CONDITION_DROWN: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are drowning."); - break; - - case CONDITION_PARALYZE: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are paralyzed."); - break; - - case CONDITION_DRUNK: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are drunk."); - break; - - case CONDITION_CURSED: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are cursed."); - break; - - case CONDITION_FREEZING: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are freezing."); - break; - - case CONDITION_DAZZLED: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are dazzled."); - break; - - case CONDITION_BLEEDING: - sendTextMessage(MESSAGE_STATUS_DEFAULT, "You are bleeding."); - break; - - default: - break; - } -} - -void Player::onEndCondition(ConditionType_t type) -{ - Creature::onEndCondition(type); - - if (type == CONDITION_INFIGHT) { - onIdleStatus(); - pzLocked = false; - clearAttacked(); - - if (getSkull() != SKULL_RED && getSkull() != SKULL_BLACK) { - setSkull(SKULL_NONE); - } - } - - sendIcons(); -} - -void Player::onCombatRemoveCondition(Condition* condition) -{ - //Creature::onCombatRemoveCondition(condition); - if (condition->getId() > 0) { - //Means the condition is from an item, id == slot - if (g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED) { - Item* item = getInventoryItem(static_cast(condition->getId())); - if (item) { - //25% chance to destroy the item - if (25 >= uniform_random(1, 100)) { - g_game.internalRemoveItem(item); - } - } - } - } else { - if (!canDoAction()) { - const uint32_t delay = getNextActionTime(); - const int32_t ticks = delay - (delay % EVENT_CREATURE_THINK_INTERVAL); - if (ticks < 0) { - removeCondition(condition); - } else { - condition->setTicks(ticks); - } - } else { - removeCondition(condition); - } - } -} - -void Player::onAttackedCreature(Creature* target) -{ - Creature::onAttackedCreature(target); - - // Fix avoid pz in pvp zones - if (target && target->getZone() == ZONE_PVP) { - return; - } - - if (target == this) { - addInFightTicks(); - return; - } - - if (hasFlag(PlayerFlag_NotGainInFight)) { - return; - } - - Player* targetPlayer = target->getPlayer(); - if (targetPlayer && !isPartner(targetPlayer) && !isGuildMate(targetPlayer)) { - if (!pzLocked && g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED) { - pzLocked = true; - sendIcons(); - } - - if (getSkull() == SKULL_NONE && getSkullClient(targetPlayer) == SKULL_YELLOW) { - addAttacked(targetPlayer); - targetPlayer->sendCreatureSkull(this); - } else if (!targetPlayer->hasAttacked(this)) { - if (!pzLocked) { - pzLocked = true; - sendIcons(); - } - - if (!Combat::isInPvpZone(this, targetPlayer) && !isInWar(targetPlayer)) { - addAttacked(targetPlayer); - - if (targetPlayer->getSkull() == SKULL_NONE && getSkull() == SKULL_NONE) { - setSkull(SKULL_WHITE); - } - - if (getSkull() == SKULL_NONE) { - targetPlayer->sendCreatureSkull(this); - } - } - } - } - - addInFightTicks(); -} - -void Player::onAttacked() -{ - Creature::onAttacked(); - - addInFightTicks(); -} - -void Player::onIdleStatus() -{ - Creature::onIdleStatus(); - - if (party) { - party->clearPlayerPoints(this); - } -} - -void Player::onPlacedCreature() -{ - //scripting event - onLogin - if (!g_creatureEvents->playerLogin(this)) { - kickPlayer(true); - } -} - -void Player::onAttackedCreatureDrainHealth(Creature* target, int32_t points) -{ - Creature::onAttackedCreatureDrainHealth(target, points); - - if (target) { - if (party && !Combat::isPlayerCombat(target)) { - Monster* tmpMonster = target->getMonster(); - if (tmpMonster && tmpMonster->isHostile()) { - //We have fulfilled a requirement for shared experience - party->updatePlayerTicks(this, points); - } - } - } -} - -void Player::onTargetCreatureGainHealth(Creature* target, int32_t points) -{ - if (target && party) { - Player* tmpPlayer = nullptr; - - if (target->getPlayer()) { - tmpPlayer = target->getPlayer(); - } else if (Creature* targetMaster = target->getMaster()) { - if (Player* targetMasterPlayer = targetMaster->getPlayer()) { - tmpPlayer = targetMasterPlayer; - } - } - - if (isPartner(tmpPlayer)) { - party->updatePlayerTicks(this, points); - } - } -} - -bool Player::onKilledCreature(Creature* target, bool lastHit/* = true*/) -{ - bool unjustified = false; - - if (hasFlag(PlayerFlag_NotGenerateLoot)) { - target->setDropLoot(false); - } - - Creature::onKilledCreature(target, lastHit); - - if (Player* targetPlayer = target->getPlayer()) { - if (targetPlayer && targetPlayer->getZone() == ZONE_PVP) { - targetPlayer->setDropLoot(false); - targetPlayer->setLossSkill(false); - } else if (!hasFlag(PlayerFlag_NotGainInFight) && !isPartner(targetPlayer)) { - if (!Combat::isInPvpZone(this, targetPlayer) && hasAttacked(targetPlayer) && !targetPlayer->hasAttacked(this) && !isGuildMate(targetPlayer) && targetPlayer != this) { - if (targetPlayer->getSkull() == SKULL_NONE && !isInWar(targetPlayer)) { - unjustified = true; - addUnjustifiedDead(targetPlayer); - } - - if (lastHit && hasCondition(CONDITION_INFIGHT)) { - pzLocked = true; - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_INFIGHT, g_config.getNumber(ConfigManager::WHITE_SKULL_TIME), 0); - addCondition(condition); - } - } - } - } - - return unjustified; -} - -void Player::gainExperience(uint64_t gainExp, Creature* source) -{ - if (hasFlag(PlayerFlag_NotGainExperience) || gainExp == 0 || staminaMinutes == 0) { - return; - } - - addExperience(source, gainExp, true); -} - -void Player::onGainExperience(uint64_t gainExp, Creature* target) -{ - if (hasFlag(PlayerFlag_NotGainExperience)) { - return; - } - - if (target && !target->getPlayer() && party && party->isSharedExperienceActive() && party->isSharedExperienceEnabled()) { - party->shareExperience(gainExp, target); - //We will get a share of the experience through the sharing mechanism - return; - } - - Creature::onGainExperience(gainExp, target); - gainExperience(gainExp, target); -} - -void Player::onGainSharedExperience(uint64_t gainExp, Creature* source) -{ - gainExperience(gainExp, source); -} - -bool Player::isImmune(CombatType_t type) const -{ - if (hasFlag(PlayerFlag_CannotBeAttacked)) { - return true; - } - return Creature::isImmune(type); -} - -bool Player::isImmune(ConditionType_t type) const -{ - if (hasFlag(PlayerFlag_CannotBeAttacked)) { - return true; - } - return Creature::isImmune(type); -} - -bool Player::isAttackable() const -{ - return !hasFlag(PlayerFlag_CannotBeAttacked); -} - -void Player::changeHealth(int32_t healthChange, bool sendHealthChange/* = true*/) -{ - Creature::changeHealth(healthChange, sendHealthChange); - sendStats(); -} - -void Player::changeMana(int32_t manaChange) -{ - if (!hasFlag(PlayerFlag_HasInfiniteMana)) { - Creature::changeMana(manaChange); - } - - sendStats(); -} - -void Player::changeSoul(int32_t soulChange) -{ - if (soulChange > 0) { - soul += std::min(soulChange, vocation->getSoulMax() - soul); - } else { - soul = std::max(0, soul + soulChange); - } - - sendStats(); -} - -bool Player::canWear(uint32_t lookType, uint8_t addons) const -{ - if (group->access) { - return true; - } - - const Outfit* outfit = Outfits::getInstance()->getOutfitByLookType(sex, lookType); - if (!outfit) { - return false; - } - - if (outfit->premium && !isPremium()) { - return false; - } - - if (outfit->unlocked && addons == 0) { - return true; - } - - for (const OutfitEntry& outfitEntry : outfits) { - if (outfitEntry.lookType != lookType) { - continue; - } - return (outfitEntry.addons & addons) == addons; - } - return false; -} - -bool Player::canLogout() -{ - if (isConnecting) { - return false; - } - - if (getTile()->hasFlag(TILESTATE_NOLOGOUT)) { - return false; - } - - if (getTile()->hasFlag(TILESTATE_PROTECTIONZONE)) { - return true; - } - - return !isPzLocked() && !hasCondition(CONDITION_INFIGHT); -} - -void Player::genReservedStorageRange() -{ - //generate outfits range - uint32_t base_key = PSTRG_OUTFITS_RANGE_START; - for (const OutfitEntry& entry : outfits) { - storageMap[++base_key] = (entry.lookType << 16) | entry.addons; - } -} - -void Player::addOutfit(uint16_t lookType, uint8_t addons) -{ - for (OutfitEntry& outfitEntry : outfits) { - if (outfitEntry.lookType == lookType) { - outfitEntry.addons |= addons; - return; - } - } - outfits.emplace_back(lookType, addons); -} - -bool Player::removeOutfit(uint16_t lookType) -{ - for (auto it = outfits.begin(), end = outfits.end(); it != end; ++it) { - OutfitEntry& entry = *it; - if (entry.lookType == lookType) { - outfits.erase(it); - return true; - } - } - return false; -} - -bool Player::removeOutfitAddon(uint16_t lookType, uint8_t addons) -{ - for (OutfitEntry& outfitEntry : outfits) { - if (outfitEntry.lookType == lookType) { - outfitEntry.addons &= ~addons; - return true; - } - } - return false; -} - -bool Player::getOutfitAddons(const Outfit& outfit, uint8_t& addons) const -{ - if (group->access) { - addons = 3; - return true; - } - - if (outfit.premium && !isPremium()) { - return false; - } - - for (const OutfitEntry& outfitEntry : outfits) { - if (outfitEntry.lookType != outfit.lookType) { - continue; - } - - addons = outfitEntry.addons; - return true; - } - - if (!outfit.unlocked) { - return false; - } - - addons = 0; - return true; -} - -void Player::setSex(PlayerSex_t newSex) -{ - sex = newSex; -} - -Skulls_t Player::getSkull() const -{ - if (hasFlag(PlayerFlag_NotGainInFight)) { - return SKULL_NONE; - } - return skull; -} - -Skulls_t Player::getSkullClient(const Creature* creature) const -{ - if (!creature || g_game.getWorldType() != WORLD_TYPE_PVP) { - return SKULL_NONE; - } - - const Player* player = creature->getPlayer(); - if (player && player->getSkull() == SKULL_NONE) { - if (isInWar(player)) { - return SKULL_GREEN; - } - - if (!player->getGuildWarList().empty() && guild == player->getGuild()) { - return SKULL_GREEN; - } - - if (player->hasAttacked(this)) { - return SKULL_YELLOW; - } - - if (isPartner(player)) { - return SKULL_GREEN; - } - } - return Creature::getSkullClient(creature); -} - -bool Player::hasAttacked(const Player* attacked) const -{ - if (hasFlag(PlayerFlag_NotGainInFight) || !attacked) { - return false; - } - - return attackedSet.find(attacked->guid) != attackedSet.end(); -} - -void Player::addAttacked(const Player* attacked) -{ - if (hasFlag(PlayerFlag_NotGainInFight) || !attacked || attacked == this) { - return; - } - - attackedSet.insert(attacked->guid); -} - -void Player::clearAttacked() -{ - attackedSet.clear(); -} - -void Player::addUnjustifiedDead(const Player* attacked) -{ - if (hasFlag(PlayerFlag_NotGainInFight) || attacked == this || g_game.getWorldType() == WORLD_TYPE_PVP_ENFORCED) { - return; - } - - sendTextMessage(MESSAGE_EVENT_ADVANCE, "Warning! The murder of " + attacked->getName() + " was not justified."); - - skullTicks += g_config.getNumber(ConfigManager::FRAG_TIME); - - if (getSkull() != SKULL_BLACK) { - if (g_config.getNumber(ConfigManager::KILLS_TO_BLACK) != 0 && skullTicks > (g_config.getNumber(ConfigManager::KILLS_TO_BLACK) - 1) * static_cast(g_config.getNumber(ConfigManager::FRAG_TIME))) { - setSkull(SKULL_BLACK); - } else if (getSkull() != SKULL_RED && g_config.getNumber(ConfigManager::KILLS_TO_RED) != 0 && skullTicks > (g_config.getNumber(ConfigManager::KILLS_TO_RED) - 1) * static_cast(g_config.getNumber(ConfigManager::FRAG_TIME))) { - setSkull(SKULL_RED); - } - } -} - -void Player::checkSkullTicks(int32_t ticks) -{ - int32_t newTicks = skullTicks - ticks; - if (newTicks < 0) { - skullTicks = 0; - } else { - skullTicks = newTicks; - } - - if ((skull == SKULL_RED || skull == SKULL_BLACK) && skullTicks < 1000 && !hasCondition(CONDITION_INFIGHT)) { - setSkull(SKULL_NONE); - } -} - -bool Player::isPromoted() const -{ - uint16_t promotedVocation = g_vocations.getPromotedVocation(vocation->getId()); - return promotedVocation == VOCATION_NONE && vocation->getId() != promotedVocation; -} - -double Player::getLostPercent() const -{ - int32_t blessingCount = std::bitset<5>(blessings).count(); - - int32_t deathLosePercent = g_config.getNumber(ConfigManager::DEATH_LOSE_PERCENT); - if (deathLosePercent != -1) { - if (isPromoted()) { - deathLosePercent -= 3; - } - - deathLosePercent -= blessingCount; - return std::max(0, deathLosePercent) / 100.; - } - - double lossPercent; - if (level >= 25) { - double tmpLevel = level + (levelPercent / 100.); - lossPercent = static_cast((tmpLevel + 50) * 50 * ((tmpLevel * tmpLevel) - (5 * tmpLevel) + 8)) / experience; - } else { - lossPercent = 10; - } - - if (isPromoted()) { - lossPercent *= 0.7; - } - - return lossPercent * pow(0.92, blessingCount) / 100; -} - -void Player::learnInstantSpell(const std::string& spellName) -{ - if (!hasLearnedInstantSpell(spellName)) { - learnedInstantSpellList.push_front(spellName); - } -} - -void Player::forgetInstantSpell(const std::string& spellName) -{ - learnedInstantSpellList.remove(spellName); -} - -bool Player::hasLearnedInstantSpell(const std::string& spellName) const -{ - if (hasFlag(PlayerFlag_CannotUseSpells)) { - return false; - } - - if (hasFlag(PlayerFlag_IgnoreSpellCheck)) { - return true; - } - - for (const auto& learnedSpellName : learnedInstantSpellList) { - if (strcasecmp(learnedSpellName.c_str(), spellName.c_str()) == 0) { - return true; - } - } - return false; -} - -bool Player::isInWar(const Player* player) const -{ - if (!player || !guild) { - return false; - } - - const Guild* playerGuild = player->getGuild(); - if (!playerGuild) { - return false; - } - - return isInWarList(playerGuild->getId()) && player->isInWarList(guild->getId()); -} - -bool Player::isInWarList(uint32_t guildId) const -{ - return std::find(guildWarList.begin(), guildWarList.end(), guildId) != guildWarList.end(); -} - -bool Player::isPremium() const -{ - if (g_config.getBoolean(ConfigManager::FREE_PREMIUM) || hasFlag(PlayerFlag_IsAlwaysPremium)) { - return true; - } - - return premiumDays > 0; -} - -void Player::setPremiumDays(int32_t v) -{ - premiumDays = v; - sendBasicData(); -} - -PartyShields_t Player::getPartyShield(const Player* player) const -{ - if (!player) { - return SHIELD_NONE; - } - - if (party) { - if (party->getLeader() == player) { - if (party->isSharedExperienceActive()) { - if (party->isSharedExperienceEnabled()) { - return SHIELD_YELLOW_SHAREDEXP; - } - - if (party->canUseSharedExperience(player)) { - return SHIELD_YELLOW_NOSHAREDEXP; - } - - return SHIELD_YELLOW_NOSHAREDEXP_BLINK; - } - - return SHIELD_YELLOW; - } - - if (player->party == party) { - if (party->isSharedExperienceActive()) { - if (party->isSharedExperienceEnabled()) { - return SHIELD_BLUE_SHAREDEXP; - } - - if (party->canUseSharedExperience(player)) { - return SHIELD_BLUE_NOSHAREDEXP; - } - - return SHIELD_BLUE_NOSHAREDEXP_BLINK; - } - - return SHIELD_BLUE; - } - - if (isInviting(player)) { - return SHIELD_WHITEBLUE; - } - } - - if (player->isInviting(this)) { - return SHIELD_WHITEYELLOW; - } - - if (player->party) { - return SHIELD_GRAY; - } - - return SHIELD_NONE; -} - -bool Player::isInviting(const Player* player) const -{ - if (!player || !party || party->getLeader() != this) { - return false; - } - return party->isPlayerInvited(player); -} - -bool Player::isPartner(const Player* player) const -{ - if (!player || !party) { - return false; - } - return party == player->party; -} - -bool Player::isGuildMate(const Player* player) const -{ - if (!player || !guild) { - return false; - } - return guild == player->guild; -} - -void Player::sendPlayerPartyIcons(Player* player) -{ - sendCreatureShield(player); - sendCreatureSkull(player); -} - -bool Player::addPartyInvitation(Party* party) -{ - auto it = std::find(invitePartyList.begin(), invitePartyList.end(), party); - if (it != invitePartyList.end()) { - return false; - } - - invitePartyList.push_front(party); - return true; -} - -void Player::removePartyInvitation(Party* party) -{ - invitePartyList.remove(party); -} - -void Player::clearPartyInvitations() -{ - for (Party* invitingParty : invitePartyList) { - invitingParty->removeInvite(*this, false); - } - invitePartyList.clear(); -} - -GuildEmblems_t Player::getGuildEmblem(const Player* player) const -{ - if (!player) { - return GUILDEMBLEM_NONE; - } - - const Guild* playerGuild = player->getGuild(); - if (!playerGuild) { - return GUILDEMBLEM_NONE; - } - - if (player->getGuildWarList().empty()) { - if (guild == playerGuild) { - return GUILDEMBLEM_MEMBER; - } else { - return GUILDEMBLEM_OTHER; - } - } else if (guild == playerGuild) { - return GUILDEMBLEM_ALLY; - } else if (isInWar(player)) { - return GUILDEMBLEM_ENEMY; - } - - return GUILDEMBLEM_NEUTRAL; -} - -uint8_t Player::getCurrentMount() const -{ - int32_t value; - if (getStorageValue(PSTRG_MOUNTS_CURRENTMOUNT, value)) { - return value; - } - return 0; -} - -void Player::setCurrentMount(uint8_t mount) -{ - addStorageValue(PSTRG_MOUNTS_CURRENTMOUNT, mount); -} - -bool Player::toggleMount(bool mount) -{ - if ((OTSYS_TIME() - lastToggleMount) < 3000 && !wasMounted) { - sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); - return false; - } - - if (mount) { - if (isMounted()) { - return false; - } - - if (!group->access && _tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - sendCancelMessage(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE); - return false; - } - - const Outfit* playerOutfit = Outfits::getInstance()->getOutfitByLookType(getSex(), defaultOutfit.lookType); - if (!playerOutfit) { - return false; - } - - uint8_t currentMountId = getCurrentMount(); - if (currentMountId == 0) { - sendOutfitWindow(); - return false; - } - - Mount* currentMount = g_game.mounts.getMountByID(currentMountId); - if (!currentMount) { - return false; - } - - if (!hasMount(currentMount)) { - setCurrentMount(0); - sendOutfitWindow(); - return false; - } - - if (currentMount->premium && !isPremium()) { - sendCancelMessage(RETURNVALUE_YOUNEEDPREMIUMACCOUNT); - return false; - } - - if (hasCondition(CONDITION_OUTFIT)) { - sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return false; - } - - defaultOutfit.lookMount = currentMount->clientId; - - if (currentMount->speed != 0) { - g_game.changeSpeed(this, currentMount->speed); - } - } else { - if (!isMounted()) { - return false; - } - - dismount(); - } - - g_game.internalCreatureChangeOutfit(this, defaultOutfit); - lastToggleMount = OTSYS_TIME(); - return true; -} - -bool Player::tameMount(uint8_t mountId) -{ - if (!g_game.mounts.getMountByID(mountId)) { - return false; - } - - const uint8_t tmpMountId = mountId - 1; - const uint32_t key = PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31); - - int32_t value; - if (getStorageValue(key, value)) { - value |= (1 << (tmpMountId % 31)); - } else { - value = (1 << (tmpMountId % 31)); - } - - addStorageValue(key, value); - return true; -} - -bool Player::untameMount(uint8_t mountId) -{ - if (!g_game.mounts.getMountByID(mountId)) { - return false; - } - - const uint8_t tmpMountId = mountId - 1; - const uint32_t key = PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31); - - int32_t value; - if (!getStorageValue(key, value)) { - return true; - } - - value &= ~(1 << (tmpMountId % 31)); - addStorageValue(key, value); - - if (getCurrentMount() == mountId) { - if (isMounted()) { - dismount(); - g_game.internalCreatureChangeOutfit(this, defaultOutfit); - } - - setCurrentMount(0); - } - - return true; -} - -bool Player::hasMount(const Mount* mount) const -{ - if (isAccessPlayer()) { - return true; - } - - if (mount->premium && !isPremium()) { - return false; - } - - const uint8_t tmpMountId = mount->id - 1; - - int32_t value; - if (!getStorageValue(PSTRG_MOUNTS_RANGE_START + (tmpMountId / 31), value)) { - return false; - } - - return ((1 << (tmpMountId % 31)) & value) != 0; -} - -void Player::dismount() -{ - Mount* mount = g_game.mounts.getMountByID(getCurrentMount()); - if (mount && mount->speed > 0) { - g_game.changeSpeed(this, -mount->speed); - } - - defaultOutfit.lookMount = 0; -} - -bool Player::addOfflineTrainingTries(skills_t skill, uint64_t tries) -{ - if (tries == 0 || skill == SKILL_LEVEL) { - return false; - } - - bool sendUpdate = false; - uint32_t oldSkillValue, newSkillValue; - long double oldPercentToNextLevel, newPercentToNextLevel; - - if (skill == SKILL_MAGLEVEL) { - uint64_t currReqMana = vocation->getReqMana(magLevel); - uint64_t nextReqMana = vocation->getReqMana(magLevel + 1); - - if (currReqMana >= nextReqMana) { - return false; - } - - oldSkillValue = magLevel; - oldPercentToNextLevel = static_cast(manaSpent * 100) / nextReqMana; - - g_events->eventPlayerOnGainSkillTries(this, SKILL_MAGLEVEL, tries); - uint32_t currMagLevel = magLevel; - - while ((manaSpent + tries) >= nextReqMana) { - tries -= nextReqMana - manaSpent; - - magLevel++; - manaSpent = 0; - - g_creatureEvents->playerAdvance(this, SKILL_MAGLEVEL, magLevel - 1, magLevel); - - sendUpdate = true; - currReqMana = nextReqMana; - nextReqMana = vocation->getReqMana(magLevel + 1); - - if (currReqMana >= nextReqMana) { - tries = 0; - break; - } - } - - manaSpent += tries; - - if (magLevel != currMagLevel) { - std::ostringstream ss; - ss << "You advanced to magic level " << magLevel << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - } - - uint8_t newPercent; - if (nextReqMana > currReqMana) { - newPercent = Player::getPercentLevel(manaSpent, nextReqMana); - newPercentToNextLevel = static_cast(manaSpent * 100) / nextReqMana; - } else { - newPercent = 0; - newPercentToNextLevel = 0; - } - - if (newPercent != magLevelPercent) { - magLevelPercent = newPercent; - sendUpdate = true; - } - - newSkillValue = magLevel; - } else { - uint64_t currReqTries = vocation->getReqSkillTries(skill, skills[skill].level); - uint64_t nextReqTries = vocation->getReqSkillTries(skill, skills[skill].level + 1); - if (currReqTries >= nextReqTries) { - return false; - } - - oldSkillValue = skills[skill].level; - oldPercentToNextLevel = static_cast(skills[skill].tries * 100) / nextReqTries; - - g_events->eventPlayerOnGainSkillTries(this, skill, tries); - uint32_t currSkillLevel = skills[skill].level; - - while ((skills[skill].tries + tries) >= nextReqTries) { - tries -= nextReqTries - skills[skill].tries; - - skills[skill].level++; - skills[skill].tries = 0; - skills[skill].percent = 0; - - g_creatureEvents->playerAdvance(this, skill, (skills[skill].level - 1), skills[skill].level); - - sendUpdate = true; - currReqTries = nextReqTries; - nextReqTries = vocation->getReqSkillTries(skill, skills[skill].level + 1); - - if (currReqTries >= nextReqTries) { - tries = 0; - break; - } - } - - skills[skill].tries += tries; - - if (currSkillLevel != skills[skill].level) { - std::ostringstream ss; - ss << "You advanced to " << getSkillName(skill) << " level " << skills[skill].level << '.'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - } - - uint8_t newPercent; - if (nextReqTries > currReqTries) { - newPercent = Player::getPercentLevel(skills[skill].tries, nextReqTries); - newPercentToNextLevel = static_cast(skills[skill].tries * 100) / nextReqTries; - } else { - newPercent = 0; - newPercentToNextLevel = 0; - } - - if (skills[skill].percent != newPercent) { - skills[skill].percent = newPercent; - sendUpdate = true; - } - - newSkillValue = skills[skill].level; - } - - if (sendUpdate) { - sendSkills(); - } - - std::ostringstream ss; - ss << std::fixed << std::setprecision(2) << "Your " << ucwords(getSkillName(skill)) << " skill changed from level " << oldSkillValue << " (with " << oldPercentToNextLevel << "% progress towards level " << (oldSkillValue + 1) << ") to level " << newSkillValue << " (with " << newPercentToNextLevel << "% progress towards level " << (newSkillValue + 1) << ')'; - sendTextMessage(MESSAGE_EVENT_ADVANCE, ss.str()); - return sendUpdate; -} - -bool Player::hasModalWindowOpen(uint32_t modalWindowId) const -{ - return find(modalWindows.begin(), modalWindows.end(), modalWindowId) != modalWindows.end(); -} - -void Player::onModalWindowHandled(uint32_t modalWindowId) -{ - modalWindows.remove(modalWindowId); -} - -void Player::sendModalWindow(const ModalWindow& modalWindow) -{ - if (!client) { - return; - } - - modalWindows.push_front(modalWindow.id); - client->sendModalWindow(modalWindow); -} - -void Player::clearModalWindows() -{ - modalWindows.clear(); -} - -uint16_t Player::getHelpers() const -{ - uint16_t helpers; - - if (guild && party) { - std::unordered_set helperSet; - - const auto& guildMembers = guild->getMembersOnline(); - helperSet.insert(guildMembers.begin(), guildMembers.end()); - - const auto& partyMembers = party->getMembers(); - helperSet.insert(partyMembers.begin(), partyMembers.end()); - - const auto& partyInvitees = party->getInvitees(); - helperSet.insert(partyInvitees.begin(), partyInvitees.end()); - - helperSet.insert(party->getLeader()); - - helpers = helperSet.size(); - } else if (guild) { - helpers = guild->getMembersOnline().size(); - } else if (party) { - helpers = party->getMemberCount() + party->getInvitationCount() + 1; - } else { - helpers = 0; - } - - return helpers; -} - -void Player::sendClosePrivate(uint16_t channelId) -{ - if (channelId == CHANNEL_GUILD || channelId == CHANNEL_PARTY) { - g_chat->removeUserFromChannel(*this, channelId); - } - - if (client) { - client->sendClosePrivate(channelId); - } -} - -uint64_t Player::getMoney() const -{ - std::vector containers; - uint64_t moneyCount = 0; - - for (int32_t i = CONST_SLOT_FIRST; i <= CONST_SLOT_LAST; ++i) { - Item* item = inventory[i]; - if (!item) { - continue; - } - - const Container* container = item->getContainer(); - if (container) { - containers.push_back(container); - } else { - moneyCount += item->getWorth(); - } - } - - size_t i = 0; - while (i < containers.size()) { - const Container* container = containers[i++]; - for (const Item* item : container->getItemList()) { - const Container* tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); - } else { - moneyCount += item->getWorth(); - } - } - } - return moneyCount; -} - -size_t Player::getMaxVIPEntries() const -{ - if (group->maxVipEntries != 0) { - return group->maxVipEntries; - } else if (isPremium()) { - return 100; - } - return 20; -} - -size_t Player::getMaxDepotItems() const -{ - if (group->maxDepotItems != 0) { - return group->maxDepotItems; - } else if (isPremium()) { - return 2000; - } - return 1000; -} - -std::forward_list Player::getMuteConditions() const -{ - std::forward_list muteConditions; - for (Condition* condition : conditions) { - if (condition->getTicks() <= 0) { - continue; - } - - ConditionType_t type = condition->getType(); - if (type != CONDITION_MUTED && type != CONDITION_CHANNELMUTEDTICKS && type != CONDITION_YELLTICKS) { - continue; - } - - muteConditions.push_front(condition); - } - return muteConditions; -} - -void Player::setGuild(Guild* guild) -{ - if (guild == this->guild) { - return; - } - - Guild* oldGuild = this->guild; - - this->guildNick.clear(); - this->guild = nullptr; - this->guildLevel = 0; - - if (guild) { - const GuildRank* rank = guild->getRankByLevel(1); - if (!rank) { - return; - } - - this->guild = guild; - this->guildLevel = 1; - guild->addMember(this); - } - - if (oldGuild) { - oldGuild->removeMember(this); - } -} diff --git a/path_10_8/src/player.h b/path_10_8/src/player.h deleted file mode 100644 index cac4d5246..000000000 --- a/path_10_8/src/player.h +++ /dev/null @@ -1,1350 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PLAYER_H_4083D3D3A05B4EDE891B31BB720CD06F -#define FS_PLAYER_H_4083D3D3A05B4EDE891B31BB720CD06F - -#include "creature.h" -#include "container.h" -#include "cylinder.h" -#include "outfit.h" -#include "enums.h" -#include "vocation.h" -#include "protocolgame.h" -#include "ioguild.h" -#include "party.h" -#include "inbox.h" -#include "depotchest.h" -#include "depotlocker.h" -#include "guild.h" -#include "groups.h" -#include "town.h" -#include "mounts.h" - -class House; -class NetworkMessage; -class Weapon; -class ProtocolGame; -class Npc; -class Party; -class SchedulerTask; -class Bed; -class Guild; - -enum skillsid_t { - SKILLVALUE_LEVEL = 0, - SKILLVALUE_TRIES = 1, - SKILLVALUE_PERCENT = 2, -}; - -enum playerinfo_t { - PLAYERINFO_LEVELPERCENT, - PLAYERINFO_HEALTH, - PLAYERINFO_MAXHEALTH, - PLAYERINFO_MANA, - PLAYERINFO_MAXMANA, - PLAYERINFO_MAGICLEVEL, - PLAYERINFO_MAGICLEVELPERCENT, -}; - -enum chaseMode_t : uint8_t { - CHASEMODE_STANDSTILL = 0, - CHASEMODE_FOLLOW = 1, -}; - -enum fightMode_t : uint8_t { - FIGHTMODE_ATTACK = 1, - FIGHTMODE_BALANCED = 2, - FIGHTMODE_DEFENSE = 3, -}; - -enum pvpMode_t : uint8_t { - PVP_MODE_DOVE = 0, - PVP_MODE_WHITE_HAND = 1, - PVP_MODE_YELLOW_HAND = 2, - PVP_MODE_RED_FIST = 3, -}; - -enum tradestate_t : uint8_t { - TRADE_NONE, - TRADE_INITIATED, - TRADE_ACCEPT, - TRADE_ACKNOWLEDGE, - TRADE_TRANSFER, -}; - -struct VIPEntry { - VIPEntry(uint32_t guid, std::string name, const std::string& description, uint32_t icon, bool notify) - : guid(guid), name(name), description(description), icon(icon), notify(notify) {} - - uint32_t guid; - std::string name; - std::string description; - uint32_t icon; - bool notify; -}; - -struct OpenContainer { - Container* container; - uint16_t index; -}; - -struct OutfitEntry { - OutfitEntry(uint16_t lookType, uint8_t addons) : lookType(lookType), addons(addons) {} - - uint16_t lookType; - uint8_t addons; -}; - -struct Skill { - Skill() : tries(0), level(10), percent(0) {} - uint64_t tries; - uint16_t level; - uint8_t percent; -}; - -typedef std::map MuteCountMap; - -#define PLAYER_MAX_SPEED 1500 -#define PLAYER_MIN_SPEED 10 - -class Player final : public Creature, public Cylinder -{ - public: - explicit Player(ProtocolGame_ptr p); - ~Player(); - - // non-copyable - Player(const Player&) = delete; - Player& operator=(const Player&) = delete; - - Player* getPlayer() final { - return this; - } - const Player* getPlayer() const final { - return this; - } - - void setID() final { - if (id == 0) { - id = playerAutoID++; - } - } - - static MuteCountMap muteCountMap; - - const std::string& getName() const final { - return name; - } - void setName(std::string name) { - this->name = name; - } - const std::string& getNameDescription() const final { - return name; - } - std::string getDescription(int32_t lookDistance) const final; - - CreatureType_t getType() const final { - return CREATURETYPE_PLAYER; - } - - uint8_t getCurrentMount() const; - void setCurrentMount(uint8_t mountId); - bool isMounted() const { - return defaultOutfit.lookMount != 0; - } - bool toggleMount(bool mount); - bool tameMount(uint8_t mountId); - bool untameMount(uint8_t mountId); - bool hasMount(const Mount* mount) const; - void dismount(); - - void sendFYIBox(const std::string& message) { - if (client) { - client->sendFYIBox(message); - } - } - - void setGUID(uint32_t _guid) { - guid = _guid; - } - uint32_t getGUID() const { - return guid; - } - bool canSeeInvisibility() const final { - return hasFlag(PlayerFlag_CanSenseInvisibility) || group->access; - } - - void removeList() final; - void addList() final; - void kickPlayer(bool displayEffect); - - static uint64_t getExpForLevel(int32_t lv) { - lv--; - return ((50ULL * lv * lv * lv) - (150ULL * lv * lv) + (400ULL * lv)) / 3ULL; - } - - uint16_t getStaminaMinutes() const { - return staminaMinutes; - } - - bool addOfflineTrainingTries(skills_t skill, uint64_t tries); - - void addOfflineTrainingTime(int32_t addTime) { - offlineTrainingTime = std::min(12 * 3600 * 1000, offlineTrainingTime + addTime); - } - void removeOfflineTrainingTime(int32_t removeTime) { - offlineTrainingTime = std::max(0, offlineTrainingTime - removeTime); - } - int32_t getOfflineTrainingTime() const { - return offlineTrainingTime; - } - - int32_t getOfflineTrainingSkill() const { - return offlineTrainingSkill; - } - void setOfflineTrainingSkill(int32_t skill) { - offlineTrainingSkill = skill; - } - - uint64_t getBankBalance() const { - return bankBalance; - } - void setBankBalance(uint64_t balance) { - bankBalance = balance; - } - - Guild* getGuild() const { - return guild; - } - void setGuild(Guild* guild); - - uint8_t getGuildLevel() const { - return guildLevel; - } - void setGuildLevel(uint8_t newGuildLevel) { - guildLevel = newGuildLevel; - } - - bool isGuildMate(const Player* player) const; - - const std::string& getGuildNick() const { - return guildNick; - } - void setGuildNick(std::string nick) { - guildNick = nick; - } - - bool isInWar(const Player* player) const; - bool isInWarList(uint32_t guild_id) const; - - void setLastWalkthroughAttempt(int64_t walkthroughAttempt) { - lastWalkthroughAttempt = walkthroughAttempt; - } - void setLastWalkthroughPosition(Position walkthroughPosition) { - lastWalkthroughPosition = walkthroughPosition; - } - - Inbox* getInbox() const { - return inbox; - } - - uint16_t getClientIcons() const; - - const GuildWarList& getGuildWarList() const { - return guildWarList; - } - void setGuildWarList(GuildWarList guildWarList) { - this->guildWarList = guildWarList; - } - - Vocation* getVocation() const { - return vocation; - } - - OperatingSystem_t getOperatingSystem() const { - return operatingSystem; - } - void setOperatingSystem(OperatingSystem_t clientos) { - operatingSystem = clientos; - } - - uint16_t getProtocolVersion() const { - if (!client) { - return 0; - } - - return client->getVersion(); - } - - bool hasSecureMode() const { - return secureMode; - } - - void setParty(Party* _party) { - party = _party; - } - Party* getParty() const { - return party; - } - PartyShields_t getPartyShield(const Player* player) const; - bool isInviting(const Player* player) const; - bool isPartner(const Player* player) const; - void sendPlayerPartyIcons(Player* player); - bool addPartyInvitation(Party* party); - void removePartyInvitation(Party* party); - void clearPartyInvitations(); - - GuildEmblems_t getGuildEmblem(const Player* player) const; - - uint64_t getSpentMana() const { - return manaSpent; - } - - bool hasFlag(PlayerFlags value) const { - return (group->flags & value) != 0; - } - - BedItem* getBedItem() { - return bedItem; - } - void setBedItem(BedItem* b) { - bedItem = b; - } - - void addBlessing(uint8_t blessing) { - blessings |= blessing; - } - void removeBlessing(uint8_t blessing) { - blessings &= ~blessing; - } - bool hasBlessing(uint8_t value) const { - return (blessings & (static_cast(1) << value)) != 0; - } - - bool isOffline() const { - return (getID() == 0); - } - void disconnect() { - if (client) { - client->disconnect(); - } - } - uint32_t getIP() const; - - void addContainer(uint8_t cid, Container* container); - void closeContainer(uint8_t cid); - void setContainerIndex(uint8_t cid, uint16_t index); - - Container* getContainerByID(uint8_t cid); - int8_t getContainerID(const Container* container) const; - uint16_t getContainerIndex(uint8_t cid) const; - - bool canOpenCorpse(uint32_t ownerId) const; - - void addStorageValue(const uint32_t key, const int32_t value, const bool isLogin = false); - bool getStorageValue(const uint32_t key, int32_t& value) const; - void genReservedStorageRange(); - - void setGroup(Group* newGroup) { - group = newGroup; - } - Group* getGroup() const { - return group; - } - - void setInMarket(bool value) { - inMarket = value; - } - bool isInMarket() const { - return inMarket; - } - - void setLastDepotId(int16_t newId) { - lastDepotId = newId; - } - int16_t getLastDepotId() const { - return lastDepotId; - } - - void resetIdleTime() { - idleTime = 0; - } - - bool isInGhostMode() const { - return ghostMode; - } - void switchGhostMode() { - ghostMode = !ghostMode; - } - - uint32_t getAccount() const { - return accountNumber; - } - AccountType_t getAccountType() const { - return accountType; - } - uint32_t getLevel() const { - return level; - } - uint32_t getMagicLevel() const { - return getPlayerInfo(PLAYERINFO_MAGICLEVEL); - } - uint32_t getBaseMagicLevel() const { - return magLevel; - } - uint8_t getSoul() const { - return soul; - } - bool isAccessPlayer() const { - return group->access; - } - bool isPremium() const; - void setPremiumDays(int32_t v); - - uint16_t getHelpers() const; - - bool setVocation(uint16_t vocId); - uint16_t getVocationId() const { - return vocation->getId(); - } - - PlayerSex_t getSex() const { - return sex; - } - void setSex(PlayerSex_t); - int32_t getPlayerInfo(playerinfo_t playerinfo) const; - uint64_t getExperience() const { - return experience; - } - - time_t getLastLoginSaved() const { - return lastLoginSaved; - } - - time_t getLastLogout() const { - return lastLogout; - } - - const Position& getLoginPosition() const { - return loginPosition; - } - const Position& getTemplePosition() const { - return town->getTemplePosition(); - } - Town* getTown() const { - return town; - } - void setTown(Town* _town) { - town = _town; - } - - void clearModalWindows(); - bool hasModalWindowOpen(uint32_t modalWindowId) const; - void onModalWindowHandled(uint32_t modalWindowId); - - bool isPushable() const final; - uint32_t isMuted() const; - void addMessageBuffer(); - void removeMessageBuffer(); - - bool removeItemOfType(uint16_t itemId, uint32_t amount, int32_t subType, bool ignoreEquipped = false) const; - - uint32_t getCapacity() const { - if (hasFlag(PlayerFlag_CannotPickupItem)) { - return 0; - } else if (hasFlag(PlayerFlag_HasInfiniteCapacity)) { - return std::numeric_limits::max(); - } - return capacity; - } - - uint32_t getFreeCapacity() const { - if (hasFlag(PlayerFlag_CannotPickupItem)) { - return 0; - } else if (hasFlag(PlayerFlag_HasInfiniteCapacity)) { - return std::numeric_limits::max(); - } else { - return std::max(0, capacity - inventoryWeight); - } - } - - int32_t getMaxHealth() const final { - return getPlayerInfo(PLAYERINFO_MAXHEALTH); - } - uint32_t getMaxMana() const { - return getPlayerInfo(PLAYERINFO_MAXMANA); - } - - Item* getInventoryItem(slots_t slot) const; - - bool isItemAbilityEnabled(slots_t slot) const { - return inventoryAbilities[slot]; - } - void setItemAbility(slots_t slot, bool enabled) { - inventoryAbilities[slot] = enabled; - } - - void setVarSkill(skills_t skill, int32_t modifier) { - varSkills[skill] += modifier; - } - - void setVarStats(stats_t stat, int32_t modifier); - int32_t getDefaultStats(stats_t stat) const; - - void addConditionSuppressions(uint32_t conditions); - void removeConditionSuppressions(uint32_t conditions); - - DepotChest* getDepotChest(uint32_t depotId, bool autoCreate); - DepotLocker* getDepotLocker(uint32_t depotId); - void onReceiveMail(); - bool isNearDepotBox() const; - - bool canSee(const Position& pos) const final; - bool canSeeCreature(const Creature* creature) const final; - - bool canWalkthrough(const Creature* creature) const; - bool canWalkthroughEx(const Creature* creature) const; - - RaceType_t getRace() const final { - return RACE_BLOOD; - } - - uint64_t getMoney() const; - - //safe-trade functions - void setTradeState(tradestate_t state) { - tradeState = state; - } - tradestate_t getTradeState() const { - return tradeState; - } - Item* getTradeItem() { - return tradeItem; - } - - //shop functions - void setShopOwner(Npc* owner, int32_t onBuy, int32_t onSell) { - shopOwner = owner; - purchaseCallback = onBuy; - saleCallback = onSell; - } - - Npc* getShopOwner(int32_t& onBuy, int32_t& onSell) { - onBuy = purchaseCallback; - onSell = saleCallback; - return shopOwner; - } - - const Npc* getShopOwner(int32_t& onBuy, int32_t& onSell) const { - onBuy = purchaseCallback; - onSell = saleCallback; - return shopOwner; - } - - //V.I.P. functions - void notifyStatusChange(Player* player, VipStatus_t status); - bool removeVIP(uint32_t vipGuid); - bool addVIP(uint32_t vipGuid, const std::string& vipName, VipStatus_t status); - bool addVIPInternal(uint32_t vipGuid); - bool editVIP(uint32_t vipGuid, const std::string& description, uint32_t icon, bool notify); - - //follow functions - bool setFollowCreature(Creature* creature) final; - void goToFollowCreature() final; - - //follow events - void onFollowCreature(const Creature* creature) final; - - //walk events - void onWalk(Direction& dir) final; - void onWalkAborted() final; - void onWalkComplete() final; - - void stopWalk(); - void openShopWindow(Npc* npc, const std::list& shop); - bool closeShopWindow(bool sendCloseShopWindow = true); - bool updateSaleShopList(const Item* item); - bool hasShopItemForSale(uint32_t itemId, uint8_t subType) const; - - void setChaseMode(chaseMode_t mode); - void setFightMode(fightMode_t mode) { - fightMode = mode; - } - void setSecureMode(bool mode) { - secureMode = mode; - } - - //combat functions - bool setAttackedCreature(Creature* creature) final; - bool isImmune(CombatType_t type) const final; - bool isImmune(ConditionType_t type) const final; - bool hasShield() const; - bool isAttackable() const final; - - void changeHealth(int32_t healthChange, bool sendHealthChange = true) final; - void changeMana(int32_t manaChange) final; - void changeSoul(int32_t soulChange); - - bool isPzLocked() const { - return pzLocked; - } - BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage, - bool checkDefense = false, bool checkArmor = false, bool field = false) final; - void doAttacking(uint32_t interval) final; - bool hasExtraSwing() final { - return lastAttack > 0 && ((OTSYS_TIME() - lastAttack) >= getAttackSpeed()); - } - - uint16_t getSkillLevel(uint8_t skill) const { - return std::max(0, skills[skill].level + varSkills[skill]); - } - uint16_t getBaseSkill(uint8_t skill) const { - return skills[skill].level; - } - uint8_t getSkillPercent(uint8_t skill) const { - return skills[skill].percent; - } - - bool getAddAttackSkill() const { - return addAttackSkillPoint; - } - BlockType_t getLastAttackBlockType() const { - return lastAttackBlockType; - } - - Item* getWeapon(slots_t slot, bool ignoreAmmo) const; - Item* getWeapon(bool ignoreAmmo = false) const; - WeaponType_t getWeaponType() const; - int32_t getWeaponSkill(const Item* item) const; - void getShieldAndWeapon(const Item*& shield, const Item*& weapon) const; - - void drainHealth(Creature* attacker, int32_t damage) final; - void drainMana(Creature* attacker, int32_t manaLoss) final; - void addManaSpent(uint64_t amount); - void addSkillAdvance(skills_t skill, uint64_t count); - - int32_t getArmor() const final; - int32_t getDefense() const final; - float getAttackFactor() const final; - float getDefenseFactor() const final; - - void addInFightTicks(bool pzlock = false); - - uint64_t getGainedExperience(Creature* attacker) const final; - - //combat event functions - void onAddCondition(ConditionType_t type) final; - void onAddCombatCondition(ConditionType_t type) final; - void onEndCondition(ConditionType_t type) final; - void onCombatRemoveCondition(Condition* condition) final; - void onAttackedCreature(Creature* target) final; - void onAttacked() final; - void onAttackedCreatureDrainHealth(Creature* target, int32_t points) final; - void onTargetCreatureGainHealth(Creature* target, int32_t points) final; - bool onKilledCreature(Creature* target, bool lastHit = true) final; - void onGainExperience(uint64_t gainExp, Creature* target) final; - void onGainSharedExperience(uint64_t gainExp, Creature* source); - void onAttackedCreatureBlockHit(BlockType_t blockType) final; - void onBlockHit() final; - void onChangeZone(ZoneType_t zone) final; - void onAttackedCreatureChangeZone(ZoneType_t zone) final; - void onIdleStatus() final; - void onPlacedCreature() final; - - void getCreatureLight(LightInfo& light) const final; - - Skulls_t getSkull() const final; - Skulls_t getSkullClient(const Creature* creature) const final; - int64_t getSkullTicks() const { return skullTicks; } - void setSkullTicks(int64_t ticks) { skullTicks = ticks; } - - bool hasAttacked(const Player* attacked) const; - void addAttacked(const Player* attacked); - void clearAttacked(); - void addUnjustifiedDead(const Player* attacked); - void sendCreatureSkull(const Creature* creature) const { - if (client) { - client->sendCreatureSkull(creature); - } - } - void checkSkullTicks(int32_t ticks); - - bool canWear(uint32_t lookType, uint8_t addons) const; - void addOutfit(uint16_t lookType, uint8_t addons); - bool removeOutfit(uint16_t lookType); - bool removeOutfitAddon(uint16_t lookType, uint8_t addons); - bool getOutfitAddons(const Outfit& outfit, uint8_t& addons) const; - - bool canLogout(); - - size_t getMaxVIPEntries() const; - size_t getMaxDepotItems() const; - - //tile - //send methods - void sendAddTileItem(const Tile* tile, const Position& pos, const Item* item) { - if (client) { - int32_t stackpos = tile->getStackposOfItem(this, item); - if (stackpos != -1) { - client->sendAddTileItem(pos, stackpos, item); - } - } - } - void sendUpdateTileItem(const Tile* tile, const Position& pos, const Item* item) { - if (client) { - int32_t stackpos = tile->getStackposOfItem(this, item); - if (stackpos != -1) { - client->sendUpdateTileItem(pos, stackpos, item); - } - } - } - void sendRemoveTileThing(const Position& pos, int32_t stackpos) { - if (stackpos != -1 && client) { - client->sendRemoveTileThing(pos, stackpos); - } - } - void sendUpdateTile(const Tile* tile, const Position& pos) { - if (client) { - client->sendUpdateTile(tile, pos); - } - } - - void sendChannelMessage(const std::string& author, const std::string& text, SpeakClasses type, uint16_t channel) { - if (client) { - client->sendChannelMessage(author, text, type, channel); - } - } - void sendChannelEvent(uint16_t channelId, const std::string& playerName, ChannelEvent_t channelEvent) { - if (client) { - client->sendChannelEvent(channelId, playerName, channelEvent); - } - } - void sendCreatureAppear(const Creature* creature, const Position& pos, bool isLogin) { - if (client) { - client->sendAddCreature(creature, pos, creature->getTile()->getStackposOfCreature(this, creature), isLogin); - } - } - void sendCreatureMove(const Creature* creature, const Position& newPos, int32_t newStackPos, const Position& oldPos, int32_t oldStackPos, bool teleport) { - if (client) { - client->sendMoveCreature(creature, newPos, newStackPos, oldPos, oldStackPos, teleport); - } - } - void sendCreatureTurn(const Creature* creature) { - if (client && canSeeCreature(creature)) { - int32_t stackpos = creature->getTile()->getStackposOfCreature(this, creature); - if (stackpos != -1) { - client->sendCreatureTurn(creature, stackpos); - } - } - } - void sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, const Position* pos = nullptr) { - if (client) { - client->sendCreatureSay(creature, type, text, pos); - } - } - void sendPrivateMessage(const Player* speaker, SpeakClasses type, const std::string& text) { - if (client) { - client->sendPrivateMessage(speaker, type, text); - } - } - void sendCreatureSquare(const Creature* creature, SquareColor_t color) { - if (client) { - client->sendCreatureSquare(creature, color); - } - } - void sendCreatureChangeOutfit(const Creature* creature, const Outfit_t& outfit) { - if (client) { - client->sendCreatureOutfit(creature, outfit); - } - } - void sendCreatureChangeVisible(const Creature* creature, bool visible) { - if (!client) { - return; - } - - if (creature->getPlayer()) { - if (visible) { - client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); - } else { - static Outfit_t outfit; - client->sendCreatureOutfit(creature, outfit); - } - } else if (canSeeInvisibility()) { - client->sendCreatureOutfit(creature, creature->getCurrentOutfit()); - } else { - int32_t stackpos = creature->getTile()->getStackposOfCreature(this, creature); - if (stackpos == -1) { - return; - } - - if (visible) { - client->sendAddCreature(creature, creature->getPosition(), stackpos, false); - } else { - client->sendRemoveTileThing(creature->getPosition(), stackpos); - } - } - } - void sendCreatureLight(const Creature* creature) { - if (client) { - client->sendCreatureLight(creature); - } - } - void sendCreatureWalkthrough(const Creature* creature, bool walkthrough) { - if (client) { - client->sendCreatureWalkthrough(creature, walkthrough); - } - } - void sendCreatureShield(const Creature* creature) { - if (client) { - client->sendCreatureShield(creature); - } - } - void sendCreatureType(uint32_t creatureId, uint8_t creatureType) { - if (client) { - client->sendCreatureType(creatureId, creatureType); - } - } - void sendCreatureHelpers(uint32_t creatureId, uint16_t helpers) { - if (client) { - client->sendCreatureHelpers(creatureId, helpers); - } - } - void sendSpellCooldown(uint8_t spellId, uint32_t time) { - if (client) { - client->sendSpellCooldown(spellId, time); - } - } - void sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time) { - if (client) { - client->sendSpellGroupCooldown(groupId, time); - } - } - void sendModalWindow(const ModalWindow& modalWindow); - - //container - void sendAddContainerItem(const Container* container, const Item* item); - void sendUpdateContainerItem(const Container* container, uint16_t slot, const Item* newItem); - void sendRemoveContainerItem(const Container* container, uint16_t slot); - void sendContainer(uint8_t cid, const Container* container, bool hasParent, uint16_t firstIndex) { - if (client) { - client->sendContainer(cid, container, hasParent, firstIndex); - } - } - - //inventory - void sendInventoryItem(slots_t slot, const Item* item) { - if (client) { - client->sendInventoryItem(slot, item); - } - } - - //event methods - void onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem, - const ItemType& oldType, const Item* newItem, const ItemType& newType) final; - void onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, - const Item* item) final; - - void onCreatureAppear(Creature* creature, bool isLogin) final; - void onRemoveCreature(Creature* creature, bool isLogout) final; - void onCreatureMove(Creature* creature, const Tile* newTile, const Position& newPos, - const Tile* oldTile, const Position& oldPos, bool teleport) final; - - void onAttackedCreatureDisappear(bool isLogout) final; - void onFollowCreatureDisappear(bool isLogout) final; - - //container - void onAddContainerItem(const Item* item); - void onUpdateContainerItem(const Container* container, const Item* oldItem, const Item* newItem); - void onRemoveContainerItem(const Container* container, const Item* item); - - void onCloseContainer(const Container* container); - void onSendContainer(const Container* container); - void autoCloseContainers(const Container* container); - - //inventory - void onUpdateInventoryItem(Item* oldItem, Item* newItem); - void onRemoveInventoryItem(Item* item); - - void sendCancelMessage(const std::string& msg) const { - if (client) { - client->sendTextMessage(TextMessage(MESSAGE_STATUS_SMALL, msg)); - } - } - void sendCancelMessage(ReturnValue message) const; - void sendCancelTarget() const { - if (client) { - client->sendCancelTarget(); - } - } - void sendCancelWalk() const { - if (client) { - client->sendCancelWalk(); - } - } - void sendChangeSpeed(const Creature* creature, uint32_t newSpeed) const { - if (client) { - client->sendChangeSpeed(creature, newSpeed); - } - } - void sendCreatureHealth(const Creature* creature) const { - if (client) { - client->sendCreatureHealth(creature); - } - } - void sendDistanceShoot(const Position& from, const Position& to, unsigned char type) const { - if (client) { - client->sendDistanceShoot(from, to, type); - } - } - void sendHouseWindow(House* house, uint32_t listId) const; - void sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName) { - if (client) { - client->sendCreatePrivateChannel(channelId, channelName); - } - } - void sendClosePrivate(uint16_t channelId); - void sendIcons() const { - if (client) { - client->sendIcons(getClientIcons()); - } - } - void sendMagicEffect(const Position& pos, uint8_t type) const { - if (client) { - client->sendMagicEffect(pos, type); - } - } - void sendPing(); - void sendPingBack() const { - if (client) { - client->sendPingBack(); - } - } - void sendStats(); - void sendBasicData() const { - if (client) { - client->sendBasicData(); - } - } - void sendSkills() const { - if (client) { - client->sendSkills(); - } - } - void sendTextMessage(MessageClasses mclass, const std::string& message) const { - if (client) { - client->sendTextMessage(TextMessage(mclass, message)); - } - } - void sendTextMessage(const TextMessage& message) const { - if (client) { - client->sendTextMessage(message); - } - } - void sendReLoginWindow(uint8_t unfairFightReduction) const { - if (client) { - client->sendReLoginWindow(unfairFightReduction); - } - } - void sendTextWindow(Item* item, uint16_t maxlen, bool canWrite) const { - if (client) { - client->sendTextWindow(windowTextId, item, maxlen, canWrite); - } - } - void sendTextWindow(uint32_t itemId, const std::string& text) const { - if (client) { - client->sendTextWindow(windowTextId, itemId, text); - } - } - void sendToChannel(const Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId) const { - if (client) { - client->sendToChannel(creature, type, text, channelId); - } - } - void sendShop(Npc* npc) const { - if (client) { - client->sendShop(npc, shopItemList); - } - } - void sendSaleItemList() const { - if (client) { - client->sendSaleItemList(shopItemList); - } - } - void sendCloseShop() const { - if (client) { - client->sendCloseShop(); - } - } - void sendMarketEnter(uint32_t depotId) const { - if (client) { - client->sendMarketEnter(depotId); - } - } - void sendMarketLeave() { - inMarket = false; - if (client) { - client->sendMarketLeave(); - } - } - void sendMarketBrowseItem(uint16_t itemId, const MarketOfferList& buyOffers, const MarketOfferList& sellOffers) const { - if (client) { - client->sendMarketBrowseItem(itemId, buyOffers, sellOffers); - } - } - void sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, const MarketOfferList& sellOffers) const { - if (client) { - client->sendMarketBrowseOwnOffers(buyOffers, sellOffers); - } - } - void sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyOffers, const HistoryMarketOfferList& sellOffers) const { - if (client) { - client->sendMarketBrowseOwnHistory(buyOffers, sellOffers); - } - } - void sendMarketDetail(uint16_t itemId) const { - if (client) { - client->sendMarketDetail(itemId); - } - } - void sendMarketAcceptOffer(const MarketOfferEx& offer) const { - if (client) { - client->sendMarketAcceptOffer(offer); - } - } - void sendMarketCancelOffer(const MarketOfferEx& offer) const { - if (client) { - client->sendMarketCancelOffer(offer); - } - } - void sendTradeItemRequest(const std::string& traderName, const Item* item, bool ack) const { - if (client) { - client->sendTradeItemRequest(traderName, item, ack); - } - } - void sendTradeClose() const { - if (client) { - client->sendCloseTrade(); - } - } - void sendWorldLight(const LightInfo& lightInfo) { - if (client) { - client->sendWorldLight(lightInfo); - } - } - void sendChannelsDialog() { - if (client) { - client->sendChannelsDialog(); - } - } - void sendOpenPrivateChannel(const std::string& receiver) { - if (client) { - client->sendOpenPrivateChannel(receiver); - } - } - void sendOutfitWindow() { - if (client) { - client->sendOutfitWindow(); - } - } - void sendCloseContainer(uint8_t cid) { - if (client) { - client->sendCloseContainer(cid); - } - } - - void sendChannel(uint16_t channelId, const std::string& channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) { - if (client) { - client->sendChannel(channelId, channelName, channelUsers, invitedUsers); - } - } - void sendTutorial(uint8_t tutorialId) { - if (client) { - client->sendTutorial(tutorialId); - } - } - void sendAddMarker(const Position& pos, uint8_t markType, const std::string& desc) { - if (client) { - client->sendAddMarker(pos, markType, desc); - } - } - void sendQuestLog() { - if (client) { - client->sendQuestLog(); - } - } - void sendQuestLine(const Quest* quest) { - if (client) { - client->sendQuestLine(quest); - } - } - void sendEnterWorld() { - if (client) { - client->sendEnterWorld(); - } - } - void sendFightModes() { - if (client) { - client->sendFightModes(); - } - } - void sendNetworkMessage(const NetworkMessage& message) { - if (client) { - client->writeToOutputBuffer(message); - } - } - - void receivePing() { - lastPong = OTSYS_TIME(); - } - - void onThink(uint32_t interval) final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - void setNextAction(int64_t time) { - if (time > nextAction) { - nextAction = time; - } - } - bool canDoAction() const { - return nextAction <= OTSYS_TIME(); - } - uint32_t getNextActionTime() const; - - Item* getWriteItem(uint32_t& _windowTextId, uint16_t& _maxWriteLen); - void setWriteItem(Item* item, uint16_t _maxWriteLen = 0); - - House* getEditHouse(uint32_t& _windowTextId, uint32_t& _listId); - void setEditHouse(House* house, uint32_t listId = 0); - - void learnInstantSpell(const std::string& spellName); - void forgetInstantSpell(const std::string& spellName); - bool hasLearnedInstantSpell(const std::string& spellName) const; - - protected: - std::forward_list getMuteConditions() const; - - void checkTradeState(const Item* item); - bool hasCapacity(const Item* item, uint32_t count) const; - - void gainExperience(uint64_t exp, Creature* source); - void addExperience(Creature* source, uint64_t exp, bool sendText = false); - void removeExperience(uint64_t exp, bool sendText = false); - - void updateInventoryWeight(); - - void setNextWalkActionTask(SchedulerTask* task); - void setNextWalkTask(SchedulerTask* task); - void setNextActionTask(SchedulerTask* task); - - void death(Creature* _lastHitCreature) final; - bool dropCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature, bool lastHitUnjustified, bool mostDamageUnjustified) final; - Item* getCorpse(Creature* _lastHitCreature, Creature* mostDamageCreature) final; - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount, - uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) final; - - void addThing(Thing*) final {} - void addThing(int32_t index, Thing* thing) final; - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - int32_t getThingIndex(const Thing* thing) const final; - size_t getFirstIndex() const final; - size_t getLastIndex() const final; - uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const final; - std::map& getAllItemTypeCount(std::map &countMap) const final; - Thing*getThing(size_t index) const final; - - void internalAddThing(Thing* thing) final; - void internalAddThing(uint32_t index, Thing* thing) final; - - std::unordered_set attackedSet; - std::unordered_set VIPList; - - std::map openContainers; - std::map depotLockerMap; - std::map depotChests; - std::map storageMap; - - std::vector outfits; - GuildWarList guildWarList; - - std::list shopItemList; - - std::forward_list invitePartyList; - std::forward_list modalWindows; - std::forward_list learnedInstantSpellList; - std::forward_list storedConditionList; // TODO: This variable is only temporarily used when logging in, get rid of it somehow - - std::string name; - std::string guildNick; - - Skill skills[SKILL_LAST + 1]; - LightInfo itemsLight; - Position loginPosition; - Position lastWalkthroughPosition; - - time_t lastLoginSaved; - time_t lastLogout; - - uint64_t experience; - uint64_t manaSpent; - uint64_t lastAttack; - uint64_t bankBalance; - uint64_t lastQuestlogUpdate; - int64_t lastFailedFollow; - int64_t skullTicks; - int64_t lastWalkthroughAttempt; - int64_t lastToggleMount; - int64_t lastPing; - int64_t lastPong; - int64_t nextAction; - - BedItem* bedItem; - Guild* guild; - Group* group; - Inbox* inbox; - Item* tradeItem; - Item* inventory[CONST_SLOT_LAST + 1]; - Item* writeItem; - House* editHouse; - Npc* shopOwner; - Party* party; - Player* tradePartner; - ProtocolGame_ptr client; - SchedulerTask* walkTask; - Town* town; - Vocation* vocation; - - uint32_t inventoryWeight; - uint32_t capacity; - uint32_t damageImmunities; - uint32_t conditionImmunities; - uint32_t conditionSuppressions; - uint32_t level; - uint32_t magLevel; - uint32_t actionTaskEvent; - uint32_t nextStepEvent; - uint32_t walkTaskEvent; - uint32_t MessageBufferTicks; - uint32_t lastIP; - uint32_t accountNumber; - uint32_t guid; - uint32_t windowTextId; - uint32_t editListId; - uint32_t manaMax; - int32_t varSkills[SKILL_LAST + 1]; - int32_t varStats[STAT_LAST + 1]; - int32_t purchaseCallback; - int32_t saleCallback; - int32_t MessageBufferCount; - int32_t premiumDays; - int32_t bloodHitCount; - int32_t shieldBlockCount; - int32_t offlineTrainingSkill; - int32_t offlineTrainingTime; - int32_t idleTime; - - uint16_t lastStatsTrainingTime; - uint16_t staminaMinutes; - uint16_t maxWriteLen; - int16_t lastDepotId; - - uint8_t soul; - uint8_t blessings; - uint8_t guildLevel; - uint8_t levelPercent; - uint8_t magLevelPercent; - - PlayerSex_t sex; - OperatingSystem_t operatingSystem; - BlockType_t lastAttackBlockType; - tradestate_t tradeState; - chaseMode_t chaseMode; - fightMode_t fightMode; - AccountType_t accountType; - - bool secureMode; - bool inMarket; - bool wasMounted; - bool ghostMode; - bool pzLocked; - bool isConnecting; - bool addAttackSkillPoint; - bool inventoryAbilities[CONST_SLOT_LAST + 1]; - - static uint32_t playerAutoID; - - void updateItemsLight(bool internal = false); - int32_t getStepSpeed() const final { - return std::max(PLAYER_MIN_SPEED, std::min(PLAYER_MAX_SPEED, getSpeed())); - } - void updateBaseSpeed() { - if (!hasFlag(PlayerFlag_SetMaxSpeed)) { - baseSpeed = vocation->getBaseSpeed() + (2 * (level - 1)); - } else { - baseSpeed = PLAYER_MAX_SPEED; - } - } - - bool isPromoted() const; - - uint32_t getAttackSpeed() const { - return vocation->getAttackSpeed(); - } - - static uint8_t getPercentLevel(uint64_t count, uint64_t nextLevelCount); - double getLostPercent() const; - uint64_t getLostExperience() const final { - return skillLoss ? static_cast(experience * getLostPercent()) : 0; - } - uint32_t getDamageImmunities() const final { - return damageImmunities; - } - uint32_t getConditionImmunities() const final { - return conditionImmunities; - } - uint32_t getConditionSuppressions() const final { - return conditionSuppressions; - } - uint16_t getLookCorpse() const final; - void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const final; - - friend class Game; - friend class Npc; - friend class LuaScriptInterface; - friend class Map; - friend class Actions; - friend class IOLoginData; - friend class ProtocolGame; -}; - -#endif diff --git a/path_10_8/src/position.cpp b/path_10_8/src/position.cpp deleted file mode 100644 index 5b943b6a6..000000000 --- a/path_10_8/src/position.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "position.h" - -std::ostream& operator<<(std::ostream& os, const Position& pos) -{ - os << "( " << std::setw(5) << std::setfill('0') << pos.x; - os << " / " << std::setw(5) << std::setfill('0') << pos.y; - os << " / " << std::setw(3) << std::setfill('0') << pos.getZ(); - os << " )"; - return os; -} - -std::ostream& operator<<(std::ostream& os, const Direction& dir) -{ - switch (dir) { - case DIRECTION_NORTH: - os << "North"; - break; - - case DIRECTION_EAST: - os << "East"; - break; - - case DIRECTION_WEST: - os << "West"; - break; - - case DIRECTION_SOUTH: - os << "South"; - break; - - case DIRECTION_SOUTHWEST: - os << "South-West"; - break; - - case DIRECTION_SOUTHEAST: - os << "South-East"; - break; - - case DIRECTION_NORTHWEST: - os << "North-West"; - break; - - case DIRECTION_NORTHEAST: - os << "North-East"; - break; - - default: - break; - } - - return os; -} diff --git a/path_10_8/src/position.h b/path_10_8/src/position.h deleted file mode 100644 index 2594ebed0..000000000 --- a/path_10_8/src/position.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_POSITION_H_5B684192F7034FB8857C8280D2CC6C75 -#define FS_POSITION_H_5B684192F7034FB8857C8280D2CC6C75 - -enum Direction : uint8_t { - DIRECTION_NORTH = 0, - DIRECTION_EAST = 1, - DIRECTION_SOUTH = 2, - DIRECTION_WEST = 3, - - DIRECTION_DIAGONAL_MASK = 4, - DIRECTION_SOUTHWEST = DIRECTION_DIAGONAL_MASK | 0, - DIRECTION_SOUTHEAST = DIRECTION_DIAGONAL_MASK | 1, - DIRECTION_NORTHWEST = DIRECTION_DIAGONAL_MASK | 2, - DIRECTION_NORTHEAST = DIRECTION_DIAGONAL_MASK | 3, - - DIRECTION_LAST = DIRECTION_NORTHEAST, - DIRECTION_SOUTH_ALT = 8, - DIRECTION_EAST_ALT = 9, - DIRECTION_NONE = 10, -}; - -struct Position -{ - Position() : x(0), y(0), z(0) {} - Position(uint16_t x, uint16_t y, uint8_t z) : x(x), y(y), z(z) {} - - template - inline static bool areInRange(const Position& p1, const Position& p2) { - return Position::getDistanceX(p1, p2) <= deltax && Position::getDistanceY(p1, p2) <= deltay; - } - - template - inline static bool areInRange(const Position& p1, const Position& p2) { - return Position::getDistanceX(p1, p2) <= deltax && Position::getDistanceY(p1, p2) <= deltay && Position::getDistanceZ(p1, p2) <= deltaz; - } - - inline static int_fast32_t getOffsetX(const Position& p1, const Position& p2) { - return p1.getX() - p2.getX(); - } - inline static int_fast32_t getOffsetY(const Position& p1, const Position& p2) { - return p1.getY() - p2.getY(); - } - inline static int_fast16_t getOffsetZ(const Position& p1, const Position& p2) { - return p1.getZ() - p2.getZ(); - } - - inline static int32_t getDistanceX(const Position& p1, const Position& p2) { - return std::abs(Position::getOffsetX(p1, p2)); - } - inline static int32_t getDistanceY(const Position& p1, const Position& p2) { - return std::abs(Position::getOffsetY(p1, p2)); - } - inline static int16_t getDistanceZ(const Position& p1, const Position& p2) { - return std::abs(Position::getOffsetZ(p1, p2)); - } - - uint16_t x; - uint16_t y; - uint8_t z; - - bool operator<(const Position& p) const { - if (z < p.z) { - return true; - } - - if (z > p.z) { - return false; - } - - if (y < p.y) { - return true; - } - - if (y > p.y) { - return false; - } - - if (x < p.x) { - return true; - } - - if (x > p.x) { - return false; - } - - return false; - } - - bool operator>(const Position& p) const { - return ! (*this < p); - } - - bool operator==(const Position& p) const { - return p.x == x && p.y == y && p.z == z; - } - - bool operator!=(const Position& p) const { - return p.x != x || p.y != y || p.z != z; - } - - Position operator+(const Position& p1) const { - return Position(x + p1.x, y + p1.y, z + p1.z); - } - - Position operator-(const Position& p1) const { - return Position(x - p1.x, y - p1.y, z - p1.z); - } - - inline int_fast32_t getX() const { return x; } - inline int_fast32_t getY() const { return y; } - inline int_fast16_t getZ() const { return z; } -}; - -std::ostream& operator<<(std::ostream&, const Position&); -std::ostream& operator<<(std::ostream&, const Direction&); - -#endif diff --git a/path_10_8/src/protocol.cpp b/path_10_8/src/protocol.cpp deleted file mode 100644 index 91dab1b54..000000000 --- a/path_10_8/src/protocol.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "protocol.h" -#include "outputmessage.h" -#include "rsa.h" - -extern RSA g_RSA; - -void Protocol::onSendMessage(const OutputMessage_ptr& msg) const -{ - if (!m_rawMessages) { - msg->writeMessageLength(); - - if (m_encryptionEnabled) { - XTEA_encrypt(*msg); - msg->addCryptoHeader(m_checksumEnabled); - } - } -} - -void Protocol::onRecvMessage(NetworkMessage& msg) -{ - if (m_encryptionEnabled && !XTEA_decrypt(msg)) { - return; - } - - parsePacket(msg); -} - -OutputMessage_ptr Protocol::getOutputBuffer(int32_t size) -{ - //dispatcher thread - if (m_outputBuffer && NetworkMessage::MAX_PROTOCOL_BODY_LENGTH >= m_outputBuffer->getLength() + size) { - return m_outputBuffer; - } else { - m_outputBuffer = OutputMessagePool::getOutputMessage(); - return m_outputBuffer; - } -} - -void Protocol::XTEA_encrypt(OutputMessage& msg) const -{ - const uint32_t delta = 0x61C88647; - - // The message must be a multiple of 8 - size_t paddingBytes = msg.getLength() % 8; - if (paddingBytes != 0) { - msg.addPaddingBytes(8 - paddingBytes); - } - - uint8_t* buffer = msg.getOutputBuffer(); - const size_t messageLength = msg.getLength(); - size_t readPos = 0; - const uint32_t k[] = {m_key[0], m_key[1], m_key[2], m_key[3]}; - while (readPos < messageLength) { - uint32_t v0; - memcpy(&v0, buffer + readPos, 4); - uint32_t v1; - memcpy(&v1, buffer + readPos + 4, 4); - - uint32_t sum = 0; - - for (int32_t i = 32; --i >= 0;) { - v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); - sum -= delta; - v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[(sum >> 11) & 3]); - } - - memcpy(buffer + readPos, &v0, 4); - readPos += 4; - memcpy(buffer + readPos, &v1, 4); - readPos += 4; - } -} - -bool Protocol::XTEA_decrypt(NetworkMessage& msg) const -{ - if (((msg.getLength() - 6) & 7) != 0) { - return false; - } - - const uint32_t delta = 0x61C88647; - - uint8_t* buffer = msg.getBuffer() + msg.getBufferPosition(); - const size_t messageLength = (msg.getLength() - 6); - size_t readPos = 0; - const uint32_t k[] = {m_key[0], m_key[1], m_key[2], m_key[3]}; - while (readPos < messageLength) { - uint32_t v0; - memcpy(&v0, buffer + readPos, 4); - uint32_t v1; - memcpy(&v1, buffer + readPos + 4, 4); - - uint32_t sum = 0xC6EF3720; - - for (int32_t i = 32; --i >= 0;) { - v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[(sum >> 11) & 3]); - sum += delta; - v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); - } - - memcpy(buffer + readPos, &v0, 4); - readPos += 4; - memcpy(buffer + readPos, &v1, 4); - readPos += 4; - } - - int innerLength = msg.get(); - if (innerLength > msg.getLength() - 8) { - return false; - } - - msg.setLength(innerLength); - return true; -} - -bool Protocol::RSA_decrypt(NetworkMessage& msg) -{ - if ((msg.getLength() - msg.getBufferPosition()) < 128) { - return false; - } - - g_RSA.decrypt(reinterpret_cast(msg.getBuffer()) + msg.getBufferPosition()); //does not break strict aliasing - return msg.getByte() == 0; -} - -uint32_t Protocol::getIP() const -{ - if (auto connection = getConnection()) { - return connection->getIP(); - } - - return 0; -} diff --git a/path_10_8/src/protocol.h b/path_10_8/src/protocol.h deleted file mode 100644 index dc0dd0e38..000000000 --- a/path_10_8/src/protocol.h +++ /dev/null @@ -1,107 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PROTOCOL_H_D71405071ACF4137A4B1203899DE80E1 -#define FS_PROTOCOL_H_D71405071ACF4137A4B1203899DE80E1 - -#include "connection.h" - -class Protocol : public std::enable_shared_from_this -{ - public: - explicit Protocol(Connection_ptr connection) : m_connection(connection), m_key(), m_encryptionEnabled(false), m_checksumEnabled(true), m_rawMessages(false) {} - virtual ~Protocol() = default; - - // non-copyable - Protocol(const Protocol&) = delete; - Protocol& operator=(const Protocol&) = delete; - - virtual void parsePacket(NetworkMessage&) {} - - virtual void onSendMessage(const OutputMessage_ptr& msg) const; - void onRecvMessage(NetworkMessage& msg); - virtual void onRecvFirstMessage(NetworkMessage& msg) = 0; - virtual void onConnect() {} - - bool isConnectionExpired() const { - return m_connection.expired(); - } - - Connection_ptr getConnection() const { - return m_connection.lock(); - } - - uint32_t getIP() const; - - //Use this function for autosend messages only - OutputMessage_ptr getOutputBuffer(int32_t size); - - OutputMessage_ptr& getCurrentBuffer() { - return m_outputBuffer; - } - - void send(OutputMessage_ptr msg) const { - if (auto connection = getConnection()) { - connection->send(msg); - } - } - - protected: - void disconnect() const { - if (auto connection = getConnection()) { - connection->close(); - } - } - void enableXTEAEncryption() { - m_encryptionEnabled = true; - } - void disableXTEAEncryption() { - m_encryptionEnabled = false; - } - void setXTEAKey(const uint32_t* key) { - memcpy(m_key, key, sizeof(*key) * 4); - } - void enableChecksum() { - m_checksumEnabled = true; - } - void disableChecksum() { - m_checksumEnabled = false; - } - - void XTEA_encrypt(OutputMessage& msg) const; - bool XTEA_decrypt(NetworkMessage& msg) const; - static bool RSA_decrypt(NetworkMessage& msg); - - void setRawMessages(bool value) { - m_rawMessages = value; - } - - virtual void release() {} - friend class Connection; - - OutputMessage_ptr m_outputBuffer; - private: - const ConnectionWeak_ptr m_connection; - uint32_t m_key[4]; - bool m_encryptionEnabled; - bool m_checksumEnabled; - bool m_rawMessages; -}; - -#endif diff --git a/path_10_8/src/protocolgame.cpp b/path_10_8/src/protocolgame.cpp deleted file mode 100644 index cab893fea..000000000 --- a/path_10_8/src/protocolgame.cpp +++ /dev/null @@ -1,3041 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "protocolgame.h" - -#include "outputmessage.h" - -#include "player.h" - -#include "configmanager.h" -#include "actions.h" -#include "game.h" -#include "iologindata.h" -#include "iomarket.h" -#include "waitlist.h" -#include "ban.h" -#include "scheduler.h" - -extern ConfigManager g_config; -extern Actions actions; -extern CreatureEvents* g_creatureEvents; -extern Chat* g_chat; - -ProtocolGame::ProtocolGame(Connection_ptr connection) : - Protocol(connection), - player(nullptr), - eventConnect(0), - m_challengeTimestamp(0), - version(CLIENT_VERSION_MIN), - m_challengeRandom(0), - m_debugAssertSent(false), - m_acceptPackets(false) -{ - // -} - -void ProtocolGame::release() -{ - //dispatcher thread - if (player && player->client == shared_from_this()) { - player->client.reset(); - player->decrementReferenceCounter(); - player = nullptr; - } - - OutputMessagePool::getInstance().removeProtocolFromAutosend(shared_from_this()); - Protocol::release(); -} - -void ProtocolGame::login(const std::string& name, uint32_t accountId, OperatingSystem_t operatingSystem) -{ - //dispatcher thread - Player* _player = g_game.getPlayerByName(name); - if (!_player || g_config.getBoolean(ConfigManager::ALLOW_CLONES)) { - player = new Player(getThis()); - player->setName(name); - - player->incrementReferenceCounter(); - player->setID(); - - if (!IOLoginData::preloadPlayer(player, name)) { - disconnectClient("Your character could not be loaded."); - return; - } - - if (IOBan::isPlayerNamelocked(player->getGUID())) { - disconnectClient("Your character has been namelocked."); - return; - } - - if (g_game.getGameState() == GAME_STATE_CLOSING && !player->hasFlag(PlayerFlag_CanAlwaysLogin)) { - disconnectClient("The game is just going down.\nPlease try again later."); - return; - } - - if (g_game.getGameState() == GAME_STATE_CLOSED && !player->hasFlag(PlayerFlag_CanAlwaysLogin)) { - disconnectClient("Server is currently closed.\nPlease try again later."); - return; - } - - if (g_config.getBoolean(ConfigManager::ONE_PLAYER_ON_ACCOUNT) && player->getAccountType() < ACCOUNT_TYPE_GAMEMASTER && g_game.getPlayerByAccount(player->getAccount())) { - disconnectClient("You may only login with one character\nof your account at the same time."); - return; - } - - if (!player->hasFlag(PlayerFlag_CannotBeBanned)) { - BanInfo banInfo; - if (IOBan::isAccountBanned(accountId, banInfo)) { - if (banInfo.reason.empty()) { - banInfo.reason = "(none)"; - } - - std::ostringstream ss; - if (banInfo.expiresAt > 0) { - ss << "Your account has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; - } else { - ss << "Your account has been permanently banned by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; - } - disconnectClient(ss.str()); - return; - } - } - - if (!WaitingList::getInstance()->clientLogin(player)) { - uint32_t currentSlot = WaitingList::getInstance()->getClientSlot(player); - uint32_t retryTime = WaitingList::getTime(currentSlot); - std::ostringstream ss; - - ss << "Too many players online.\nYou are at place " - << currentSlot << " on the waiting list."; - - auto output = OutputMessagePool::getOutputMessage(); - output->addByte(0x16); - output->addString(ss.str()); - output->addByte(retryTime); - send(output); - disconnect(); - return; - } - - if (!IOLoginData::loadPlayerByName(player, name)) { - disconnectClient("Your character could not be loaded."); - return; - } - - player->setOperatingSystem(operatingSystem); - - if (!g_game.placeCreature(player, player->getLoginPosition())) { - if (!g_game.placeCreature(player, player->getTemplePosition(), false, true)) { - disconnectClient("Temple position is wrong. Contact the administrator."); - return; - } - } - - if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { - player->registerCreatureEvent("ExtendedOpcode"); - } - - player->lastIP = player->getIP(); - player->lastLoginSaved = std::max(time(nullptr), player->lastLoginSaved + 1); - m_acceptPackets = true; - } else { - if (eventConnect != 0 || !g_config.getBoolean(ConfigManager::REPLACE_KICK_ON_LOGIN)) { - //Already trying to connect - disconnectClient("You are already logged in."); - return; - } - - if (_player->client) { - _player->disconnect(); - _player->isConnecting = true; - - eventConnect = g_scheduler.addEvent(createSchedulerTask(1000, std::bind(&ProtocolGame::connect, getThis(), _player->getID(), operatingSystem))); - } else { - connect(_player->getID(), operatingSystem); - } - } - OutputMessagePool::getInstance().addProtocolToAutosend(shared_from_this()); -} - -void ProtocolGame::connect(uint32_t playerId, OperatingSystem_t operatingSystem) -{ - eventConnect = 0; - - Player* _player = g_game.getPlayerByID(playerId); - if (!_player || _player->client) { - disconnectClient("You are already logged in."); - return; - } - - if (isConnectionExpired()) { - //ProtocolGame::release() has been called at this point and the Connection object - //no longer exists, so we return to prevent leakage of the Player. - return; - } - - player = _player; - player->incrementReferenceCounter(); - - g_chat->removeUserFromAllChannels(*player); - player->clearModalWindows(); - player->setOperatingSystem(operatingSystem); - player->isConnecting = false; - - player->client = getThis(); - sendAddCreature(player, player->getPosition(), 0, false); - player->lastIP = player->getIP(); - player->lastLoginSaved = std::max(time(nullptr), player->lastLoginSaved + 1); - m_acceptPackets = true; -} - -void ProtocolGame::logout(bool displayEffect, bool forced) -{ - //dispatcher thread - if (!player) { - return; - } - - if (!player->isRemoved()) { - if (!forced) { - if (!player->isAccessPlayer()) { - if (player->getTile()->hasFlag(TILESTATE_NOLOGOUT)) { - player->sendCancelMessage(RETURNVALUE_YOUCANNOTLOGOUTHERE); - return; - } - - if (!player->getTile()->hasFlag(TILESTATE_PROTECTIONZONE) && player->hasCondition(CONDITION_INFIGHT)) { - player->sendCancelMessage(RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT); - return; - } - } - - //scripting event - onLogout - if (!g_creatureEvents->playerLogout(player)) { - //Let the script handle the error message - return; - } - } - - if (displayEffect && player->getHealth() > 0) { - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - } - } - - disconnect(); - - g_game.removeCreature(player); -} - -void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg) -{ - if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { - disconnect(); - return; - } - - OperatingSystem_t operatingSystem = static_cast(msg.get()); - version = msg.get(); - - msg.skipBytes(7); // U32 client version, U8 client type, U16 dat revision - - if (!Protocol::RSA_decrypt(msg)) { - disconnect(); - return; - } - - uint32_t key[4]; - key[0] = msg.get(); - key[1] = msg.get(); - key[2] = msg.get(); - key[3] = msg.get(); - enableXTEAEncryption(); - setXTEAKey(key); - - if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) { - NetworkMessage opcodeMessage; - opcodeMessage.addByte(0x32); - opcodeMessage.addByte(0x00); - opcodeMessage.add(0x00); - writeToOutputBuffer(opcodeMessage); - } - - msg.skipBytes(1); // gamemaster flag - - std::string sessionKey = msg.getString(); - size_t pos = sessionKey.find('\n'); - if (pos == std::string::npos) { - disconnectClient("You must enter your account name."); - return; - } - - std::string accountName = sessionKey.substr(0, pos); - if (accountName.empty()) { - disconnectClient("You must enter your account name."); - return; - } - - std::string password = sessionKey.substr(pos + 1); - - std::string characterName = msg.getString(); - - uint32_t timeStamp = msg.get(); - uint8_t randNumber = msg.getByte(); - if (m_challengeTimestamp != timeStamp || m_challengeRandom != randNumber) { - disconnect(); - return; - } - - if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); - return; - } - - if (g_game.getGameState() == GAME_STATE_STARTUP) { - disconnectClient("Gameworld is starting up. Please wait."); - return; - } - - if (g_game.getGameState() == GAME_STATE_MAINTAIN) { - disconnectClient("Gameworld is under maintenance. Please re-connect in a while."); - return; - } - - BanInfo banInfo; - if (IOBan::isIpBanned(getIP(), banInfo)) { - if (banInfo.reason.empty()) { - banInfo.reason = "(none)"; - } - - std::ostringstream ss; - ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; - disconnectClient(ss.str()); - return; - } - - uint32_t accountId = IOLoginData::gameworldAuthentication(accountName, password, characterName); - if (accountId == 0) { - disconnectClient("Account name or password is not correct."); - return; - } - - g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::login, getThis(), characterName, accountId, operatingSystem))); -} - -void ProtocolGame::onConnect() -{ - auto output = OutputMessagePool::getOutputMessage(); - static std::random_device rd; - static std::ranlux24 generator(rd()); - static std::uniform_int_distribution randNumber(0x00, 0xFF); - - // Skip checksum - output->skipBytes(sizeof(uint32_t)); - - // Packet length & type - output->add(0x0006); - output->addByte(0x1F); - - // Add timestamp & random number - m_challengeTimestamp = static_cast(time(nullptr)); - output->add(m_challengeTimestamp); - - m_challengeRandom = randNumber(generator); - output->addByte(m_challengeRandom); - - // Go back and write checksum - output->skipBytes(-12); - output->add(adlerChecksum(output->getOutputBuffer() + sizeof(uint32_t), 8)); - - send(output); -} - -void ProtocolGame::disconnectClient(const std::string& message) const -{ - auto output = OutputMessagePool::getOutputMessage(); - output->addByte(0x14); - output->addString(message); - send(output); - disconnect(); -} - -void ProtocolGame::writeToOutputBuffer(const NetworkMessage& msg) -{ - auto out = getOutputBuffer(msg.getLength()); - out->append(msg); -} - -void ProtocolGame::parsePacket(NetworkMessage& msg) -{ - if (!m_acceptPackets || g_game.getGameState() == GAME_STATE_SHUTDOWN || msg.getLength() <= 0) { - return; - } - - uint8_t recvbyte = msg.getByte(); - - if (!player) { - if (recvbyte == 0x0F) { - disconnect(); - } - - return; - } - - //a dead player can not performs actions - if (player->isRemoved() || player->getHealth() <= 0) { - if (recvbyte == 0x0F) { - disconnect(); - return; - } - - if (recvbyte != 0x14) { - return; - } - } - - switch (recvbyte) { - case 0x14: g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::logout, getThis(), true, false))); break; - case 0x1D: addGameTask(&Game::playerReceivePingBack, player->getID()); break; - case 0x1E: addGameTask(&Game::playerReceivePing, player->getID()); break; - case 0x32: parseExtendedOpcode(msg); break; //otclient extended opcode - case 0x64: parseAutoWalk(msg); break; - case 0x65: addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTH); break; - case 0x66: addGameTask(&Game::playerMove, player->getID(), DIRECTION_EAST); break; - case 0x67: addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTH); break; - case 0x68: addGameTask(&Game::playerMove, player->getID(), DIRECTION_WEST); break; - case 0x69: addGameTask(&Game::playerStopAutoWalk, player->getID()); break; - case 0x6A: addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHEAST); break; - case 0x6B: addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHEAST); break; - case 0x6C: addGameTask(&Game::playerMove, player->getID(), DIRECTION_SOUTHWEST); break; - case 0x6D: addGameTask(&Game::playerMove, player->getID(), DIRECTION_NORTHWEST); break; - case 0x6F: addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), DIRECTION_NORTH); break; - case 0x70: addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), DIRECTION_EAST); break; - case 0x71: addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), DIRECTION_SOUTH); break; - case 0x72: addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerTurn, player->getID(), DIRECTION_WEST); break; - case 0x78: parseThrow(msg); break; - case 0x79: parseLookInShop(msg); break; - case 0x7A: parsePlayerPurchase(msg); break; - case 0x7B: parsePlayerSale(msg); break; - case 0x7C: addGameTask(&Game::playerCloseShop, player->getID()); break; - case 0x7D: parseRequestTrade(msg); break; - case 0x7E: parseLookInTrade(msg); break; - case 0x7F: addGameTask(&Game::playerAcceptTrade, player->getID()); break; - case 0x80: addGameTask(&Game::playerCloseTrade, player->getID()); break; - case 0x82: parseUseItem(msg); break; - case 0x83: parseUseItemEx(msg); break; - case 0x84: parseUseWithCreature(msg); break; - case 0x85: parseRotateItem(msg); break; - case 0x87: parseCloseContainer(msg); break; - case 0x88: parseUpArrowContainer(msg); break; - case 0x89: parseTextWindow(msg); break; - case 0x8A: parseHouseWindow(msg); break; - case 0x8C: parseLookAt(msg); break; - case 0x8D: parseLookInBattleList(msg); break; - case 0x8E: /* join aggression */ break; - case 0x96: parseSay(msg); break; - case 0x97: addGameTask(&Game::playerRequestChannels, player->getID()); break; - case 0x98: parseOpenChannel(msg); break; - case 0x99: parseCloseChannel(msg); break; - case 0x9A: parseOpenPrivateChannel(msg); break; - case 0x9E: addGameTask(&Game::playerCloseNpcChannel, player->getID()); break; - case 0xA0: parseFightModes(msg); break; - case 0xA1: parseAttack(msg); break; - case 0xA2: parseFollow(msg); break; - case 0xA3: parseInviteToParty(msg); break; - case 0xA4: parseJoinParty(msg); break; - case 0xA5: parseRevokePartyInvite(msg); break; - case 0xA6: parsePassPartyLeadership(msg); break; - case 0xA7: addGameTask(&Game::playerLeaveParty, player->getID()); break; - case 0xA8: parseEnableSharedPartyExperience(msg); break; - case 0xAA: addGameTask(&Game::playerCreatePrivateChannel, player->getID()); break; - case 0xAB: parseChannelInvite(msg); break; - case 0xAC: parseChannelExclude(msg); break; - case 0xBE: addGameTask(&Game::playerCancelAttackAndFollow, player->getID()); break; - case 0xC9: /* update tile */ break; - case 0xCA: parseUpdateContainer(msg); break; - case 0xCB: parseBrowseField(msg); break; - case 0xCC: parseSeekInContainer(msg); break; - case 0xD2: addGameTask(&Game::playerRequestOutfit, player->getID()); break; - case 0xD3: parseSetOutfit(msg); break; - case 0xD4: parseToggleMount(msg); break; - case 0xDC: parseAddVip(msg); break; - case 0xDD: parseRemoveVip(msg); break; - case 0xDE: parseEditVip(msg); break; - case 0xE6: parseBugReport(msg); break; - case 0xE7: /* thank you */ break; - case 0xE8: parseDebugAssert(msg); break; - case 0xF0: addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerShowQuestLog, player->getID()); break; - case 0xF1: parseQuestLine(msg); break; - case 0xF2: /* rule violation report */ break; - case 0xF3: /* get object info */ break; - case 0xF4: parseMarketLeave(); break; - case 0xF5: parseMarketBrowse(msg); break; - case 0xF6: parseMarketCreateOffer(msg); break; - case 0xF7: parseMarketCancelOffer(msg); break; - case 0xF8: parseMarketAcceptOffer(msg); break; - case 0xF9: parseModalWindowAnswer(msg); break; - - default: - // std::cout << "Player: " << player->getName() << " sent an unknown packet header: 0x" << std::hex << static_cast(recvbyte) << std::dec << "!" << std::endl; - break; - } - - if (msg.isOverrun()) { - disconnect(); - } -} - -void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage& msg) -{ - msg.add(0x00); //environmental effects - - int32_t count; - Item* ground = tile->getGround(); - if (ground) { - msg.addItem(ground); - count = 1; - } else { - count = 0; - } - - const TileItemVector* items = tile->getItemList(); - if (items) { - for (auto it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - msg.addItem(*it); - - if (++count == 10) { - return; - } - } - } - - const CreatureVector* creatures = tile->getCreatures(); - if (creatures) { - for (const Creature* creature : boost::adaptors::reverse(*creatures)) { - if (!player->canSeeCreature(creature)) { - continue; - } - - bool known; - uint32_t removedKnown; - checkCreatureAsKnown(creature->getID(), known, removedKnown); - AddCreature(msg, creature, known, removedKnown); - - if (++count == 10) { - return; - } - } - } - - if (items) { - for (auto it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - msg.addItem(*it); - - if (++count == 10) { - return; - } - } - } -} - -void ProtocolGame::GetMapDescription(int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, NetworkMessage& msg) -{ - int32_t skip = -1; - int32_t startz, endz, zstep; - - if (z > 7) { - startz = z - 2; - endz = std::min(MAP_MAX_LAYERS - 1, z + 2); - zstep = 1; - } else { - startz = 7; - endz = 0; - zstep = -1; - } - - for (int32_t nz = startz; nz != endz + zstep; nz += zstep) { - GetFloorDescription(msg, x, y, nz, width, height, z - nz, skip); - } - - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } -} - -void ProtocolGame::GetFloorDescription(NetworkMessage& msg, int32_t x, int32_t y, int32_t z, int32_t width, int32_t height, int32_t offset, int32_t& skip) -{ - for (int32_t nx = 0; nx < width; nx++) { - for (int32_t ny = 0; ny < height; ny++) { - Tile* tile = g_game.map.getTile(x + nx + offset, y + ny + offset, z); - if (tile) { - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } - - skip = 0; - GetTileDescription(tile, msg); - } else if (skip == 0xFE) { - msg.addByte(0xFF); - msg.addByte(0xFF); - skip = -1; - } else { - ++skip; - } - } - } -} - -void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& removedKnown) -{ - auto result = knownCreatureSet.insert(id); - if (!result.second) { - known = true; - return; - } - - known = false; - - if (knownCreatureSet.size() > 1300) { - // Look for a creature to remove - for (std::unordered_set::iterator it = knownCreatureSet.begin(), end = knownCreatureSet.end(); it != end; ++it) { - Creature* creature = g_game.getCreatureByID(*it); - if (!canSee(creature)) { - removedKnown = *it; - knownCreatureSet.erase(it); - return; - } - } - - // Bad situation. Let's just remove anyone. - std::unordered_set::iterator it = knownCreatureSet.begin(); - if (*it == id) { - ++it; - } - - removedKnown = *it; - knownCreatureSet.erase(it); - } else { - removedKnown = 0; - } -} - -bool ProtocolGame::canSee(const Creature* c) const -{ - if (!c || !player || c->isRemoved()) { - return false; - } - - if (!player->canSeeCreature(c)) { - return false; - } - - return canSee(c->getPosition()); -} - -bool ProtocolGame::canSee(const Position& pos) const -{ - return canSee(pos.x, pos.y, pos.z); -} - -bool ProtocolGame::canSee(int32_t x, int32_t y, int32_t z) const -{ - if (!player) { - return false; - } - - const Position& myPos = player->getPosition(); - if (myPos.z <= 7) { - //we are on ground level or above (7 -> 0) - //view is from 7 -> 0 - if (z > 7) { - return false; - } - } else if (myPos.z >= 8) { - //we are underground (8 -> 15) - //view is +/- 2 from the floor we stand on - if (std::abs(myPos.getZ() - z) > 2) { - return false; - } - } - - //negative offset means that the action taken place is on a lower floor than ourself - int32_t offsetz = myPos.getZ() - z; - if ((x >= myPos.getX() - 8 + offsetz) && (x <= myPos.getX() + 9 + offsetz) && - (y >= myPos.getY() - 6 + offsetz) && (y <= myPos.getY() + 7 + offsetz)) { - return true; - } - return false; -} - -// Parse methods -void ProtocolGame::parseChannelInvite(NetworkMessage& msg) -{ - const std::string name = msg.getString(); - addGameTask(&Game::playerChannelInvite, player->getID(), name); -} - -void ProtocolGame::parseChannelExclude(NetworkMessage& msg) -{ - const std::string name = msg.getString(); - addGameTask(&Game::playerChannelExclude, player->getID(), name); -} - -void ProtocolGame::parseOpenChannel(NetworkMessage& msg) -{ - uint16_t channelId = msg.get(); - addGameTask(&Game::playerOpenChannel, player->getID(), channelId); -} - -void ProtocolGame::parseCloseChannel(NetworkMessage& msg) -{ - uint16_t channelId = msg.get(); - addGameTask(&Game::playerCloseChannel, player->getID(), channelId); -} - -void ProtocolGame::parseOpenPrivateChannel(NetworkMessage& msg) -{ - const std::string receiver = msg.getString(); - addGameTask(&Game::playerOpenPrivateChannel, player->getID(), receiver); -} - -void ProtocolGame::parseAutoWalk(NetworkMessage& msg) -{ - uint8_t numdirs = msg.getByte(); - if (numdirs == 0 || (msg.getBufferPosition() + numdirs) != (msg.getLength() + 8)) { - return; - } - - msg.skipBytes(numdirs); - - std::forward_list path; - for (uint8_t i = 0; i < numdirs; ++i) { - uint8_t rawdir = msg.getPreviousByte(); - switch (rawdir) { - case 1: path.push_front(DIRECTION_EAST); break; - case 2: path.push_front(DIRECTION_NORTHEAST); break; - case 3: path.push_front(DIRECTION_NORTH); break; - case 4: path.push_front(DIRECTION_NORTHWEST); break; - case 5: path.push_front(DIRECTION_WEST); break; - case 6: path.push_front(DIRECTION_SOUTHWEST); break; - case 7: path.push_front(DIRECTION_SOUTH); break; - case 8: path.push_front(DIRECTION_SOUTHEAST); break; - default: break; - } - } - - if (path.empty()) { - return; - } - - addGameTask(&Game::playerAutoWalk, player->getID(), path); -} - -void ProtocolGame::parseSetOutfit(NetworkMessage& msg) -{ - Outfit_t newOutfit; - newOutfit.lookType = msg.get(); - newOutfit.lookHead = msg.getByte(); - newOutfit.lookBody = msg.getByte(); - newOutfit.lookLegs = msg.getByte(); - newOutfit.lookFeet = msg.getByte(); - newOutfit.lookAddons = msg.getByte(); - newOutfit.lookMount = msg.get(); - addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit); -} - -void ProtocolGame::parseToggleMount(NetworkMessage& msg) -{ - bool mount = msg.getByte() != 0; - addGameTask(&Game::playerToggleMount, player->getID(), mount); -} - -void ProtocolGame::parseUseItem(NetworkMessage& msg) -{ - Position pos = msg.getPosition(); - uint16_t spriteId = msg.get(); - uint8_t stackpos = msg.getByte(); - uint8_t index = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItem, player->getID(), pos, stackpos, index, spriteId); -} - -void ProtocolGame::parseUseItemEx(NetworkMessage& msg) -{ - Position fromPos = msg.getPosition(); - uint16_t fromSpriteId = msg.get(); - uint8_t fromStackPos = msg.getByte(); - Position toPos = msg.getPosition(); - uint16_t toSpriteId = msg.get(); - uint8_t toStackPos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseItemEx, player->getID(), fromPos, fromStackPos, fromSpriteId, toPos, toStackPos, toSpriteId); -} - -void ProtocolGame::parseUseWithCreature(NetworkMessage& msg) -{ - Position fromPos = msg.getPosition(); - uint16_t spriteId = msg.get(); - uint8_t fromStackPos = msg.getByte(); - uint32_t creatureId = msg.get(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerUseWithCreature, player->getID(), fromPos, fromStackPos, creatureId, spriteId); -} - -void ProtocolGame::parseCloseContainer(NetworkMessage& msg) -{ - uint8_t cid = msg.getByte(); - addGameTask(&Game::playerCloseContainer, player->getID(), cid); -} - -void ProtocolGame::parseUpArrowContainer(NetworkMessage& msg) -{ - uint8_t cid = msg.getByte(); - addGameTask(&Game::playerMoveUpContainer, player->getID(), cid); -} - -void ProtocolGame::parseUpdateContainer(NetworkMessage& msg) -{ - uint8_t cid = msg.getByte(); - addGameTask(&Game::playerUpdateContainer, player->getID(), cid); -} - -void ProtocolGame::parseThrow(NetworkMessage& msg) -{ - Position fromPos = msg.getPosition(); - uint16_t spriteId = msg.get(); - uint8_t fromStackpos = msg.getByte(); - Position toPos = msg.getPosition(); - uint8_t count = msg.getByte(); - - if (toPos != fromPos) { - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerMoveThing, player->getID(), fromPos, spriteId, fromStackpos, toPos, count); - } -} - -void ProtocolGame::parseLookAt(NetworkMessage& msg) -{ - Position pos = msg.getPosition(); - msg.skipBytes(2); // spriteId - uint8_t stackpos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookAt, player->getID(), pos, stackpos); -} - -void ProtocolGame::parseLookInBattleList(NetworkMessage& msg) -{ - uint32_t creatureId = msg.get(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInBattleList, player->getID(), creatureId); -} - -void ProtocolGame::parseSay(NetworkMessage& msg) -{ - std::string receiver; - uint16_t channelId; - - SpeakClasses type = static_cast(msg.getByte()); - switch (type) { - case TALKTYPE_PRIVATE_TO: - case TALKTYPE_PRIVATE_RED_TO: - receiver = msg.getString(); - channelId = 0; - break; - - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - channelId = msg.get(); - break; - - default: - channelId = 0; - break; - } - - const std::string text = msg.getString(); - if (text.length() > 255) { - return; - } - - addGameTask(&Game::playerSay, player->getID(), channelId, type, receiver, text); -} - -void ProtocolGame::parseFightModes(NetworkMessage& msg) -{ - uint8_t rawFightMode = msg.getByte(); // 1 - offensive, 2 - balanced, 3 - defensive - uint8_t rawChaseMode = msg.getByte(); // 0 - stand while fightning, 1 - chase opponent - uint8_t rawSecureMode = msg.getByte(); // 0 - can't attack unmarked, 1 - can attack unmarked - // uint8_t rawPvpMode = msg.getByte(); // pvp mode introduced in 10.0 - - chaseMode_t chaseMode; - if (rawChaseMode == 1) { - chaseMode = CHASEMODE_FOLLOW; - } else { - chaseMode = CHASEMODE_STANDSTILL; - } - - fightMode_t fightMode; - if (rawFightMode == 1) { - fightMode = FIGHTMODE_ATTACK; - } else if (rawFightMode == 2) { - fightMode = FIGHTMODE_BALANCED; - } else { - fightMode = FIGHTMODE_DEFENSE; - } - - addGameTask(&Game::playerSetFightModes, player->getID(), fightMode, chaseMode, rawSecureMode != 0); -} - -void ProtocolGame::parseAttack(NetworkMessage& msg) -{ - uint32_t creatureId = msg.get(); - // msg.get(); creatureId (same as above) - addGameTask(&Game::playerSetAttackedCreature, player->getID(), creatureId); -} - -void ProtocolGame::parseFollow(NetworkMessage& msg) -{ - uint32_t creatureId = msg.get(); - // msg.get(); creatureId (same as above) - addGameTask(&Game::playerFollowCreature, player->getID(), creatureId); -} - -void ProtocolGame::parseTextWindow(NetworkMessage& msg) -{ - uint32_t windowTextId = msg.get(); - const std::string newText = msg.getString(); - addGameTask(&Game::playerWriteItem, player->getID(), windowTextId, newText); -} - -void ProtocolGame::parseHouseWindow(NetworkMessage& msg) -{ - uint8_t doorId = msg.getByte(); - uint32_t id = msg.get(); - const std::string text = msg.getString(); - addGameTask(&Game::playerUpdateHouseWindow, player->getID(), doorId, id, text); -} - -void ProtocolGame::parseLookInShop(NetworkMessage& msg) -{ - uint16_t id = msg.get(); - uint8_t count = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInShop, player->getID(), id, count); -} - -void ProtocolGame::parsePlayerPurchase(NetworkMessage& msg) -{ - uint16_t id = msg.get(); - uint8_t count = msg.getByte(); - uint8_t amount = msg.getByte(); - bool ignoreCap = msg.getByte() != 0; - bool inBackpacks = msg.getByte() != 0; - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerPurchaseItem, player->getID(), id, count, amount, ignoreCap, inBackpacks); -} - -void ProtocolGame::parsePlayerSale(NetworkMessage& msg) -{ - uint16_t id = msg.get(); - uint8_t count = msg.getByte(); - uint8_t amount = msg.getByte(); - bool ignoreEquipped = msg.getByte() != 0; - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerSellItem, player->getID(), id, count, amount, ignoreEquipped); -} - -void ProtocolGame::parseRequestTrade(NetworkMessage& msg) -{ - Position pos = msg.getPosition(); - uint16_t spriteId = msg.get(); - uint8_t stackpos = msg.getByte(); - uint32_t playerId = msg.get(); - addGameTask(&Game::playerRequestTrade, player->getID(), pos, stackpos, playerId, spriteId); -} - -void ProtocolGame::parseLookInTrade(NetworkMessage& msg) -{ - bool counterOffer = (msg.getByte() == 0x01); - uint8_t index = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerLookInTrade, player->getID(), counterOffer, index); -} - -void ProtocolGame::parseAddVip(NetworkMessage& msg) -{ - const std::string name = msg.getString(); - addGameTask(&Game::playerRequestAddVip, player->getID(), name); -} - -void ProtocolGame::parseRemoveVip(NetworkMessage& msg) -{ - uint32_t guid = msg.get(); - addGameTask(&Game::playerRequestRemoveVip, player->getID(), guid); -} - -void ProtocolGame::parseEditVip(NetworkMessage& msg) -{ - uint32_t guid = msg.get(); - const std::string description = msg.getString(); - uint32_t icon = std::min(10, msg.get()); // 10 is max icon in 9.63 - bool notify = msg.getByte() != 0; - addGameTask(&Game::playerRequestEditVip, player->getID(), guid, description, icon, notify); -} - -void ProtocolGame::parseRotateItem(NetworkMessage& msg) -{ - Position pos = msg.getPosition(); - uint16_t spriteId = msg.get(); - uint8_t stackpos = msg.getByte(); - addGameTaskTimed(DISPATCHER_TASK_EXPIRATION, &Game::playerRotateItem, player->getID(), pos, stackpos, spriteId); -} - -void ProtocolGame::parseBugReport(NetworkMessage& msg) -{ - uint8_t category = msg.getByte(); - std::string message = msg.getString(); - - Position position; - if (category == BUG_CATEGORY_MAP) { - position = msg.getPosition(); - } - - addGameTask(&Game::playerReportBug, player->getID(), message, position, category); -} - -void ProtocolGame::parseDebugAssert(NetworkMessage& msg) -{ - if (m_debugAssertSent) { - return; - } - - m_debugAssertSent = true; - - std::string assertLine = msg.getString(); - std::string date = msg.getString(); - std::string description = msg.getString(); - std::string comment = msg.getString(); - addGameTask(&Game::playerDebugAssert, player->getID(), assertLine, date, description, comment); -} - -void ProtocolGame::parseInviteToParty(NetworkMessage& msg) -{ - uint32_t targetId = msg.get(); - addGameTask(&Game::playerInviteToParty, player->getID(), targetId); -} - -void ProtocolGame::parseJoinParty(NetworkMessage& msg) -{ - uint32_t targetId = msg.get(); - addGameTask(&Game::playerJoinParty, player->getID(), targetId); -} - -void ProtocolGame::parseRevokePartyInvite(NetworkMessage& msg) -{ - uint32_t targetId = msg.get(); - addGameTask(&Game::playerRevokePartyInvitation, player->getID(), targetId); -} - -void ProtocolGame::parsePassPartyLeadership(NetworkMessage& msg) -{ - uint32_t targetId = msg.get(); - addGameTask(&Game::playerPassPartyLeadership, player->getID(), targetId); -} - -void ProtocolGame::parseEnableSharedPartyExperience(NetworkMessage& msg) -{ - bool sharedExpActive = msg.getByte() == 1; - addGameTask(&Game::playerEnableSharedPartyExperience, player->getID(), sharedExpActive); -} - -void ProtocolGame::parseQuestLine(NetworkMessage& msg) -{ - uint16_t questId = msg.get(); - addGameTask(&Game::playerShowQuestLine, player->getID(), questId); -} - -void ProtocolGame::parseMarketLeave() -{ - addGameTask(&Game::playerLeaveMarket, player->getID()); -} - -void ProtocolGame::parseMarketBrowse(NetworkMessage& msg) -{ - uint16_t browseId = msg.get(); - - if (browseId == MARKETREQUEST_OWN_OFFERS) { - addGameTask(&Game::playerBrowseMarketOwnOffers, player->getID()); - } else if (browseId == MARKETREQUEST_OWN_HISTORY) { - addGameTask(&Game::playerBrowseMarketOwnHistory, player->getID()); - } else { - addGameTask(&Game::playerBrowseMarket, player->getID(), browseId); - } -} - -void ProtocolGame::parseMarketCreateOffer(NetworkMessage& msg) -{ - uint8_t type = msg.getByte(); - uint16_t spriteId = msg.get(); - uint16_t amount = msg.get(); - uint32_t price = msg.get(); - bool anonymous = (msg.getByte() != 0); - addGameTask(&Game::playerCreateMarketOffer, player->getID(), type, spriteId, amount, price, anonymous); -} - -void ProtocolGame::parseMarketCancelOffer(NetworkMessage& msg) -{ - uint32_t timestamp = msg.get(); - uint16_t counter = msg.get(); - addGameTask(&Game::playerCancelMarketOffer, player->getID(), timestamp, counter); -} - -void ProtocolGame::parseMarketAcceptOffer(NetworkMessage& msg) -{ - uint32_t timestamp = msg.get(); - uint16_t counter = msg.get(); - uint16_t amount = msg.get(); - addGameTask(&Game::playerAcceptMarketOffer, player->getID(), timestamp, counter, amount); -} - -void ProtocolGame::parseModalWindowAnswer(NetworkMessage& msg) -{ - uint32_t id = msg.get(); - uint8_t button = msg.getByte(); - uint8_t choice = msg.getByte(); - addGameTask(&Game::playerAnswerModalWindow, player->getID(), id, button, choice); -} - -void ProtocolGame::parseBrowseField(NetworkMessage& msg) -{ - const Position& pos = msg.getPosition(); - addGameTask(&Game::playerBrowseField, player->getID(), pos); -} - -void ProtocolGame::parseSeekInContainer(NetworkMessage& msg) -{ - uint8_t containerId = msg.getByte(); - uint16_t index = msg.get(); - addGameTask(&Game::playerSeekInContainer, player->getID(), containerId, index); -} - -// Send methods -void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver) -{ - NetworkMessage msg; - msg.addByte(0xAD); - msg.addString(receiver); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChannelEvent(uint16_t channelId, const std::string& playerName, ChannelEvent_t channelEvent) -{ - NetworkMessage msg; - msg.addByte(0xF3); - msg.add(channelId); - msg.addString(playerName); - msg.addByte(channelEvent); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x8E); - msg.add(creature->getID()); - AddOutfit(msg, outfit); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureLight(const Creature* creature) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - AddCreatureLight(msg, creature); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendWorldLight(const LightInfo& lightInfo) -{ - NetworkMessage msg; - AddWorldLight(msg, lightInfo); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureWalkthrough(const Creature* creature, bool walkthrough) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x92); - msg.add(creature->getID()); - msg.addByte(walkthrough ? 0x00 : 0x01); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureShield(const Creature* creature) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x91); - msg.add(creature->getID()); - msg.addByte(player->getPartyShield(creature->getPlayer())); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureSkull(const Creature* creature) -{ - if (g_game.getWorldType() != WORLD_TYPE_PVP) { - return; - } - - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x90); - msg.add(creature->getID()); - msg.addByte(player->getSkullClient(creature)); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureType(uint32_t creatureId, uint8_t creatureType) -{ - NetworkMessage msg; - msg.addByte(0x95); - msg.add(creatureId); - msg.addByte(creatureType); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureHelpers(uint32_t creatureId, uint16_t helpers) -{ - NetworkMessage msg; - msg.addByte(0x94); - msg.add(creatureId); - msg.add(helpers); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureSquare(const Creature* creature, SquareColor_t color) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x93); - msg.add(creature->getID()); - msg.addByte(0x01); - msg.addByte(color); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTutorial(uint8_t tutorialId) -{ - NetworkMessage msg; - msg.addByte(0xDC); - msg.addByte(tutorialId); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAddMarker(const Position& pos, uint8_t markType, const std::string& desc) -{ - NetworkMessage msg; - msg.addByte(0xDD); - msg.addPosition(pos); - msg.addByte(markType); - msg.addString(desc); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendReLoginWindow(uint8_t unfairFightReduction) -{ - NetworkMessage msg; - msg.addByte(0x28); - msg.addByte(0x00); - msg.addByte(unfairFightReduction); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendStats() -{ - NetworkMessage msg; - AddPlayerStats(msg); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendBasicData() -{ - NetworkMessage msg; - msg.addByte(0x9F); - msg.addByte(player->isPremium() ? 0x01 : 0x00); - msg.add(std::numeric_limits::max()); - msg.addByte(player->getVocation()->getClientId()); - msg.add(0x00); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextMessage(const TextMessage& message) -{ - NetworkMessage msg; - msg.addByte(0xB4); - msg.addByte(message.type); - switch (message.type) { - case MESSAGE_DAMAGE_DEALT: - case MESSAGE_DAMAGE_RECEIVED: - case MESSAGE_DAMAGE_OTHERS: { - msg.addPosition(message.position); - msg.add(message.primary.value); - msg.addByte(message.primary.color); - msg.add(message.secondary.value); - msg.addByte(message.secondary.color); - break; - } - case MESSAGE_HEALED: - case MESSAGE_HEALED_OTHERS: - case MESSAGE_EXPERIENCE: - case MESSAGE_EXPERIENCE_OTHERS: { - msg.addPosition(message.position); - msg.add(message.primary.value); - msg.addByte(message.primary.color); - break; - } - default: { - break; - } - } - msg.addString(message.text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendClosePrivate(uint16_t channelId) -{ - NetworkMessage msg; - msg.addByte(0xB3); - msg.add(channelId); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName) -{ - NetworkMessage msg; - msg.addByte(0xB2); - msg.add(channelId); - msg.addString(channelName); - msg.add(0x01); - msg.addString(player->getName()); - msg.add(0x00); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChannelsDialog() -{ - NetworkMessage msg; - msg.addByte(0xAB); - - const ChannelList& list = g_chat->getChannelList(*player); - msg.addByte(list.size()); - for (ChatChannel* channel : list) { - msg.add(channel->getId()); - msg.addString(channel->getName()); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChannel(uint16_t channelId, const std::string& channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers) -{ - NetworkMessage msg; - msg.addByte(0xAC); - - msg.add(channelId); - msg.addString(channelName); - - if (channelUsers) { - msg.add(channelUsers->size()); - for (const auto& it : *channelUsers) { - msg.addString(it.second->getName()); - } - } else { - msg.add(0x00); - } - - if (invitedUsers) { - msg.add(invitedUsers->size()); - for (const auto& it : *invitedUsers) { - msg.addString(it.second->getName()); - } - } else { - msg.add(0x00); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChannelMessage(const std::string& author, const std::string& text, SpeakClasses type, uint16_t channel) -{ - NetworkMessage msg; - msg.addByte(0xAA); - msg.add(0x00); - msg.addString(author); - msg.add(0x00); - msg.addByte(type); - msg.add(channel); - msg.addString(text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendIcons(uint16_t icons) -{ - NetworkMessage msg; - msg.addByte(0xA2); - msg.add(icons); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendContainer(uint8_t cid, const Container* container, bool hasParent, uint16_t firstIndex) -{ - NetworkMessage msg; - msg.addByte(0x6E); - - msg.addByte(cid); - - if (container->getID() == ITEM_BROWSEFIELD) { - msg.addItem(1987, 1); - msg.addString("Browse Field"); - } else { - msg.addItem(container); - msg.addString(container->getName()); - } - - msg.addByte(container->capacity()); - - msg.addByte(hasParent ? 0x01 : 0x00); - - msg.addByte(container->isUnlocked() ? 0x01 : 0x00); // Drag and drop - msg.addByte(container->hasPagination() ? 0x01 : 0x00); // Pagination - - uint32_t containerSize = container->size(); - msg.add(containerSize); - msg.add(firstIndex); - if (firstIndex < containerSize) { - uint8_t itemsToSend = std::min(std::min(container->capacity(), containerSize - firstIndex), std::numeric_limits::max()); - - msg.addByte(itemsToSend); - for (ItemDeque::const_iterator it = container->getItemList().begin() + firstIndex, end = it + itemsToSend; it != end; ++it) { - msg.addItem(*it); - } - } else { - msg.addByte(0x00); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendShop(Npc* npc, const ShopInfoList& itemList) -{ - NetworkMessage msg; - msg.addByte(0x7A); - msg.addString(npc->getName()); - - uint16_t itemsToSend = std::min(itemList.size(), std::numeric_limits::max()); - msg.add(itemsToSend); - - uint16_t i = 0; - for (ShopInfoList::const_iterator it = itemList.begin(); i < itemsToSend; ++it, ++i) { - AddShopItem(msg, *it); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCloseShop() -{ - NetworkMessage msg; - msg.addByte(0x7C); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendSaleItemList(const std::list& shop) -{ - NetworkMessage msg; - msg.addByte(0x7B); - msg.add(player->getMoney()); - - std::map saleMap; - - if (shop.size() <= 5) { - // For very small shops it's not worth it to create the complete map - for (const ShopInfo& shopInfo : shop) { - if (shopInfo.sellPrice == 0) { - continue; - } - - int8_t subtype = -1; - - const ItemType& itemType = Item::items[shopInfo.itemId]; - if (itemType.hasSubType() && !itemType.stackable) { - subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType); - } - - uint32_t count = player->getItemTypeCount(shopInfo.itemId, subtype); - if (count > 0) { - saleMap[shopInfo.itemId] = count; - } - } - } else { - // Large shop, it's better to get a cached map of all item counts and use it - // We need a temporary map since the finished map should only contain items - // available in the shop - std::map tempSaleMap; - player->getAllItemTypeCount(tempSaleMap); - - // We must still check manually for the special items that require subtype matches - // (That is, fluids such as potions etc., actually these items are very few since - // health potions now use their own ID) - for (const ShopInfo& shopInfo : shop) { - if (shopInfo.sellPrice == 0) { - continue; - } - - int8_t subtype = -1; - - const ItemType& itemType = Item::items[shopInfo.itemId]; - if (itemType.hasSubType() && !itemType.stackable) { - subtype = (shopInfo.subType == 0 ? -1 : shopInfo.subType); - } - - if (subtype != -1) { - uint32_t count; - if (!itemType.isFluidContainer() && !itemType.isSplash()) { - count = player->getItemTypeCount(shopInfo.itemId, subtype); // This shop item requires extra checks - } else { - count = subtype; - } - - if (count > 0) { - saleMap[shopInfo.itemId] = count; - } - } else { - std::map::const_iterator findIt = tempSaleMap.find(shopInfo.itemId); - if (findIt != tempSaleMap.end() && findIt->second > 0) { - saleMap[shopInfo.itemId] = findIt->second; - } - } - } - } - - uint8_t itemsToSend = std::min(saleMap.size(), std::numeric_limits::max()); - msg.addByte(itemsToSend); - - uint8_t i = 0; - for (std::map::const_iterator it = saleMap.begin(); i < itemsToSend; ++it, ++i) { - msg.addItemId(it->first); - msg.addByte(std::min(it->second, std::numeric_limits::max())); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketEnter(uint32_t depotId) -{ - NetworkMessage msg; - msg.addByte(0xF6); - - msg.add(player->getBankBalance()); - msg.addByte(std::min(IOMarket::getPlayerOfferCount(player->getGUID()), std::numeric_limits::max())); - - DepotChest* depotChest = player->getDepotChest(depotId, false); - if (!depotChest) { - msg.add(0x00); - writeToOutputBuffer(msg); - return; - } - - player->setInMarket(true); - - std::map depotItems; - std::forward_list containerList { depotChest, player->getInbox() }; - - do { - Container* container = containerList.front(); - containerList.pop_front(); - - for (Item* item : container->getItemList()) { - Container* c = item->getContainer(); - if (c && !c->empty()) { - containerList.push_front(c); - continue; - } - - const ItemType& itemType = Item::items[item->getID()]; - if (itemType.wareId == 0) { - continue; - } - - if (c && (!itemType.isContainer() || c->capacity() != itemType.maxItems)) { - continue; - } - - if (!item->hasMarketAttributes()) { - continue; - } - - depotItems[itemType.wareId] += Item::countByType(item, -1); - } - } while (!containerList.empty()); - - uint16_t itemsToSend = std::min(depotItems.size(), std::numeric_limits::max()); - msg.add(itemsToSend); - - uint16_t i = 0; - for (std::map::const_iterator it = depotItems.begin(); i < itemsToSend; ++it, ++i) { - msg.add(it->first); - msg.add(std::min(0xFFFF, it->second)); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketLeave() -{ - NetworkMessage msg; - msg.addByte(0xF7); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketBrowseItem(uint16_t itemId, const MarketOfferList& buyOffers, const MarketOfferList& sellOffers) -{ - NetworkMessage msg; - - msg.addByte(0xF9); - msg.addItemId(itemId); - - msg.add(buyOffers.size()); - for (const MarketOffer& offer : buyOffers) { - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.add(offer.amount); - msg.add(offer.price); - msg.addString(offer.playerName); - } - - msg.add(sellOffers.size()); - for (const MarketOffer& offer : sellOffers) { - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.add(offer.amount); - msg.add(offer.price); - msg.addString(offer.playerName); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketAcceptOffer(const MarketOfferEx& offer) -{ - NetworkMessage msg; - msg.addByte(0xF9); - msg.addItemId(offer.itemId); - - if (offer.type == MARKETACTION_BUY) { - msg.add(0x01); - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.add(offer.amount); - msg.add(offer.price); - msg.addString(offer.playerName); - msg.add(0x00); - } else { - msg.add(0x00); - msg.add(0x01); - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.add(offer.amount); - msg.add(offer.price); - msg.addString(offer.playerName); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, const MarketOfferList& sellOffers) -{ - NetworkMessage msg; - msg.addByte(0xF9); - msg.add(MARKETREQUEST_OWN_OFFERS); - - msg.add(buyOffers.size()); - for (const MarketOffer& offer : buyOffers) { - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.addItemId(offer.itemId); - msg.add(offer.amount); - msg.add(offer.price); - } - - msg.add(sellOffers.size()); - for (const MarketOffer& offer : sellOffers) { - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.addItemId(offer.itemId); - msg.add(offer.amount); - msg.add(offer.price); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketCancelOffer(const MarketOfferEx& offer) -{ - NetworkMessage msg; - msg.addByte(0xF9); - msg.add(MARKETREQUEST_OWN_OFFERS); - - if (offer.type == MARKETACTION_BUY) { - msg.add(0x01); - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.addItemId(offer.itemId); - msg.add(offer.amount); - msg.add(offer.price); - msg.add(0x00); - } else { - msg.add(0x00); - msg.add(0x01); - msg.add(offer.timestamp); - msg.add(offer.counter); - msg.addItemId(offer.itemId); - msg.add(offer.amount); - msg.add(offer.price); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyOffers, const HistoryMarketOfferList& sellOffers) -{ - uint32_t i = 0; - std::map counterMap; - uint32_t buyOffersToSend = std::min(buyOffers.size(), 810 + std::max(0, 810 - sellOffers.size())); - uint32_t sellOffersToSend = std::min(sellOffers.size(), 810 + std::max(0, 810 - buyOffers.size())); - - NetworkMessage msg; - msg.addByte(0xF9); - msg.add(MARKETREQUEST_OWN_HISTORY); - - msg.add(buyOffersToSend); - for (HistoryMarketOfferList::const_iterator it = buyOffers.begin(); i < buyOffersToSend; ++it, ++i) { - msg.add(it->timestamp); - msg.add(counterMap[it->timestamp]++); - msg.addItemId(it->itemId); - msg.add(it->amount); - msg.add(it->price); - msg.addByte(it->state); - } - - counterMap.clear(); - i = 0; - - msg.add(sellOffersToSend); - for (HistoryMarketOfferList::const_iterator it = sellOffers.begin(); i < sellOffersToSend; ++it, ++i) { - msg.add(it->timestamp); - msg.add(counterMap[it->timestamp]++); - msg.addItemId(it->itemId); - msg.add(it->amount); - msg.add(it->price); - msg.addByte(it->state); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMarketDetail(uint16_t itemId) -{ - NetworkMessage msg; - msg.addByte(0xF8); - msg.addItemId(itemId); - - const ItemType& it = Item::items[itemId]; - if (it.armor != 0) { - msg.addString(std::to_string(it.armor)); - } else { - msg.add(0x00); - } - - if (it.attack != 0) { - // TODO: chance to hit, range - // example: - // "attack +x, chance to hit +y%, z fields" - if (it.abilities && it.abilities->elementType != COMBAT_NONE && it.abilities->elementDamage != 0) { - std::ostringstream ss; - ss << it.attack << " physical +" << it.abilities->elementDamage << ' ' << getCombatName(it.abilities->elementType); - msg.addString(ss.str()); - } else { - msg.addString(std::to_string(it.attack)); - } - } else { - msg.add(0x00); - } - - if (it.isContainer()) { - msg.addString(std::to_string(it.maxItems)); - } else { - msg.add(0x00); - } - - if (it.defense != 0) { - if (it.extraDefense != 0) { - std::ostringstream ss; - ss << it.defense << ' ' << std::showpos << it.extraDefense << std::noshowpos; - msg.addString(ss.str()); - } else { - msg.addString(std::to_string(it.defense)); - } - } else { - msg.add(0x00); - } - - if (!it.description.empty()) { - const std::string& descr = it.description; - if (descr.back() == '.') { - msg.addString(std::string(descr, 0, descr.length() - 1)); - } else { - msg.addString(descr); - } - } else { - msg.add(0x00); - } - - if (it.decayTime != 0) { - std::ostringstream ss; - ss << it.decayTime << " seconds"; - msg.addString(ss.str()); - } else { - msg.add(0x00); - } - - if (it.abilities) { - std::ostringstream ss; - bool separator = false; - - for (size_t i = 0; i < COMBAT_COUNT; ++i) { - if (it.abilities->absorbPercent[i] == 0) { - continue; - } - - if (separator) { - ss << ", "; - } else { - separator = true; - } - - ss << getCombatName(indexToCombatType(i)) << ' ' << std::showpos << it.abilities->absorbPercent[i] << std::noshowpos << '%'; - } - - msg.addString(ss.str()); - } else { - msg.add(0x00); - } - - if (it.minReqLevel != 0) { - msg.addString(std::to_string(it.minReqLevel)); - } else { - msg.add(0x00); - } - - if (it.minReqMagicLevel != 0) { - msg.addString(std::to_string(it.minReqMagicLevel)); - } else { - msg.add(0x00); - } - - msg.addString(it.vocationString); - - msg.addString(it.runeSpellName); - - if (it.abilities) { - std::ostringstream ss; - bool separator = false; - - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { - if (!it.abilities->skills[i]) { - continue; - } - - if (separator) { - ss << ", "; - } else { - separator = true; - } - - ss << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; - } - - if (it.abilities->stats[STAT_MAGICPOINTS] != 0) { - if (separator) { - ss << ", "; - } else { - separator = true; - } - - ss << "magic level " << std::showpos << it.abilities->stats[STAT_MAGICPOINTS] << std::noshowpos; - } - - if (it.abilities->speed != 0) { - if (separator) { - ss << ", "; - } - - ss << "speed " << std::showpos << (it.abilities->speed >> 1) << std::noshowpos; - } - - msg.addString(ss.str()); - } else { - msg.add(0x00); - } - - if (it.charges != 0) { - msg.addString(std::to_string(it.charges)); - } else { - msg.add(0x00); - } - - std::string weaponName = getWeaponName(it.weaponType); - - if (it.slotPosition & SLOTP_TWO_HAND) { - if (!weaponName.empty()) { - weaponName += ", two-handed"; - } else { - weaponName = "two-handed"; - } - } - - msg.addString(weaponName); - - if (it.weight != 0) { - std::ostringstream ss; - if (it.weight < 10) { - ss << "0.0" << it.weight; - } else if (it.weight < 100) { - ss << "0." << it.weight; - } else { - std::string weightString = std::to_string(it.weight); - weightString.insert(weightString.end() - 2, '.'); - ss << weightString; - } - ss << " oz"; - msg.addString(ss.str()); - } else { - msg.add(0x00); - } - - MarketStatistics* statistics = IOMarket::getInstance()->getPurchaseStatistics(itemId); - if (statistics) { - msg.addByte(0x01); - msg.add(statistics->numTransactions); - msg.add(std::min(std::numeric_limits::max(), statistics->totalPrice)); - msg.add(statistics->highestPrice); - msg.add(statistics->lowestPrice); - } else { - msg.addByte(0x00); - } - - statistics = IOMarket::getInstance()->getSaleStatistics(itemId); - if (statistics) { - msg.addByte(0x01); - msg.add(statistics->numTransactions); - msg.add(std::min(std::numeric_limits::max(), statistics->totalPrice)); - msg.add(statistics->highestPrice); - msg.add(statistics->lowestPrice); - } else { - msg.addByte(0x00); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendQuestLog() -{ - NetworkMessage msg; - msg.addByte(0xF0); - msg.add(g_game.quests.getQuestsCount(player)); - - for (const Quest& quest : g_game.quests.getQuests()) { - if (quest.isStarted(player)) { - msg.add(quest.getID()); - msg.addString(quest.getName()); - msg.addByte(quest.isCompleted(player)); - } - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendQuestLine(const Quest* quest) -{ - NetworkMessage msg; - msg.addByte(0xF1); - msg.add(quest->getID()); - msg.addByte(quest->getMissionsCount(player)); - - for (const Mission& mission : quest->getMissions()) { - if (mission.isStarted(player)) { - msg.addString(mission.getName(player)); - msg.addString(mission.getDescription(player)); - } - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTradeItemRequest(const std::string& traderName, const Item* item, bool ack) -{ - NetworkMessage msg; - - if (ack) { - msg.addByte(0x7D); - } else { - msg.addByte(0x7E); - } - - msg.addString(traderName); - - if (const Container* tradeContainer = item->getContainer()) { - std::list listContainer {tradeContainer}; - std::list itemList {tradeContainer}; - while (!listContainer.empty()) { - const Container* container = listContainer.front(); - listContainer.pop_front(); - - for (Item* containerItem : container->getItemList()) { - Container* tmpContainer = containerItem->getContainer(); - if (tmpContainer) { - listContainer.push_back(tmpContainer); - } - itemList.push_back(containerItem); - } - } - - msg.addByte(itemList.size()); - for (const Item* listItem : itemList) { - msg.addItem(listItem); - } - } else { - msg.addByte(0x01); - msg.addItem(item); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCloseTrade() -{ - NetworkMessage msg; - msg.addByte(0x7F); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCloseContainer(uint8_t cid) -{ - NetworkMessage msg; - msg.addByte(0x6F); - msg.addByte(cid); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureTurn(const Creature* creature, uint32_t stackPos) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x6B); - msg.addPosition(creature->getPosition()); - msg.addByte(stackPos); - msg.add(0x63); - msg.add(creature->getID()); - msg.addByte(creature->getDirection()); - msg.addByte(player->canWalkthroughEx(creature) ? 0x00 : 0x01); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, const Position* pos/* = nullptr*/) -{ - NetworkMessage msg; - msg.addByte(0xAA); - - static uint32_t statementId = 0; - msg.add(++statementId); - - msg.addString(creature->getName()); - - //Add level only for players - if (const Player* speaker = creature->getPlayer()) { - msg.add(speaker->getLevel()); - } else { - msg.add(0x00); - } - - msg.addByte(type); - if (pos) { - msg.addPosition(*pos); - } else { - msg.addPosition(creature->getPosition()); - } - - msg.addString(text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendToChannel(const Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId) -{ - NetworkMessage msg; - msg.addByte(0xAA); - - static uint32_t statementId = 0; - msg.add(++statementId); - if (!creature) { - msg.add(0x00); - } else if (type == TALKTYPE_CHANNEL_R2) { - msg.add(0x00); - type = TALKTYPE_CHANNEL_R1; - } else { - msg.addString(creature->getName()); - //Add level only for players - if (const Player* speaker = creature->getPlayer()) { - msg.add(speaker->getLevel()); - } else { - msg.add(0x00); - } - } - - msg.addByte(type); - msg.add(channelId); - msg.addString(text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendPrivateMessage(const Player* speaker, SpeakClasses type, const std::string& text) -{ - NetworkMessage msg; - msg.addByte(0xAA); - static uint32_t statementId = 0; - msg.add(++statementId); - if (speaker) { - msg.addString(speaker->getName()); - msg.add(speaker->getLevel()); - } else { - msg.add(0x00); - } - msg.addByte(type); - msg.addString(text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCancelTarget() -{ - NetworkMessage msg; - msg.addByte(0xA3); - msg.add(0x00); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed) -{ - NetworkMessage msg; - msg.addByte(0x8F); - msg.add(creature->getID()); - msg.add(creature->getBaseSpeed() / 2); - msg.add(speed / 2); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCancelWalk() -{ - NetworkMessage msg; - msg.addByte(0xB5); - msg.addByte(player->getDirection()); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendSkills() -{ - NetworkMessage msg; - AddPlayerSkills(msg); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendPing() -{ - NetworkMessage msg; - msg.addByte(0x1D); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendPingBack() -{ - NetworkMessage msg; - msg.addByte(0x1E); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendDistanceShoot(const Position& from, const Position& to, uint8_t type) -{ - NetworkMessage msg; - msg.addByte(0x85); - msg.addPosition(from); - msg.addPosition(to); - msg.addByte(type); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendMagicEffect(const Position& pos, uint8_t type) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x83); - msg.addPosition(pos); - msg.addByte(type); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendCreatureHealth(const Creature* creature) -{ - NetworkMessage msg; - msg.addByte(0x8C); - msg.add(creature->getID()); - - if (creature->isHealthHidden()) { - msg.addByte(0x00); - } else { - msg.addByte(std::ceil((static_cast(creature->getHealth()) / std::max(creature->getMaxHealth(), 1)) * 100)); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendFYIBox(const std::string& message) -{ - NetworkMessage msg; - msg.addByte(0x15); - msg.addString(message); - writeToOutputBuffer(msg); -} - -//tile -void ProtocolGame::sendMapDescription(const Position& pos) -{ - NetworkMessage msg; - msg.addByte(0x64); - msg.addPosition(player->getPosition()); - GetMapDescription(pos.x - 8, pos.y - 6, pos.z, 18, 14, msg); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAddTileItem(const Position& pos, uint32_t stackpos, const Item* item) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x6A); - msg.addPosition(pos); - msg.addByte(stackpos); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdateTileItem(const Position& pos, uint32_t stackpos, const Item* item) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x6B); - msg.addPosition(pos); - msg.addByte(stackpos); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendRemoveTileThing(const Position& pos, uint32_t stackpos) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - RemoveTileThing(msg, pos, stackpos); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdateTile(const Tile* tile, const Position& pos) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x69); - msg.addPosition(pos); - - if (tile) { - GetTileDescription(tile, msg); - msg.addByte(0x00); - msg.addByte(0xFF); - } else { - msg.addByte(0x01); - msg.addByte(0xFF); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendPendingStateEntered() -{ - NetworkMessage msg; - msg.addByte(0x0A); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendEnterWorld() -{ - NetworkMessage msg; - msg.addByte(0x0F); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendFightModes() -{ - NetworkMessage msg; - msg.addByte(0xA7); - msg.addByte(player->fightMode); - msg.addByte(player->chaseMode); - msg.addByte(player->secureMode); - msg.addByte(PVP_MODE_DOVE); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos, int32_t stackpos, bool isLogin) -{ - if (!canSee(pos)) { - return; - } - - if (creature != player) { - if (stackpos != -1) { - NetworkMessage msg; - msg.addByte(0x6A); - msg.addPosition(pos); - msg.addByte(stackpos); - - bool known; - uint32_t removedKnown; - checkCreatureAsKnown(creature->getID(), known, removedKnown); - AddCreature(msg, creature, known, removedKnown); - writeToOutputBuffer(msg); - } - - if (isLogin) { - sendMagicEffect(pos, CONST_ME_TELEPORT); - } - return; - } - - NetworkMessage msg; - msg.addByte(0x17); - - msg.add(player->getID()); - msg.add(0x32); // beat duration (50) - - msg.addDouble(Creature::speedA, 3); - msg.addDouble(Creature::speedB, 3); - msg.addDouble(Creature::speedC, 3); - - // can report bugs? - if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) { - msg.addByte(0x01); - } else { - msg.addByte(0x00); - } - - msg.addByte(0x00); // can change pvp framing option - msg.addByte(0x00); // expert mode button enabled - - msg.addString("http://static.tibia.com/images/store/"); - msg.addByte(0x19); - msg.addByte(g_config.getNumber(ConfigManager::MAX_PACKETS_PER_SECOND)); - - writeToOutputBuffer(msg); - - sendPendingStateEntered(); - sendEnterWorld(); - sendMapDescription(pos); - - if (isLogin) { - sendMagicEffect(pos, CONST_ME_TELEPORT); - } - - sendInventoryItem(CONST_SLOT_HEAD, player->getInventoryItem(CONST_SLOT_HEAD)); - sendInventoryItem(CONST_SLOT_NECKLACE, player->getInventoryItem(CONST_SLOT_NECKLACE)); - sendInventoryItem(CONST_SLOT_BACKPACK, player->getInventoryItem(CONST_SLOT_BACKPACK)); - sendInventoryItem(CONST_SLOT_ARMOR, player->getInventoryItem(CONST_SLOT_ARMOR)); - sendInventoryItem(CONST_SLOT_RIGHT, player->getInventoryItem(CONST_SLOT_RIGHT)); - sendInventoryItem(CONST_SLOT_LEFT, player->getInventoryItem(CONST_SLOT_LEFT)); - sendInventoryItem(CONST_SLOT_LEGS, player->getInventoryItem(CONST_SLOT_LEGS)); - sendInventoryItem(CONST_SLOT_FEET, player->getInventoryItem(CONST_SLOT_FEET)); - sendInventoryItem(CONST_SLOT_RING, player->getInventoryItem(CONST_SLOT_RING)); - sendInventoryItem(CONST_SLOT_AMMO, player->getInventoryItem(CONST_SLOT_AMMO)); - - sendStats(); - sendSkills(); - - //gameworld light-settings - LightInfo lightInfo; - g_game.getWorldLightInfo(lightInfo); - sendWorldLight(lightInfo); - - //player light level - sendCreatureLight(creature); - - const std::forward_list& vipEntries = IOLoginData::getVIPEntries(player->getAccount()); - - if (player->isAccessPlayer()) { - for (const VIPEntry& entry : vipEntries) { - VipStatus_t vipStatus; - - Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); - if (!vipPlayer) { - vipStatus = VIPSTATUS_OFFLINE; - } else { - vipStatus = VIPSTATUS_ONLINE; - } - - sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); - } - } else { - for (const VIPEntry& entry : vipEntries) { - VipStatus_t vipStatus; - - Player* vipPlayer = g_game.getPlayerByGUID(entry.guid); - if (!vipPlayer || vipPlayer->isInGhostMode()) { - vipStatus = VIPSTATUS_OFFLINE; - } else { - vipStatus = VIPSTATUS_ONLINE; - } - - sendVIP(entry.guid, entry.name, entry.description, entry.icon, entry.notify, vipStatus); - } - } - - sendBasicData(); - player->sendIcons(); -} - -void ProtocolGame::sendMoveCreature(const Creature* creature, const Position& newPos, int32_t newStackPos, const Position& oldPos, int32_t oldStackPos, bool teleport) -{ - if (creature == player) { - if (oldStackPos >= 10) { - sendMapDescription(newPos); - } else if (teleport) { - NetworkMessage msg; - RemoveTileThing(msg, oldPos, oldStackPos); - writeToOutputBuffer(msg); - sendMapDescription(newPos); - } else { - NetworkMessage msg; - if (oldPos.z == 7 && newPos.z >= 8) { - RemoveTileThing(msg, oldPos, oldStackPos); - } else { - msg.addByte(0x6D); - msg.addPosition(oldPos); - msg.addByte(oldStackPos); - msg.addPosition(newPos); - } - - if (newPos.z > oldPos.z) { - MoveDownCreature(msg, creature, newPos, oldPos); - } else if (newPos.z < oldPos.z) { - MoveUpCreature(msg, creature, newPos, oldPos); - } - - if (oldPos.y > newPos.y) { // north, for old x - msg.addByte(0x65); - GetMapDescription(oldPos.x - 8, newPos.y - 6, newPos.z, 18, 1, msg); - } else if (oldPos.y < newPos.y) { // south, for old x - msg.addByte(0x67); - GetMapDescription(oldPos.x - 8, newPos.y + 7, newPos.z, 18, 1, msg); - } - - if (oldPos.x < newPos.x) { // east, [with new y] - msg.addByte(0x66); - GetMapDescription(newPos.x + 9, newPos.y - 6, newPos.z, 1, 14, msg); - } else if (oldPos.x > newPos.x) { // west, [with new y] - msg.addByte(0x68); - GetMapDescription(newPos.x - 8, newPos.y - 6, newPos.z, 1, 14, msg); - } - writeToOutputBuffer(msg); - } - } else if (canSee(oldPos) && canSee(creature->getPosition())) { - if (teleport || (oldPos.z == 7 && newPos.z >= 8) || oldStackPos >= 10) { - sendRemoveTileThing(oldPos, oldStackPos); - sendAddCreature(creature, newPos, newStackPos, false); - } else { - NetworkMessage msg; - msg.addByte(0x6D); - msg.addPosition(oldPos); - msg.addByte(oldStackPos); - msg.addPosition(creature->getPosition()); - writeToOutputBuffer(msg); - } - } else if (canSee(oldPos)) { - sendRemoveTileThing(oldPos, oldStackPos); - } else if (canSee(creature->getPosition())) { - sendAddCreature(creature, newPos, newStackPos, false); - } -} - -void ProtocolGame::sendInventoryItem(slots_t slot, const Item* item) -{ - NetworkMessage msg; - if (item) { - msg.addByte(0x78); - msg.addByte(slot); - msg.addItem(item); - } else { - msg.addByte(0x79); - msg.addByte(slot); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAddContainerItem(uint8_t cid, uint16_t slot, const Item* item) -{ - NetworkMessage msg; - msg.addByte(0x70); - msg.addByte(cid); - msg.add(slot); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdateContainerItem(uint8_t cid, uint16_t slot, const Item* item) -{ - NetworkMessage msg; - msg.addByte(0x71); - msg.addByte(cid); - msg.add(slot); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot, const Item* lastItem) -{ - NetworkMessage msg; - msg.addByte(0x72); - msg.addByte(cid); - msg.add(slot); - if (lastItem) { - msg.addItem(lastItem); - } else { - msg.add(0x00); - } - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxlen, bool canWrite) -{ - NetworkMessage msg; - msg.addByte(0x96); - msg.add(windowTextId); - msg.addItem(item); - - if (canWrite) { - msg.add(maxlen); - msg.addString(item->getText()); - } else { - const std::string& text = item->getText(); - msg.add(text.size()); - msg.addString(text); - } - - const std::string& writer = item->getWriter(); - if (!writer.empty()) { - msg.addString(writer); - } else { - msg.add(0x00); - } - - time_t writtenDate = item->getDate(); - if (writtenDate != 0) { - msg.addString(formatDateShort(writtenDate)); - } else { - msg.add(0x00); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string& text) -{ - NetworkMessage msg; - msg.addByte(0x96); - msg.add(windowTextId); - msg.addItem(itemId, 1); - msg.add(text.size()); - msg.addString(text); - msg.add(0x00); - msg.add(0x00); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendHouseWindow(uint32_t windowTextId, const std::string& text) -{ - NetworkMessage msg; - msg.addByte(0x97); - msg.addByte(0x00); - msg.add(windowTextId); - msg.addString(text); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendOutfitWindow() -{ - NetworkMessage msg; - msg.addByte(0xC8); - - Outfit_t currentOutfit = player->getDefaultOutfit(); - Mount* currentMount = g_game.mounts.getMountByID(player->getCurrentMount()); - if (currentMount) { - currentOutfit.lookMount = currentMount->clientId; - } - - AddOutfit(msg, currentOutfit); - - std::vector protocolOutfits; - if (player->isAccessPlayer()) { - static const std::string gamemasterOutfitName = "Gamemaster"; - protocolOutfits.emplace_back( - &gamemasterOutfitName, - 75, - 0 - ); - } - - const auto& outfits = Outfits::getInstance()->getOutfits(player->getSex()); - protocolOutfits.reserve(outfits.size()); - for (const Outfit& outfit : outfits) { - uint8_t addons; - if (!player->getOutfitAddons(outfit, addons)) { - continue; - } - - protocolOutfits.emplace_back( - &outfit.name, - outfit.lookType, - addons - ); - if (protocolOutfits.size() == 100) { // Game client doesn't allow more than 100 outfits - break; - } - } - - msg.addByte(protocolOutfits.size()); - for (const ProtocolOutfit& outfit : protocolOutfits) { - msg.add(outfit.lookType); - msg.addString(*outfit.name); - msg.addByte(outfit.addons); - } - - std::vector mounts; - for (const Mount& mount : g_game.mounts.getMounts()) { - if (player->hasMount(&mount)) { - mounts.push_back(&mount); - } - } - - msg.addByte(mounts.size()); - for (const Mount* mount : mounts) { - msg.add(mount->clientId); - msg.addString(mount->name); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdatedVIPStatus(uint32_t guid, VipStatus_t newStatus) -{ - NetworkMessage msg; - msg.addByte(0xD3); - msg.add(guid); - msg.addByte(newStatus); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, const std::string& description, uint32_t icon, bool notify, VipStatus_t status) -{ - NetworkMessage msg; - msg.addByte(0xD2); - msg.add(guid); - msg.addString(name); - msg.addString(description); - msg.add(std::min(10, icon)); - msg.addByte(notify ? 0x01 : 0x00); - msg.addByte(status); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendSpellCooldown(uint8_t spellId, uint32_t time) -{ - NetworkMessage msg; - msg.addByte(0xA4); - msg.addByte(spellId); - msg.add(time); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time) -{ - NetworkMessage msg; - msg.addByte(0xA5); - msg.addByte(groupId); - msg.add(time); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendModalWindow(const ModalWindow& modalWindow) -{ - NetworkMessage msg; - msg.addByte(0xFA); - - msg.add(modalWindow.id); - msg.addString(modalWindow.title); - msg.addString(modalWindow.message); - - msg.addByte(modalWindow.buttons.size()); - for (const auto& it : modalWindow.buttons) { - msg.addString(it.first); - msg.addByte(it.second); - } - - msg.addByte(modalWindow.choices.size()); - for (const auto& it : modalWindow.choices) { - msg.addString(it.first); - msg.addByte(it.second); - } - - msg.addByte(modalWindow.defaultEscapeButton); - msg.addByte(modalWindow.defaultEnterButton); - msg.addByte(modalWindow.priority ? 0x01 : 0x00); - - writeToOutputBuffer(msg); -} - -////////////// Add common messages -void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bool known, uint32_t remove) -{ - CreatureType_t creatureType = creature->getType(); - - const Player* otherPlayer = creature->getPlayer(); - - if (known) { - msg.add(0x62); - msg.add(creature->getID()); - } else { - msg.add(0x61); - msg.add(remove); - msg.add(creature->getID()); - msg.addByte(creatureType); - msg.addString(creature->getName()); - } - - if (creature->isHealthHidden()) { - msg.addByte(0x00); - } else { - msg.addByte(std::ceil((static_cast(creature->getHealth()) / std::max(creature->getMaxHealth(), 1)) * 100)); - } - - msg.addByte(creature->getDirection()); - - if (!creature->isInGhostMode() && !creature->isInvisible()) { - AddOutfit(msg, creature->getCurrentOutfit()); - } else { - static Outfit_t outfit; - AddOutfit(msg, outfit); - } - - LightInfo lightInfo; - creature->getCreatureLight(lightInfo); - msg.addByte(player->isAccessPlayer() ? 0xFF : lightInfo.level); - msg.addByte(lightInfo.color); - - msg.add(creature->getStepSpeed() / 2); - - msg.addByte(player->getSkullClient(creature)); - msg.addByte(player->getPartyShield(otherPlayer)); - - if (!known) { - msg.addByte(player->getGuildEmblem(otherPlayer)); - } - - if (creatureType == CREATURETYPE_MONSTER) { - const Creature* master = creature->getMaster(); - if (master) { - const Player* masterPlayer = master->getPlayer(); - if (masterPlayer) { - if (masterPlayer == player) { - creatureType = CREATURETYPE_SUMMON_OWN; - } else { - creatureType = CREATURETYPE_SUMMON_OTHERS; - } - } - } - } - - msg.addByte(creatureType); // Type (for summons) - msg.addByte(creature->getSpeechBubble()); - msg.addByte(0xFF); // MARK_UNMARKED - - if (otherPlayer) { - msg.add(otherPlayer->getHelpers()); - } else { - msg.add(0x00); - } - - msg.addByte(player->canWalkthroughEx(creature) ? 0x00 : 0x01); -} - -void ProtocolGame::AddPlayerStats(NetworkMessage& msg) -{ - msg.addByte(0xA0); - - msg.add(std::min(player->getHealth(), std::numeric_limits::max())); - msg.add(std::min(player->getPlayerInfo(PLAYERINFO_MAXHEALTH), std::numeric_limits::max())); - - msg.add(player->getFreeCapacity()); - msg.add(player->getCapacity()); - - msg.add(player->getExperience()); - - msg.add(player->getLevel()); - msg.addByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT)); - msg.addDouble(0, 3); // experience bonus - - msg.add(std::min(player->getMana(), std::numeric_limits::max())); - msg.add(std::min(player->getPlayerInfo(PLAYERINFO_MAXMANA), std::numeric_limits::max())); - - msg.addByte(std::min(player->getMagicLevel(), std::numeric_limits::max())); - msg.addByte(std::min(player->getBaseMagicLevel(), std::numeric_limits::max())); - msg.addByte(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT)); - - msg.addByte(player->getSoul()); - - msg.add(player->getStaminaMinutes()); - - msg.add(player->getBaseSpeed() / 2); - - Condition* condition = player->getCondition(CONDITION_REGENERATION); - msg.add(condition ? condition->getTicks() / 1000 : 0x00); - - msg.add(player->getOfflineTrainingTime() / 60 / 1000); -} - -void ProtocolGame::AddPlayerSkills(NetworkMessage& msg) -{ - msg.addByte(0xA1); - - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - msg.add(std::min(player->getSkillLevel(i), std::numeric_limits::max())); - msg.add(player->getBaseSkill(i)); - msg.addByte(player->getSkillPercent(i)); - } -} - -void ProtocolGame::AddOutfit(NetworkMessage& msg, const Outfit_t& outfit) -{ - msg.add(outfit.lookType); - - if (outfit.lookType != 0) { - msg.addByte(outfit.lookHead); - msg.addByte(outfit.lookBody); - msg.addByte(outfit.lookLegs); - msg.addByte(outfit.lookFeet); - msg.addByte(outfit.lookAddons); - } else { - msg.addItemId(outfit.lookTypeEx); - } - - msg.add(outfit.lookMount); -} - -void ProtocolGame::AddWorldLight(NetworkMessage& msg, const LightInfo& lightInfo) -{ - msg.addByte(0x82); - msg.addByte((player->isAccessPlayer() ? 0xFF : lightInfo.level)); - msg.addByte(lightInfo.color); -} - -void ProtocolGame::AddCreatureLight(NetworkMessage& msg, const Creature* creature) -{ - LightInfo lightInfo; - creature->getCreatureLight(lightInfo); - - msg.addByte(0x8D); - msg.add(creature->getID()); - msg.addByte((player->isAccessPlayer() ? 0xFF : lightInfo.level)); - msg.addByte(lightInfo.color); -} - -//tile -void ProtocolGame::RemoveTileThing(NetworkMessage& msg, const Position& pos, uint32_t stackpos) -{ - if (stackpos >= 10) { - return; - } - - msg.addByte(0x6C); - msg.addPosition(pos); - msg.addByte(stackpos); -} - -void ProtocolGame::MoveUpCreature(NetworkMessage& msg, const Creature* creature, const Position& newPos, const Position& oldPos) -{ - if (creature != player) { - return; - } - - //floor change up - msg.addByte(0xBE); - - //going to surface - if (newPos.z == 7) { - int32_t skip = -1; - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 5, 18, 14, 3, skip); //(floor 7 and 6 already set) - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 4, 18, 14, 4, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 3, 18, 14, 5, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 2, 18, 14, 6, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 1, 18, 14, 7, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, 0, 18, 14, 8, skip); - - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } - } - //underground, going one floor up (still underground) - else if (newPos.z > 7) { - int32_t skip = -1; - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, oldPos.getZ() - 3, 18, 14, 3, skip); - - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } - } - - //moving up a floor up makes us out of sync - //west - msg.addByte(0x68); - GetMapDescription(oldPos.x - 8, oldPos.y - 5, newPos.z, 1, 14, msg); - - //north - msg.addByte(0x65); - GetMapDescription(oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 1, msg); -} - -void ProtocolGame::MoveDownCreature(NetworkMessage& msg, const Creature* creature, const Position& newPos, const Position& oldPos) -{ - if (creature != player) { - return; - } - - //floor change down - msg.addByte(0xBF); - - //going from surface to underground - if (newPos.z == 8) { - int32_t skip = -1; - - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z, 18, 14, -1, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 1, 18, 14, -2, skip); - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip); - - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } - } - //going further down - else if (newPos.z > oldPos.z && newPos.z > 8 && newPos.z < 14) { - int32_t skip = -1; - GetFloorDescription(msg, oldPos.x - 8, oldPos.y - 6, newPos.z + 2, 18, 14, -3, skip); - - if (skip >= 0) { - msg.addByte(skip); - msg.addByte(0xFF); - } - } - - //moving down a floor makes us out of sync - //east - msg.addByte(0x66); - GetMapDescription(oldPos.x + 9, oldPos.y - 7, newPos.z, 1, 14, msg); - - //south - msg.addByte(0x67); - GetMapDescription(oldPos.x - 8, oldPos.y + 7, newPos.z, 18, 1, msg); -} - -void ProtocolGame::AddShopItem(NetworkMessage& msg, const ShopInfo& item) -{ - const ItemType& it = Item::items[item.itemId]; - msg.add(it.clientId); - - if (it.isSplash() || it.isFluidContainer()) { - msg.addByte(serverFluidToClient(item.subType)); - } else { - msg.addByte(0x00); - } - - msg.addString(item.realName); - msg.add(it.weight); - msg.add(item.buyPrice); - msg.add(item.sellPrice); -} - -void ProtocolGame::parseExtendedOpcode(NetworkMessage& msg) -{ - uint8_t opcode = msg.getByte(); - const std::string& buffer = msg.getString(); - - // process additional opcodes via lua script event - addGameTask(&Game::parsePlayerExtendedOpcode, player->getID(), opcode, buffer); -} diff --git a/path_10_8/src/protocolgame.h b/path_10_8/src/protocolgame.h deleted file mode 100644 index e20aba576..000000000 --- a/path_10_8/src/protocolgame.h +++ /dev/null @@ -1,341 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PROTOCOLGAME_H_FACA2A2D1A9348B78E8FD7E8003EBB87 -#define FS_PROTOCOLGAME_H_FACA2A2D1A9348B78E8FD7E8003EBB87 - -#include "protocol.h" -#include "chat.h" -#include "creature.h" -#include "tasks.h" - -class NetworkMessage; -class Player; -class Game; -class House; -class Container; -class Tile; -class Connection; -class Quest; -class ProtocolGame; -typedef std::shared_ptr ProtocolGame_ptr; - -extern Game g_game; - -struct TextMessage -{ - MessageClasses type; - std::string text; - Position position; - struct { - int32_t value; - TextColor_t color; - } primary, secondary; - - TextMessage() { - type = MESSAGE_STATUS_DEFAULT; - primary.value = 0; - secondary.value = 0; - } - TextMessage(MessageClasses type, std::string text) : type(type), text(text) { - primary.value = 0; - secondary.value = 0; - } -}; - -class ProtocolGame final : public Protocol -{ - public: - // static protocol information - enum {server_sends_first = true}; - enum {protocol_identifier = 0}; // Not required as we send first - enum {use_checksum = true}; - static const char* protocol_name() { - return "gameworld protocol"; - } - - explicit ProtocolGame(Connection_ptr connection); - - void login(const std::string& name, uint32_t accnumber, OperatingSystem_t operatingSystem); - void logout(bool displayEffect, bool forced); - - uint16_t getVersion() const { - return version; - } - - private: - ProtocolGame_ptr getThis() { - return std::dynamic_pointer_cast(shared_from_this()); - } - void connect(uint32_t playerId, OperatingSystem_t operatingSystem); - void disconnectClient(const std::string& message) const; - void writeToOutputBuffer(const NetworkMessage& msg); - - void release() final; - - void checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& removedKnown); - - bool canSee(int32_t x, int32_t y, int32_t z) const; - bool canSee(const Creature*) const; - bool canSee(const Position& pos) const; - - // we have all the parse methods - void parsePacket(NetworkMessage& msg) final; - void onRecvFirstMessage(NetworkMessage& msg) final; - void onConnect() final; - - //Parse methods - void parseAutoWalk(NetworkMessage& msg); - void parseSetOutfit(NetworkMessage& msg); - void parseSay(NetworkMessage& msg); - void parseLookAt(NetworkMessage& msg); - void parseLookInBattleList(NetworkMessage& msg); - void parseFightModes(NetworkMessage& msg); - void parseAttack(NetworkMessage& msg); - void parseFollow(NetworkMessage& msg); - - void parseBugReport(NetworkMessage& msg); - void parseDebugAssert(NetworkMessage& msg); - - void parseThrow(NetworkMessage& msg); - void parseUseItemEx(NetworkMessage& msg); - void parseUseWithCreature(NetworkMessage& msg); - void parseUseItem(NetworkMessage& msg); - void parseCloseContainer(NetworkMessage& msg); - void parseUpArrowContainer(NetworkMessage& msg); - void parseUpdateContainer(NetworkMessage& msg); - void parseTextWindow(NetworkMessage& msg); - void parseHouseWindow(NetworkMessage& msg); - - void parseLookInShop(NetworkMessage& msg); - void parsePlayerPurchase(NetworkMessage& msg); - void parsePlayerSale(NetworkMessage& msg); - - void parseQuestLine(NetworkMessage& msg); - - void parseInviteToParty(NetworkMessage& msg); - void parseJoinParty(NetworkMessage& msg); - void parseRevokePartyInvite(NetworkMessage& msg); - void parsePassPartyLeadership(NetworkMessage& msg); - void parseEnableSharedPartyExperience(NetworkMessage& msg); - - void parseToggleMount(NetworkMessage& msg); - - void parseModalWindowAnswer(NetworkMessage& msg); - - void parseBrowseField(NetworkMessage& msg); - void parseSeekInContainer(NetworkMessage& msg); - - //trade methods - void parseRequestTrade(NetworkMessage& msg); - void parseLookInTrade(NetworkMessage& msg); - - //market methods - void parseMarketLeave(); - void parseMarketBrowse(NetworkMessage& msg); - void parseMarketCreateOffer(NetworkMessage& msg); - void parseMarketCancelOffer(NetworkMessage& msg); - void parseMarketAcceptOffer(NetworkMessage& msg); - - //VIP methods - void parseAddVip(NetworkMessage& msg); - void parseRemoveVip(NetworkMessage& msg); - void parseEditVip(NetworkMessage& msg); - - void parseRotateItem(NetworkMessage& msg); - - //Channel tabs - void parseChannelInvite(NetworkMessage& msg); - void parseChannelExclude(NetworkMessage& msg); - void parseOpenChannel(NetworkMessage& msg); - void parseOpenPrivateChannel(NetworkMessage& msg); - void parseCloseChannel(NetworkMessage& msg); - - //Send functions - void sendChannelMessage(const std::string& author, const std::string& text, SpeakClasses type, uint16_t channel); - void sendChannelEvent(uint16_t channelId, const std::string& playerName, ChannelEvent_t channelEvent); - void sendClosePrivate(uint16_t channelId); - void sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName); - void sendChannelsDialog(); - void sendChannel(uint16_t channelId, const std::string& channelName, const UsersMap* channelUsers, const InvitedMap* invitedUsers); - void sendOpenPrivateChannel(const std::string& receiver); - void sendToChannel(const Creature* creature, SpeakClasses type, const std::string& text, uint16_t channelId); - void sendPrivateMessage(const Player* speaker, SpeakClasses type, const std::string& text); - void sendIcons(uint16_t icons); - void sendFYIBox(const std::string& message); - - void sendDistanceShoot(const Position& from, const Position& to, uint8_t type); - void sendMagicEffect(const Position& pos, uint8_t type); - void sendCreatureHealth(const Creature* creature); - void sendSkills(); - void sendPing(); - void sendPingBack(); - void sendCreatureTurn(const Creature* creature, uint32_t stackpos); - void sendCreatureSay(const Creature* creature, SpeakClasses type, const std::string& text, const Position* pos = nullptr); - - void sendQuestLog(); - void sendQuestLine(const Quest* quest); - - void sendCancelWalk(); - void sendChangeSpeed(const Creature* creature, uint32_t speed); - void sendCancelTarget(); - void sendCreatureVisible(const Creature* creature, bool visible); - void sendCreatureOutfit(const Creature* creature, const Outfit_t& outfit); - void sendStats(); - void sendBasicData(); - void sendTextMessage(const TextMessage& message); - void sendReLoginWindow(uint8_t unfairFightReduction); - - void sendTutorial(uint8_t tutorialId); - void sendAddMarker(const Position& pos, uint8_t markType, const std::string& desc); - - void sendCreatureWalkthrough(const Creature* creature, bool walkthrough); - void sendCreatureShield(const Creature* creature); - void sendCreatureSkull(const Creature* creature); - void sendCreatureType(uint32_t creatureId, uint8_t creatureType); - void sendCreatureHelpers(uint32_t creatureId, uint16_t helpers); - - void sendShop(Npc* npc, const ShopInfoList& itemList); - void sendCloseShop(); - void sendSaleItemList(const std::list& shop); - void sendMarketEnter(uint32_t depotId); - void sendMarketLeave(); - void sendMarketBrowseItem(uint16_t itemId, const MarketOfferList& buyOffers, const MarketOfferList& sellOffers); - void sendMarketAcceptOffer(const MarketOfferEx& offer); - void sendMarketBrowseOwnOffers(const MarketOfferList& buyOffers, const MarketOfferList& sellOffers); - void sendMarketCancelOffer(const MarketOfferEx& offer); - void sendMarketBrowseOwnHistory(const HistoryMarketOfferList& buyOffers, const HistoryMarketOfferList& sellOffers); - void sendMarketDetail(uint16_t itemId); - void sendTradeItemRequest(const std::string& traderName, const Item* item, bool ack); - void sendCloseTrade(); - - void sendTextWindow(uint32_t windowTextId, Item* item, uint16_t maxlen, bool canWrite); - void sendTextWindow(uint32_t windowTextId, uint32_t itemId, const std::string& text); - void sendHouseWindow(uint32_t windowTextId, const std::string& text); - void sendOutfitWindow(); - - void sendUpdatedVIPStatus(uint32_t guid, VipStatus_t newStatus); - void sendVIP(uint32_t guid, const std::string& name, const std::string& description, uint32_t icon, bool notify, VipStatus_t status); - - void sendPendingStateEntered(); - void sendEnterWorld(); - - void sendFightModes(); - - void sendCreatureLight(const Creature* creature); - void sendWorldLight(const LightInfo& lightInfo); - - void sendCreatureSquare(const Creature* creature, SquareColor_t color); - - void sendSpellCooldown(uint8_t spellId, uint32_t time); - void sendSpellGroupCooldown(SpellGroup_t groupId, uint32_t time); - - //tiles - void sendMapDescription(const Position& pos); - - void sendAddTileItem(const Position& pos, uint32_t stackpos, const Item* item); - void sendUpdateTileItem(const Position& pos, uint32_t stackpos, const Item* item); - void sendRemoveTileThing(const Position& pos, uint32_t stackpos); - void sendUpdateTile(const Tile* tile, const Position& pos); - - void sendAddCreature(const Creature* creature, const Position& pos, int32_t stackpos, bool isLogin); - void sendMoveCreature(const Creature* creature, const Position& newPos, int32_t newStackPos, - const Position& oldPos, int32_t oldStackPos, bool teleport); - - //containers - void sendAddContainerItem(uint8_t cid, uint16_t slot, const Item* item); - void sendUpdateContainerItem(uint8_t cid, uint16_t slot, const Item* item); - void sendRemoveContainerItem(uint8_t cid, uint16_t slot, const Item* lastItem); - - void sendContainer(uint8_t cid, const Container* container, bool hasParent, uint16_t firstIndex); - void sendCloseContainer(uint8_t cid); - - //inventory - void sendInventoryItem(slots_t slot, const Item* item); - - //messages - void sendModalWindow(const ModalWindow& modalWindow); - - //Help functions - - // translate a tile to clientreadable format - void GetTileDescription(const Tile* tile, NetworkMessage& msg); - - // translate a floor to clientreadable format - void GetFloorDescription(NetworkMessage& msg, int32_t x, int32_t y, int32_t z, - int32_t width, int32_t height, int32_t offset, int32_t& skip); - - // translate a map area to clientreadable format - void GetMapDescription(int32_t x, int32_t y, int32_t z, - int32_t width, int32_t height, NetworkMessage& msg); - - void AddCreature(NetworkMessage& msg, const Creature* creature, bool known, uint32_t remove); - void AddPlayerStats(NetworkMessage& msg); - void AddOutfit(NetworkMessage& msg, const Outfit_t& outfit); - void AddPlayerSkills(NetworkMessage& msg); - void AddWorldLight(NetworkMessage& msg, const LightInfo& lightInfo); - void AddCreatureLight(NetworkMessage& msg, const Creature* creature); - - //tiles - static void RemoveTileThing(NetworkMessage& msg, const Position& pos, uint32_t stackpos); - - void MoveUpCreature(NetworkMessage& msg, const Creature* creature, const Position& newPos, const Position& oldPos); - void MoveDownCreature(NetworkMessage& msg, const Creature* creature, const Position& newPos, const Position& oldPos); - - //container - void AddContainerItem(NetworkMessage& msg, uint8_t cid, const Item* item); - void UpdateContainerItem(NetworkMessage& msg, uint8_t cid, uint16_t slot, const Item* item); - void RemoveContainerItem(NetworkMessage& msg, uint8_t cid, uint16_t slot); - - //inventory - void SetInventoryItem(NetworkMessage& msg, slots_t slot, const Item* item); - - //shop - void AddShopItem(NetworkMessage& msg, const ShopInfo& item); - - //otclient - void parseExtendedOpcode(NetworkMessage& msg); - - friend class Player; - - // Helpers so we don't need to bind every time - template - void addGameTask(Callable function, Args&&... args) { - g_dispatcher.addTask(createTask(std::bind(function, &g_game, std::forward(args)...))); - } - - template - void addGameTaskTimed(uint32_t delay, Callable function, Args&&... args) { - g_dispatcher.addTask(createTask(delay, std::bind(function, &g_game, std::forward(args)...))); - } - - std::unordered_set knownCreatureSet; - Player* player; - - uint32_t eventConnect; - uint32_t m_challengeTimestamp; - uint16_t version; - - uint8_t m_challengeRandom; - - bool m_debugAssertSent; - bool m_acceptPackets; -}; - -#endif diff --git a/path_10_8/src/protocollogin.cpp b/path_10_8/src/protocollogin.cpp deleted file mode 100644 index a34aa8150..000000000 --- a/path_10_8/src/protocollogin.cpp +++ /dev/null @@ -1,183 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "protocollogin.h" - -#include "outputmessage.h" -#include "rsa.h" -#include "tasks.h" - -#include "configmanager.h" -#include "iologindata.h" -#include "ban.h" -#include "game.h" - -extern ConfigManager g_config; -extern Game g_game; - -void ProtocolLogin::disconnectClient(const std::string& message, uint16_t version) -{ - auto output = OutputMessagePool::getOutputMessage(); - - output->addByte(version >= 1076 ? 0x0B : 0x0A); - output->addString(message); - send(output); - - disconnect(); -} - -void ProtocolLogin::getCharacterList(const std::string& accountName, const std::string& password, uint16_t version) -{ - Account account; - if (!IOLoginData::loginserverAuthentication(accountName, password, account)) { - disconnectClient("Account name or password is not correct.", version); - return; - } - - auto output = OutputMessagePool::getOutputMessage(); - //Update premium days - Game::updatePremium(account); - - const std::string& motd = g_config.getString(ConfigManager::MOTD); - if (!motd.empty()) { - //Add MOTD - output->addByte(0x14); - - std::ostringstream ss; - ss << g_game.getMotdNum() << "\n" << motd; - output->addString(ss.str()); - } - - //Add session key - output->addByte(0x28); - output->addString(accountName + "\n" + password); - - //Add char list - output->addByte(0x64); - - output->addByte(1); // number of worlds - - output->addByte(0); // world id - output->addString(g_config.getString(ConfigManager::SERVER_NAME)); - output->addString(g_config.getString(ConfigManager::IP)); - output->add(g_config.getNumber(ConfigManager::GAME_PORT)); - output->addByte(0); - - uint8_t size = std::min(std::numeric_limits::max(), account.characters.size()); - output->addByte(size); - for (uint8_t i = 0; i < size; i++) { - output->addByte(0); - output->addString(account.characters[i]); - } - - //Add premium days - output->addByte(0); - - output->addByte(g_config.getBoolean(ConfigManager::FREE_PREMIUM) || account.premiumDays > 0); - output->add(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : (time(nullptr) + (account.premiumDays * 86400))); - - send(output); - - disconnect(); -} - -void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg) -{ - if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { - disconnect(); - return; - } - - msg.skipBytes(2); // client OS - - uint16_t version = msg.get(); - if (version >= 971) { - msg.skipBytes(17); - } else { - msg.skipBytes(12); - } - /* - * Skipped bytes: - * 4 bytes: protocolVersion - * 12 bytes: dat, spr, pic signatures (4 bytes each) - * 1 byte: 0 - */ - - if (version <= 760) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!", version); - return; - } - - if (!Protocol::RSA_decrypt(msg)) { - disconnect(); - return; - } - - uint32_t key[4]; - key[0] = msg.get(); - key[1] = msg.get(); - key[2] = msg.get(); - key[3] = msg.get(); - enableXTEAEncryption(); - setXTEAKey(key); - - if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!", version); - return; - } - - if (g_game.getGameState() == GAME_STATE_STARTUP) { - disconnectClient("Gameworld is starting up. Please wait.", version); - return; - } - - if (g_game.getGameState() == GAME_STATE_MAINTAIN) { - disconnectClient("Gameworld is under maintenance.\nPlease re-connect in a while.", version); - return; - } - - BanInfo banInfo; - auto connection = getConnection(); - if (!connection) { - return; - } - - if (IOBan::isIpBanned(connection->getIP(), banInfo)) { - if (banInfo.reason.empty()) { - banInfo.reason = "(none)"; - } - - std::ostringstream ss; - ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason; - disconnectClient(ss.str(), version); - return; - } - - std::string accountName = msg.getString(); - if (accountName.empty()) { - disconnectClient("Invalid account name.", version); - return; - } - - std::string password = msg.getString(); - auto thisPtr = std::dynamic_pointer_cast(shared_from_this()); - g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountName, password, version))); -} diff --git a/path_10_8/src/protocollogin.h b/path_10_8/src/protocollogin.h deleted file mode 100644 index 1fce30a90..000000000 --- a/path_10_8/src/protocollogin.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PROTOCOLLOGIN_H_1238F4B473074DF2ABC595C29E81C46D -#define FS_PROTOCOLLOGIN_H_1238F4B473074DF2ABC595C29E81C46D - -#include "protocol.h" - -class NetworkMessage; -class OutputMessage; - -class ProtocolLogin : public Protocol -{ - public: - // static protocol information - enum {server_sends_first = false}; - enum {protocol_identifier = 0x01}; - enum {use_checksum = true}; - static const char* protocol_name() { - return "login protocol"; - } - - explicit ProtocolLogin(Connection_ptr connection) : Protocol(connection) {} - - void onRecvFirstMessage(NetworkMessage& msg); - - protected: - void disconnectClient(const std::string& message, uint16_t version); - - void getCharacterList(const std::string& accountName, const std::string& password, uint16_t version); -}; - -#endif diff --git a/path_10_8/src/protocolold.cpp b/path_10_8/src/protocolold.cpp deleted file mode 100644 index a68e857b2..000000000 --- a/path_10_8/src/protocolold.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "protocolold.h" -#include "outputmessage.h" -#include "tasks.h" - -#include "game.h" - -extern Game g_game; - -void ProtocolOld::disconnectClient(const std::string& message) -{ - auto output = OutputMessagePool::getOutputMessage(); - output->addByte(0x0A); - output->addString(message); - send(output); - - disconnect(); -} - -void ProtocolOld::onRecvFirstMessage(NetworkMessage& msg) -{ - if (g_game.getGameState() == GAME_STATE_SHUTDOWN) { - disconnect(); - return; - } - - /*uint16_t clientOS =*/ msg.get(); - uint16_t version = msg.get(); - msg.skipBytes(12); - - if (version <= 760) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); - return; - } - - if (!Protocol::RSA_decrypt(msg)) { - disconnect(); - return; - } - - uint32_t key[4]; - key[0] = msg.get(); - key[1] = msg.get(); - key[2] = msg.get(); - key[3] = msg.get(); - enableXTEAEncryption(); - setXTEAKey(key); - - if (version <= 822) { - disableChecksum(); - } - - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); -} diff --git a/path_10_8/src/protocolold.h b/path_10_8/src/protocolold.h deleted file mode 100644 index 071e85637..000000000 --- a/path_10_8/src/protocolold.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PROTOCOLOLD_H_5487B862FE144AE0904D098A3238E161 -#define FS_PROTOCOLOLD_H_5487B862FE144AE0904D098A3238E161 - -#include "protocol.h" - -class NetworkMessage; -class OutputMessage; - -class ProtocolOld final : public Protocol -{ - public: - // static protocol information - enum {server_sends_first = false}; - enum {protocol_identifier = 0x01}; - enum {use_checksum = false}; - static const char* protocol_name() { - return "old login protocol"; - } - - explicit ProtocolOld(Connection_ptr connection) : Protocol(connection) {} - - void onRecvFirstMessage(NetworkMessage& msg) final; - - protected: - void disconnectClient(const std::string& message); -}; - -#endif diff --git a/path_10_8/src/protocolstatus.cpp b/path_10_8/src/protocolstatus.cpp deleted file mode 100644 index 18e517acf..000000000 --- a/path_10_8/src/protocolstatus.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "protocolstatus.h" -#include "configmanager.h" -#include "game.h" -#include "connection.h" -#include "networkmessage.h" -#include "outputmessage.h" -#include "tools.h" -#include "tasks.h" - -extern ConfigManager g_config; -extern Game g_game; - -std::map ProtocolStatus::ipConnectMap; -const uint64_t ProtocolStatus::start = OTSYS_TIME(); - -enum RequestedInfo_t : uint16_t { - REQUEST_BASIC_SERVER_INFO = 1 << 0, - REQUEST_OWNER_SERVER_INFO = 1 << 1, - REQUEST_MISC_SERVER_INFO = 1 << 2, - REQUEST_PLAYERS_INFO = 1 << 3, - REQUEST_MAP_INFO = 1 << 4, - REQUEST_EXT_PLAYERS_INFO = 1 << 5, - REQUEST_PLAYER_STATUS_INFO = 1 << 6, - REQUEST_SERVER_SOFTWARE_INFO = 1 << 7, -}; - -void ProtocolStatus::onRecvFirstMessage(NetworkMessage& msg) -{ - uint32_t ip = getIP(); - if (ip != 0x0100007F) { - std::string ipStr = convertIPToString(ip); - if (ipStr != g_config.getString(ConfigManager::IP)) { - std::map::const_iterator it = ipConnectMap.find(ip); - if (it != ipConnectMap.end() && (OTSYS_TIME() < (it->second + g_config.getNumber(ConfigManager::STATUSQUERY_TIMEOUT)))) { - disconnect(); - return; - } - } - } - - ipConnectMap[ip] = OTSYS_TIME(); - - switch (msg.getByte()) { - //XML info protocol - case 0xFF: { - if (msg.getString(4) == "info") { - g_dispatcher.addTask(createTask(std::bind(&ProtocolStatus::sendStatusString, - std::static_pointer_cast(shared_from_this())))); - return; - } - break; - } - - //Another ServerInfo protocol - case 0x01: { - uint16_t requestedInfo = msg.get(); // only a Byte is necessary, though we could add new info here - std::string characterName; - if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { - characterName = msg.getString(); - } - g_dispatcher.addTask(createTask(std::bind(&ProtocolStatus::sendInfo, std::static_pointer_cast(shared_from_this()), - requestedInfo, characterName))); - return; - } - - default: - break; - } - disconnect(); -} - -void ProtocolStatus::sendStatusString() -{ - auto output = OutputMessagePool::getOutputMessage(); - - setRawMessages(true); - - pugi::xml_document doc; - - pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); - decl.append_attribute("version") = "1.0"; - - pugi::xml_node tsqp = doc.append_child("tsqp"); - tsqp.append_attribute("version") = "1.0"; - - pugi::xml_node serverinfo = tsqp.append_child("serverinfo"); - uint64_t uptime = (OTSYS_TIME() - ProtocolStatus::start) / 1000; - serverinfo.append_attribute("uptime") = std::to_string(uptime).c_str(); - serverinfo.append_attribute("ip") = g_config.getString(ConfigManager::IP).c_str(); - serverinfo.append_attribute("servername") = g_config.getString(ConfigManager::SERVER_NAME).c_str(); - serverinfo.append_attribute("port") = std::to_string(g_config.getNumber(ConfigManager::LOGIN_PORT)).c_str(); - serverinfo.append_attribute("location") = g_config.getString(ConfigManager::LOCATION).c_str(); - serverinfo.append_attribute("url") = g_config.getString(ConfigManager::URL).c_str(); - serverinfo.append_attribute("server") = STATUS_SERVER_NAME; - serverinfo.append_attribute("version") = STATUS_SERVER_VERSION; - serverinfo.append_attribute("client") = CLIENT_VERSION_STR; - - pugi::xml_node owner = tsqp.append_child("owner"); - owner.append_attribute("name") = g_config.getString(ConfigManager::OWNER_NAME).c_str(); - owner.append_attribute("email") = g_config.getString(ConfigManager::OWNER_EMAIL).c_str(); - - pugi::xml_node players = tsqp.append_child("players"); - players.append_attribute("online") = std::to_string(g_game.getPlayersOnline()).c_str(); - players.append_attribute("max") = std::to_string(g_config.getNumber(ConfigManager::MAX_PLAYERS)).c_str(); - players.append_attribute("peak") = std::to_string(g_game.getPlayersRecord()).c_str(); - - pugi::xml_node monsters = tsqp.append_child("monsters"); - monsters.append_attribute("total") = std::to_string(g_game.getMonstersOnline()).c_str(); - - pugi::xml_node npcs = tsqp.append_child("npcs"); - npcs.append_attribute("total") = std::to_string(g_game.getNpcsOnline()).c_str(); - - pugi::xml_node rates = tsqp.append_child("rates"); - rates.append_attribute("experience") = std::to_string(g_config.getNumber(ConfigManager::RATE_EXPERIENCE)).c_str(); - rates.append_attribute("skill") = std::to_string(g_config.getNumber(ConfigManager::RATE_SKILL)).c_str(); - rates.append_attribute("loot") = std::to_string(g_config.getNumber(ConfigManager::RATE_LOOT)).c_str(); - rates.append_attribute("magic") = std::to_string(g_config.getNumber(ConfigManager::RATE_MAGIC)).c_str(); - rates.append_attribute("spawn") = std::to_string(g_config.getNumber(ConfigManager::RATE_SPAWN)).c_str(); - - pugi::xml_node map = tsqp.append_child("map"); - map.append_attribute("name") = g_config.getString(ConfigManager::MAP_NAME).c_str(); - map.append_attribute("author") = g_config.getString(ConfigManager::MAP_AUTHOR).c_str(); - - uint32_t mapWidth, mapHeight; - g_game.getMapDimensions(mapWidth, mapHeight); - map.append_attribute("width") = std::to_string(mapWidth).c_str(); - map.append_attribute("height") = std::to_string(mapHeight).c_str(); - - pugi::xml_node motd = tsqp.append_child("motd"); - motd.text() = g_config.getString(ConfigManager::MOTD).c_str(); - - std::ostringstream ss; - doc.save(ss, "", pugi::format_raw); - - std::string data = ss.str(); - output->addBytes(data.c_str(), data.size()); - send(output); - disconnect(); -} - -void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& characterName) -{ - auto output = OutputMessagePool::getOutputMessage(); - - if (requestedInfo & REQUEST_BASIC_SERVER_INFO) { - output->addByte(0x10); - output->addString(g_config.getString(ConfigManager::SERVER_NAME)); - output->addString(g_config.getString(ConfigManager::IP)); - output->addString(std::to_string(g_config.getNumber(ConfigManager::LOGIN_PORT))); - } - - if (requestedInfo & REQUEST_OWNER_SERVER_INFO) { - output->addByte(0x11); - output->addString(g_config.getString(ConfigManager::OWNER_NAME)); - output->addString(g_config.getString(ConfigManager::OWNER_EMAIL)); - } - - if (requestedInfo & REQUEST_MISC_SERVER_INFO) { - output->addByte(0x12); - output->addString(g_config.getString(ConfigManager::MOTD)); - output->addString(g_config.getString(ConfigManager::LOCATION)); - output->addString(g_config.getString(ConfigManager::URL)); - output->add((OTSYS_TIME() - ProtocolStatus::start) / 1000); - } - - if (requestedInfo & REQUEST_PLAYERS_INFO) { - output->addByte(0x20); - output->add(g_game.getPlayersOnline()); - output->add(g_config.getNumber(ConfigManager::MAX_PLAYERS)); - output->add(g_game.getPlayersRecord()); - } - - if (requestedInfo & REQUEST_MAP_INFO) { - output->addByte(0x30); - output->addString(g_config.getString(ConfigManager::MAP_NAME)); - output->addString(g_config.getString(ConfigManager::MAP_AUTHOR)); - uint32_t mapWidth, mapHeight; - g_game.getMapDimensions(mapWidth, mapHeight); - output->add(mapWidth); - output->add(mapHeight); - } - - if (requestedInfo & REQUEST_EXT_PLAYERS_INFO) { - output->addByte(0x21); // players info - online players list - - const auto& players = g_game.getPlayers(); - output->add(players.size()); - for (const auto& it : players) { - output->addString(it.second->getName()); - output->add(it.second->getLevel()); - } - } - - if (requestedInfo & REQUEST_PLAYER_STATUS_INFO) { - output->addByte(0x22); // players info - online status info of a player - if (g_game.getPlayerByName(characterName) != nullptr) { - output->addByte(0x01); - } else { - output->addByte(0x00); - } - } - - if (requestedInfo & REQUEST_SERVER_SOFTWARE_INFO) { - output->addByte(0x23); // server software info - output->addString(STATUS_SERVER_NAME); - output->addString(STATUS_SERVER_VERSION); - output->addString(CLIENT_VERSION_STR); - } - send(output); - disconnect(); -} diff --git a/path_10_8/src/protocolstatus.h b/path_10_8/src/protocolstatus.h deleted file mode 100644 index 861f2126d..000000000 --- a/path_10_8/src/protocolstatus.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_STATUS_H_8B28B354D65B4C0483E37AD1CA316EB4 -#define FS_STATUS_H_8B28B354D65B4C0483E37AD1CA316EB4 - -#include "networkmessage.h" -#include "protocol.h" - -class ProtocolStatus final : public Protocol -{ - public: - // static protocol information - enum {server_sends_first = false}; - enum {protocol_identifier = 0xFF}; - enum {use_checksum = false}; - static const char* protocol_name() { - return "status protocol"; - } - - explicit ProtocolStatus(Connection_ptr connection) : Protocol(connection) {} - - void onRecvFirstMessage(NetworkMessage& msg) final; - - void sendStatusString(); - void sendInfo(uint16_t requestedInfo, const std::string& characterName); - - static const uint64_t start; - - protected: - static std::map ipConnectMap; -}; - -#endif diff --git a/path_10_8/src/pugicast.h b/path_10_8/src/pugicast.h deleted file mode 100644 index e8b7fd515..000000000 --- a/path_10_8/src/pugicast.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_PUGICAST_H_07810DF7954D411EB14A16C3ED2A7548 -#define FS_PUGICAST_H_07810DF7954D411EB14A16C3ED2A7548 - -#include - -namespace pugi { - template - T cast(const pugi::char_t* str) - { - T value; - try { - value = boost::lexical_cast(str); - } catch (boost::bad_lexical_cast&) { - value = T(); - } - return value; - } -} - -#endif diff --git a/path_10_8/src/quests.cpp b/path_10_8/src/quests.cpp deleted file mode 100644 index b0e4377ad..000000000 --- a/path_10_8/src/quests.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "quests.h" - -#include "pugicast.h" - -std::string Mission::getDescription(Player* player) const -{ - int32_t value; - player->getStorageValue(storageID, value); - - if (mainState) { - std::string desc = mainState->getMissionDescription(); - replaceString(desc, "|STATE|", std::to_string(value)); - replaceString(desc, "\\n", "\n"); - return desc; - } - - int32_t current = endValue; - - if (ignoreEndValue) { - while (current >= startValue) { - if (value >= current) { - auto sit = state.find(current); - if (sit != state.end()) { - return sit->second.getMissionDescription(); - } - } - - current--; - } - } else { - while (current >= startValue) { - if (value == current) { - auto sit = state.find(current); - if (sit != state.end()) { - return sit->second.getMissionDescription(); - } - } - - current--; - } - } - - return "An error has occurred, please contact a gamemaster."; -} - -bool Mission::isStarted(Player* player) const -{ - if (!player) { - return false; - } - - int32_t value; - if (!player->getStorageValue(storageID, value)) { - return false; - } - - if (value < startValue) { - return false; - } - - if (!ignoreEndValue && value > endValue) { - return false; - } - - return true; -} - -bool Mission::isCompleted(Player* player) const -{ - if (!player) { - return false; - } - - int32_t value; - if (!player->getStorageValue(storageID, value)) { - return false; - } - - if (ignoreEndValue) { - return value >= endValue; - } - - return value == endValue; -} - -std::string Mission::getName(Player* player) const -{ - if (isCompleted(player)) { - return name + " (completed)"; - } - return name; -} - -uint16_t Quest::getMissionsCount(Player* player) const -{ - uint16_t count = 0; - for (const Mission& mission : missions) { - if (mission.isStarted(player)) { - count++; - } - } - return count; -} - -bool Quest::isCompleted(Player* player) const -{ - for (const Mission& mission : missions) { - if (!mission.isCompleted(player)) { - return false; - } - } - return true; -} - -bool Quest::isStarted(Player* player) const -{ - if (!player) { - return false; - } - - int32_t value; - if (!player->getStorageValue(startStorageID, value) || value < startStorageValue) { - return false; - } - - return true; -} - -bool Quests::reload() -{ - quests.clear(); - return loadFromXml(); -} - -bool Quests::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/quests.xml"); - if (!result) { - printXMLError("Error - Quests::loadFromXml", "data/XML/quests.xml", result); - return false; - } - - uint16_t id = 0; - for (auto questNode : doc.child("quests").children()) { - quests.emplace_back( - questNode.attribute("name").as_string(), - ++id, - pugi::cast(questNode.attribute("startstorageid").value()), - pugi::cast(questNode.attribute("startstoragevalue").value()) - ); - Quest& quest = quests.back(); - - for (auto missionNode : questNode.children()) { - std::string missionState = missionNode.attribute("description").as_string(); - - quest.missions.emplace_back( - missionNode.attribute("name").as_string(), - pugi::cast(missionNode.attribute("storageid").value()), - pugi::cast(missionNode.attribute("startvalue").value()), - pugi::cast(missionNode.attribute("endvalue").value()), - missionNode.attribute("ignoreendvalue").as_bool() - ); - Mission& mission = quest.missions.back(); - - if (missionState.empty()) { - for (auto missionStateNode : missionNode.children()) { - int32_t missionId = pugi::cast(missionStateNode.attribute("id").value()); - mission.state.emplace(missionId, MissionState(missionStateNode.attribute("description").as_string(), missionId)); - } - } else { - mission.mainState = new MissionState(missionState, 0); - } - } - } - return true; -} - -Quest* Quests::getQuestByID(uint16_t id) -{ - for (Quest& quest : quests) { - if (quest.id == id) { - return ? - } - } - return nullptr; -} - -uint16_t Quests::getQuestsCount(Player* player) const -{ - uint16_t count = 0; - for (const Quest& quest : quests) { - if (quest.isStarted(player)) { - count++; - } - } - return count; -} - -bool Quests::isQuestStorage(const uint32_t key, const int32_t value, const int32_t oldValue) const -{ - for (const Quest& quest : quests) { - if (quest.getStartStorageId() == key && quest.getStartStorageValue() == value) { - return true; - } - - for (const Mission& mission : quest.getMissions()) { - if (mission.mainState) { - if (mission.getStorageId() == key && value >= mission.getStartStorageValue() && value <= mission.getEndStorageValue() && (oldValue < mission.getStartStorageValue() || oldValue > mission.getEndStorageValue())) { - return true; - } - } else { - if (mission.getStorageId() == key && value >= mission.getStartStorageValue() && value <= mission.getEndStorageValue()) { - return true; - } - } - } - } - return false; -} diff --git a/path_10_8/src/quests.h b/path_10_8/src/quests.h deleted file mode 100644 index d566461a0..000000000 --- a/path_10_8/src/quests.h +++ /dev/null @@ -1,138 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 -#define FS_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 - -#include "player.h" -#include "networkmessage.h" - -class MissionState; -class Mission; -class Quest; - -typedef std::list MissionsList; -typedef std::list QuestsList; - -class MissionState -{ - public: - MissionState() = default; - MissionState(std::string description, int32_t missionID) : description(description), missionID(missionID) {} - - int32_t getMissionID() const { - return missionID; - } - std::string getMissionDescription() const { - return description; - } - - private: - std::string description; - int32_t missionID; -}; - -class Mission -{ - public: - Mission(std::string name, int32_t storageID, int32_t startValue, int32_t endValue, bool ignoreEndValue) - : mainState(nullptr), name(name), storageID(storageID), startValue(startValue), endValue(endValue), ignoreEndValue(ignoreEndValue) {} - - bool isCompleted(Player* player) const; - bool isStarted(Player* player) const; - std::string getName(Player* player) const; - std::string getDescription(Player* player) const; - - uint32_t getStorageId() const { - return storageID; - } - int32_t getStartStorageValue() const { - return startValue; - } - int32_t getEndStorageValue() const { - return endValue; - } - - std::map state; - MissionState* mainState; - - private: - std::string name; - uint32_t storageID; - int32_t startValue, endValue; - bool ignoreEndValue; -}; - -class Quest -{ - public: - Quest(std::string name, uint16_t id, int32_t startStorageID, int32_t startStorageValue) - : name(name), startStorageID(startStorageID), startStorageValue(startStorageValue), id(id) {} - - bool isCompleted(Player* player) const; - bool isStarted(Player* player) const; - uint16_t getID() const { - return id; - } - std::string getName() const { - return name; - } - uint16_t getMissionsCount(Player* player) const; - - uint32_t getStartStorageId() const { - return startStorageID; - } - int32_t getStartStorageValue() const { - return startStorageValue; - } - - const MissionsList& getMissions() const { - return missions; - } - - private: - std::string name; - - uint32_t startStorageID; - int32_t startStorageValue; - uint16_t id; - - MissionsList missions; - - friend class Quests; -}; - -class Quests -{ - public: - const QuestsList& getQuests() const { - return quests; - } - - bool loadFromXml(); - Quest* getQuestByID(uint16_t id); - bool isQuestStorage(const uint32_t key, const int32_t value, const int32_t oldValue) const; - uint16_t getQuestsCount(Player* player) const; - bool reload(); - - private: - QuestsList quests; -}; - -#endif diff --git a/path_10_8/src/raids.cpp b/path_10_8/src/raids.cpp deleted file mode 100644 index 60d620a44..000000000 --- a/path_10_8/src/raids.cpp +++ /dev/null @@ -1,599 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "raids.h" - -#include "pugicast.h" - -#include "game.h" -#include "configmanager.h" -#include "scheduler.h" -#include "monster.h" - -extern Game g_game; -extern ConfigManager g_config; - -Raids::Raids() - : scriptInterface("Raid Interface") -{ - loaded = false; - started = false; - running = nullptr; - lastRaidEnd = 0; - checkRaidsEvent = 0; - - scriptInterface.initState(); -} - -Raids::~Raids() -{ - for (Raid* raid : raidList) { - delete raid; - } -} - -bool Raids::loadFromXml() -{ - if (isLoaded()) { - return true; - } - - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/raids/raids.xml"); - if (!result) { - printXMLError("Error - Raids::loadFromXml", "data/raids/raids.xml", result); - return false; - } - - for (auto raidNode : doc.child("raids").children()) { - std::string name, file; - uint32_t interval, margin; - - pugi::xml_attribute attr; - if ((attr = raidNode.attribute("name"))) { - name = attr.as_string(); - } else { - std::cout << "[Error - Raids::loadFromXml] Name tag missing for raid" << std::endl; - continue; - } - - if ((attr = raidNode.attribute("file"))) { - file = attr.as_string(); - } else { - std::ostringstream ss; - ss << "raids/" << name << ".xml"; - file = ss.str(); - std::cout << "[Warning - Raids::loadFromXml] File tag missing for raid " << name << ". Using default: " << file << std::endl; - } - - interval = pugi::cast(raidNode.attribute("interval2").value()) * 60; - if (interval == 0) { - std::cout << "[Error - Raids::loadFromXml] interval2 tag missing or zero (would divide by 0) for raid: " << name << std::endl; - continue; - } - - if ((attr = raidNode.attribute("margin"))) { - margin = pugi::cast(attr.value()) * 60 * 1000; - } else { - std::cout << "[Warning - Raids::loadFromXml] margin tag missing for raid: " << name << std::endl; - margin = 0; - } - - bool repeat; - if ((attr = raidNode.attribute("repeat"))) { - repeat = booleanString(attr.as_string()); - } else { - repeat = false; - } - - Raid* newRaid = new Raid(name, interval, margin, repeat); - if (newRaid->loadFromXml("data/raids/" + file)) { - raidList.push_back(newRaid); - } else { - std::cout << "[Error - Raids::loadFromXml] Failed to load raid: " << name << std::endl; - delete newRaid; - } - } - - loaded = true; - return true; -} - -#define MAX_RAND_RANGE 10000000 - -bool Raids::startup() -{ - if (!isLoaded() || isStarted()) { - return false; - } - - setLastRaidEnd(OTSYS_TIME()); - - checkRaidsEvent = g_scheduler.addEvent(createSchedulerTask(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this))); - - started = true; - return started; -} - -void Raids::checkRaids() -{ - if (!getRunning()) { - uint64_t now = OTSYS_TIME(); - - for (auto it = raidList.begin(), end = raidList.end(); it != end; ++it) { - Raid* raid = *it; - if (now >= (getLastRaidEnd() + raid->getMargin())) { - if (((MAX_RAND_RANGE * CHECK_RAIDS_INTERVAL) / raid->getInterval()) >= static_cast(uniform_random(0, MAX_RAND_RANGE))) { - setRunning(raid); - raid->startRaid(); - - if (!raid->canBeRepeated()) { - raidList.erase(it); - } - break; - } - } - } - } - - checkRaidsEvent = g_scheduler.addEvent(createSchedulerTask(CHECK_RAIDS_INTERVAL * 1000, std::bind(&Raids::checkRaids, this))); -} - -void Raids::clear() -{ - g_scheduler.stopEvent(checkRaidsEvent); - checkRaidsEvent = 0; - - for (Raid* raid : raidList) { - raid->stopEvents(); - delete raid; - } - raidList.clear(); - - loaded = false; - started = false; - running = nullptr; - lastRaidEnd = 0; - - scriptInterface.reInitState(); -} - -bool Raids::reload() -{ - clear(); - return loadFromXml(); -} - -Raid* Raids::getRaidByName(const std::string& name) -{ - for (Raid* raid : raidList) { - if (strcasecmp(raid->getName().c_str(), name.c_str()) == 0) { - return raid; - } - } - return nullptr; -} - -Raid::~Raid() -{ - for (RaidEvent* raidEvent : raidEvents) { - delete raidEvent; - } -} - -bool Raid::loadFromXml(const std::string& _filename) -{ - if (isLoaded()) { - return true; - } - - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(_filename.c_str()); - if (!result) { - printXMLError("Error - Raid::loadFromXml", _filename, result); - return false; - } - - for (auto eventNode : doc.child("raid").children()) { - RaidEvent* event; - if (strcasecmp(eventNode.name(), "announce") == 0) { - event = new AnnounceEvent(); - } else if (strcasecmp(eventNode.name(), "singlespawn") == 0) { - event = new SingleSpawnEvent(); - } else if (strcasecmp(eventNode.name(), "areaspawn") == 0) { - event = new AreaSpawnEvent(); - } else if (strcasecmp(eventNode.name(), "script") == 0) { - event = new ScriptEvent(&g_game.raids.getScriptInterface()); - } else { - continue; - } - - if (event->configureRaidEvent(eventNode)) { - raidEvents.push_back(event); - } else { - std::cout << "[Error - Raid::loadFromXml] In file (" << _filename << "), eventNode: " << eventNode.name() << std::endl; - delete event; - } - } - - //sort by delay time - std::sort(raidEvents.begin(), raidEvents.end(), RaidEvent::compareEvents); - - loaded = true; - return true; -} - -void Raid::startRaid() -{ - RaidEvent* raidEvent = getNextRaidEvent(); - if (raidEvent) { - state = RAIDSTATE_EXECUTING; - nextEventEvent = g_scheduler.addEvent(createSchedulerTask(raidEvent->getDelay(), std::bind(&Raid::executeRaidEvent, this, raidEvent))); - } -} - -void Raid::executeRaidEvent(RaidEvent* raidEvent) -{ - if (raidEvent->executeEvent()) { - nextEvent++; - RaidEvent* newRaidEvent = getNextRaidEvent(); - - if (newRaidEvent) { - uint32_t ticks = static_cast(std::max(RAID_MINTICKS, newRaidEvent->getDelay() - raidEvent->getDelay())); - nextEventEvent = g_scheduler.addEvent(createSchedulerTask(ticks, std::bind(&Raid::executeRaidEvent, this, newRaidEvent))); - } else { - resetRaid(); - } - } else { - resetRaid(); - } -} - -void Raid::resetRaid() -{ - nextEvent = 0; - state = RAIDSTATE_IDLE; - g_game.raids.setRunning(nullptr); - g_game.raids.setLastRaidEnd(OTSYS_TIME()); -} - -void Raid::stopEvents() -{ - if (nextEventEvent != 0) { - g_scheduler.stopEvent(nextEventEvent); - nextEventEvent = 0; - } -} - -RaidEvent* Raid::getNextRaidEvent() -{ - if (nextEvent < raidEvents.size()) { - return raidEvents[nextEvent]; - } else { - return nullptr; - } -} - -bool RaidEvent::configureRaidEvent(const pugi::xml_node& eventNode) -{ - pugi::xml_attribute delayAttribute = eventNode.attribute("delay"); - if (!delayAttribute) { - std::cout << "[Error] Raid: delay tag missing." << std::endl; - return false; - } - - delay = std::max(RAID_MINTICKS, pugi::cast(delayAttribute.value())); - return true; -} - -bool AnnounceEvent::configureRaidEvent(const pugi::xml_node& eventNode) -{ - if (!RaidEvent::configureRaidEvent(eventNode)) { - return false; - } - - pugi::xml_attribute messageAttribute = eventNode.attribute("message"); - if (!messageAttribute) { - std::cout << "[Error] Raid: message tag missing for announce event." << std::endl; - return false; - } - message = messageAttribute.as_string(); - - pugi::xml_attribute typeAttribute = eventNode.attribute("type"); - if (typeAttribute) { - std::string tmpStrValue = asLowerCaseString(typeAttribute.as_string()); - if (tmpStrValue == "warning") { - messageType = MESSAGE_STATUS_WARNING; - } else if (tmpStrValue == "event") { - messageType = MESSAGE_EVENT_ADVANCE; - } else if (tmpStrValue == "default") { - messageType = MESSAGE_EVENT_DEFAULT; - } else if (tmpStrValue == "description") { - messageType = MESSAGE_INFO_DESCR; - } else if (tmpStrValue == "smallstatus") { - messageType = MESSAGE_STATUS_SMALL; - } else if (tmpStrValue == "blueconsole") { - messageType = MESSAGE_STATUS_CONSOLE_BLUE; - } else if (tmpStrValue == "redconsole") { - messageType = MESSAGE_STATUS_CONSOLE_RED; - } else { - std::cout << "[Notice] Raid: Unknown type tag missing for announce event. Using default: " << static_cast(messageType) << std::endl; - } - } else { - messageType = MESSAGE_EVENT_ADVANCE; - std::cout << "[Notice] Raid: type tag missing for announce event. Using default: " << static_cast(messageType) << std::endl; - } - return true; -} - -bool AnnounceEvent::executeEvent() -{ - g_game.broadcastMessage(message, messageType); - return true; -} - -bool SingleSpawnEvent::configureRaidEvent(const pugi::xml_node& eventNode) -{ - if (!RaidEvent::configureRaidEvent(eventNode)) { - return false; - } - - pugi::xml_attribute attr; - if ((attr = eventNode.attribute("name"))) { - monsterName = attr.as_string(); - } else { - std::cout << "[Error] Raid: name tag missing for singlespawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("x"))) { - position.x = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: x tag missing for singlespawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("y"))) { - position.y = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: y tag missing for singlespawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("z"))) { - position.z = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: z tag missing for singlespawn event." << std::endl; - return false; - } - return true; -} - -bool SingleSpawnEvent::executeEvent() -{ - Monster* monster = Monster::createMonster(monsterName); - if (!monster) { - std::cout << "[Error] Raids: Cant create monster " << monsterName << std::endl; - return false; - } - - if (!g_game.placeCreature(monster, position, false, true)) { - delete monster; - std::cout << "[Error] Raids: Cant place monster " << monsterName << std::endl; - return false; - } - return true; -} - -bool AreaSpawnEvent::configureRaidEvent(const pugi::xml_node& eventNode) -{ - if (!RaidEvent::configureRaidEvent(eventNode)) { - return false; - } - - pugi::xml_attribute attr; - if ((attr = eventNode.attribute("radius"))) { - int32_t radius = pugi::cast(attr.value()); - Position centerPos; - - if ((attr = eventNode.attribute("centerx"))) { - centerPos.x = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: centerx tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("centery"))) { - centerPos.y = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: centery tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("centerz"))) { - centerPos.z = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: centerz tag missing for areaspawn event." << std::endl; - return false; - } - - fromPos.x = std::max(0, centerPos.getX() - radius); - fromPos.y = std::max(0, centerPos.getY() - radius); - fromPos.z = centerPos.z; - - toPos.x = std::min(0xFFFF, centerPos.getX() + radius); - toPos.y = std::min(0xFFFF, centerPos.getY() + radius); - toPos.z = centerPos.z; - } else { - if ((attr = eventNode.attribute("fromx"))) { - fromPos.x = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: fromx tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("fromy"))) { - fromPos.y = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: fromy tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("fromz"))) { - fromPos.z = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: fromz tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("tox"))) { - toPos.x = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: tox tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("toy"))) { - toPos.y = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: toy tag missing for areaspawn event." << std::endl; - return false; - } - - if ((attr = eventNode.attribute("toz"))) { - toPos.z = pugi::cast(attr.value()); - } else { - std::cout << "[Error] Raid: toz tag missing for areaspawn event." << std::endl; - return false; - } - } - - for (auto monsterNode : eventNode.children()) { - const char* name; - - if ((attr = monsterNode.attribute("name"))) { - name = attr.value(); - } else { - std::cout << "[Error] Raid: name tag missing for monster node." << std::endl; - return false; - } - - uint32_t minAmount; - if ((attr = monsterNode.attribute("minamount"))) { - minAmount = pugi::cast(attr.value()); - } else { - minAmount = 0; - } - - uint32_t maxAmount; - if ((attr = monsterNode.attribute("maxamount"))) { - maxAmount = pugi::cast(attr.value()); - } else { - maxAmount = 0; - } - - if (maxAmount == 0 && minAmount == 0) { - if ((attr = monsterNode.attribute("amount"))) { - minAmount = pugi::cast(attr.value()); - maxAmount = minAmount; - } else { - std::cout << "[Error] Raid: amount tag missing for monster node." << std::endl; - return false; - } - } - - spawnList.emplace_back(name, minAmount, maxAmount); - } - return true; -} - -bool AreaSpawnEvent::executeEvent() -{ - for (const MonsterSpawn& spawn : spawnList) { - uint32_t amount = uniform_random(spawn.minAmount, spawn.maxAmount); - for (uint32_t i = 0; i < amount; ++i) { - Monster* monster = Monster::createMonster(spawn.name); - if (!monster) { - std::cout << "[Error - AreaSpawnEvent::executeEvent] Can't create monster " << spawn.name << std::endl; - return false; - } - - bool success = false; - for (int32_t tries = 0; tries < MAXIMUM_TRIES_PER_MONSTER; tries++) { - Tile* tile = g_game.map.getTile(uniform_random(fromPos.x, toPos.x), uniform_random(fromPos.y, toPos.y), uniform_random(fromPos.z, toPos.z)); - if (tile && !tile->isMoveableBlocking() && !tile->hasFlag(TILESTATE_PROTECTIONZONE) && tile->getTopCreature() == nullptr && g_game.placeCreature(monster, tile->getPosition(), false, true)) { - success = true; - break; - } - } - - if (!success) { - delete monster; - } - } - } - return true; -} - -ScriptEvent::ScriptEvent(LuaScriptInterface* _interface) : - Event(_interface) -{ -} - -bool ScriptEvent::configureRaidEvent(const pugi::xml_node& eventNode) -{ - if (!RaidEvent::configureRaidEvent(eventNode)) { - return false; - } - - pugi::xml_attribute scriptAttribute = eventNode.attribute("script"); - if (!scriptAttribute) { - std::cout << "Error: [ScriptEvent::configureRaidEvent] No script file found for raid" << std::endl; - return false; - } - - if (!loadScript("data/raids/scripts/" + std::string(scriptAttribute.as_string()))) { - std::cout << "Error: [ScriptEvent::configureRaidEvent] Can not load raid script." << std::endl; - return false; - } - return true; -} - -std::string ScriptEvent::getScriptEventName() const -{ - return "onRaid"; -} - -bool ScriptEvent::executeEvent() -{ - //onRaid() - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ScriptEvent::onRaid] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - m_scriptInterface->pushFunction(m_scriptId); - - return m_scriptInterface->callFunction(0); -} diff --git a/path_10_8/src/raids.h b/path_10_8/src/raids.h deleted file mode 100644 index 5191e0840..000000000 --- a/path_10_8/src/raids.h +++ /dev/null @@ -1,236 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_RAIDS_H_3583C7C054584881856D55765DEDAFA9 -#define FS_RAIDS_H_3583C7C054584881856D55765DEDAFA9 - -#include "const.h" -#include "position.h" -#include "baseevents.h" - -enum RaidState_t { - RAIDSTATE_IDLE, - RAIDSTATE_EXECUTING, -}; - -struct MonsterSpawn { - MonsterSpawn(const char* name, uint32_t minAmount, uint32_t maxAmount) : name(name), minAmount(minAmount), maxAmount(maxAmount) {} - - std::string name; - uint32_t minAmount; - uint32_t maxAmount; -}; - -//How many times it will try to find a tile to add the monster to before giving up -#define MAXIMUM_TRIES_PER_MONSTER 10 -#define CHECK_RAIDS_INTERVAL 60 -#define RAID_MINTICKS 1000 - -class Raid; -class RaidEvent; - -class Raids -{ - public: - Raids(); - ~Raids(); - - // non-copyable - Raids(const Raids&) = delete; - Raids& operator=(const Raids&) = delete; - - bool loadFromXml(); - bool startup(); - - void clear(); - bool reload(); - - bool isLoaded() const { - return loaded; - } - bool isStarted() const { - return started; - } - - Raid* getRunning() { - return running; - } - void setRunning(Raid* newRunning) { - running = newRunning; - } - - Raid* getRaidByName(const std::string& name); - - uint64_t getLastRaidEnd() const { - return lastRaidEnd; - } - void setLastRaidEnd(uint64_t newLastRaidEnd) { - lastRaidEnd = newLastRaidEnd; - } - - void checkRaids(); - - LuaScriptInterface& getScriptInterface() { - return scriptInterface; - } - - private: - LuaScriptInterface scriptInterface; - - std::list raidList; - Raid* running; - uint64_t lastRaidEnd; - uint32_t checkRaidsEvent; - bool loaded, started; -}; - -class Raid -{ - public: - Raid(std::string name, uint32_t interval, uint32_t marginTime, bool repeat) - : name(name), interval(interval), nextEvent(0), margin(marginTime), state(RAIDSTATE_IDLE), nextEventEvent(0), loaded(false), repeat(repeat) {} - ~Raid(); - - // non-copyable - Raid(const Raid&) = delete; - Raid& operator=(const Raid&) = delete; - - bool loadFromXml(const std::string& _filename); - - void startRaid(); - - void executeRaidEvent(RaidEvent* raidEvent); - void resetRaid(); - - RaidEvent* getNextRaidEvent(); - void setState(RaidState_t newState) { - state = newState; - } - std::string getName() const { - return name; - } - - bool isLoaded() const { - return loaded; - } - uint64_t getMargin() const { - return margin; - } - uint32_t getInterval() const { - return interval; - } - bool canBeRepeated() const { - return repeat; - } - - void stopEvents(); - - private: - std::vector raidEvents; - std::string name; - uint32_t interval; - uint32_t nextEvent; - uint64_t margin; - RaidState_t state; - uint32_t nextEventEvent; - bool loaded; - bool repeat; -}; - -class RaidEvent -{ - public: - virtual ~RaidEvent() = default; - - virtual bool configureRaidEvent(const pugi::xml_node& eventNode); - - virtual bool executeEvent() = 0; - uint32_t getDelay() const { - return delay; - } - void setDelay(uint32_t newDelay) { - delay = newDelay; - } - - static bool compareEvents(const RaidEvent* lhs, const RaidEvent* rhs) { - return lhs->getDelay() < rhs->getDelay(); - } - - private: - uint32_t delay; -}; - -class AnnounceEvent final : public RaidEvent -{ - public: - AnnounceEvent() : messageType(MESSAGE_EVENT_ADVANCE) {} - - bool configureRaidEvent(const pugi::xml_node& eventNode) final; - - bool executeEvent() final; - - private: - std::string message; - MessageClasses messageType; -}; - -class SingleSpawnEvent final : public RaidEvent -{ - public: - bool configureRaidEvent(const pugi::xml_node& eventNode) final; - - bool executeEvent() final; - - private: - std::string monsterName; - Position position; -}; - -class AreaSpawnEvent final : public RaidEvent -{ - public: - bool configureRaidEvent(const pugi::xml_node& eventNode) final; - - void addMonster(const std::string& monsterName, uint32_t minAmount, uint32_t maxAmount); - - bool executeEvent() final; - - private: - std::list spawnList; - Position fromPos, toPos; -}; - -class ScriptEvent final : public RaidEvent, public Event -{ - public: - explicit ScriptEvent(LuaScriptInterface* _interface); - explicit ScriptEvent(const ScriptEvent* copy); - - bool configureRaidEvent(const pugi::xml_node& eventNode) final; - bool configureEvent(const pugi::xml_node&) final { - return false; - } - - bool executeEvent() final; - - protected: - std::string getScriptEventName() const final; -}; - -#endif diff --git a/path_10_8/src/rsa.cpp b/path_10_8/src/rsa.cpp deleted file mode 100644 index 32d77e690..000000000 --- a/path_10_8/src/rsa.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "rsa.h" - -RSA::RSA() -{ - mpz_init(n); - mpz_init2(d, 1024); -} - -RSA::~RSA() -{ - mpz_clear(n); - mpz_clear(d); -} - -void RSA::setKey(const char* pString, const char* qString) -{ - mpz_t p, q, e; - mpz_init2(p, 1024); - mpz_init2(q, 1024); - mpz_init(e); - - mpz_set_str(p, pString, 10); - mpz_set_str(q, qString, 10); - - // e = 65537 - mpz_set_ui(e, 65537); - - // n = p * q - mpz_mul(n, p, q); - - mpz_t p_1, q_1, pq_1; - mpz_init2(p_1, 1024); - mpz_init2(q_1, 1024); - mpz_init2(pq_1, 1024); - - mpz_sub_ui(p_1, p, 1); - mpz_sub_ui(q_1, q, 1); - - // pq_1 = (p -1)(q - 1) - mpz_mul(pq_1, p_1, q_1); - - // d = e^-1 mod (p - 1)(q - 1) - mpz_invert(d, e, pq_1); - - mpz_clear(p_1); - mpz_clear(q_1); - mpz_clear(pq_1); - - mpz_clear(p); - mpz_clear(q); - mpz_clear(e); -} - -void RSA::decrypt(char* msg) const -{ - mpz_t c, m; - mpz_init2(c, 1024); - mpz_init2(m, 1024); - - mpz_import(c, 128, 1, 1, 0, 0, msg); - - // m = c^d mod n - mpz_powm(m, c, d, n); - - size_t count = (mpz_sizeinbase(m, 2) + 7) / 8; - memset(msg, 0, 128 - count); - mpz_export(msg + (128 - count), nullptr, 1, 1, 0, 0, m); - - mpz_clear(c); - mpz_clear(m); -} diff --git a/path_10_8/src/rsa.h b/path_10_8/src/rsa.h deleted file mode 100644 index c356a9d64..000000000 --- a/path_10_8/src/rsa.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_RSA_H_C4E277DA8E884B578DDBF0566F504E91 -#define FS_RSA_H_C4E277DA8E884B578DDBF0566F504E91 - -#include - -class RSA -{ - public: - RSA(); - ~RSA(); - - // non-copyable - RSA(const RSA&) = delete; - RSA& operator=(const RSA&) = delete; - - void setKey(const char* pString, const char* qString); - void decrypt(char* msg) const; - - private: - //use only GMP - mpz_t n, d; -}; - -#endif diff --git a/path_10_8/src/scheduler.cpp b/path_10_8/src/scheduler.cpp deleted file mode 100644 index 5a275b215..000000000 --- a/path_10_8/src/scheduler.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "scheduler.h" - -void Scheduler::threadMain() -{ - std::unique_lock eventLockUnique(eventLock, std::defer_lock); - while (getState() != THREAD_STATE_TERMINATED) { - std::cv_status ret = std::cv_status::no_timeout; - - eventLockUnique.lock(); - if (eventList.empty()) { - eventSignal.wait(eventLockUnique); - } else { - ret = eventSignal.wait_until(eventLockUnique, eventList.top()->getCycle()); - } - - // the mutex is locked again now... - if (ret == std::cv_status::timeout) { - // ok we had a timeout, so there has to be an event we have to execute... - SchedulerTask* task = eventList.top(); - eventList.pop(); - - // check if the event was stopped - auto it = eventIds.find(task->getEventId()); - if (it == eventIds.end()) { - eventLockUnique.unlock(); - delete task; - continue; - } - eventIds.erase(it); - eventLockUnique.unlock(); - - task->setDontExpire(); - g_dispatcher.addTask(task, true); - } else { - eventLockUnique.unlock(); - } - } -} - -uint32_t Scheduler::addEvent(SchedulerTask* task) -{ - bool do_signal = false; - eventLock.lock(); - - if (getState() == THREAD_STATE_RUNNING) { - // check if the event has a valid id - if (task->getEventId() == 0) { - // if not generate one - if (++lastEventId == 0) { - lastEventId = 1; - } - - task->setEventId(lastEventId); - } - - // insert the event id in the list of active events - eventIds.insert(task->getEventId()); - - // add the event to the queue - eventList.push(task); - - // if the list was empty or this event is the top in the list - // we have to signal it - do_signal = (task == eventList.top()); - } else { - eventLock.unlock(); - delete task; - return 0; - } - - eventLock.unlock(); - - if (do_signal) { - eventSignal.notify_one(); - } - - return task->getEventId(); -} - -bool Scheduler::stopEvent(uint32_t eventid) -{ - if (eventid == 0) { - return false; - } - - std::lock_guard lockGuard(eventLock); - - // search the event id.. - auto it = eventIds.find(eventid); - if (it == eventIds.end()) { - return false; - } - - eventIds.erase(it); - return true; -} - -void Scheduler::shutdown() -{ - setState(THREAD_STATE_TERMINATED); - eventLock.lock(); - - //this list should already be empty - while (!eventList.empty()) { - delete eventList.top(); - eventList.pop(); - } - - eventIds.clear(); - eventLock.unlock(); - eventSignal.notify_one(); -} - diff --git a/path_10_8/src/scheduler.h b/path_10_8/src/scheduler.h deleted file mode 100644 index 0a0f9a9f5..000000000 --- a/path_10_8/src/scheduler.h +++ /dev/null @@ -1,89 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_SCHEDULER_H_2905B3D5EAB34B4BA8830167262D2DC1 -#define FS_SCHEDULER_H_2905B3D5EAB34B4BA8830167262D2DC1 - -#include "tasks.h" -#include -#include - - -#include "thread_holder_base.h" - - -#define SCHEDULER_MINTICKS 50 - -class SchedulerTask : public Task -{ - public: - void setEventId(uint32_t id) { - eventId = id; - } - uint32_t getEventId() const { - return eventId; - } - - std::chrono::system_clock::time_point getCycle() const { - return expiration; - } - - protected: - SchedulerTask(uint32_t delay, const std::function& f) : Task(delay, f) { - eventId = 0; - } - - uint32_t eventId; - - friend SchedulerTask* createSchedulerTask(uint32_t, const std::function&); -}; - -inline SchedulerTask* createSchedulerTask(uint32_t delay, const std::function& f) -{ - return new SchedulerTask(delay, f); -} - -struct TaskComparator { - bool operator()(const SchedulerTask* lhs, const SchedulerTask* rhs) const { - return lhs->getCycle() > rhs->getCycle(); - } -}; - -class Scheduler : public ThreadHolder -{ - public: - uint32_t addEvent(SchedulerTask* task); - bool stopEvent(uint32_t eventId); - - void shutdown(); - - void threadMain(); - protected: - std::thread thread; - std::mutex eventLock; - std::condition_variable eventSignal; - - uint32_t lastEventId {0}; - std::priority_queue, TaskComparator> eventList; - std::unordered_set eventIds; -}; - -extern Scheduler g_scheduler; - -#endif diff --git a/path_10_8/src/scriptmanager.cpp b/path_10_8/src/scriptmanager.cpp deleted file mode 100644 index 0f44b04c1..000000000 --- a/path_10_8/src/scriptmanager.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "scriptmanager.h" - -#include "actions.h" -#include "chat.h" -#include "talkaction.h" -#include "spells.h" -#include "movement.h" -#include "weapons.h" -#include "globalevent.h" -#include "events.h" - -Actions* g_actions = nullptr; -CreatureEvents* g_creatureEvents = nullptr; -Chat* g_chat = nullptr; -Events* g_events = nullptr; -GlobalEvents* g_globalEvents = nullptr; -Spells* g_spells = nullptr; -TalkActions* g_talkActions = nullptr; -MoveEvents* g_moveEvents = nullptr; -Weapons* g_weapons = nullptr; - -extern LuaEnvironment g_luaEnvironment; - -ScriptingManager::ScriptingManager() -{ - // -} - -ScriptingManager::~ScriptingManager() -{ - delete g_events; - delete g_weapons; - delete g_spells; - delete g_actions; - delete g_talkActions; - delete g_moveEvents; - delete g_chat; - delete g_creatureEvents; - delete g_globalEvents; -} - -bool ScriptingManager::loadScriptSystems() -{ - if (g_luaEnvironment.loadFile("data/global.lua") == -1) { - std::cout << "[Warning - ScriptingManager::loadScriptSystems] Can not load data/global.lua" << std::endl; - } - - g_chat = new Chat(); - - g_weapons = new Weapons(); - if (!g_weapons->loadFromXml()) { - std::cout << "> ERROR: Unable to load weapons!" << std::endl; - return false; - } - - g_weapons->loadDefaults(); - - g_spells = new Spells(); - if (!g_spells->loadFromXml()) { - std::cout << "> ERROR: Unable to load spells!" << std::endl; - return false; - } - - g_actions = new Actions(); - if (!g_actions->loadFromXml()) { - std::cout << "> ERROR: Unable to load actions!" << std::endl; - return false; - } - - g_talkActions = new TalkActions(); - if (!g_talkActions->loadFromXml()) { - std::cout << "> ERROR: Unable to load talk actions!" << std::endl; - return false; - } - - g_moveEvents = new MoveEvents(); - if (!g_moveEvents->loadFromXml()) { - std::cout << "> ERROR: Unable to load move events!" << std::endl; - return false; - } - - g_creatureEvents = new CreatureEvents(); - if (!g_creatureEvents->loadFromXml()) { - std::cout << "> ERROR: Unable to load creature events!" << std::endl; - return false; - } - - g_globalEvents = new GlobalEvents(); - if (!g_globalEvents->loadFromXml()) { - std::cout << "> ERROR: Unable to load global events!" << std::endl; - return false; - } - - g_events = new Events(); - if (!g_events->load()) { - std::cout << "> ERROR: Unable to load events!" << std::endl; - return false; - } - - return true; -} diff --git a/path_10_8/src/scriptmanager.h b/path_10_8/src/scriptmanager.h deleted file mode 100644 index 5a3f26fb2..000000000 --- a/path_10_8/src/scriptmanager.h +++ /dev/null @@ -1,41 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_SCRIPTMANAGER_H_F9428B7803A44FB88EB1A915CFD37F8B -#define FS_SCRIPTMANAGER_H_F9428B7803A44FB88EB1A915CFD37F8B - -class ScriptingManager -{ - public: - ScriptingManager(); - ~ScriptingManager(); - - // non-copyable - ScriptingManager(const ScriptingManager&) = delete; - ScriptingManager& operator=(const ScriptingManager&) = delete; - - static ScriptingManager* getInstance() { - static ScriptingManager instance; - return &instance; - } - - bool loadScriptSystems(); -}; - -#endif diff --git a/path_10_8/src/server.cpp b/path_10_8/src/server.cpp deleted file mode 100644 index 3fb3f6126..000000000 --- a/path_10_8/src/server.cpp +++ /dev/null @@ -1,221 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "outputmessage.h" -#include "server.h" -#include "scheduler.h" -#include "configmanager.h" -#include "ban.h" - -extern ConfigManager g_config; -Ban g_bans; - -ServiceManager::ServiceManager(): - death_timer(io_service), - running(false) -{ - // -} - -ServiceManager::~ServiceManager() -{ - stop(); -} - -void ServiceManager::die() -{ - io_service.stop(); -} - -void ServiceManager::run() -{ - assert(!running); - running = true; - io_service.run(); -} - -void ServiceManager::stop() -{ - if (!running) { - return; - } - - running = false; - - for (auto& servicePortIt : acceptors) { - try { - io_service.post(std::bind(&ServicePort::onStopServer, servicePortIt.second)); - } catch (boost::system::system_error& e) { - std::cout << "[ServiceManager::stop] Network Error: " << e.what() << std::endl; - } - } - - acceptors.clear(); - - death_timer.expires_from_now(boost::posix_time::seconds(3)); - death_timer.async_wait(std::bind(&ServiceManager::die, this)); -} - -ServicePort::ServicePort(boost::asio::io_service& io_service) : - io_service(io_service), - serverPort(0), - pendingStart(false) -{ - // -} - -ServicePort::~ServicePort() -{ - close(); -} - -bool ServicePort::is_single_socket() const -{ - return !services.empty() && services.front()->is_single_socket(); -} - -std::string ServicePort::get_protocol_names() const -{ - if (services.empty()) { - return std::string(); - } - - std::string str = services.front()->get_protocol_name(); - for (size_t i = 1; i < services.size(); ++i) { - str.push_back(','); - str.push_back(' '); - str.append(services[i]->get_protocol_name()); - } - return str; -} - -void ServicePort::accept() -{ - if (!acceptor) { - return; - } - - auto connection = ConnectionManager::getInstance().createConnection(io_service, shared_from_this()); - acceptor->async_accept(connection->getSocket(), std::bind(&ServicePort::onAccept, shared_from_this(), connection, std::placeholders::_1)); -} - -void ServicePort::onAccept(Connection_ptr connection, const boost::system::error_code& error) -{ - if (!error) { - if (services.empty()) { - return; - } - - auto remote_ip = connection->getIP(); - if (remote_ip != 0 && g_bans.acceptConnection(remote_ip)) { - Service_ptr service = services.front(); - if (service->is_single_socket()) { - connection->accept(service->make_protocol(connection)); - } else { - connection->accept(); - } - } else { - connection->close(Connection::FORCE_CLOSE); - } - - accept(); - } else if (error != boost::asio::error::operation_aborted) { - if (!pendingStart) { - close(); - pendingStart = true; - g_scheduler.addEvent(createSchedulerTask(15000, - std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), serverPort))); - } - } -} - -Protocol_ptr ServicePort::make_protocol(bool checksummed, NetworkMessage& msg, const Connection_ptr& connection) const -{ - uint8_t protocolID = msg.getByte(); - for (auto& service : services) { - if (protocolID != service->get_protocol_identifier()) { - continue; - } - - if ((checksummed && service->is_checksummed()) || !service->is_checksummed()) { - return service->make_protocol(connection); - } - } - return nullptr; -} - -void ServicePort::onStopServer() -{ - close(); -} - -void ServicePort::openAcceptor(std::weak_ptr weak_service, uint16_t port) -{ - if (auto service = weak_service.lock()) { - service->open(port); - } -} - -void ServicePort::open(uint16_t port) -{ - close(); - - serverPort = port; - pendingStart = false; - - try { - if (g_config.getBoolean(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS)) { - acceptor.reset(new boost::asio::ip::tcp::acceptor(io_service, boost::asio::ip::tcp::endpoint( - boost::asio::ip::address(boost::asio::ip::address_v4::from_string(g_config.getString(ConfigManager::IP))), serverPort))); - } else { - acceptor.reset(new boost::asio::ip::tcp::acceptor(io_service, boost::asio::ip::tcp::endpoint( - boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), serverPort))); - } - - acceptor->set_option(boost::asio::ip::tcp::no_delay(true)); - - accept(); - } catch (boost::system::system_error& e) { - std::cout << "[ServicePort::open] Error: " << e.what() << std::endl; - - pendingStart = true; - g_scheduler.addEvent(createSchedulerTask(15000, - std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), port))); - } -} - -void ServicePort::close() -{ - if (acceptor && acceptor->is_open()) { - boost::system::error_code error; - acceptor->close(error); - } -} - -bool ServicePort::add_service(const Service_ptr& new_svc) -{ - if (std::any_of(services.begin(), services.end(), [](const Service_ptr& svc) {return svc->is_single_socket();})) { - return false; - } - - services.push_back(new_svc); - return true; -} diff --git a/path_10_8/src/server.h b/path_10_8/src/server.h deleted file mode 100644 index 26316b664..000000000 --- a/path_10_8/src/server.h +++ /dev/null @@ -1,156 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_SERVER_H_984DA68ABF744127850F90CC710F281B -#define FS_SERVER_H_984DA68ABF744127850F90CC710F281B - -#include "connection.h" -#include - -class Protocol; - -class ServiceBase -{ - public: - virtual bool is_single_socket() const = 0; - virtual bool is_checksummed() const = 0; - virtual uint8_t get_protocol_identifier() const = 0; - virtual const char* get_protocol_name() const = 0; - - virtual Protocol_ptr make_protocol(const Connection_ptr& c) const = 0; -}; - -template -class Service final : public ServiceBase -{ - public: - bool is_single_socket() const final { - return ProtocolType::server_sends_first; - } - bool is_checksummed() const final { - return ProtocolType::use_checksum; - } - uint8_t get_protocol_identifier() const final { - return ProtocolType::protocol_identifier; - } - const char* get_protocol_name() const final { - return ProtocolType::protocol_name(); - } - - Protocol_ptr make_protocol(const Connection_ptr& c) const final { - return std::make_shared(c); - } -}; - -class ServicePort : public std::enable_shared_from_this -{ - public: - explicit ServicePort(boost::asio::io_service& io_service); - ~ServicePort(); - - // non-copyable - ServicePort(const ServicePort&) = delete; - ServicePort& operator=(const ServicePort&) = delete; - - static void openAcceptor(std::weak_ptr weak_service, uint16_t port); - void open(uint16_t port); - void close(); - bool is_single_socket() const; - std::string get_protocol_names() const; - - bool add_service(const Service_ptr& new_svc); - Protocol_ptr make_protocol(bool checksummed, NetworkMessage& msg, const Connection_ptr& connection) const; - - void onStopServer(); - void onAccept(Connection_ptr connection, const boost::system::error_code& error); - - protected: - void accept(); - - boost::asio::io_service& io_service; - std::unique_ptr acceptor; - std::vector services; - - uint16_t serverPort; - bool pendingStart; -}; - -class ServiceManager -{ - public: - ServiceManager(); - ~ServiceManager(); - - // non-copyable - ServiceManager(const ServiceManager&) = delete; - ServiceManager& operator=(const ServiceManager&) = delete; - - void run(); - void stop(); - - bool okay(); - - template - bool add(uint16_t port); - - bool is_running() const { - return acceptors.empty() == false; - } - - protected: - void die(); - - std::unordered_map acceptors; - - boost::asio::io_service io_service; - boost::asio::deadline_timer death_timer; - bool running; -}; - -template -bool ServiceManager::add(uint16_t port) -{ - if (port == 0) { - std::cout << "ERROR: No port provided for service " << ProtocolType::protocol_name() << ". Service disabled." << std::endl; - return false; - } - - ServicePort_ptr service_port; - - auto foundServicePort = acceptors.find(port); - - if (foundServicePort == acceptors.end()) { - service_port = std::make_shared(io_service); - service_port->open(port); - acceptors[port] = service_port; - } else { - service_port = foundServicePort->second; - - if (service_port->is_single_socket() || ProtocolType::server_sends_first) { - std::cout << "ERROR: " << ProtocolType::protocol_name() << - " and " << service_port->get_protocol_names() << - " cannot use the same port " << port << '.' << std::endl; - return false; - } - } - - return service_port->add_service(std::make_shared>()); -} - -#endif diff --git a/path_10_8/src/spawn.cpp b/path_10_8/src/spawn.cpp deleted file mode 100644 index 56fab6664..000000000 --- a/path_10_8/src/spawn.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "spawn.h" -#include "game.h" -#include "monster.h" -#include "configmanager.h" -#include "scheduler.h" -#include "events.h" - -#include "pugicast.h" - -extern Events* g_events; -extern ConfigManager g_config; -extern Monsters g_monsters; -extern Game g_game; - -#define MINSPAWN_INTERVAL 1000 - -Spawns::Spawns() -{ - loaded = false; - started = false; -} - -bool Spawns::loadFromXml(const std::string& _filename) -{ - if (loaded) { - return true; - } - - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file(_filename.c_str()); - if (!result) { - printXMLError("Error - Spawns::loadFromXml", _filename, result); - return false; - } - - filename = _filename; - loaded = true; - - for (auto spawnNode : doc.child("spawns").children()) { - Position centerPos( - pugi::cast(spawnNode.attribute("centerx").value()), - pugi::cast(spawnNode.attribute("centery").value()), - pugi::cast(spawnNode.attribute("centerz").value()) - ); - - int32_t radius; - pugi::xml_attribute radiusAttribute = spawnNode.attribute("radius"); - if (radiusAttribute) { - radius = pugi::cast(radiusAttribute.value()); - } else { - radius = -1; - } - - spawnList.emplace_front(centerPos, radius); - Spawn& spawn = spawnList.front(); - - for (auto childNode : spawnNode.children()) { - if (strcasecmp(childNode.name(), "monster") == 0) { - pugi::xml_attribute nameAttribute = childNode.attribute("name"); - if (!nameAttribute) { - continue; - } - - Direction dir; - - pugi::xml_attribute directionAttribute = childNode.attribute("direction"); - if (directionAttribute) { - dir = static_cast(pugi::cast(directionAttribute.value())); - } else { - dir = DIRECTION_NORTH; - } - - Position pos( - centerPos.x + pugi::cast(childNode.attribute("x").value()), - centerPos.y + pugi::cast(childNode.attribute("y").value()), - centerPos.z - ); - uint32_t interval = pugi::cast(childNode.attribute("spawntime").value()) * 1000; - if (interval > MINSPAWN_INTERVAL) { - spawn.addMonster(nameAttribute.as_string(), pos, dir, interval); - } else { - std::cout << "[Warning - Spawns::loadFromXml] " << nameAttribute.as_string() << ' ' << pos << " spawntime can not be less than " << MINSPAWN_INTERVAL / 1000 << " seconds." << std::endl; - } - } else if (strcasecmp(childNode.name(), "npc") == 0) { - pugi::xml_attribute nameAttribute = childNode.attribute("name"); - if (!nameAttribute) { - continue; - } - - Npc* npc = Npc::createNpc(nameAttribute.as_string()); - if (!npc) { - continue; - } - - pugi::xml_attribute directionAttribute = childNode.attribute("direction"); - if (directionAttribute) { - npc->setDirection(static_cast(pugi::cast(directionAttribute.value()))); - } - - npc->setMasterPos(Position( - centerPos.x + pugi::cast(childNode.attribute("x").value()), - centerPos.y + pugi::cast(childNode.attribute("y").value()), - centerPos.z - ), radius); - npcList.push_front(npc); - } - } - } - return true; -} - -void Spawns::startup() -{ - if (!loaded || isStarted()) { - return; - } - - for (Npc* npc : npcList) { - g_game.placeCreature(npc, npc->getMasterPos(), false, true); - } - npcList.clear(); - - for (Spawn& spawn : spawnList) { - spawn.startup(); - } - - started = true; -} - -void Spawns::clear() -{ - for (Spawn& spawn : spawnList) { - spawn.stopEvent(); - } - spawnList.clear(); - - loaded = false; - started = false; - filename.clear(); -} - -bool Spawns::isInZone(const Position& centerPos, int32_t radius, const Position& pos) -{ - if (radius == -1) { - return true; - } - - return ((pos.getX() >= centerPos.getX() - radius) && (pos.getX() <= centerPos.getX() + radius) && - (pos.getY() >= centerPos.getY() - radius) && (pos.getY() <= centerPos.getY() + radius)); -} - -void Spawn::startSpawnCheck() -{ - if (checkSpawnEvent == 0) { - checkSpawnEvent = g_scheduler.addEvent(createSchedulerTask(getInterval(), std::bind(&Spawn::checkSpawn, this))); - } -} - -Spawn::~Spawn() -{ - for (const auto& it : spawnedMap) { - Monster* monster = it.second; - monster->setSpawn(nullptr); - monster->decrementReferenceCounter(); - } -} - -bool Spawn::findPlayer(const Position& pos) -{ - SpectatorVec list; - g_game.map.getSpectators(list, pos, false, true); - for (Creature* spectator : list) { - if (!spectator->getPlayer()->hasFlag(PlayerFlag_IgnoredByMonsters)) { - return true; - } - } - return false; -} - -bool Spawn::isInSpawnZone(const Position& pos) -{ - return Spawns::isInZone(centerPos, radius, pos); -} - -bool Spawn::spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup /*= false*/) -{ - std::unique_ptr monster_ptr(new Monster(mType)); - - if (!g_events->eventMonsterOnSpawn(monster_ptr.get(), pos, startup)) { - delete monster_ptr.get(); - return false; - } - - if (startup) { - //No need to send out events to the surrounding since there is no one out there to listen! - if (!g_game.internalPlaceCreature(monster_ptr.get(), pos, true)) { - return false; - } - } else { - if (!g_game.placeCreature(monster_ptr.get(), pos, false, true)) { - return false; - } - } - - Monster* monster = monster_ptr.release(); - monster->setDirection(dir); - monster->setSpawn(this); - monster->setMasterPos(pos); - monster->incrementReferenceCounter(); - - spawnedMap.insert(spawned_pair(spawnId, monster)); - spawnMap[spawnId].lastSpawn = OTSYS_TIME(); - return true; -} - -void Spawn::startup() -{ - for (const auto& it : spawnMap) { - uint32_t spawnId = it.first; - const spawnBlock_t& sb = it.second; - spawnMonster(spawnId, sb.mType, sb.pos, sb.direction, true); - } -} - -void Spawn::checkSpawn() -{ - checkSpawnEvent = 0; - - cleanup(); - - uint32_t spawnCount = 0; - - for (auto& it : spawnMap) { - uint32_t spawnId = it.first; - if (spawnedMap.find(spawnId) != spawnedMap.end()) { - continue; - } - - spawnBlock_t& sb = it.second; - if (OTSYS_TIME() >= sb.lastSpawn + sb.interval) { - if (findPlayer(sb.pos)) { - sb.lastSpawn = OTSYS_TIME(); - continue; - } - - spawnMonster(spawnId, sb.mType, sb.pos, sb.direction); - if (++spawnCount >= static_cast(g_config.getNumber(ConfigManager::RATE_SPAWN))) { - break; - } - } - } - - if (spawnedMap.size() < spawnMap.size()) { - checkSpawnEvent = g_scheduler.addEvent(createSchedulerTask(getInterval(), std::bind(&Spawn::checkSpawn, this))); - } -} - -void Spawn::cleanup() -{ - auto it = spawnedMap.begin(); - while (it != spawnedMap.end()) { - uint32_t spawnId = it->first; - Monster* monster = it->second; - if (monster->isRemoved()) { - if (spawnId != 0) { - spawnMap[spawnId].lastSpawn = OTSYS_TIME(); - } - - monster->decrementReferenceCounter(); - it = spawnedMap.erase(it); - } else if (!isInSpawnZone(monster->getPosition()) && spawnId != 0) { - spawnedMap.insert(spawned_pair(0, monster)); - it = spawnedMap.erase(it); - } else { - ++it; - } - } -} - -bool Spawn::addMonster(const std::string& _name, const Position& _pos, Direction _dir, uint32_t _interval) -{ - MonsterType* mType = g_monsters.getMonsterType(_name); - if (!mType) { - std::cout << "[Spawn::addMonster] Can not find " << _name << std::endl; - return false; - } - - if (_interval < interval) { - interval = _interval; - } - - spawnBlock_t sb; - sb.mType = mType; - sb.pos = _pos; - sb.direction = _dir; - sb.interval = _interval; - sb.lastSpawn = 0; - - uint32_t spawnId = spawnMap.size() + 1; - spawnMap[spawnId] = sb; - return true; -} - -void Spawn::removeMonster(Monster* monster) -{ - for (auto it = spawnedMap.begin(), end = spawnedMap.end(); it != end; ++it) { - if (it->second == monster) { - monster->decrementReferenceCounter(); - spawnedMap.erase(it); - break; - } - } -} - -void Spawn::stopEvent() -{ - if (checkSpawnEvent != 0) { - g_scheduler.stopEvent(checkSpawnEvent); - checkSpawnEvent = 0; - } -} diff --git a/path_10_8/src/spawn.h b/path_10_8/src/spawn.h deleted file mode 100644 index c04aa1187..000000000 --- a/path_10_8/src/spawn.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_SPAWN_H_1A86089E080846A9AE53ED12E7AE863B -#define FS_SPAWN_H_1A86089E080846A9AE53ED12E7AE863B - -#include "tile.h" -#include "position.h" - -class Monster; -class MonsterType; -class Npc; - -struct spawnBlock_t { - Position pos; - MonsterType* mType; - int64_t lastSpawn; - uint32_t interval; - Direction direction; -}; - -class Spawn -{ - public: - Spawn(const Position& pos, int32_t radius) : centerPos(pos), radius(radius), interval(60000), checkSpawnEvent() {} - ~Spawn(); - - // non-copyable - Spawn(const Spawn&) = delete; - Spawn& operator=(const Spawn&) = delete; - - bool addMonster(const std::string& _name, const Position& _pos, Direction _dir, uint32_t _interval); - void removeMonster(Monster* monster); - - uint32_t getInterval() const { - return interval; - } - void startup(); - - void startSpawnCheck(); - void stopEvent(); - - bool isInSpawnZone(const Position& pos); - void cleanup(); - - private: - //map of the spawned creatures - typedef std::multimap SpawnedMap; - typedef SpawnedMap::value_type spawned_pair; - SpawnedMap spawnedMap; - - //map of creatures in the spawn - std::map spawnMap; - - Position centerPos; - int32_t radius; - - uint32_t interval; - uint32_t checkSpawnEvent; - - static bool findPlayer(const Position& pos); - bool spawnMonster(uint32_t spawnId, MonsterType* mType, const Position& pos, Direction dir, bool startup = false); - void checkSpawn(); -}; - -class Spawns -{ - public: - Spawns(); - - static bool isInZone(const Position& centerPos, int32_t radius, const Position& pos); - - bool loadFromXml(const std::string& _filename); - void startup(); - void clear(); - - bool isStarted() const { - return started; - } - - private: - std::forward_list npcList; - std::forward_list spawnList; - std::string filename; - bool loaded, started; -}; - -#endif diff --git a/path_10_8/src/spells.cpp b/path_10_8/src/spells.cpp deleted file mode 100644 index f3944d89b..000000000 --- a/path_10_8/src/spells.cpp +++ /dev/null @@ -1,2042 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "combat.h" -#include "configmanager.h" -#include "game.h" -#include "monster.h" -#include "pugicast.h" -#include "spells.h" - -extern Game g_game; -extern Spells* g_spells; -extern Monsters g_monsters; -extern Vocations g_vocations; -extern ConfigManager g_config; -extern LuaEnvironment g_luaEnvironment; - -Spells::Spells(): - m_scriptInterface("Spell Interface") -{ - m_scriptInterface.initState(); -} - -Spells::~Spells() -{ - clear(); -} - -TalkActionResult_t Spells::playerSaySpell(Player* player, std::string& words) -{ - std::string str_words = words; - - //strip trailing spaces - trimString(str_words); - - InstantSpell* instantSpell = getInstantSpell(str_words); - if (!instantSpell) { - return TALKACTION_CONTINUE; - } - - std::string param; - - if (instantSpell->getHasParam()) { - size_t spellLen = instantSpell->getWords().length(); - size_t paramLen = str_words.length() - spellLen; - std::string paramText = str_words.substr(spellLen, paramLen); - if (!paramText.empty() && paramText.front() == ' ') { - size_t loc1 = paramText.find('"', 1); - if (loc1 != std::string::npos) { - size_t loc2 = paramText.find('"', loc1 + 1); - if (loc2 == std::string::npos) { - loc2 = paramText.length(); - } else if (paramText.find_last_not_of(' ') != loc2) { - return TALKACTION_CONTINUE; - } - - param = paramText.substr(loc1 + 1, loc2 - loc1 - 1); - } else { - trimString(paramText); - loc1 = paramText.find(' ', 0); - if (loc1 == std::string::npos) { - param = paramText; - } else { - return TALKACTION_CONTINUE; - } - } - } - } - - if (instantSpell->playerCastInstant(player, param)) { - words = instantSpell->getWords(); - - if (instantSpell->getHasParam() && !param.empty()) { - words += " \"" + param + "\""; - } - - return TALKACTION_BREAK; - } - - return TALKACTION_FAILED; -} - -void Spells::clear() -{ - for (const auto& it : runes) { - delete it.second; - } - runes.clear(); - - for (const auto& it : instants) { - delete it.second; - } - instants.clear(); - - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& Spells::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string Spells::getScriptBaseName() const -{ - return "spells"; -} - -Event* Spells::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "rune") == 0) { - return new RuneSpell(&m_scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "instant") == 0) { - return new InstantSpell(&m_scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "conjure") == 0) { - return new ConjureSpell(&m_scriptInterface); - } - return nullptr; -} - -bool Spells::registerEvent(Event* event, const pugi::xml_node&) -{ - InstantSpell* instant = dynamic_cast(event); - if (instant) { - auto result = instants.emplace(instant->getWords(), instant); - if (!result.second) { - std::cout << "[Warning - Spells::registerEvent] Duplicate registered instant spell with words: " << instant->getWords() << std::endl; - } - return result.second; - } - - RuneSpell* rune = dynamic_cast(event); - if (rune) { - auto result = runes.emplace(rune->getRuneItemId(), rune); - if (!result.second) { - std::cout << "[Warning - Spells::registerEvent] Duplicate registered rune with id: " << rune->getRuneItemId() << std::endl; - } - return result.second; - } - - return false; -} - -Spell* Spells::getSpellByName(const std::string& name) -{ - Spell* spell = getRuneSpellByName(name); - if (!spell) { - spell = getInstantSpellByName(name); - } - return spell; -} - -RuneSpell* Spells::getRuneSpell(uint32_t id) -{ - auto it = runes.find(id); - if (it == runes.end()) { - return nullptr; - } - return it->second; -} - -RuneSpell* Spells::getRuneSpellByName(const std::string& name) -{ - for (const auto& it : runes) { - if (strcasecmp(it.second->getName().c_str(), name.c_str()) == 0) { - return it.second; - } - } - return nullptr; -} - -InstantSpell* Spells::getInstantSpell(const std::string& words) -{ - InstantSpell* result = nullptr; - - for (const auto& it : instants) { - InstantSpell* instantSpell = it.second; - - const std::string& instantSpellWords = instantSpell->getWords(); - size_t spellLen = instantSpellWords.length(); - if (strncasecmp(instantSpellWords.c_str(), words.c_str(), spellLen) == 0) { - if (!result || spellLen > result->getWords().length()) { - result = instantSpell; - if (words.length() == spellLen) { - break; - } - } - } - } - - if (result) { - const std::string& resultWords = result->getWords(); - if (words.length() > resultWords.length()) { - if (!result->getHasParam()) { - return nullptr; - } - - size_t spellLen = resultWords.length(); - size_t paramLen = words.length() - spellLen; - if (paramLen < 2 || words[spellLen] != ' ') { - return nullptr; - } - } - return result; - } - return nullptr; -} - -uint32_t Spells::getInstantSpellCount(const Player* player) const -{ - uint32_t count = 0; - for (const auto& it : instants) { - InstantSpell* instantSpell = it.second; - if (instantSpell->canCast(player)) { - ++count; - } - } - return count; -} - -InstantSpell* Spells::getInstantSpellByIndex(const Player* player, uint32_t index) -{ - uint32_t count = 0; - for (const auto& it : instants) { - InstantSpell* instantSpell = it.second; - if (instantSpell->canCast(player)) { - if (count == index) { - return instantSpell; - } - ++count; - } - } - return nullptr; -} - -InstantSpell* Spells::getInstantSpellByName(const std::string& name) -{ - for (const auto& it : instants) { - if (strcasecmp(it.second->getName().c_str(), name.c_str()) == 0) { - return it.second; - } - } - return nullptr; -} - -Position Spells::getCasterPosition(Creature* creature, Direction dir) -{ - return getNextPosition(dir, creature->getPosition()); -} - -CombatSpell::CombatSpell(Combat* _combat, bool _needTarget, bool _needDirection) : - Event(&g_spells->getScriptInterface()) -{ - combat = _combat; - needTarget = _needTarget; - needDirection = _needDirection; -} - -CombatSpell::~CombatSpell() -{ - if (!m_scripted) { - delete combat; - } -} - -bool CombatSpell::loadScriptCombat() -{ - combat = g_luaEnvironment.getCombatObject(g_luaEnvironment.m_lastCombatId); - return combat != nullptr; -} - -bool CombatSpell::castSpell(Creature* creature) -{ - if (m_scripted) { - LuaVariant var; - var.type = VARIANT_POSITION; - - if (needDirection) { - var.pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - var.pos = creature->getPosition(); - } - - return executeCastSpell(creature, var); - } - - Position pos; - if (needDirection) { - pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - pos = creature->getPosition(); - } - - combat->doCombat(creature, pos); - return true; -} - -bool CombatSpell::castSpell(Creature* creature, Creature* target) -{ - if (m_scripted) { - LuaVariant var; - - if (combat->hasArea()) { - var.type = VARIANT_POSITION; - - if (needTarget) { - var.pos = target->getPosition(); - } else if (needDirection) { - var.pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - var.pos = creature->getPosition(); - } - } else { - var.type = VARIANT_NUMBER; - var.number = target->getID(); - } - return executeCastSpell(creature, var); - } - - if (combat->hasArea()) { - if (needTarget) { - combat->doCombat(creature, target->getPosition()); - } else { - return castSpell(creature); - } - } else { - combat->doCombat(creature, target); - } - return true; -} - -bool CombatSpell::executeCastSpell(Creature* creature, const LuaVariant& var) -{ - //onCastSpell(creature, var) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CombatSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return m_scriptInterface->callFunction(2); -} - -Spell::Spell() -{ - spellId = 0; - level = 0; - magLevel = 0; - mana = 0; - manaPercent = 0; - soul = 0; - range = -1; - fist = 0; - club = 0; - sword = 0; - axe = 0; - distance = 0; - shield = 0; - fish = 0; - cooldown = 1000; - needTarget = false; - needWeapon = false; - selfTarget = false; - blockingSolid = false; - blockingCreature = false; - premium = false; - enabled = true; - aggressive = true; - learnable = false; - group = SPELLGROUP_NONE; - groupCooldown = 1000; - secondaryGroup = SPELLGROUP_NONE; - secondaryGroupCooldown = 0; -} - -bool Spell::configureSpell(const pugi::xml_node& node) -{ - pugi::xml_attribute nameAttribute = node.attribute("name"); - if (!nameAttribute) { - std::cout << "[Error - Spell::configureSpell] Spell without name" << std::endl; - return false; - } - - name = nameAttribute.as_string(); - - static const char* reservedList[] = { - "melee", - "physical", - "poison", - "fire", - "energy", - "drown", - "lifedrain", - "manadrain", - "healing", - "speed", - "outfit", - "invisible", - "drunk", - "firefield", - "poisonfield", - "energyfield", - "firecondition", - "poisoncondition", - "energycondition", - "drowncondition", - "freezecondition", - "cursecondition", - "dazzlecondition" - }; - - //static size_t size = sizeof(reservedList) / sizeof(const char*); - //for (size_t i = 0; i < size; ++i) { - for (const char* reserved : reservedList) { - if (strcasecmp(reserved, name.c_str()) == 0) { - std::cout << "[Error - Spell::configureSpell] Spell is using a reserved name: " << reserved << std::endl; - return false; - } - } - - pugi::xml_attribute attr; - if ((attr = node.attribute("spellid"))) { - spellId = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("group"))) { - std::string tmpStr = asLowerCaseString(attr.as_string()); - if (tmpStr == "none" || tmpStr == "0") { - group = SPELLGROUP_NONE; - } else if (tmpStr == "attack" || tmpStr == "1") { - group = SPELLGROUP_ATTACK; - } else if (tmpStr == "healing" || tmpStr == "2") { - group = SPELLGROUP_HEALING; - } else if (tmpStr == "support" || tmpStr == "3") { - group = SPELLGROUP_SUPPORT; - } else if (tmpStr == "special" || tmpStr == "4") { - group = SPELLGROUP_SPECIAL; - } else { - std::cout << "[Warning - Spell::configureSpell] Unknown group: " << attr.as_string() << std::endl; - } - } - - if ((attr = node.attribute("groupcooldown"))) { - groupCooldown = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("secondarygroup"))) { - std::string tmpStr = asLowerCaseString(attr.as_string()); - if (tmpStr == "none" || tmpStr == "0") { - secondaryGroup = SPELLGROUP_NONE; - } else if (tmpStr == "attack" || tmpStr == "1") { - secondaryGroup = SPELLGROUP_ATTACK; - } else if (tmpStr == "healing" || tmpStr == "2") { - secondaryGroup = SPELLGROUP_HEALING; - } else if (tmpStr == "support" || tmpStr == "3") { - secondaryGroup = SPELLGROUP_SUPPORT; - } else if (tmpStr == "special" || tmpStr == "4") { - secondaryGroup = SPELLGROUP_SPECIAL; - } else { - std::cout << "[Warning - Spell::configureSpell] Unknown secondarygroup: " << attr.as_string() << std::endl; - } - } - - if ((attr = node.attribute("secondarygroupcooldown"))) { - secondaryGroupCooldown = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("lvl"))) { - level = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("maglv"))) { - magLevel = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("mana"))) { - mana = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("manapercent"))) { - manaPercent = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("soul"))) { - soul = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("range"))) { - range = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("fist"))) { - fist = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("club"))) { - club = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("sword"))) { - sword = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("axe"))) { - axe = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("dist")) || (attr = node.attribute("distance"))) { - distance = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("shield"))) { - shield = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("fish"))) { - fish = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("exhaustion")) || (attr = node.attribute("cooldown"))) { - cooldown = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("prem"))) { - premium = attr.as_bool(); - } - - if ((attr = node.attribute("enabled"))) { - enabled = attr.as_bool(); - } - - if ((attr = node.attribute("needtarget"))) { - needTarget = attr.as_bool(); - } - - if ((attr = node.attribute("needweapon"))) { - needWeapon = attr.as_bool(); - } - - if ((attr = node.attribute("selftarget"))) { - selfTarget = attr.as_bool(); - } - - if ((attr = node.attribute("needlearn"))) { - learnable = attr.as_bool(); - } - - if ((attr = node.attribute("blocking"))) { - blockingSolid = attr.as_bool(); - blockingCreature = blockingSolid; - } - - if ((attr = node.attribute("blocktype"))) { - std::string tmpStrValue = asLowerCaseString(attr.as_string()); - if (tmpStrValue == "all") { - blockingSolid = true; - blockingCreature = true; - } else if (tmpStrValue == "solid") { - blockingSolid = true; - } else if (tmpStrValue == "creature") { - blockingCreature = true; - } else { - std::cout << "[Warning - Spell::configureSpell] Blocktype \"" << attr.as_string() << "\" does not exist." << std::endl; - } - } - - if ((attr = node.attribute("aggressive"))) { - aggressive = booleanString(attr.as_string()); - } - - if (group == SPELLGROUP_NONE) { - group = (aggressive ? SPELLGROUP_ATTACK : SPELLGROUP_HEALING); - } - - for (auto vocationNode : node.children()) { - if (!(attr = vocationNode.attribute("name"))) { - continue; - } - - int32_t vocationId = g_vocations.getVocationId(attr.as_string()); - if (vocationId != -1) { - attr = vocationNode.attribute("showInDescription"); - vocSpellMap[vocationId] = !attr || attr.as_bool(); - } else { - std::cout << "[Warning - Spell::configureSpell] Wrong vocation name: " << attr.as_string() << std::endl; - } - } - return true; -} - -bool Spell::playerSpellCheck(Player* player) const -{ - if (player->hasFlag(PlayerFlag_CannotUseSpells)) { - return false; - } - - if (player->hasFlag(PlayerFlag_IgnoreSpellCheck)) { - return true; - } - - if (!enabled) { - return false; - } - - if (aggressive && !player->hasFlag(PlayerFlag_IgnoreProtectionZone) && player->getZone() == ZONE_PROTECTION) { - player->sendCancelMessage(RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE); - return false; - } - - if (player->hasCondition(CONDITION_SPELLGROUPCOOLDOWN, group) || player->hasCondition(CONDITION_SPELLCOOLDOWN, spellId) || (secondaryGroup != SPELLGROUP_NONE && player->hasCondition(CONDITION_SPELLGROUPCOOLDOWN, secondaryGroup))) { - player->sendCancelMessage(RETURNVALUE_YOUAREEXHAUSTED); - - if (isInstant()) { - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - } - - return false; - } - - if (player->getLevel() < level) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getMagicLevel() < magLevel) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHMAGICLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getMana() < getManaCost(player) && !player->hasFlag(PlayerFlag_HasInfiniteMana)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHMANA); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSoul() < soul && !player->hasFlag(PlayerFlag_HasInfiniteSoul)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHSOUL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_FIST) < fist) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHFISTLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_CLUB) < club) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHCLUBLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_SWORD) < sword) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHSWORDLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_AXE) < axe) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHAXELEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_DISTANCE) < distance) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHDISTANCELEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_SHIELD) < shield) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHSHIELDLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSkillLevel(SKILL_FISHING) < fish) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHFISHLEVEL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (isInstant() && isLearnable()) { - if (!player->hasLearnedInstantSpell(getName())) { - player->sendCancelMessage(RETURNVALUE_YOUNEEDTOLEARNTHISSPELL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - } else if (!vocSpellMap.empty() && vocSpellMap.find(player->getVocationId()) == vocSpellMap.end()) { - player->sendCancelMessage(RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (needWeapon) { - switch (player->getWeaponType()) { - case WEAPON_SWORD: - case WEAPON_CLUB: - case WEAPON_AXE: - break; - - default: { - player->sendCancelMessage(RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - } - } - - if (isPremium() && !player->isPremium()) { - player->sendCancelMessage(RETURNVALUE_YOUNEEDPREMIUMACCOUNT); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - return true; -} - -bool Spell::playerInstantSpellCheck(Player* player, const Position& toPos) -{ - if (toPos.x == 0xFFFF) { - return true; - } - - const Position& playerPos = player->getPosition(); - if (playerPos.z > toPos.z) { - player->sendCancelMessage(RETURNVALUE_FIRSTGOUPSTAIRS); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } else if (playerPos.z < toPos.z) { - player->sendCancelMessage(RETURNVALUE_FIRSTGODOWNSTAIRS); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Tile* tile = g_game.map.getTile(toPos); - if (!tile) { - tile = new StaticTile(toPos.x, toPos.y, toPos.z); - g_game.map.setTile(toPos, tile); - } - - ReturnValue ret = Combat::canDoCombat(player, tile, aggressive); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (blockingCreature && tile->getBottomVisibleCreature(player) != nullptr) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (blockingSolid && tile->hasProperty(CONST_PROP_BLOCKSOLID)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - return true; -} - -bool Spell::playerRuneSpellCheck(Player* player, const Position& toPos) -{ - if (!playerSpellCheck(player)) { - return false; - } - - if (toPos.x == 0xFFFF) { - return true; - } - - const Position& playerPos = player->getPosition(); - if (playerPos.z > toPos.z) { - player->sendCancelMessage(RETURNVALUE_FIRSTGOUPSTAIRS); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } else if (playerPos.z < toPos.z) { - player->sendCancelMessage(RETURNVALUE_FIRSTGODOWNSTAIRS); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Tile* tile = g_game.map.getTile(toPos); - if (!tile) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (range != -1 && !g_game.canThrowObjectTo(playerPos, toPos, true, range, range)) { - player->sendCancelMessage(RETURNVALUE_DESTINATIONOUTOFREACH); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - ReturnValue ret = Combat::canDoCombat(player, tile, aggressive); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - const Creature* topVisibleCreature = tile->getBottomVisibleCreature(player); - if (blockingCreature && topVisibleCreature) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } else if (blockingSolid && tile->hasProperty(CONST_PROP_BLOCKSOLID)) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (needTarget && !topVisibleCreature) { - player->sendCancelMessage(RETURNVALUE_CANONLYUSETHISRUNEONCREATURES); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (aggressive && needTarget && topVisibleCreature && player->hasSecureMode()) { - const Player* targetPlayer = topVisibleCreature->getPlayer(); - if (targetPlayer && targetPlayer != player && player->getSkullClient(targetPlayer) == SKULL_NONE && !Combat::isInPvpZone(player, targetPlayer)) { - player->sendCancelMessage(RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - } - return true; -} - -void Spell::postCastSpell(Player* player, bool finishedCast /*= true*/, bool payCost /*= true*/) const -{ - if (finishedCast) { - if (!player->hasFlag(PlayerFlag_HasNoExhaustion)) { - if (cooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, cooldown, 0, false, spellId); - player->addCondition(condition); - } - - if (groupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, groupCooldown, 0, false, group); - player->addCondition(condition); - } - - if (secondaryGroupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, secondaryGroupCooldown, 0, false, secondaryGroup); - player->addCondition(condition); - } - } - - if (aggressive) { - player->addInFightTicks(); - } - } - - if (payCost) { - Spell::postCastSpell(player, getManaCost(player), getSoulCost()); - } -} - -void Spell::postCastSpell(Player* player, uint32_t manaCost, uint32_t soulCost) -{ - if (manaCost > 0) { - player->addManaSpent(manaCost); - player->changeMana(-static_cast(manaCost)); - } - - if (!player->hasFlag(PlayerFlag_HasInfiniteSoul)) { - if (soulCost > 0) { - player->changeSoul(-static_cast(soulCost)); - } - } -} - -uint32_t Spell::getManaCost(const Player* player) const -{ - if (mana != 0) { - return mana; - } - - if (manaPercent != 0) { - uint32_t maxMana = player->getMaxMana(); - uint32_t manaCost = (maxMana * manaPercent) / 100; - return manaCost; - } - - return 0; -} - -ReturnValue Spell::CreateIllusion(Creature* creature, const Outfit_t& outfit, int32_t time) -{ - ConditionOutfit* outfitCondition = new ConditionOutfit(CONDITIONID_COMBAT, CONDITION_OUTFIT, time); - outfitCondition->setOutfit(outfit); - creature->addCondition(outfitCondition); - return RETURNVALUE_NOERROR; -} - -ReturnValue Spell::CreateIllusion(Creature* creature, const std::string& name, int32_t time) -{ - const auto mType = g_monsters.getMonsterType(name); - if (mType == nullptr) { - return RETURNVALUE_CREATUREDOESNOTEXIST; - } - - Player* player = creature->getPlayer(); - if (player && !player->hasFlag(PlayerFlag_CanIllusionAll)) { - if (!mType->isIllusionable) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - - return CreateIllusion(creature, mType->outfit, time); -} - -ReturnValue Spell::CreateIllusion(Creature* creature, uint32_t itemId, int32_t time) -{ - const ItemType& it = Item::items[itemId]; - if (it.id == 0) { - return RETURNVALUE_NOTPOSSIBLE; - } - - Outfit_t outfit; - outfit.lookTypeEx = itemId; - - return CreateIllusion(creature, outfit, time); -} - -InstantSpell::InstantSpell(LuaScriptInterface* _interface) : - TalkAction(_interface) -{ - needDirection = false; - hasParam = false; - hasPlayerNameParam = false; - checkLineOfSight = true; - casterTargetOrDirection = false; - function = nullptr; -} - -std::string InstantSpell::getScriptEventName() const -{ - return "onCastSpell"; -} - -bool InstantSpell::configureEvent(const pugi::xml_node& node) -{ - if (!Spell::configureSpell(node)) { - return false; - } - - if (!TalkAction::configureEvent(node)) { - return false; - } - - pugi::xml_attribute attr; - if ((attr = node.attribute("params"))) { - hasParam = attr.as_bool(); - } - - if ((attr = node.attribute("playernameparam"))) { - hasPlayerNameParam = attr.as_bool(); - } - - if ((attr = node.attribute("direction"))) { - needDirection = attr.as_bool(); - } else if ((attr = node.attribute("casterTargetOrDirection"))) { - casterTargetOrDirection = attr.as_bool(); - } - - if ((attr = node.attribute("blockwalls"))) { - checkLineOfSight = attr.as_bool(); - } - return true; -} - -bool InstantSpell::loadFunction(const pugi::xml_attribute& attr) -{ - const char* functionName = attr.as_string(); - if (strcasecmp(functionName, "edithouseguest") == 0) { - function = HouseGuestList; - } else if (strcasecmp(functionName, "edithousesubowner") == 0) { - function = HouseSubOwnerList; - } else if (strcasecmp(functionName, "edithousedoor") == 0) { - function = HouseDoorList; - } else if (strcasecmp(functionName, "housekick") == 0) { - function = HouseKick; - } else if (strcasecmp(functionName, "searchplayer") == 0) { - function = SearchPlayer; - } else if (strcasecmp(functionName, "levitate") == 0) { - function = Levitate; - } else if (strcasecmp(functionName, "illusion") == 0) { - function = Illusion; - } else if (strcasecmp(functionName, "summonmonster") == 0) { - function = SummonMonster; - } else { - std::cout << "[Warning - InstantSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - m_scripted = false; - return true; -} - -bool InstantSpell::playerCastInstant(Player* player, std::string& param) -{ - if (!playerSpellCheck(player)) { - return false; - } - - LuaVariant var; - - if (selfTarget) { - var.type = VARIANT_NUMBER; - var.number = player->getID(); - } else if (needTarget || casterTargetOrDirection) { - Creature* target = nullptr; - bool useDirection = false; - - if (hasParam) { - Player* playerTarget = nullptr; - ReturnValue ret = g_game.getPlayerByNameWildcard(param, playerTarget); - - if (playerTarget && playerTarget->isAccessPlayer() && !player->isAccessPlayer()) { - playerTarget = nullptr; - } - - target = playerTarget; - if (!target || target->getHealth() <= 0) { - if (!casterTargetOrDirection) { - if (cooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, cooldown, 0, false, spellId); - player->addCondition(condition); - } - - if (groupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, groupCooldown, 0, false, group); - player->addCondition(condition); - } - - if (secondaryGroupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, secondaryGroupCooldown, 0, false, secondaryGroup); - player->addCondition(condition); - } - - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - useDirection = true; - } - - if (playerTarget) { - param = playerTarget->getName(); - } - } else { - target = player->getAttackedCreature(); - if (!target || target->getHealth() <= 0) { - if (!casterTargetOrDirection) { - player->sendCancelMessage(RETURNVALUE_YOUCANONLYUSEITONCREATURES); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - useDirection = true; - } - } - - if (!useDirection) { - if (!canThrowSpell(player, target)) { - player->sendCancelMessage(RETURNVALUE_CREATUREISNOTREACHABLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - var.type = VARIANT_NUMBER; - var.number = target->getID(); - } else { - var.type = VARIANT_POSITION; - var.pos = Spells::getCasterPosition(player, player->getDirection()); - - if (!playerInstantSpellCheck(player, var.pos)) { - return false; - } - } - } else if (hasParam) { - var.type = VARIANT_STRING; - - if (getHasPlayerNameParam()) { - Player* playerTarget = nullptr; - ReturnValue ret = g_game.getPlayerByNameWildcard(param, playerTarget); - - if (ret != RETURNVALUE_NOERROR) { - if (cooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLCOOLDOWN, cooldown, 0, false, spellId); - player->addCondition(condition); - } - - if (groupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, groupCooldown, 0, false, group); - player->addCondition(condition); - } - - if (secondaryGroupCooldown > 0) { - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_SPELLGROUPCOOLDOWN, secondaryGroupCooldown, 0, false, secondaryGroup); - player->addCondition(condition); - } - - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (playerTarget && (!playerTarget->isAccessPlayer() || player->isAccessPlayer())) { - param = playerTarget->getName(); - } - } - - var.text = param; - } else { - var.type = VARIANT_POSITION; - - if (needDirection) { - var.pos = Spells::getCasterPosition(player, player->getDirection()); - } else { - var.pos = player->getPosition(); - } - - if (!playerInstantSpellCheck(player, var.pos)) { - return false; - } - } - - bool result = internalCastSpell(player, var); - if (result) { - postCastSpell(player); - } - - return result; -} - -bool InstantSpell::canThrowSpell(const Creature* creature, const Creature* target) const -{ - const Position& fromPos = creature->getPosition(); - const Position& toPos = target->getPosition(); - if (fromPos.z != toPos.z || - (range == -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight)) || - (range != -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight, range, range))) { - return false; - } - return true; -} - -bool InstantSpell::castSpell(Creature* creature) -{ - LuaVariant var; - - if (casterTargetOrDirection) { - Creature* target = creature->getAttackedCreature(); - if (target && target->getHealth() > 0) { - if (!canThrowSpell(creature, target)) { - return false; - } - - var.type = VARIANT_NUMBER; - var.number = target->getID(); - return internalCastSpell(creature, var); - } - - return false; - } else if (needDirection) { - var.type = VARIANT_POSITION; - var.pos = Spells::getCasterPosition(creature, creature->getDirection()); - } else { - var.type = VARIANT_POSITION; - var.pos = creature->getPosition(); - } - - return internalCastSpell(creature, var); -} - -bool InstantSpell::castSpell(Creature* creature, Creature* target) -{ - if (needTarget) { - LuaVariant var; - var.type = VARIANT_NUMBER; - var.number = target->getID(); - return internalCastSpell(creature, var); - } else { - return castSpell(creature); - } -} - -bool InstantSpell::internalCastSpell(Creature* creature, const LuaVariant& var) -{ - if (m_scripted) { - return executeCastSpell(creature, var); - } else if (function) { - return function(this, creature, var.text); - } - - return false; -} - -bool InstantSpell::executeCastSpell(Creature* creature, const LuaVariant& var) -{ - //onCastSpell(creature, var) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - InstantSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return m_scriptInterface->callFunction(2); -} - -House* InstantSpell::getHouseFromPos(Creature* creature) -{ - if (!creature) { - return nullptr; - } - - Player* player = creature->getPlayer(); - if (!player) { - return nullptr; - } - - HouseTile* houseTile = dynamic_cast(player->getTile()); - if (!houseTile) { - return nullptr; - } - - House* house = houseTile->getHouse(); - if (!house) { - return nullptr; - } - - return house; -} - -bool InstantSpell::HouseGuestList(const InstantSpell*, Creature* creature, const std::string&) -{ - House* house = getHouseFromPos(creature); - if (!house) { - return false; - } - - Player* player = creature->getPlayer(); - if (house->canEditAccessList(GUEST_LIST, player)) { - player->setEditHouse(house, GUEST_LIST); - player->sendHouseWindow(house, GUEST_LIST); - } else { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - } - return true; -} - -bool InstantSpell::HouseSubOwnerList(const InstantSpell*, Creature* creature, const std::string&) -{ - House* house = getHouseFromPos(creature); - if (!house) { - return false; - } - - Player* player = creature->getPlayer(); - if (house->canEditAccessList(SUBOWNER_LIST, player)) { - player->setEditHouse(house, SUBOWNER_LIST); - player->sendHouseWindow(house, SUBOWNER_LIST); - } else { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - } - return true; -} - -bool InstantSpell::HouseDoorList(const InstantSpell*, Creature* creature, const std::string&) -{ - House* house = getHouseFromPos(creature); - if (!house) { - return false; - } - - Player* player = creature->getPlayer(); - Position pos = Spells::getCasterPosition(player, player->getDirection()); - Door* door = house->getDoorByPosition(pos); - if (door && house->canEditAccessList(door->getDoorId(), player)) { - player->setEditHouse(house, door->getDoorId()); - player->sendHouseWindow(house, door->getDoorId()); - } else { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - } - return true; -} - -bool InstantSpell::HouseKick(const InstantSpell*, Creature* creature, const std::string& param) -{ - Player* player = creature->getPlayer(); - - Player* targetPlayer = g_game.getPlayerByName(param); - if (!targetPlayer) { - targetPlayer = player; - } - - House* house = getHouseFromPos(targetPlayer); - if (!house) { - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return false; - } - - if (!house->kickPlayer(player, targetPlayer)) { - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - return false; - } - return true; -} - -bool InstantSpell::SearchPlayer(const InstantSpell*, Creature* creature, const std::string& param) -{ - //a. From 1 to 4 sq's [Person] is standing next to you. - //b. From 5 to 100 sq's [Person] is to the south, north, east, west. - //c. From 101 to 274 sq's [Person] is far to the south, north, east, west. - //d. From 275 to infinite sq's [Person] is very far to the south, north, east, west. - //e. South-west, s-e, n-w, n-e (corner coordinates): this phrase appears if the player you're looking for has moved five squares in any direction from the south, north, east or west. - //f. Lower level to the (direction): this phrase applies if the person you're looking for is from 1-25 squares up/down the actual floor you're in. - //g. Higher level to the (direction): this phrase applies if the person you're looking for is from 1-25 squares up/down the actual floor you're in. - - Player* player = creature->getPlayer(); - if (!player) { - return false; - } - - enum distance_t { - DISTANCE_BESIDE, - DISTANCE_CLOSE, - DISTANCE_FAR, - DISTANCE_VERYFAR, - }; - - enum direction_t { - DIR_N, DIR_S, DIR_E, DIR_W, - DIR_NE, DIR_NW, DIR_SE, DIR_SW, - }; - - enum level_t { - LEVEL_HIGHER, - LEVEL_LOWER, - LEVEL_SAME, - }; - - Player* playerExiva = g_game.getPlayerByName(param); - if (!playerExiva) { - return false; - } - - if (playerExiva->isAccessPlayer() && !player->isAccessPlayer()) { - player->sendCancelMessage(RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - const Position& lookPos = player->getPosition(); - const Position& searchPos = playerExiva->getPosition(); - - int32_t dx = Position::getOffsetX(lookPos, searchPos); - int32_t dy = Position::getOffsetY(lookPos, searchPos); - int32_t dz = Position::getOffsetZ(lookPos, searchPos); - - distance_t distance; - - direction_t direction; - - level_t level; - - //getting floor - if (dz > 0) { - level = LEVEL_HIGHER; - } else if (dz < 0) { - level = LEVEL_LOWER; - } else { - level = LEVEL_SAME; - } - - //getting distance - if (std::abs(dx) < 4 && std::abs(dy) < 4) { - distance = DISTANCE_BESIDE; - } else { - int32_t distance2 = dx * dx + dy * dy; - if (distance2 < 10000) { - distance = DISTANCE_CLOSE; - } else if (distance2 < 75076) { - distance = DISTANCE_FAR; - } else { - distance = DISTANCE_VERYFAR; - } - } - - //getting direction - float tan; - if (dx != 0) { - tan = static_cast(dy) / dx; - } else { - tan = 10.; - } - - if (std::abs(tan) < 0.4142) { - if (dx > 0) { - direction = DIR_W; - } else { - direction = DIR_E; - } - } else if (std::abs(tan) < 2.4142) { - if (tan > 0) { - if (dy > 0) { - direction = DIR_NW; - } else { - direction = DIR_SE; - } - } else { - if (dx > 0) { - direction = DIR_SW; - } else { - direction = DIR_NE; - } - } - } else { - if (dy > 0) { - direction = DIR_N; - } else { - direction = DIR_S; - } - } - - std::ostringstream ss; - ss << playerExiva->getName(); - - if (distance == DISTANCE_BESIDE) { - if (level == LEVEL_SAME) { - ss << " is standing next to you."; - } else if (level == LEVEL_HIGHER) { - ss << " is above you."; - } else if (level == LEVEL_LOWER) { - ss << " is below you."; - } - } else { - switch (distance) { - case DISTANCE_CLOSE: - if (level == LEVEL_SAME) { - ss << " is to the "; - } else if (level == LEVEL_HIGHER) { - ss << " is on a higher level to the "; - } else if (level == LEVEL_LOWER) { - ss << " is on a lower level to the "; - } - break; - case DISTANCE_FAR: - ss << " is far to the "; - break; - case DISTANCE_VERYFAR: - ss << " is very far to the "; - break; - default: - break; - } - - switch (direction) { - case DIR_N: - ss << "north."; - break; - case DIR_S: - ss << "south."; - break; - case DIR_E: - ss << "east."; - break; - case DIR_W: - ss << "west."; - break; - case DIR_NE: - ss << "north-east."; - break; - case DIR_NW: - ss << "north-west."; - break; - case DIR_SE: - ss << "south-east."; - break; - case DIR_SW: - ss << "south-west."; - break; - } - } - player->sendTextMessage(MESSAGE_INFO_DESCR, ss.str()); - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_BLUE); - return true; -} - -bool InstantSpell::SummonMonster(const InstantSpell* spell, Creature* creature, const std::string& param) -{ - Player* player = creature->getPlayer(); - if (!player) { - return false; - } - - MonsterType* mType = g_monsters.getMonsterType(param); - if (!mType) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (!player->hasFlag(PlayerFlag_CanSummonAll)) { - if (!mType->isSummonable) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getMana() < mType->manaCost) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHMANA); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (player->getSummonCount() >= 2) { - player->sendCancelMessage("You cannot summon more creatures."); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - } - - Monster* monster = Monster::createMonster(param); - if (!monster) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - // Place the monster - creature->addSummon(monster); - - if (!g_game.placeCreature(monster, creature->getPosition(), true)) { - creature->removeSummon(monster); - player->sendCancelMessage(RETURNVALUE_NOTENOUGHROOM); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Spell::postCastSpell(player, mType->manaCost, spell->getSoulCost()); - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_BLUE); - g_game.addMagicEffect(monster->getPosition(), CONST_ME_TELEPORT); - return true; -} - -bool InstantSpell::Levitate(const InstantSpell*, Creature* creature, const std::string& param) -{ - Player* player = creature->getPlayer(); - if (!player) { - return false; - } - - const Position& currentPos = creature->getPosition(); - const Position& destPos = Spells::getCasterPosition(creature, creature->getDirection()); - - ReturnValue ret = RETURNVALUE_NOTPOSSIBLE; - - if (strcasecmp(param.c_str(), "up") == 0) { - if (currentPos.z != 8) { - Tile* tmpTile = g_game.map.getTile(currentPos.x, currentPos.y, currentPos.getZ() - 1); - if (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && !tmpTile->floorChange()) { - ret = g_game.internalMoveCreature(*player, *tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE); - } - } - } - } else if (strcasecmp(param.c_str(), "down") == 0) { - if (currentPos.z != 7) { - Tile* tmpTile = g_game.map.getTile(destPos); - if (tmpTile == nullptr || (tmpTile->getGround() == nullptr && !tmpTile->hasProperty(CONST_PROP_BLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.z + 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && !tmpTile->floorChange()) { - ret = g_game.internalMoveCreature(*player, *tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE); - } - } - } - } - - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - g_game.addMagicEffect(player->getPosition(), CONST_ME_TELEPORT); - return true; -} - -bool InstantSpell::Illusion(const InstantSpell*, Creature* creature, const std::string& param) -{ - Player* player = creature->getPlayer(); - if (!player) { - return false; - } - - ReturnValue ret = CreateIllusion(creature, param, 180000); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_RED); - return true; -} - -bool InstantSpell::canCast(const Player* player) const -{ - if (player->hasFlag(PlayerFlag_CannotUseSpells)) { - return false; - } - - if (player->hasFlag(PlayerFlag_IgnoreSpellCheck)) { - return true; - } - - if (isLearnable()) { - if (player->hasLearnedInstantSpell(getName())) { - return true; - } - } else { - if (vocSpellMap.empty() || vocSpellMap.find(player->getVocationId()) != vocSpellMap.end()) { - return true; - } - } - - return false; -} - - -ConjureSpell::ConjureSpell(LuaScriptInterface* _interface) : - InstantSpell(_interface) -{ - aggressive = false; - conjureId = 0; - conjureCount = 1; - reagentId = 0; -} - -std::string ConjureSpell::getScriptEventName() const -{ - return "onCastSpell"; -} - -bool ConjureSpell::configureEvent(const pugi::xml_node& node) -{ - if (!InstantSpell::configureEvent(node)) { - return false; - } - - pugi::xml_attribute attr; - if ((attr = node.attribute("conjureId"))) { - conjureId = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("conjureCount"))) { - conjureCount = pugi::cast(attr.value()); - } else if (conjureId != 0) { - // load default charges from items.xml - const ItemType& it = Item::items[conjureId]; - if (it.charges != 0) { - conjureCount = it.charges; - } - } - - if ((attr = node.attribute("reagentId"))) { - reagentId = pugi::cast(attr.value()); - } - - return true; -} - -bool ConjureSpell::loadFunction(const pugi::xml_attribute&) -{ - m_scripted = false; - return true; -} - -bool ConjureSpell::conjureItem(Creature* creature) const -{ - Player* player = creature->getPlayer(); - if (!player) { - return false; - } - - if (reagentId != 0 && !player->removeItemOfType(reagentId, 1, -1)) { - player->sendCancelMessage(RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Item* newItem = Item::CreateItem(conjureId, conjureCount); - if (!newItem) { - return false; - } - - ReturnValue ret = g_game.internalPlayerAddItem(player, newItem); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - delete newItem; - return false; - } - - g_game.startDecay(newItem); - - postCastSpell(player); - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_RED); - return true; -} - -bool ConjureSpell::playerCastInstant(Player* player, std::string& param) -{ - if (!playerSpellCheck(player)) { - return false; - } - - if (m_scripted) { - LuaVariant var; - var.type = VARIANT_STRING; - var.text = param; - return executeCastSpell(player, var); - } - return conjureItem(player); -} - -RuneSpell::RuneSpell(LuaScriptInterface* _interface) : - Action(_interface) -{ - hasCharges = true; - runeId = 0; - runeFunction = nullptr; - - allowFarUse = true; -} - -std::string RuneSpell::getScriptEventName() const -{ - return "onCastSpell"; -} - -bool RuneSpell::configureEvent(const pugi::xml_node& node) -{ - if (!Spell::configureSpell(node)) { - return false; - } - - if (!Action::configureEvent(node)) { - return false; - } - - pugi::xml_attribute attr; - if (!(attr = node.attribute("id"))) { - std::cout << "[Error - RuneSpell::configureSpell] Rune spell without id." << std::endl; - return false; - } - runeId = pugi::cast(attr.value()); - - uint32_t charges; - if ((attr = node.attribute("charges"))) { - charges = pugi::cast(attr.value()); - } else { - charges = 0; - } - - hasCharges = (charges > 0); - if (magLevel != 0 || level != 0) { - //Change information in the ItemType to get accurate description - ItemType& iType = Item::items.getItemType(runeId); - iType.runeMagLevel = magLevel; - iType.runeLevel = level; - iType.charges = charges; - } - - return true; -} - -bool RuneSpell::loadFunction(const pugi::xml_attribute& attr) -{ - const char* functionName = attr.as_string(); - if (strcasecmp(functionName, "chameleon") == 0) { - runeFunction = Illusion; - } else if (strcasecmp(functionName, "convince") == 0) { - runeFunction = Convince; - } else { - std::cout << "[Warning - RuneSpell::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - m_scripted = false; - return true; -} - -bool RuneSpell::Illusion(const RuneSpell*, Player* player, const Position& posTo) -{ - Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_MOVE); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Item* illusionItem = thing->getItem(); - if (!illusionItem || !illusionItem->isMoveable()) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - ReturnValue ret = CreateIllusion(player, illusionItem->getID(), 200000); - if (ret != RETURNVALUE_NOERROR) { - player->sendCancelMessage(ret); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_RED); - return true; -} - -bool RuneSpell::Convince(const RuneSpell* spell, Player* player, const Position& posTo) -{ - if (!player->hasFlag(PlayerFlag_CanConvinceAll)) { - if (player->getSummonCount() >= 2) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - } - - Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_LOOK); - if (!thing) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Creature* convinceCreature = thing->getCreature(); - if (!convinceCreature) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - uint32_t manaCost = 0; - if (convinceCreature->getMonster()) { - manaCost = convinceCreature->getMonster()->getManaCost(); - } - - if (!player->hasFlag(PlayerFlag_HasInfiniteMana) && player->getMana() < manaCost) { - player->sendCancelMessage(RETURNVALUE_NOTENOUGHMANA); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - if (!convinceCreature->convinceCreature(player)) { - player->sendCancelMessage(RETURNVALUE_NOTPOSSIBLE); - g_game.addMagicEffect(player->getPosition(), CONST_ME_POFF); - return false; - } - - Spell::postCastSpell(player, manaCost, spell->getSoulCost()); - g_game.updateCreatureType(convinceCreature); - g_game.addMagicEffect(player->getPosition(), CONST_ME_MAGIC_RED); - return true; -} - -ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& toPos) -{ - if (player->hasFlag(PlayerFlag_CannotUseSpells)) { - return RETURNVALUE_CANNOTUSETHISOBJECT; - } - - ReturnValue ret = Action::canExecuteAction(player, toPos); - if (ret != RETURNVALUE_NOERROR) { - return ret; - } - - if (toPos.x == 0xFFFF) { - if (needTarget) { - return RETURNVALUE_CANONLYUSETHISRUNEONCREATURES; - } else if (!selfTarget) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - - return RETURNVALUE_NOERROR; -} - -bool RuneSpell::executeUse(Player* player, Item* item, const Position&, Thing* target, const Position& toPosition, bool isHotkey) -{ - if (!playerRuneSpellCheck(player, toPosition)) { - return false; - } - - bool result = false; - if (m_scripted) { - LuaVariant var; - - if (needTarget) { - var.type = VARIANT_NUMBER; - - if (target == nullptr) { - Tile* toTile = g_game.map.getTile(toPosition); - if (toTile) { - const Creature* visibleCreature = toTile->getBottomVisibleCreature(player); - if (visibleCreature) { - var.number = visibleCreature->getID(); - } - } - } else { - var.number = target->getCreature()->getID(); - } - } else { - var.type = VARIANT_POSITION; - var.pos = toPosition; - } - - result = internalCastSpell(player, var, isHotkey); - } else if (runeFunction) { - result = runeFunction(this, player, toPosition); - } - - if (!result) { - return false; - } - - postCastSpell(player); - if (hasCharges && item && g_config.getBoolean(ConfigManager::REMOVE_RUNE_CHARGES)) { - int32_t newCount = std::max(0, item->getItemCount() - 1); - g_game.transformItem(item, item->getID(), newCount); - } - return true; -} - -bool RuneSpell::castSpell(Creature* creature) -{ - LuaVariant var; - var.type = VARIANT_NUMBER; - var.number = creature->getID(); - return internalCastSpell(creature, var, false); -} - -bool RuneSpell::castSpell(Creature* creature, Creature* target) -{ - LuaVariant var; - var.type = VARIANT_NUMBER; - var.number = target->getID(); - return internalCastSpell(creature, var, false); -} - -bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey) -{ - bool result; - if (m_scripted) { - result = executeCastSpell(creature, var, isHotkey); - } else { - result = false; - } - return result; -} - -bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey) -{ - //onCastSpell(creature, var, isHotkey) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - RuneSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - LuaScriptInterface::pushBoolean(L, isHotkey); - - return m_scriptInterface->callFunction(3); -} diff --git a/path_10_8/src/spells.h b/path_10_8/src/spells.h deleted file mode 100644 index 4d7e3bf92..000000000 --- a/path_10_8/src/spells.h +++ /dev/null @@ -1,333 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_SPELLS_H_D78A7CCB7080406E8CAA6B1D31D3DA71 -#define FS_SPELLS_H_D78A7CCB7080406E8CAA6B1D31D3DA71 - -#include "luascript.h" -#include "player.h" -#include "actions.h" -#include "talkaction.h" -#include "baseevents.h" - -class InstantSpell; -class ConjureSpell; -class RuneSpell; -class Spell; - -typedef std::map VocSpellMap; - -class Spells final : public BaseEvents -{ - public: - Spells(); - ~Spells(); - - // non-copyable - Spells(const Spells&) = delete; - Spells& operator=(const Spells&) = delete; - - Spell* getSpellByName(const std::string& name); - RuneSpell* getRuneSpell(uint32_t id); - RuneSpell* getRuneSpellByName(const std::string& name); - - InstantSpell* getInstantSpell(const std::string& words); - InstantSpell* getInstantSpellByName(const std::string& name); - - uint32_t getInstantSpellCount(const Player* player) const; - InstantSpell* getInstantSpellByIndex(const Player* player, uint32_t index); - - TalkActionResult_t playerSaySpell(Player* player, std::string& words); - - static Position getCasterPosition(Creature* creature, Direction dir); - std::string getScriptBaseName() const final; - - protected: - void clear() final; - LuaScriptInterface& getScriptInterface() final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - - std::map runes; - std::map instants; - - friend class CombatSpell; - LuaScriptInterface m_scriptInterface; -}; - -typedef bool (InstantSpellFunction)(const InstantSpell* spell, Creature* creature, const std::string& param); -typedef bool (RuneSpellFunction)(const RuneSpell* spell, Player* player, const Position& posTo); - -class BaseSpell -{ - public: - BaseSpell() = default; - virtual ~BaseSpell() = default; - - virtual bool castSpell(Creature* creature) = 0; - virtual bool castSpell(Creature* creature, Creature* target) = 0; -}; - -class CombatSpell final : public Event, public BaseSpell -{ - public: - CombatSpell(Combat* _combat, bool _needTarget, bool _needDirection); - ~CombatSpell(); - - // non-copyable - CombatSpell(const CombatSpell&) = delete; - CombatSpell& operator=(const CombatSpell&) = delete; - - bool castSpell(Creature* creature) final; - bool castSpell(Creature* creature, Creature* target) final; - bool configureEvent(const pugi::xml_node&) final { - return true; - } - - //scripting - bool executeCastSpell(Creature* creature, const LuaVariant& var); - - bool loadScriptCombat(); - Combat* getCombat() { - return combat; - } - - protected: - std::string getScriptEventName() const final { - return "onCastSpell"; - } - - Combat* combat; - - bool needDirection; - bool needTarget; -}; - -class Spell : public BaseSpell -{ - public: - Spell(); - - bool configureSpell(const pugi::xml_node& node); - const std::string& getName() const { - return name; - } - - void postCastSpell(Player* player, bool finishedSpell = true, bool payCost = true) const; - static void postCastSpell(Player* player, uint32_t manaCost, uint32_t soulCost); - - uint32_t getManaCost(const Player* player) const; - uint32_t getSoulCost() const { - return soul; - } - uint32_t getLevel() const { - return level; - } - uint32_t getMagicLevel() const { - return magLevel; - } - uint32_t getManaPercent() const { - return manaPercent; - } - bool isPremium() const { - return premium; - } - - virtual bool isInstant() const = 0; - bool isLearnable() const { - return learnable; - } - - static ReturnValue CreateIllusion(Creature* creature, const Outfit_t& outfit, int32_t time); - static ReturnValue CreateIllusion(Creature* creature, const std::string& name, int32_t time); - static ReturnValue CreateIllusion(Creature* creature, uint32_t itemId, int32_t time); - - const VocSpellMap& getVocMap() const { - return vocSpellMap; - } - - protected: - bool playerSpellCheck(Player* player) const; - bool playerInstantSpellCheck(Player* player, const Position& toPos); - bool playerRuneSpellCheck(Player* player, const Position& toPos); - - uint8_t spellId; - SpellGroup_t group; - uint32_t groupCooldown; - SpellGroup_t secondaryGroup; - uint32_t secondaryGroupCooldown; - - uint32_t mana; - uint32_t manaPercent; - uint32_t soul; - uint32_t cooldown; - uint32_t level; - uint32_t magLevel; - int32_t range; - int32_t fist; - int32_t club; - int32_t sword; - int32_t axe; - int32_t distance; - int32_t shield; - int32_t fish; - - bool needTarget; - bool needWeapon; - bool selfTarget; - bool blockingSolid; - bool blockingCreature; - bool aggressive; - bool learnable; - bool enabled; - bool premium; - - VocSpellMap vocSpellMap; - - private: - std::string name; -}; - -class InstantSpell : public TalkAction, public Spell -{ - public: - explicit InstantSpell(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) override; - bool loadFunction(const pugi::xml_attribute& attr) override; - - virtual bool playerCastInstant(Player* player, std::string& param); - - bool castSpell(Creature* creature) override; - bool castSpell(Creature* creature, Creature* target) override; - - //scripting - bool executeCastSpell(Creature* creature, const LuaVariant& var); - - bool isInstant() const final { - return true; - } - bool getHasParam() const { - return hasParam; - } - bool getHasPlayerNameParam() const { - return hasPlayerNameParam; - } - bool canCast(const Player* player) const; - bool canThrowSpell(const Creature* creature, const Creature* target) const; - - protected: - std::string getScriptEventName() const override; - - static InstantSpellFunction HouseGuestList; - static InstantSpellFunction HouseSubOwnerList; - static InstantSpellFunction HouseDoorList; - static InstantSpellFunction HouseKick; - static InstantSpellFunction SearchPlayer; - static InstantSpellFunction SummonMonster; - static InstantSpellFunction Levitate; - static InstantSpellFunction Illusion; - - static House* getHouseFromPos(Creature* creature); - - bool internalCastSpell(Creature* creature, const LuaVariant& var); - - InstantSpellFunction* function; - - bool needDirection; - bool hasParam; - bool hasPlayerNameParam; - bool checkLineOfSight; - bool casterTargetOrDirection; -}; - -class ConjureSpell final : public InstantSpell -{ - public: - explicit ConjureSpell(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - bool loadFunction(const pugi::xml_attribute& attr) final; - - bool playerCastInstant(Player* player, std::string& param) final; - - bool castSpell(Creature*) final { - return false; - } - bool castSpell(Creature*, Creature*) final { - return false; - } - - protected: - std::string getScriptEventName() const final; - - bool conjureItem(Creature* creature) const; - bool internalCastSpell(Creature* creature, const LuaVariant& var); - Position getCasterPosition(Creature* creature); - - uint32_t conjureId; - uint32_t conjureCount; - uint32_t reagentId; -}; - -class RuneSpell final : public Action, public Spell -{ - public: - explicit RuneSpell(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - bool loadFunction(const pugi::xml_attribute& attr) final; - - ReturnValue canExecuteAction(const Player* player, const Position& toPos) final; - bool hasOwnErrorHandler() final { - return true; - } - Thing* getTarget(Player*, Creature* targetCreature, const Position&, uint8_t) const final { - return targetCreature; - } - - bool executeUse(Player* player, Item* item, const Position& fromPosition, Thing* target, const Position& toPosition, bool isHotkey) final; - - bool castSpell(Creature* creature) final; - bool castSpell(Creature* creature, Creature* target) final; - - //scripting - bool executeCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey); - - bool isInstant() const final { - return false; - } - uint16_t getRuneItemId() const { - return runeId; - } - - protected: - std::string getScriptEventName() const final; - - static RuneSpellFunction Illusion; - static RuneSpellFunction Convince; - - bool internalCastSpell(Creature* creature, const LuaVariant& var, bool isHotkey); - - RuneSpellFunction* runeFunction; - uint16_t runeId; - bool hasCharges; -}; - -#endif diff --git a/path_10_8/src/talkaction.cpp b/path_10_8/src/talkaction.cpp deleted file mode 100644 index 40c560bad..000000000 --- a/path_10_8/src/talkaction.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "player.h" -#include "talkaction.h" -#include "pugicast.h" - -TalkActions::TalkActions() - : m_scriptInterface("TalkAction Interface") -{ - m_scriptInterface.initState(); -} - -TalkActions::~TalkActions() -{ - clear(); -} - -void TalkActions::clear() -{ - for (TalkAction* talkAction : talkActions) { - delete talkAction; - } - talkActions.clear(); - - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& TalkActions::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string TalkActions::getScriptBaseName() const -{ - return "talkactions"; -} - -Event* TalkActions::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "talkaction") != 0) { - return nullptr; - } - return new TalkAction(&m_scriptInterface); -} - -bool TalkActions::registerEvent(Event* event, const pugi::xml_node&) -{ - talkActions.push_front(static_cast(event)); // event is guaranteed to be a TalkAction - return true; -} - -TalkActionResult_t TalkActions::playerSaySpell(Player* player, SpeakClasses type, const std::string& words) const -{ - size_t wordsLength = words.length(); - for (TalkAction* talkAction : talkActions) { - const std::string& talkactionWords = talkAction->getWords(); - size_t talkactionLength = talkactionWords.length(); - if (wordsLength < talkactionLength || strncasecmp(words.c_str(), talkactionWords.c_str(), talkactionLength) != 0) { - continue; - } - - std::string param; - if (wordsLength != talkactionLength) { - param = words.substr(talkactionLength); - if (param.front() != ' ') { - continue; - } - trim_left(param, ' '); - - char separator = talkAction->getSeparator(); - if (separator != ' ') { - if (!param.empty()) { - if (param.front() != separator) { - continue; - } else { - param.erase(param.begin()); - } - } - } - } - - if (talkAction->executeSay(player, param, type)) { - return TALKACTION_CONTINUE; - } else { - return TALKACTION_BREAK; - } - } - return TALKACTION_CONTINUE; -} - -TalkAction::TalkAction(LuaScriptInterface* _interface) : - Event(_interface) -{ - separator = '"'; -} - -bool TalkAction::configureEvent(const pugi::xml_node& node) -{ - pugi::xml_attribute wordsAttribute = node.attribute("words"); - if (!wordsAttribute) { - std::cout << "[Error - TalkAction::configureEvent] Missing words for talk action or spell" << std::endl; - return false; - } - - pugi::xml_attribute separatorAttribute = node.attribute("separator"); - if (separatorAttribute) { - separator = pugi::cast(separatorAttribute.value()); - } - - words = wordsAttribute.as_string(); - return true; -} - -std::string TalkAction::getScriptEventName() const -{ - return "onSay"; -} - -bool TalkAction::executeSay(Player* player, const std::string& param, SpeakClasses type) const -{ - //onSay(player, words, param, type) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TalkAction::executeSay] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushString(L, words); - LuaScriptInterface::pushString(L, param); - lua_pushnumber(L, type); - - return m_scriptInterface->callFunction(4); -} diff --git a/path_10_8/src/talkaction.h b/path_10_8/src/talkaction.h deleted file mode 100644 index 4b0389058..000000000 --- a/path_10_8/src/talkaction.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TALKACTION_H_E6AABAC0F89843469526ADF310F3131C -#define FS_TALKACTION_H_E6AABAC0F89843469526ADF310F3131C - -#include "luascript.h" -#include "baseevents.h" -#include "const.h" - -enum TalkActionResult_t { - TALKACTION_CONTINUE, - TALKACTION_BREAK, - TALKACTION_FAILED, -}; - -class TalkAction; - -class TalkActions : public BaseEvents -{ - public: - TalkActions(); - ~TalkActions(); - - // non-copyable - TalkActions(const TalkActions&) = delete; - TalkActions& operator=(const TalkActions&) = delete; - - TalkActionResult_t playerSaySpell(Player* player, SpeakClasses type, const std::string& words) const; - - protected: - LuaScriptInterface& getScriptInterface() final; - std::string getScriptBaseName() const final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - void clear() final; - - // TODO: Store TalkAction objects directly in the list instead of using pointers - std::forward_list talkActions; - - LuaScriptInterface m_scriptInterface; -}; - -class TalkAction : public Event -{ - public: - explicit TalkAction(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) override; - - std::string getWords() const { - return words; - } - char getSeparator() const { - return separator; - } - - //scripting - bool executeSay(Player* player, const std::string& param, SpeakClasses type) const; - // - - protected: - std::string getScriptEventName() const override; - - std::string words; - char separator; -}; - -#endif diff --git a/path_10_8/src/tasks.cpp b/path_10_8/src/tasks.cpp deleted file mode 100644 index e1b9e014b..000000000 --- a/path_10_8/src/tasks.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "tasks.h" -#include "game.h" - -extern Game g_game; - -void Dispatcher::threadMain() -{ - // NOTE: second argument defer_lock is to prevent from immediate locking - std::unique_lock taskLockUnique(taskLock, std::defer_lock); - - while (getState() != THREAD_STATE_TERMINATED) { - // check if there are tasks waiting - taskLockUnique.lock(); - - if (taskList.empty()) { - //if the list is empty wait for signal - taskSignal.wait(taskLockUnique); - } - - if (!taskList.empty()) { - // take the first task - Task* task = taskList.front(); - taskList.pop_front(); - taskLockUnique.unlock(); - - if (!task->hasExpired()) { - ++dispatcherCycle; - // execute it - (*task)(); - - g_game.map.clearSpectatorCache(); - } - delete task; - } else { - taskLockUnique.unlock(); - } - } -} - -void Dispatcher::addTask(Task* task, bool push_front /*= false*/) -{ - bool do_signal = false; - - taskLock.lock(); - - if (getState() == THREAD_STATE_RUNNING) { - do_signal = taskList.empty(); - - if (push_front) { - taskList.push_front(task); - } else { - taskList.push_back(task); - } - } else { - delete task; - } - - taskLock.unlock(); - - // send a signal if the list was empty - if (do_signal) { - taskSignal.notify_one(); - } -} - -void Dispatcher::shutdown() -{ - Task* task = createTask([this]() { - setState(THREAD_STATE_TERMINATED); - taskSignal.notify_one(); - }); - - std::lock_guard lockGuard(taskLock); - taskList.push_back(task); - - taskSignal.notify_one(); -} diff --git a/path_10_8/src/tasks.h b/path_10_8/src/tasks.h deleted file mode 100644 index 33b68d00f..000000000 --- a/path_10_8/src/tasks.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TASKS_H_A66AC384766041E59DCA059DAB6E1976 -#define FS_TASKS_H_A66AC384766041E59DCA059DAB6E1976 - -#include -#include "thread_holder_base.h" -#include "enums.h" - -const int DISPATCHER_TASK_EXPIRATION = 2000; -const auto SYSTEM_TIME_ZERO = std::chrono::system_clock::time_point(std::chrono::milliseconds(0)); - -class Task -{ - public: - // DO NOT allocate this class on the stack - Task(uint32_t ms, const std::function& f) : func(f) { - expiration = std::chrono::system_clock::now() + std::chrono::milliseconds(ms); - } - explicit Task(const std::function& f) - : expiration(SYSTEM_TIME_ZERO), func(f) {} - - virtual ~Task() = default; - void operator()() { - func(); - } - - void setDontExpire() { - expiration = SYSTEM_TIME_ZERO; - } - - bool hasExpired() const { - if (expiration == SYSTEM_TIME_ZERO) { - return false; - } - return expiration < std::chrono::system_clock::now(); - } - - protected: - // Expiration has another meaning for scheduler tasks, - // then it is the time the task should be added to the - // dispatcher - std::chrono::system_clock::time_point expiration; - std::function func; -}; - -inline Task* createTask(const std::function& f) -{ - return new Task(f); -} - -inline Task* createTask(uint32_t expiration, const std::function& f) -{ - return new Task(expiration, f); -} - -class Dispatcher : public ThreadHolder -{ - public: - void addTask(Task* task, bool push_front = false); - void shutdown(); - - uint64_t getDispatcherCycle() const { - return dispatcherCycle; - } - void threadMain(); - protected: - std::thread thread; - std::mutex taskLock; - std::condition_variable taskSignal; - - std::list taskList; - uint64_t dispatcherCycle {0}; -}; - -extern Dispatcher g_dispatcher; - -#endif diff --git a/path_10_8/src/teleport.cpp b/path_10_8/src/teleport.cpp deleted file mode 100644 index ba0a8a2f0..000000000 --- a/path_10_8/src/teleport.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "teleport.h" -#include "game.h" - -extern Game g_game; - -Teleport::Teleport(uint16_t _type) : Item(_type) -{ -} - -Attr_ReadValue Teleport::readAttr(AttrTypes_t attr, PropStream& propStream) -{ - if (attr == ATTR_TELE_DEST) { - if (!propStream.read(destPos.x) || !propStream.read(destPos.y) || !propStream.read(destPos.z)) { - return ATTR_READ_ERROR; - } - return ATTR_READ_CONTINUE; - } - return Item::readAttr(attr, propStream); -} - -void Teleport::serializeAttr(PropWriteStream& propWriteStream) const -{ - Item::serializeAttr(propWriteStream); - - propWriteStream.write(ATTR_TELE_DEST); - propWriteStream.write(destPos.x); - propWriteStream.write(destPos.y); - propWriteStream.write(destPos.z); -} - -ReturnValue Teleport::queryAdd(int32_t, const Thing&, uint32_t, uint32_t, Creature*) const -{ - return RETURNVALUE_NOTPOSSIBLE; -} - -ReturnValue Teleport::queryMaxCount(int32_t, const Thing&, uint32_t, uint32_t&, uint32_t) const -{ - return RETURNVALUE_NOTPOSSIBLE; -} - -ReturnValue Teleport::queryRemove(const Thing&, uint32_t, uint32_t) const -{ - return RETURNVALUE_NOERROR; -} - -Cylinder* Teleport::queryDestination(int32_t&, const Thing&, Item**, uint32_t&) -{ - return this; -} - -void Teleport::addThing(Thing* thing) -{ - return addThing(0, thing); -} - -void Teleport::addThing(int32_t, Thing* thing) -{ - Tile* destTile = g_game.map.getTile(destPos); - if (!destTile) { - return; - } - - const MagicEffectClasses effect = Item::items[id].magicEffect; - - if (Creature* creature = thing->getCreature()) { - Position origPos = creature->getPosition(); - g_game.internalCreatureTurn(creature, origPos.x > destPos.x ? DIRECTION_WEST : DIRECTION_EAST); - g_game.map.moveCreature(*creature, *destTile); - if (effect != CONST_ME_NONE) { - g_game.addMagicEffect(origPos, effect); - g_game.addMagicEffect(destTile->getPosition(), effect); - } - } else if (Item* item = thing->getItem()) { - if (effect != CONST_ME_NONE) { - g_game.addMagicEffect(destTile->getPosition(), effect); - g_game.addMagicEffect(item->getPosition(), effect); - } - g_game.internalMoveItem(getTile(), destTile, INDEX_WHEREEVER, item, item->getItemCount(), nullptr); - } -} - -void Teleport::updateThing(Thing*, uint16_t, uint32_t) -{ - // -} - -void Teleport::replaceThing(uint32_t, Thing*) -{ - // -} - -void Teleport::removeThing(Thing*, uint32_t) -{ - // -} - -void Teleport::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); -} - -void Teleport::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); -} diff --git a/path_10_8/src/teleport.h b/path_10_8/src/teleport.h deleted file mode 100644 index 41aad9260..000000000 --- a/path_10_8/src/teleport.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TELEPORT_H_873B7F7F1DB24101A7ACFB54B25E0ABC -#define FS_TELEPORT_H_873B7F7F1DB24101A7ACFB54B25E0ABC - -#include "tile.h" - -class Teleport final : public Item, public Cylinder -{ - public: - explicit Teleport(uint16_t _type); - - Teleport* getTeleport() final { - return this; - } - const Teleport* getTeleport() const final { - return this; - } - - //serialization - Attr_ReadValue readAttr(AttrTypes_t attr, PropStream& propStream) final; - void serializeAttr(PropWriteStream& propWriteStream) const final; - - const Position& getDestPos() const { - return destPos; - } - void setDestPos(Position pos) { - destPos = pos; - } - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const final; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, - uint32_t& maxQueryCount, uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, - uint32_t& flags) final; - - void addThing(Thing* thing) final; - void addThing(int32_t index, Thing* thing) final; - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - private: - Position destPos; -}; - -#endif diff --git a/path_10_8/src/thing.cpp b/path_10_8/src/thing.cpp deleted file mode 100644 index 24e8c95c5..000000000 --- a/path_10_8/src/thing.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "thing.h" -#include "tile.h" - -const Position& Thing::getPosition() const -{ - const Tile* tile = getTile(); - if (!tile) { - return Tile::nullptr_tile.getPosition(); - } - return tile->getPosition(); -} - -Tile* Thing::getTile() -{ - return dynamic_cast(this); -} - -const Tile* Thing::getTile() const -{ - return dynamic_cast(this); -} diff --git a/path_10_8/src/thing.h b/path_10_8/src/thing.h deleted file mode 100644 index 47c04a686..000000000 --- a/path_10_8/src/thing.h +++ /dev/null @@ -1,86 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_THING_H_6F16A8E566AF4ACEAE02CF32A7246144 -#define FS_THING_H_6F16A8E566AF4ACEAE02CF32A7246144 - -#include "position.h" - -class Tile; -class Cylinder; -class Item; -class Creature; -class Container; - -class Thing -{ - protected: - Thing() = default; - ~Thing() = default; - - public: - // non-copyable - Thing(const Thing&) = delete; - Thing& operator=(const Thing&) = delete; - - virtual std::string getDescription(int32_t lookDistance) const = 0; - - virtual Cylinder* getParent() const { - return nullptr; - } - virtual Cylinder* getRealParent() const { - return getParent(); - } - - virtual void setParent(Cylinder*) { - // - } - - virtual Tile* getTile(); - virtual const Tile* getTile() const; - - virtual const Position& getPosition() const; - virtual int32_t getThrowRange() const = 0; - virtual bool isPushable() const = 0; - - virtual Container* getContainer() { - return nullptr; - } - virtual const Container* getContainer() const { - return nullptr; - } - virtual Item* getItem() { - return nullptr; - } - virtual const Item* getItem() const { - return nullptr; - } - virtual Creature* getCreature() { - return nullptr; - } - virtual const Creature* getCreature() const { - return nullptr; - } - - virtual bool isRemoved() const { - return true; - } -}; - -#endif diff --git a/path_10_8/src/thread_holder_base.h b/path_10_8/src/thread_holder_base.h deleted file mode 100644 index 79ce284d5..000000000 --- a/path_10_8/src/thread_holder_base.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_THREAD_HOLDER_H_BEB56FC46748E71D15A5BF0773ED2E67 -#define FS_THREAD_HOLDER_H_BEB56FC46748E71D15A5BF0773ED2E67 - -#include -#include -#include "enums.h" - -template -class ThreadHolder -{ - public: - ThreadHolder(): threadState(THREAD_STATE_TERMINATED) {} - void start() { - setState(THREAD_STATE_RUNNING); - thread = std::thread(&Derived::threadMain, static_cast(this)); - } - - void stop() { - setState(THREAD_STATE_CLOSING); - } - - void join() { - if (thread.joinable()) { - thread.join(); - } - } - protected: - void setState(ThreadState newState) { - threadState.store(newState, std::memory_order_relaxed); - } - - ThreadState getState() const { - return threadState.load(std::memory_order_relaxed); - } - private: - std::atomic threadState; - std::thread thread; -}; - -#endif diff --git a/path_10_8/src/tile.cpp b/path_10_8/src/tile.cpp deleted file mode 100644 index b707aa759..000000000 --- a/path_10_8/src/tile.cpp +++ /dev/null @@ -1,1690 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "tile.h" - -#include "creature.h" -#include "combat.h" -#include "game.h" -#include "mailbox.h" -#include "monster.h" -#include "movement.h" -#include "player.h" -#include "teleport.h" -#include "trashholder.h" - -extern Game g_game; -extern MoveEvents* g_moveEvents; - -StaticTile real_nullptr_tile(0xFFFF, 0xFFFF, 0xFF); -Tile& Tile::nullptr_tile = real_nullptr_tile; - -bool Tile::hasProperty(ITEMPROPERTY prop) const -{ - if (ground && ground->hasProperty(prop)) { - return true; - } - - if (const TileItemVector* items = getItemList()) { - for (const Item* item : *items) { - if (item->hasProperty(prop)) { - return true; - } - } - } - return false; -} - -bool Tile::hasProperty(const Item* exclude, ITEMPROPERTY prop) const -{ - assert(exclude); - - if (ground && exclude != ground && ground->hasProperty(prop)) { - return true; - } - - if (const TileItemVector* items = getItemList()) { - for (const Item* item : *items) { - if (item != exclude && item->hasProperty(prop)) { - return true; - } - } - } - - return false; -} - -bool Tile::hasHeight(uint32_t n) const -{ - uint32_t height = 0; - - if (ground) { - if (ground->hasProperty(CONST_PROP_HASHEIGHT)) { - ++height; - } - - if (n == height) { - return true; - } - } - - if (const TileItemVector* items = getItemList()) { - for (const Item* item : *items) { - if (item->hasProperty(CONST_PROP_HASHEIGHT)) { - ++height; - } - - if (n == height) { - return true; - } - } - } - return false; -} - -size_t Tile::getCreatureCount() const -{ - if (const CreatureVector* creatures = getCreatures()) { - return creatures->size(); - } - return 0; -} - -size_t Tile::getItemCount() const -{ - if (const TileItemVector* items = getItemList()) { - return items->size(); - } - return 0; -} - -uint32_t Tile::getTopItemCount() const -{ - if (const TileItemVector* items = getItemList()) { - return items->getTopItemCount(); - } - return 0; -} - -uint32_t Tile::getDownItemCount() const -{ - if (const TileItemVector* items = getItemList()) { - return items->getDownItemCount(); - } - return 0; -} - -std::string Tile::getDescription(int32_t) const -{ - return "You dont know why, but you cant see anything!"; -} - -Teleport* Tile::getTeleportItem() const -{ - if (!hasFlag(TILESTATE_TELEPORT)) { - return nullptr; - } - - if (const TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getTeleport()) { - return (*it)->getTeleport(); - } - } - } - return nullptr; -} - -MagicField* Tile::getFieldItem() const -{ - if (!hasFlag(TILESTATE_MAGICFIELD)) { - return nullptr; - } - - if (ground && ground->getMagicField()) { - return ground->getMagicField(); - } - - if (const TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getMagicField()) { - return (*it)->getMagicField(); - } - } - } - return nullptr; -} - -TrashHolder* Tile::getTrashHolder() const -{ - if (!hasFlag(TILESTATE_TRASHHOLDER)) { - return nullptr; - } - - if (ground && ground->getTrashHolder()) { - return ground->getTrashHolder(); - } - - if (const TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getTrashHolder()) { - return (*it)->getTrashHolder(); - } - } - } - return nullptr; -} - -Mailbox* Tile::getMailbox() const -{ - if (!hasFlag(TILESTATE_MAILBOX)) { - return nullptr; - } - - if (ground && ground->getMailbox()) { - return ground->getMailbox(); - } - - if (const TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getMailbox()) { - return (*it)->getMailbox(); - } - } - } - return nullptr; -} - -BedItem* Tile::getBedItem() const -{ - if (!hasFlag(TILESTATE_BED)) { - return nullptr; - } - - if (ground && ground->getBed()) { - return ground->getBed(); - } - - if (const TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = items->rbegin(), end = items->rend(); it != end; ++it) { - if ((*it)->getBed()) { - return (*it)->getBed(); - } - } - } - return nullptr; -} - -Creature* Tile::getTopCreature() const -{ - if (const CreatureVector* creatures = getCreatures()) { - if (!creatures->empty()) { - return *creatures->begin(); - } - } - return nullptr; -} - -const Creature* Tile::getBottomCreature() const -{ - if (const CreatureVector* creatures = getCreatures()) { - if (!creatures->empty()) { - return *creatures->rbegin(); - } - } - return nullptr; -} - -Creature* Tile::getTopVisibleCreature(const Creature* creature) const -{ - if (const CreatureVector* creatures = getCreatures()) { - if (creature) { - const Player* player = creature->getPlayer(); - if (player && player->isAccessPlayer()) { - return getTopCreature(); - } - - for (Creature* tileCreature : *creatures) { - if (creature->canSeeCreature(tileCreature)) { - return tileCreature; - } - } - } else { - for (Creature* tileCreature : *creatures) { - if (!tileCreature->isInvisible()) { - const Player* player = tileCreature->getPlayer(); - if (!player || !player->isInGhostMode()) { - return tileCreature; - } - } - } - } - } - return nullptr; -} - -const Creature* Tile::getBottomVisibleCreature(const Creature* creature) const -{ - if (const CreatureVector* creatures = getCreatures()) { - if (creature) { - const Player* player = creature->getPlayer(); - if (player && player->isAccessPlayer()) { - return getBottomCreature(); - } - - for (CreatureVector::const_reverse_iterator it = creatures->rbegin(), end = creatures->rend(); it != end; ++it) { - if (creature->canSeeCreature(*it)) { - return *it; - } - } - } else { - for (CreatureVector::const_reverse_iterator it = creatures->rbegin(), end = creatures->rend(); it != end; ++it) { - if (!(*it)->isInvisible()) { - const Player* player = (*it)->getPlayer(); - if (!player || !player->isInGhostMode()) { - return *it; - } - } - } - } - } - return nullptr; -} - -Item* Tile::getTopDownItem() const -{ - if (const TileItemVector* items = getItemList()) { - return items->getTopDownItem(); - } - return nullptr; -} - -Item* Tile::getTopTopItem() const -{ - if (const TileItemVector* items = getItemList()) { - return items->getTopTopItem(); - } - return nullptr; -} - -Item* Tile::getItemByTopOrder(int32_t topOrder) -{ - //topOrder: - //1: borders - //2: ladders, signs, splashes - //3: doors etc - //4: creatures - if (TileItemVector* items = getItemList()) { - for (ItemVector::const_reverse_iterator it = ItemVector::const_reverse_iterator(items->getEndTopItem()), end = ItemVector::const_reverse_iterator(items->getBeginTopItem()); it != end; ++it) { - if (Item::items[(*it)->getID()].alwaysOnTopOrder == topOrder) { - return (*it); - } - } - } - return nullptr; -} - -Thing* Tile::getTopVisibleThing(const Creature* creature) -{ - Thing* thing = getTopVisibleCreature(creature); - if (thing) { - return thing; - } - - TileItemVector* items = getItemList(); - if (items) { - for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - const ItemType& iit = Item::items[(*it)->getID()]; - if (!iit.lookThrough) { - return (*it); - } - } - - for (ItemVector::const_reverse_iterator it = ItemVector::const_reverse_iterator(items->getEndTopItem()), end = ItemVector::const_reverse_iterator(items->getBeginTopItem()); it != end; ++it) { - const ItemType& iit = Item::items[(*it)->getID()]; - if (!iit.lookThrough) { - return (*it); - } - } - } - - return ground; -} - -void Tile::onAddTileItem(Item* item) -{ - if (item->hasProperty(CONST_PROP_MOVEABLE) || item->getContainer()) { - auto it = g_game.browseFields.find(this); - if (it != g_game.browseFields.end()) { - it->second->addItemBack(item); - item->setParent(this); - } - } - - setTileFlags(item); - - const Position& cylinderMapPos = getPosition(); - - SpectatorVec list; - g_game.map.getSpectators(list, cylinderMapPos, true); - - //send to client - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendAddTileItem(this, cylinderMapPos, item); - } - } - - //event methods - for (Creature* spectator : list) { - spectator->onAddTileItem(this, cylinderMapPos); - } -} - -void Tile::onUpdateTileItem(Item* oldItem, const ItemType& oldType, Item* newItem, const ItemType& newType) -{ - if (newItem->hasProperty(CONST_PROP_MOVEABLE) || newItem->getContainer()) { - auto it = g_game.browseFields.find(this); - if (it != g_game.browseFields.end()) { - int32_t index = it->second->getThingIndex(oldItem); - if (index != -1) { - it->second->replaceThing(index, newItem); - newItem->setParent(this); - } - } - } else if (oldItem->hasProperty(CONST_PROP_MOVEABLE) || oldItem->getContainer()) { - auto it = g_game.browseFields.find(this); - if (it != g_game.browseFields.end()) { - Cylinder* oldParent = oldItem->getParent(); - it->second->removeThing(oldItem, oldItem->getItemCount()); - oldItem->setParent(oldParent); - } - } - - const Position& cylinderMapPos = getPosition(); - - SpectatorVec list; - g_game.map.getSpectators(list, cylinderMapPos, true); - - //send to client - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendUpdateTileItem(this, cylinderMapPos, newItem); - } - } - - //event methods - for (Creature* spectator : list) { - spectator->onUpdateTileItem(this, cylinderMapPos, oldItem, oldType, newItem, newType); - } -} - -void Tile::onRemoveTileItem(const SpectatorVec& list, const std::vector& oldStackPosVector, Item* item) -{ - if (item->hasProperty(CONST_PROP_MOVEABLE) || item->getContainer()) { - auto it = g_game.browseFields.find(this); - if (it != g_game.browseFields.end()) { - it->second->removeThing(item, item->getItemCount()); - } - } - - resetTileFlags(item); - - const Position& cylinderMapPos = getPosition(); - const ItemType& iType = Item::items[item->getID()]; - - //send to client - size_t i = 0; - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendRemoveTileThing(cylinderMapPos, oldStackPosVector[i++]); - } - } - - //event methods - for (Creature* spectator : list) { - spectator->onRemoveTileItem(this, cylinderMapPos, iType, item); - } -} - -void Tile::onUpdateTile(const SpectatorVec& list) -{ - const Position& cylinderMapPos = getPosition(); - - //send to clients - for (Creature* spectator : list) { - spectator->getPlayer()->sendUpdateTile(this, cylinderMapPos); - } -} - -ReturnValue Tile::queryAdd(int32_t, const Thing& thing, uint32_t, uint32_t flags, Creature*) const -{ - if (const Creature* creature = thing.getCreature()) { - if (hasBitSet(FLAG_NOLIMIT, flags)) { - return RETURNVALUE_NOERROR; - } - - if (hasBitSet(FLAG_PATHFINDING, flags)) { - if (floorChange() || positionChange()) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - - if (ground == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (const Monster* monster = creature->getMonster()) { - if (hasFlag(TILESTATE_PROTECTIONZONE)) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (floorChange() || positionChange()) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const CreatureVector* creatures = getCreatures(); - if (monster->canPushCreatures() && !monster->isSummon()) { - if (creatures) { - for (Creature* tileCreature : *creatures) { - if (tileCreature->getPlayer() && tileCreature->getPlayer()->isInGhostMode()) { - continue; - } - - const Monster* creatureMonster = tileCreature->getMonster(); - if (!creatureMonster || !tileCreature->isPushable() || - (creatureMonster->isSummon() && creatureMonster->getMaster()->getPlayer())) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - } - } else if (creatures && !creatures->empty()) { - for (const Creature* tileCreature : *creatures) { - if (!tileCreature->isInGhostMode()) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - } - - if (hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID)) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH)) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (hasFlag(TILESTATE_BLOCKSOLID) || (hasBitSet(FLAG_PATHFINDING, flags) && hasFlag(TILESTATE_NOFIELDBLOCKPATH))) { - if (!(monster->canPushItems() || hasBitSet(FLAG_IGNOREBLOCKITEM, flags))) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - - MagicField* field = getFieldItem(); - if (field && !field->isBlocking()) { - CombatType_t combatType = field->getCombatType(); - - //There is 3 options for a monster to enter a magic field - //1) Monster is immune - if (!monster->isImmune(combatType)) { - //1) Monster is "strong" enough to handle the damage - //2) Monster is already afflicated by this type of condition - if (hasBitSet(FLAG_IGNOREFIELDDAMAGE, flags)) { - if (!(monster->canPushItems() || monster->hasCondition(Combat::DamageToConditionType(combatType)))) { - return RETURNVALUE_NOTPOSSIBLE; - } - } else { - return RETURNVALUE_NOTPOSSIBLE; - } - } - } - - return RETURNVALUE_NOERROR; - } - - const CreatureVector* creatures = getCreatures(); - if (const Player* player = creature->getPlayer()) { - if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags) && !player->isAccessPlayer()) { - for (const Creature* tileCreature : *creatures) { - if (!player->canWalkthrough(tileCreature)) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - } - - if (player->getParent() == nullptr && hasFlag(TILESTATE_NOLOGOUT)) { - //player is trying to login to a "no logout" tile - return RETURNVALUE_NOTPOSSIBLE; - } - - const Tile* playerTile = player->getTile(); - if (playerTile && player->isPzLocked()) { - if (!playerTile->hasFlag(TILESTATE_PVPZONE)) { - //player is trying to enter a pvp zone while being pz-locked - if (hasFlag(TILESTATE_PVPZONE)) { - return RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE; - } - } else if (!hasFlag(TILESTATE_PVPZONE)) { - // player is trying to leave a pvp zone while being pz-locked - return RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE; - } - - if ((!playerTile->hasFlag(TILESTATE_NOPVPZONE) && hasFlag(TILESTATE_NOPVPZONE)) || - (!playerTile->hasFlag(TILESTATE_PROTECTIONZONE) && hasFlag(TILESTATE_PROTECTIONZONE))) { - // player is trying to enter a non-pvp/protection zone while being pz-locked - return RETURNVALUE_PLAYERISPZLOCKED; - } - } - } else if (creatures && !creatures->empty() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) { - for (const Creature* tileCreature : *creatures) { - if (!tileCreature->isInGhostMode()) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - } - - if (!hasBitSet(FLAG_IGNOREBLOCKITEM, flags)) { - //If the FLAG_IGNOREBLOCKITEM bit isn't set we dont have to iterate every single item - if (hasFlag(TILESTATE_BLOCKSOLID)) { - return RETURNVALUE_NOTENOUGHROOM; - } - } else { - //FLAG_IGNOREBLOCKITEM is set - if (ground) { - const ItemType& iiType = Item::items[ground->getID()]; - if (iiType.blockSolid && (!iiType.moveable || ground->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - - if (const auto items = getItemList()) { - for (const Item* item : *items) { - const ItemType& iiType = Item::items[item->getID()]; - if (iiType.blockSolid && (!iiType.moveable || item->hasAttribute(ITEM_ATTRIBUTE_UNIQUEID))) { - return RETURNVALUE_NOTPOSSIBLE; - } - } - } - } - } else if (const Item* item = thing.getItem()) { - const TileItemVector* items = getItemList(); - if (items && items->size() >= 0xFFFF) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (hasBitSet(FLAG_NOLIMIT, flags)) { - return RETURNVALUE_NOERROR; - } - - bool itemIsHangable = item->isHangable(); - if (ground == nullptr && !itemIsHangable) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const CreatureVector* creatures = getCreatures(); - if (creatures && !creatures->empty() && item->isBlocking() && !hasBitSet(FLAG_IGNOREBLOCKCREATURE, flags)) { - for (const Creature* tileCreature : *creatures) { - if (!tileCreature->isInGhostMode()) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - } - - if (itemIsHangable && hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { - if (items) { - for (const Item* tileItem : *items) { - if (tileItem->isHangable()) { - return RETURNVALUE_NEEDEXCHANGE; - } - } - } - } else { - if (ground) { - const ItemType& iiType = Item::items[ground->getID()]; - if (iiType.blockSolid) { - if (!iiType.allowPickupable || item->isMagicField() || item->isBlocking()) { - if (!item->isPickupable()) { - return RETURNVALUE_NOTENOUGHROOM; - } - - if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - } - } - - if (items) { - for (const Item* tileItem : *items) { - const ItemType& iiType = Item::items[tileItem->getID()]; - if (!iiType.blockSolid) { - continue; - } - - if (iiType.allowPickupable && !item->isMagicField() && !item->isBlocking()) { - continue; - } - - if (!item->isPickupable()) { - return RETURNVALUE_NOTENOUGHROOM; - } - - if (!iiType.hasHeight || iiType.pickupable || iiType.isBed()) { - return RETURNVALUE_NOTENOUGHROOM; - } - } - } - } - } - return RETURNVALUE_NOERROR; -} - -ReturnValue Tile::queryMaxCount(int32_t, const Thing&, uint32_t count, uint32_t& maxQueryCount, uint32_t) const -{ - maxQueryCount = std::max(1, count); - return RETURNVALUE_NOERROR; -} - -ReturnValue Tile::queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const -{ - int32_t index = getThingIndex(&thing); - if (index == -1) { - return RETURNVALUE_NOTPOSSIBLE; - } - - const Item* item = thing.getItem(); - if (item == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (count == 0 || (item->isStackable() && count > item->getItemCount())) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (!item->isMoveable() && !hasBitSet(FLAG_IGNORENOTMOVEABLE, flags)) { - return RETURNVALUE_NOTMOVEABLE; - } - - return RETURNVALUE_NOERROR; -} - -Tile* Tile::queryDestination(int32_t&, const Thing&, Item** destItem, uint32_t& flags) -{ - Tile* destTile = nullptr; - *destItem = nullptr; - - if (floorChangeDown()) { - uint16_t dx = tilePos.x; - uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z + 1; - - Tile* southDownTile = g_game.map.getTile(dx, dy - 1, dz); - if (southDownTile && southDownTile->floorChange(DIRECTION_SOUTH_ALT)) { - dy -= 2; - destTile = g_game.map.getTile(dx, dy, dz); - } else { - Tile* eastDownTile = g_game.map.getTile(dx - 1, dy, dz); - if (eastDownTile && eastDownTile->floorChange(DIRECTION_EAST_ALT)) { - dx -= 2; - destTile = g_game.map.getTile(dx, dy, dz); - } else { - Tile* downTile = g_game.map.getTile(dx, dy, dz); - if (downTile) { - if (downTile->floorChange(DIRECTION_NORTH)) { - ++dy; - } - - if (downTile->floorChange(DIRECTION_SOUTH)) { - --dy; - } - - if (downTile->floorChange(DIRECTION_SOUTH_ALT)) { - dy -= 2; - } - - if (downTile->floorChange(DIRECTION_EAST)) { - --dx; - } - - if (downTile->floorChange(DIRECTION_EAST_ALT)) { - dx -= 2; - } - - if (downTile->floorChange(DIRECTION_WEST)) { - ++dx; - } - - destTile = g_game.map.getTile(dx, dy, dz); - } - } - } - } else if (floorChange()) { - uint16_t dx = tilePos.x; - uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z - 1; - - if (floorChange(DIRECTION_NORTH)) { - --dy; - } - - if (floorChange(DIRECTION_SOUTH)) { - ++dy; - } - - if (floorChange(DIRECTION_EAST)) { - ++dx; - } - - if (floorChange(DIRECTION_WEST)) { - --dx; - } - - if (floorChange(DIRECTION_SOUTH_ALT)) { - dy += 2; - } - - if (floorChange(DIRECTION_EAST_ALT)) { - dx += 2; - } - - destTile = g_game.map.getTile(dx, dy, dz); - } - - if (destTile == nullptr) { - destTile = this; - } else { - flags |= FLAG_NOLIMIT; //Will ignore that there is blocking items/creatures - } - - if (destTile) { - Thing* destThing = destTile->getTopDownItem(); - if (destThing) { - *destItem = destThing->getItem(); - } - } - - return destTile; -} - -void Tile::addThing(Thing* thing) -{ - addThing(0, thing); -} - -void Tile::addThing(int32_t, Thing* thing) -{ - Creature* creature = thing->getCreature(); - if (creature) { - g_game.map.clearSpectatorCache(); - creature->setParent(this); - CreatureVector* creatures = makeCreatures(); - creatures->insert(creatures->begin(), creature); - } else { - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - TileItemVector* items = getItemList(); - if (items && items->size() >= 0xFFFF) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - item->setParent(this); - - const ItemType& itemType = Item::items[item->getID()]; - if (itemType.isGroundTile()) { - if (ground == nullptr) { - ground = item; - onAddTileItem(item); - } else { - const ItemType& oldType = Item::items[ground->getID()]; - - Item* oldGround = ground; - ground->setParent(nullptr); - g_game.ReleaseItem(ground); - ground = item; - resetTileFlags(oldGround); - setTileFlags(item); - onUpdateTileItem(oldGround, oldType, item, itemType); - postRemoveNotification(oldGround, nullptr, 0); - } - } else if (itemType.alwaysOnTop) { - if (itemType.isSplash() && items) { - //remove old splash if exists - for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - Item* oldSplash = *it; - if (!Item::items[oldSplash->getID()].isSplash()) { - continue; - } - - removeThing(oldSplash, 1); - oldSplash->setParent(nullptr); - g_game.ReleaseItem(oldSplash); - postRemoveNotification(oldSplash, nullptr, 0); - break; - } - } - - bool isInserted = false; - - if (items) { - for (ItemVector::iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - //Note: this is different from internalAddThing - if (itemType.alwaysOnTopOrder <= Item::items[(*it)->getID()].alwaysOnTopOrder) { - items->insert(it, item); - isInserted = true; - break; - } - } - } else { - items = makeItemList(); - } - - if (!isInserted) { - items->push_back(item); - } - - onAddTileItem(item); - } else { - if (itemType.isMagicField()) { - //remove old field item if exists - if (items) { - for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - MagicField* oldField = (*it)->getMagicField(); - if (oldField) { - if (oldField->isReplaceable()) { - removeThing(oldField, 1); - - oldField->setParent(nullptr); - g_game.ReleaseItem(oldField); - postRemoveNotification(oldField, nullptr, 0); - break; - } else { - //This magic field cannot be replaced. - item->setParent(nullptr); - g_game.ReleaseItem(item); - return; - } - } - } - } - } - - items = makeItemList(); - items->insert(items->getBeginDownItem(), item); - items->addDownItemCount(1); - onAddTileItem(item); - } - } -} - -void Tile::updateThing(Thing* thing, uint16_t itemId, uint32_t count) -{ - int32_t index = getThingIndex(thing); - if (index == -1) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - const ItemType& oldType = Item::items[item->getID()]; - const ItemType& newType = Item::items[itemId]; - resetTileFlags(item); - item->setID(itemId); - item->setSubType(count); - setTileFlags(item); - onUpdateTileItem(item, oldType, item, newType); -} - -void Tile::replaceThing(uint32_t index, Thing* thing) -{ - int32_t pos = index; - - Item* item = thing->getItem(); - if (item == nullptr) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - Item* oldItem = nullptr; - bool isInserted = false; - - if (ground) { - if (pos == 0) { - oldItem = ground; - ground = item; - isInserted = true; - } - - --pos; - } - - TileItemVector* items = getItemList(); - if (items && !isInserted) { - int32_t topItemSize = getTopItemCount(); - if (pos < topItemSize) { - ItemVector::iterator it = items->getBeginTopItem(); - it += pos; - - oldItem = (*it); - it = items->erase(it); - items->insert(it, item); - isInserted = true; - } - - pos -= topItemSize; - } - - CreatureVector* creatures = getCreatures(); - if (creatures) { - if (!isInserted && pos < static_cast(creatures->size())) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - pos -= static_cast(creatures->size()); - } - - if (items && !isInserted) { - int32_t downItemSize = getDownItemCount(); - if (pos < downItemSize) { - ItemVector::iterator it = items->getBeginDownItem() + pos; - oldItem = *it; - it = items->erase(it); - items->insert(it, item); - isInserted = true; - } - } - - if (isInserted) { - item->setParent(this); - - resetTileFlags(oldItem); - setTileFlags(item); - const ItemType& oldType = Item::items[oldItem->getID()]; - const ItemType& newType = Item::items[item->getID()]; - onUpdateTileItem(oldItem, oldType, item, newType); - - oldItem->setParent(nullptr); - return /*RETURNVALUE_NOERROR*/; - } -} - -void Tile::removeThing(Thing* thing, uint32_t count) -{ - Creature* creature = thing->getCreature(); - if (creature) { - CreatureVector* creatures = getCreatures(); - if (creatures) { - CreatureVector::iterator it = std::find(creatures->begin(), creatures->end(), thing); - if (it != creatures->end()) { - g_game.map.clearSpectatorCache(); - creatures->erase(it); - } - } - return; - } - - Item* item = thing->getItem(); - if (!item) { - return; - } - - int32_t index = getThingIndex(item); - if (index == -1) { - return; - } - - if (item == ground) { - ground->setParent(nullptr); - ground = nullptr; - - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true); - onRemoveTileItem(list, std::vector(list.size(), 0), item); - return; - } - - TileItemVector* items = getItemList(); - if (!items) { - return; - } - - const ItemType& itemType = Item::items[item->getID()]; - if (itemType.alwaysOnTop) { - auto it = std::find(items->getBeginTopItem(), items->getEndTopItem(), item); - if (it == items->getEndTopItem()) { - return; - } - - std::vector oldStackPosVector; - - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true); - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item)); - } - } - - item->setParent(nullptr); - items->erase(it); - onRemoveTileItem(list, oldStackPosVector, item); - } else { - auto it = std::find(items->getBeginDownItem(), items->getEndDownItem(), item); - if (it == items->getEndDownItem()) { - return; - } - - if (itemType.stackable && count != item->getItemCount()) { - uint8_t newCount = static_cast(std::max(0, static_cast(item->getItemCount() - count))); - item->setItemCount(newCount); - onUpdateTileItem(item, itemType, item, itemType); - } else { - std::vector oldStackPosVector; - - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true); - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - oldStackPosVector.push_back(getStackposOfItem(tmpPlayer, item)); - } - } - - item->setParent(nullptr); - items->erase(it); - items->addDownItemCount(-1); - onRemoveTileItem(list, oldStackPosVector, item); - } - } -} - -void Tile::removeCreature(Creature* creature) -{ - g_game.map.getQTNode(tilePos.x, tilePos.y)->removeCreature(creature); - removeThing(creature, 0); -} - -int32_t Tile::getThingIndex(const Thing* thing) const -{ - int32_t n = -1; - if (ground) { - if (ground == thing) { - return 0; - } - ++n; - } - - const TileItemVector* items = getItemList(); - if (items) { - const Item* item = thing->getItem(); - if (item && item->isAlwaysOnTop()) { - for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - ++n; - if (*it == item) { - return n; - } - } - } else { - n += items->getTopItemCount(); - } - } - - if (const CreatureVector* creatures = getCreatures()) { - if (thing->getCreature()) { - for (Creature* creature : *creatures) { - ++n; - if (creature == thing) { - return n; - } - } - } else { - n += creatures->size(); - } - } - - if (items) { - const Item* item = thing->getItem(); - if (item && !item->isAlwaysOnTop()) { - for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - ++n; - if (*it == item) { - return n; - } - } - } - } - return -1; -} - -int32_t Tile::getClientIndexOfCreature(const Player* player, const Creature* creature) const -{ - int32_t n; - if (ground) { - n = 1; - } else { - n = 0; - } - - const TileItemVector* items = getItemList(); - if (items) { - n += items->getTopItemCount(); - } - - if (const CreatureVector* creatures = getCreatures()) { - for (const Creature* c : boost::adaptors::reverse(*creatures)) { - if (c == creature) { - return n; - } else if (player->canSeeCreature(c)) { - ++n; - } - } - } - return -1; -} - -int32_t Tile::getStackposOfCreature(const Player* player, const Creature* creature) const -{ - int32_t n; - if (ground) { - n = 1; - } else { - n = 0; - } - - const TileItemVector* items = getItemList(); - if (items) { - n += items->getTopItemCount(); - if (n >= 10) { - return -1; - } - } - - if (const CreatureVector* creatures = getCreatures()) { - for (const Creature* c : boost::adaptors::reverse(*creatures)) { - if (c == creature) { - return n; - } else if (player->canSeeCreature(c)) { - if (++n >= 10) { - return -1; - } - } - } - } - return -1; -} - -int32_t Tile::getStackposOfItem(const Player* player, const Item* item) const -{ - int32_t n = 0; - if (ground) { - if (ground == item) { - return n; - } - ++n; - } - - const TileItemVector* items = getItemList(); - if (items) { - if (item->isAlwaysOnTop()) { - for (ItemVector::const_iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - if (*it == item) { - return n; - } else if (++n == 10) { - return -1; - } - } - } else { - n += items->getTopItemCount(); - if (n >= 10) { - return -1; - } - } - } - - if (const CreatureVector* creatures = getCreatures()) { - for (const Creature* creature : *creatures) { - if (player->canSeeCreature(creature)) { - if (++n >= 10) { - return -1; - } - } - } - } - - if (items && !item->isAlwaysOnTop()) { - for (ItemVector::const_iterator it = items->getBeginDownItem(), end = items->getEndDownItem(); it != end; ++it) { - if (*it == item) { - return n; - } else if (++n >= 10) { - return -1; - } - } - } - return -1; -} - -size_t Tile::getFirstIndex() const -{ - return 0; -} - -size_t Tile::getLastIndex() const -{ - return getThingCount(); -} - -uint32_t Tile::getItemTypeCount(uint16_t itemId, int32_t subType /*= -1*/) const -{ - uint32_t count = 0; - if (ground && ground->getID() == itemId) { - count += Item::countByType(ground, subType); - } - - const TileItemVector* items = getItemList(); - if (items) { - for (const Item* item : *items) { - if (item->getID() == itemId) { - count += Item::countByType(item, subType); - } - } - } - return count; -} - -Thing* Tile::getThing(size_t index) const -{ - if (ground) { - if (index == 0) { - return ground; - } - - --index; - } - - const TileItemVector* items = getItemList(); - if (items) { - uint32_t topItemSize = items->getTopItemCount(); - if (index < topItemSize) { - return items->at(items->getDownItemCount() + index); - } - index -= topItemSize; - } - - if (const CreatureVector* creatures = getCreatures()) { - if (index < creatures->size()) { - return (*creatures)[index]; - } - index -= creatures->size(); - } - - if (items && index < items->getDownItemCount()) { - return items->at(index); - } - return nullptr; -} - -void Tile::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link /*= LINK_OWNER*/) -{ - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true, true); - for (Creature* spectator : list) { - spectator->getPlayer()->postAddNotification(thing, oldParent, index, LINK_NEAR); - } - - //add a reference to this item, it may be deleted after being added (mailbox for example) - Creature* creature = thing->getCreature(); - Item* item; - if (creature) { - creature->incrementReferenceCounter(); - item = nullptr; - } else { - item = thing->getItem(); - if (item) { - item->incrementReferenceCounter(); - } - } - - if (link == LINK_OWNER) { - if (hasFlag(TILESTATE_TELEPORT)) { - Teleport* teleport = getTeleportItem(); - if (teleport) { - teleport->addThing(thing); - } - } else if (hasFlag(TILESTATE_TRASHHOLDER)) { - TrashHolder* trashholder = getTrashHolder(); - if (trashholder) { - trashholder->addThing(thing); - } - } else if (hasFlag(TILESTATE_MAILBOX)) { - Mailbox* mailbox = getMailbox(); - if (mailbox) { - mailbox->addThing(thing); - } - } - - //calling movement scripts - if (creature) { - g_moveEvents->onCreatureMove(creature, this, oldParent ? oldParent->getPosition() : getPosition(), MOVE_EVENT_STEP_IN); - } else if (item) { - g_moveEvents->onItemMove(item, this, true); - } - } - - //release the reference to this item onces we are finished - if (creature) { - g_game.ReleaseCreature(creature); - } else if (item) { - g_game.ReleaseItem(item); - } -} - -void Tile::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - SpectatorVec list; - g_game.map.getSpectators(list, getPosition(), true, true); - - if (getThingCount() > 8) { - onUpdateTile(list); - } - - for (Creature* spectator : list) { - spectator->getPlayer()->postRemoveNotification(thing, newParent, index, LINK_NEAR); - } - - //calling movement scripts - Creature* creature = thing->getCreature(); - if (creature) { - g_moveEvents->onCreatureMove(creature, this, getPosition(), MOVE_EVENT_STEP_OUT); - } else { - Item* item = thing->getItem(); - if (item) { - g_moveEvents->onItemMove(item, this, false); - } - } -} - -void Tile::internalAddThing(Thing* thing) -{ - internalAddThing(0, thing); -} - -void Tile::internalAddThing(uint32_t, Thing* thing) -{ - thing->setParent(this); - - Creature* creature = thing->getCreature(); - if (creature) { - g_game.map.clearSpectatorCache(); - CreatureVector* creatures = makeCreatures(); - creatures->insert(creatures->begin(), creature); - } else { - Item* item = thing->getItem(); - if (item == nullptr) { - return; - } - - const ItemType& itemType = Item::items[item->getID()]; - if (itemType.isGroundTile()) { - if (ground == nullptr) { - ground = item; - setTileFlags(item); - } - return; - } - - TileItemVector* items = makeItemList(); - if (items->size() >= 0xFFFF) { - return /*RETURNVALUE_NOTPOSSIBLE*/; - } - - if (itemType.alwaysOnTop) { - bool isInserted = false; - for (ItemVector::iterator it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) { - if (Item::items[(*it)->getID()].alwaysOnTopOrder > itemType.alwaysOnTopOrder) { - items->insert(it, item); - isInserted = true; - break; - } - } - - if (!isInserted) { - items->push_back(item); - } - } else { - items->insert(items->getBeginDownItem(), item); - items->addDownItemCount(1); - } - - setTileFlags(item); - } -} - -void Tile::setTileFlags(const Item* item) -{ - if (!hasFlag(TILESTATE_FLOORCHANGE)) { - const ItemType& it = Item::items[item->getID()]; - if (it.floorChangeDown) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_DOWN); - } - - if (it.floorChangeNorth) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_NORTH); - } - - if (it.floorChangeSouth) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_SOUTH); - } - - if (it.floorChangeEast) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_EAST); - } - - if (it.floorChangeWest) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_WEST); - } - - if (it.floorChangeSouthAlt) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT); - } - - if (it.floorChangeEastAlt) { - setFlag(TILESTATE_FLOORCHANGE); - setFlag(TILESTATE_FLOORCHANGE_EAST_ALT); - } - } - - if (item->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID)) { - setFlag(TILESTATE_IMMOVABLEBLOCKSOLID); - } - - if (item->hasProperty(CONST_PROP_BLOCKPATH)) { - setFlag(TILESTATE_BLOCKPATH); - } - - if (item->hasProperty(CONST_PROP_NOFIELDBLOCKPATH)) { - setFlag(TILESTATE_NOFIELDBLOCKPATH); - } - - if (item->hasProperty(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH)) { - setFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH); - } - - if (item->getTeleport()) { - setFlag(TILESTATE_TELEPORT); - } - - if (item->getMagicField()) { - setFlag(TILESTATE_MAGICFIELD); - } - - if (item->getMailbox()) { - setFlag(TILESTATE_MAILBOX); - } - - if (item->getTrashHolder()) { - setFlag(TILESTATE_TRASHHOLDER); - } - - if (item->hasProperty(CONST_PROP_BLOCKSOLID)) { - setFlag(TILESTATE_BLOCKSOLID); - } - - if (item->getBed()) { - setFlag(TILESTATE_BED); - } - - const Container* container = item->getContainer(); - if (container && container->getDepotLocker()) { - setFlag(TILESTATE_DEPOT); - } - - if (item->hasProperty(CONST_PROP_SUPPORTHANGABLE)) { - setFlag(TILESTATE_SUPPORTS_HANGABLE); - } -} - -void Tile::resetTileFlags(const Item* item) -{ - const ItemType& it = Item::items[item->getID()]; - if (it.floorChangeDown) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_DOWN); - } - - if (it.floorChangeNorth) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_NORTH); - } - - if (it.floorChangeSouth) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_SOUTH); - } - - if (it.floorChangeEast) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_EAST); - } - - if (it.floorChangeWest) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_WEST); - } - - if (it.floorChangeSouthAlt) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT); - } - - if (it.floorChangeEastAlt) { - resetFlag(TILESTATE_FLOORCHANGE); - resetFlag(TILESTATE_FLOORCHANGE_EAST_ALT); - } - - if (item->hasProperty(CONST_PROP_BLOCKSOLID) && !hasProperty(item, CONST_PROP_BLOCKSOLID)) { - resetFlag(TILESTATE_BLOCKSOLID); - } - - if (item->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && !hasProperty(item, CONST_PROP_IMMOVABLEBLOCKSOLID)) { - resetFlag(TILESTATE_IMMOVABLEBLOCKSOLID); - } - - if (item->hasProperty(CONST_PROP_BLOCKPATH) && !hasProperty(item, CONST_PROP_BLOCKPATH)) { - resetFlag(TILESTATE_BLOCKPATH); - } - - if (item->hasProperty(CONST_PROP_NOFIELDBLOCKPATH) && !hasProperty(item, CONST_PROP_NOFIELDBLOCKPATH)) { - resetFlag(TILESTATE_NOFIELDBLOCKPATH); - } - - if (item->hasProperty(CONST_PROP_IMMOVABLEBLOCKPATH) && !hasProperty(item, CONST_PROP_IMMOVABLEBLOCKPATH)) { - resetFlag(TILESTATE_IMMOVABLEBLOCKPATH); - } - - if (item->hasProperty(CONST_PROP_IMMOVABLENOFIELDBLOCKPATH) && !hasProperty(item, CONST_PROP_IMMOVABLENOFIELDBLOCKPATH)) { - resetFlag(TILESTATE_IMMOVABLENOFIELDBLOCKPATH); - } - - if (item->getTeleport()) { - resetFlag(TILESTATE_TELEPORT); - } - - if (item->getMagicField()) { - resetFlag(TILESTATE_MAGICFIELD); - } - - if (item->getMailbox()) { - resetFlag(TILESTATE_MAILBOX); - } - - if (item->getTrashHolder()) { - resetFlag(TILESTATE_TRASHHOLDER); - } - - if (item->getBed()) { - resetFlag(TILESTATE_BED); - } - - const Container* container = item->getContainer(); - if (container && container->getDepotLocker()) { - resetFlag(TILESTATE_DEPOT); - } - - if (item->hasProperty(CONST_PROP_SUPPORTHANGABLE)) { - resetFlag(TILESTATE_SUPPORTS_HANGABLE); - } -} - -bool Tile::isMoveableBlocking() const -{ - return !ground || hasFlag(TILESTATE_BLOCKSOLID); -} - -Item* Tile::getUseItem() const -{ - const TileItemVector* items = getItemList(); - if (!items || items->size() == 0) { - return ground; - } - - for (Item* item : boost::adaptors::reverse(*items)) { - if (Item::items[item->getID()].forceUse) { - return item; - } - } - - Item* item = items->getTopDownItem(); - if (!item) { - item = items->getTopTopItem(); - } - return item; -} diff --git a/path_10_8/src/tile.h b/path_10_8/src/tile.h deleted file mode 100644 index 474316ede..000000000 --- a/path_10_8/src/tile.h +++ /dev/null @@ -1,459 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TILE_H_96C7EE7CF8CD48E59D5D554A181F0C56 -#define FS_TILE_H_96C7EE7CF8CD48E59D5D554A181F0C56 - -#include - -#include "cylinder.h" -#include "item.h" -#include "tools.h" - -class Creature; -class Teleport; -class TrashHolder; -class Mailbox; -class MagicField; -class QTreeLeafNode; -class BedItem; - -typedef std::vector CreatureVector; -typedef std::vector ItemVector; -typedef std::unordered_set SpectatorVec; - -enum tileflags_t : uint32_t { - TILESTATE_NONE, - - TILESTATE_PROTECTIONZONE = 1 << 0, - TILESTATE_DEPRECATED_HOUSE = 1 << 1, - TILESTATE_NOPVPZONE = 1 << 2, - TILESTATE_NOLOGOUT = 1 << 3, - TILESTATE_PVPZONE = 1 << 4, - TILESTATE_REFRESH = 1 << 5, // unused - - //internal usage - TILESTATE_HOUSE = 1 << 6, - TILESTATE_FLOORCHANGE = 1 << 7, - TILESTATE_FLOORCHANGE_DOWN = 1 << 8, - TILESTATE_FLOORCHANGE_NORTH = 1 << 9, - TILESTATE_FLOORCHANGE_SOUTH = 1 << 10, - TILESTATE_FLOORCHANGE_EAST = 1 << 11, - TILESTATE_FLOORCHANGE_WEST = 1 << 12, - TILESTATE_TELEPORT = 1 << 13, - TILESTATE_MAGICFIELD = 1 << 14, - TILESTATE_MAILBOX = 1 << 15, - TILESTATE_TRASHHOLDER = 1 << 16, - TILESTATE_BED = 1 << 17, - TILESTATE_DEPOT = 1 << 18, - TILESTATE_BLOCKSOLID = 1 << 19, - TILESTATE_BLOCKPATH = 1 << 20, - TILESTATE_IMMOVABLEBLOCKSOLID = 1 << 21, - TILESTATE_IMMOVABLEBLOCKPATH = 1 << 22, - TILESTATE_IMMOVABLENOFIELDBLOCKPATH = 1 << 23, - TILESTATE_NOFIELDBLOCKPATH = 1 << 24, - TILESTATE_DYNAMIC_TILE = 1 << 25, //DEPRECATED - TILESTATE_FLOORCHANGE_SOUTH_ALT = 1 << 26, - TILESTATE_FLOORCHANGE_EAST_ALT = 1 << 27, - TILESTATE_SUPPORTS_HANGABLE = 1 << 28, -}; - -enum ZoneType_t { - ZONE_PROTECTION, - ZONE_NOPVP, - ZONE_PVP, - ZONE_NOLOGOUT, - ZONE_NORMAL, -}; - -class TileItemVector : private ItemVector -{ - public: - using ItemVector::begin; - using ItemVector::end; - using ItemVector::rbegin; - using ItemVector::rend; - using ItemVector::size; - using ItemVector::clear; - using ItemVector::at; - using ItemVector::insert; - using ItemVector::erase; - using ItemVector::push_back; - using ItemVector::value_type; - using ItemVector::iterator; - using ItemVector::const_iterator; - using ItemVector::reverse_iterator; - using ItemVector::const_reverse_iterator; - - iterator getBeginDownItem() { - return begin(); - } - const_iterator getBeginDownItem() const { - return begin(); - } - iterator getEndDownItem() { - return begin() + downItemCount; - } - const_iterator getEndDownItem() const { - return begin() + downItemCount; - } - iterator getBeginTopItem() { - return getEndDownItem(); - } - const_iterator getBeginTopItem() const { - return getEndDownItem(); - } - iterator getEndTopItem() { - return end(); - } - const_iterator getEndTopItem() const { - return end(); - } - - uint32_t getTopItemCount() const { - return size() - downItemCount; - } - uint32_t getDownItemCount() const { - return downItemCount; - } - inline Item* getTopTopItem() const { - if (getTopItemCount() == 0) { - return nullptr; - } - return *(getEndTopItem() - 1); - } - inline Item* getTopDownItem() const { - if (downItemCount == 0) { - return nullptr; - } - return *getBeginDownItem(); - } - void addDownItemCount(int32_t increment) { - downItemCount += increment; - } - private: - uint16_t downItemCount {0}; -}; - -class Tile : public Cylinder -{ - public: - static Tile& nullptr_tile; - Tile(uint16_t x, uint16_t y, uint8_t z); - virtual ~Tile(); - - // non-copyable - Tile(const Tile&) = delete; - Tile& operator=(const Tile&) = delete; - - virtual TileItemVector* getItemList() = 0; - virtual const TileItemVector* getItemList() const = 0; - virtual TileItemVector* makeItemList() = 0; - - virtual CreatureVector* getCreatures() = 0; - virtual const CreatureVector* getCreatures() const = 0; - virtual CreatureVector* makeCreatures() = 0; - - int32_t getThrowRange() const final { - return 0; - } - bool isPushable() const final { - return false; - } - - MagicField* getFieldItem() const; - Teleport* getTeleportItem() const; - TrashHolder* getTrashHolder() const; - Mailbox* getMailbox() const; - BedItem* getBedItem() const; - - Creature* getTopCreature() const; - const Creature* getBottomCreature() const; - Creature* getTopVisibleCreature(const Creature* creature) const; - const Creature* getBottomVisibleCreature(const Creature* creature) const; - Item* getTopTopItem() const; - Item* getTopDownItem() const; - bool isMoveableBlocking() const; - Thing* getTopVisibleThing(const Creature* creature); - Item* getItemByTopOrder(int32_t topOrder); - - size_t getThingCount() const { - size_t thingCount = getCreatureCount() + getItemCount(); - if (ground) { - thingCount++; - } - return thingCount; - } - // If these return != 0 the associated vectors are guaranteed to exists - size_t getCreatureCount() const; - size_t getItemCount() const; - uint32_t getTopItemCount() const; - uint32_t getDownItemCount() const; - - bool hasProperty(ITEMPROPERTY prop) const; - bool hasProperty(const Item* exclude, ITEMPROPERTY prop) const; - - bool hasFlag(tileflags_t flag) const { - return hasBitSet(flag, m_flags); - } - void setFlag(tileflags_t flag) { - m_flags |= static_cast(flag); - } - void resetFlag(tileflags_t flag) { - m_flags &= ~static_cast(flag); - } - - bool positionChange() const { - return hasFlag(TILESTATE_TELEPORT); - } - bool floorChange() const { - return hasFlag(TILESTATE_FLOORCHANGE); - } - bool floorChangeDown() const { - return hasFlag(TILESTATE_FLOORCHANGE_DOWN); - } - bool floorChange(Direction direction) const { - switch (direction) { - case DIRECTION_NORTH: - return hasFlag(TILESTATE_FLOORCHANGE_NORTH); - - case DIRECTION_SOUTH: - return hasFlag(TILESTATE_FLOORCHANGE_SOUTH); - - case DIRECTION_EAST: - return hasFlag(TILESTATE_FLOORCHANGE_EAST); - - case DIRECTION_WEST: - return hasFlag(TILESTATE_FLOORCHANGE_WEST); - - case DIRECTION_SOUTH_ALT: - return hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT); - - case DIRECTION_EAST_ALT: - return hasFlag(TILESTATE_FLOORCHANGE_EAST_ALT); - - default: - return false; - } - } - - ZoneType_t getZone() const { - if (hasFlag(TILESTATE_PROTECTIONZONE)) { - return ZONE_PROTECTION; - } else if (hasFlag(TILESTATE_NOPVPZONE)) { - return ZONE_NOPVP; - } else if (hasFlag(TILESTATE_PVPZONE)) { - return ZONE_PVP; - } else { - return ZONE_NORMAL; - } - } - - bool hasHeight(uint32_t n) const; - - std::string getDescription(int32_t lookDistance) const final; - - int32_t getClientIndexOfCreature(const Player* player, const Creature* creature) const; - int32_t getStackposOfCreature(const Player* player, const Creature* creature) const; - int32_t getStackposOfItem(const Player* player, const Item* item) const; - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor = nullptr) const override; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, - uint32_t& maxQueryCount, uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Tile* queryDestination(int32_t& index, const Thing& thing, Item** destItem, uint32_t& flags) override; - - void addThing(Thing* thing) final; - void addThing(int32_t index, Thing* thing) override; - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - void removeCreature(Creature* creature); - - int32_t getThingIndex(const Thing* thing) const final; - size_t getFirstIndex() const final; - size_t getLastIndex() const final; - uint32_t getItemTypeCount(uint16_t itemId, int32_t subType = -1) const final; - Thing* getThing(size_t index) const final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - - void internalAddThing(Thing* thing) final; - void internalAddThing(uint32_t index, Thing* thing) override; - - const Position& getPosition() const final { - return tilePos; - } - - bool isRemoved() const final { - return false; - } - - Item* getUseItem() const; - - Item* getGround() const { - return ground; - } - void setGround(Item* item) { - ground = item; - } - - private: - void onAddTileItem(Item* item); - void onUpdateTileItem(Item* oldItem, const ItemType& oldType, Item* newItem, const ItemType& newType); - void onRemoveTileItem(const SpectatorVec& list, const std::vector& oldStackPosVector, Item* item); - void onUpdateTile(const SpectatorVec& list); - - void setTileFlags(const Item* item); - void resetTileFlags(const Item* item); - - protected: - Item* ground; - Position tilePos; - uint32_t m_flags; -}; - -// Used for walkable tiles, where there is high likeliness of -// items being added/removed -class DynamicTile : public Tile -{ - // By allocating the vectors in-house, we avoid some memory fragmentation - TileItemVector items; - CreatureVector creatures; - - public: - DynamicTile(uint16_t x, uint16_t y, uint8_t z); - ~DynamicTile(); - - // non-copyable - DynamicTile(const DynamicTile&) = delete; - DynamicTile& operator=(const DynamicTile&) = delete; - - TileItemVector* getItemList() final { - return &items; - } - const TileItemVector* getItemList() const final { - return &items; - } - TileItemVector* makeItemList() final { - return &items; - } - - CreatureVector* getCreatures() final { - return &creatures; - } - const CreatureVector* getCreatures() const final { - return &creatures; - } - CreatureVector* makeCreatures() final { - return &creatures; - } -}; - -// For blocking tiles, where we very rarely actually have items -class StaticTile final : public Tile -{ - // We very rarely even need the vectors, so don't keep them in memory - std::unique_ptr items; - std::unique_ptr creatures; - - public: - StaticTile(uint16_t x, uint16_t y, uint8_t z); - ~StaticTile(); - - // non-copyable - StaticTile(const StaticTile&) = delete; - StaticTile& operator=(const StaticTile&) = delete; - - TileItemVector* getItemList() final { - return items.get(); - } - const TileItemVector* getItemList() const final { - return items.get(); - } - TileItemVector* makeItemList() final { - if (!items) { - items.reset(new TileItemVector); - } - return items.get(); - } - - CreatureVector* getCreatures() final { - return creatures.get(); - } - const CreatureVector* getCreatures() const final { - return creatures.get(); - } - CreatureVector* makeCreatures() final { - if (!creatures) { - creatures.reset(new CreatureVector); - } - return creatures.get(); - } -}; - -inline Tile::Tile(uint16_t x, uint16_t y, uint8_t z) : - ground(nullptr), - tilePos(x, y, z), - m_flags(0) -{ -} - -inline Tile::~Tile() -{ - delete ground; -} - - -inline StaticTile::StaticTile(uint16_t x, uint16_t y, uint8_t z) : - Tile(x, y, z), - items(nullptr), - creatures(nullptr) -{ -} - -inline StaticTile::~StaticTile() -{ - if (items) { - for (Item* item : *items) { - item->decrementReferenceCounter(); - } - } -} - -inline DynamicTile::DynamicTile(uint16_t x, uint16_t y, uint8_t z) : - Tile(x, y, z) -{ - m_flags |= TILESTATE_DYNAMIC_TILE; -} - -inline DynamicTile::~DynamicTile() -{ - for (Item* item : items) { - item->decrementReferenceCounter(); - } -} - -#endif diff --git a/path_10_8/src/tools.cpp b/path_10_8/src/tools.cpp deleted file mode 100644 index 1d900ebb5..000000000 --- a/path_10_8/src/tools.cpp +++ /dev/null @@ -1,1184 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "tools.h" -#include "configmanager.h" - -extern ConfigManager g_config; - -void printXMLError(const std::string& where, const std::string& fileName, const pugi::xml_parse_result& result) -{ - std::cout << '[' << where << "] Failed to load " << fileName << ": " << result.description() << std::endl; - - FILE* file = fopen(fileName.c_str(), "rb"); - if (!file) { - return; - } - - char buffer[32768]; - uint32_t currentLine = 1; - std::string line; - - size_t offset = static_cast(result.offset); - size_t lineOffsetPosition = 0; - size_t index = 0; - size_t bytes; - do { - bytes = fread(buffer, 1, 32768, file); - for (size_t i = 0; i < bytes; ++i) { - char ch = buffer[i]; - if (ch == '\n') { - if ((index + i) >= offset) { - lineOffsetPosition = line.length() - ((index + i) - offset); - bytes = 0; - break; - } - ++currentLine; - line.clear(); - } else { - line.push_back(ch); - } - } - index += bytes; - } while (bytes == 32768); - fclose(file); - - std::cout << "Line " << currentLine << ':' << std::endl; - std::cout << line << std::endl; - for (size_t i = 0; i < lineOffsetPosition; i++) { - if (line[i] == '\t') { - std::cout << '\t'; - } else { - std::cout << ' '; - } - } - std::cout << '^' << std::endl; -} - -inline static uint32_t circularShift(int bits, uint32_t value) -{ - return (value << bits) | (value >> (32 - bits)); -} - -static void processSHA1MessageBlock(const uint8_t* messageBlock, uint32_t* H) -{ - uint32_t W[80]; - for (int i = 0; i < 16; ++i) { - const size_t offset = i << 2; - W[i] = messageBlock[offset] << 24 | messageBlock[offset + 1] << 16 | messageBlock[offset + 2] << 8 | messageBlock[offset + 3]; - } - - for (int i = 16; i < 80; ++i) { - W[i] = circularShift(1, W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]); - } - - uint32_t A = H[0], B = H[1], C = H[2], D = H[3], E = H[4]; - - for (int i = 0; i < 20; ++i) { - const uint32_t tmp = circularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[i] + 0x5A827999; - E = D; D = C; C = circularShift(30, B); B = A; A = tmp; - } - - for (int i = 20; i < 40; ++i) { - const uint32_t tmp = circularShift(5, A) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1; - E = D; D = C; C = circularShift(30, B); B = A; A = tmp; - } - - for (int i = 40; i < 60; ++i) { - const uint32_t tmp = circularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC; - E = D; D = C; C = circularShift(30, B); B = A; A = tmp; - } - - for (int i = 60; i < 80; ++i) { - const uint32_t tmp = circularShift(5, A) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6; - E = D; D = C; C = circularShift(30, B); B = A; A = tmp; - } - - H[0] += A; - H[1] += B; - H[2] += C; - H[3] += D; - H[4] += E; -} - -std::string transformToSHA1(const std::string& input) -{ - uint32_t H[] = { - 0x67452301, - 0xEFCDAB89, - 0x98BADCFE, - 0x10325476, - 0xC3D2E1F0 - }; - - uint8_t messageBlock[64]; - size_t index = 0; - - uint32_t length_low = 0; - uint32_t length_high = 0; - for (char ch : input) { - messageBlock[index++] = ch; - - length_low += 8; - if (length_low == 0) { - length_high++; - } - - if (index == 64) { - processSHA1MessageBlock(messageBlock, H); - index = 0; - } - } - - messageBlock[index++] = 0x80; - - if (index > 56) { - while (index < 64) { - messageBlock[index++] = 0; - } - - processSHA1MessageBlock(messageBlock, H); - index = 0; - } - - while (index < 56) { - messageBlock[index++] = 0; - } - - messageBlock[56] = length_high >> 24; - messageBlock[57] = length_high >> 16; - messageBlock[58] = length_high >> 8; - messageBlock[59] = length_high; - - messageBlock[60] = length_low >> 24; - messageBlock[61] = length_low >> 16; - messageBlock[62] = length_low >> 8; - messageBlock[63] = length_low; - - processSHA1MessageBlock(messageBlock, H); - - char hexstring[41]; - static const char hexDigits[] = {"0123456789abcdef"}; - for (int hashByte = 20; --hashByte >= 0;) { - const uint8_t byte = H[hashByte >> 2] >> (((3 - hashByte) & 3) << 3); - index = hashByte << 1; - hexstring[index] = hexDigits[byte >> 4]; - hexstring[index + 1] = hexDigits[byte & 15]; - } - return std::string(hexstring, 40); -} - -void replaceString(std::string& str, const std::string& sought, const std::string& replacement) -{ - size_t pos = 0; - size_t start = 0; - size_t soughtLen = sought.length(); - size_t replaceLen = replacement.length(); - - while ((pos = str.find(sought, start)) != std::string::npos) { - str = str.substr(0, pos) + replacement + str.substr(pos + soughtLen); - start = pos + replaceLen; - } -} - -void trim_right(std::string& source, char t) -{ - source.erase(source.find_last_not_of(t) + 1); -} - -void trim_left(std::string& source, char t) -{ - source.erase(0, source.find_first_not_of(t)); -} - -void toLowerCaseString(std::string& source) -{ - std::transform(source.begin(), source.end(), source.begin(), tolower); -} - -std::string asLowerCaseString(const std::string& source) -{ - std::string s = source; - toLowerCaseString(s); - return s; -} - -std::string asUpperCaseString(const std::string& source) -{ - std::string s = source; - std::transform(s.begin(), s.end(), s.begin(), toupper); - return s; -} - -StringVec explodeString(const std::string& inString, const std::string& separator, int32_t limit/* = -1*/) -{ - StringVec returnVector; - std::string::size_type start = 0, end = 0; - - while (--limit != -1 && (end = inString.find(separator, start)) != std::string::npos) { - returnVector.push_back(inString.substr(start, end - start)); - start = end + separator.size(); - } - - returnVector.push_back(inString.substr(start)); - return returnVector; -} - -IntegerVec vectorAtoi(const StringVec& stringVector) -{ - IntegerVec returnVector; - for (const auto& string : stringVector) { - returnVector.push_back(std::stoi(string)); - } - return returnVector; -} - -bool hasBitSet(uint32_t flag, uint32_t flags) -{ - return ((flags & flag) == flag); -} - -std::mt19937& getRandomGenerator() -{ - static std::random_device rd; - static std::mt19937 generator(rd()); - return generator; -} - -int32_t uniform_random(int32_t minNumber, int32_t maxNumber) -{ - static std::uniform_int_distribution uniformRand; - if (minNumber == maxNumber) { - return minNumber; - } else if (minNumber > maxNumber) { - std::swap(minNumber, maxNumber); - } - return uniformRand(getRandomGenerator(), std::uniform_int_distribution::param_type(minNumber, maxNumber)); -} - -int32_t normal_random(int32_t minNumber, int32_t maxNumber) -{ - static std::normal_distribution normalRand(0.5f, 0.25f); - if (minNumber == maxNumber) { - return minNumber; - } else if (minNumber > maxNumber) { - std::swap(minNumber, maxNumber); - } - return minNumber + std::max(0.f, std::min(1.f, normalRand(getRandomGenerator()))) * (maxNumber - minNumber); -} - -bool boolean_random(double probability/* = 0.5*/) -{ - static std::bernoulli_distribution booleanRand; - return booleanRand(getRandomGenerator(), std::bernoulli_distribution::param_type(probability)); -} - -void trimString(std::string& str) -{ - str.erase(str.find_last_not_of(' ') + 1); - str.erase(0, str.find_first_not_of(' ')); -} - -std::string convertIPToString(uint32_t ip) -{ - char buffer[17]; - - int res = sprintf(buffer, "%u.%u.%u.%u", ip & 0xFF, (ip >> 8) & 0xFF, (ip >> 16) & 0xFF, (ip >> 24)); - if (res < 0) { - return std::string(); - } - - return buffer; -} - -std::string formatDate(time_t time) -{ - const tm* tms = localtime(&time); - if (!tms) { - return std::string(); - } - - char buffer[20]; - int res = sprintf(buffer, "%02d/%02d/%04d %02d:%02d:%02d", tms->tm_mday, tms->tm_mon + 1, tms->tm_year + 1900, tms->tm_hour, tms->tm_min, tms->tm_sec); - if (res < 0) { - return std::string(); - } - return std::string(buffer, 19); -} - -std::string formatDateShort(time_t time) -{ - const tm* tms = localtime(&time); - if (!tms) { - return std::string(); - } - - char buffer[12]; - size_t res = strftime(buffer, 12, "%d %b %Y", tms); - if (res == 0) { - return std::string(); - } - return std::string(buffer, 11); -} - -Direction getDirection(const std::string& string) -{ - Direction direction = DIRECTION_NORTH; - - if (string == "north" || string == "n" || string == "0") { - direction = DIRECTION_NORTH; - } else if (string == "east" || string == "e" || string == "1") { - direction = DIRECTION_EAST; - } else if (string == "south" || string == "s" || string == "2") { - direction = DIRECTION_SOUTH; - } else if (string == "west" || string == "w" || string == "3") { - direction = DIRECTION_WEST; - } else if (string == "southwest" || string == "south west" || string == "south-west" || string == "sw" || string == "4") { - direction = DIRECTION_SOUTHWEST; - } else if (string == "southeast" || string == "south east" || string == "south-east" || string == "se" || string == "5") { - direction = DIRECTION_SOUTHEAST; - } else if (string == "northwest" || string == "north west" || string == "north-west" || string == "nw" || string == "6") { - direction = DIRECTION_NORTHWEST; - } else if (string == "northeast" || string == "north east" || string == "north-east" || string == "ne" || string == "7") { - direction = DIRECTION_NORTHEAST; - } - - return direction; -} - -Position getNextPosition(Direction direction, Position pos) -{ - switch (direction) { - case DIRECTION_NORTH: - pos.y--; - break; - - case DIRECTION_SOUTH: - pos.y++; - break; - - case DIRECTION_WEST: - pos.x--; - break; - - case DIRECTION_EAST: - pos.x++; - break; - - case DIRECTION_SOUTHWEST: - pos.x--; - pos.y++; - break; - - case DIRECTION_NORTHWEST: - pos.x--; - pos.y--; - break; - - case DIRECTION_NORTHEAST: - pos.x++; - pos.y--; - break; - - case DIRECTION_SOUTHEAST: - pos.x++; - pos.y++; - break; - - default: - break; - } - - return pos; -} - -Direction getDirectionTo(const Position& from, const Position& to) -{ - Direction dir; - - int32_t x_offset = Position::getOffsetX(from, to); - if (x_offset < 0) { - dir = DIRECTION_EAST; - x_offset = std::abs(x_offset); - } else { - dir = DIRECTION_WEST; - } - - int32_t y_offset = Position::getOffsetY(from, to); - if (y_offset >= 0) { - if (y_offset > x_offset) { - dir = DIRECTION_NORTH; - } else if (y_offset == x_offset) { - if (dir == DIRECTION_EAST) { - dir = DIRECTION_NORTHEAST; - } else { - dir = DIRECTION_NORTHWEST; - } - } - } else { - y_offset = std::abs(y_offset); - if (y_offset > x_offset) { - dir = DIRECTION_SOUTH; - } else if (y_offset == x_offset) { - if (dir == DIRECTION_EAST) { - dir = DIRECTION_SOUTHEAST; - } else { - dir = DIRECTION_SOUTHWEST; - } - } - } - return dir; -} - -struct MagicEffectNames { - const char* name; - MagicEffectClasses effect; -}; - -struct ShootTypeNames { - const char* name; - ShootType_t shoot; -}; - -struct CombatTypeNames { - const char* name; - CombatType_t combat; -}; - -struct AmmoTypeNames { - const char* name; - Ammo_t ammoType; -}; - -struct WeaponActionNames { - const char* name; - WeaponAction_t weaponAction; -}; - -struct SkullNames { - const char* name; - Skulls_t skull; -}; - -MagicEffectNames magicEffectNames[] = { - {"redspark", CONST_ME_DRAWBLOOD}, - {"bluebubble", CONST_ME_LOSEENERGY}, - {"poff", CONST_ME_POFF}, - {"yellowspark", CONST_ME_BLOCKHIT}, - {"explosionarea", CONST_ME_EXPLOSIONAREA}, - {"explosion", CONST_ME_EXPLOSIONHIT}, - {"firearea", CONST_ME_FIREAREA}, - {"yellowbubble", CONST_ME_YELLOW_RINGS}, - {"greenbubble", CONST_ME_GREEN_RINGS}, - {"blackspark", CONST_ME_HITAREA}, - {"teleport", CONST_ME_TELEPORT}, - {"energy", CONST_ME_ENERGYHIT}, - {"blueshimmer", CONST_ME_MAGIC_BLUE}, - {"redshimmer", CONST_ME_MAGIC_RED}, - {"greenshimmer", CONST_ME_MAGIC_GREEN}, - {"fire", CONST_ME_HITBYFIRE}, - {"greenspark", CONST_ME_HITBYPOISON}, - {"mortarea", CONST_ME_MORTAREA}, - {"greennote", CONST_ME_SOUND_GREEN}, - {"rednote", CONST_ME_SOUND_RED}, - {"poison", CONST_ME_POISONAREA}, - {"yellownote", CONST_ME_SOUND_YELLOW}, - {"purplenote", CONST_ME_SOUND_PURPLE}, - {"bluenote", CONST_ME_SOUND_BLUE}, - {"whitenote", CONST_ME_SOUND_WHITE}, - {"bubbles", CONST_ME_BUBBLES}, - {"dice", CONST_ME_CRAPS}, - {"giftwraps", CONST_ME_GIFT_WRAPS}, - {"yellowfirework", CONST_ME_FIREWORK_YELLOW}, - {"redfirework", CONST_ME_FIREWORK_RED}, - {"bluefirework", CONST_ME_FIREWORK_BLUE}, - {"stun", CONST_ME_STUN}, - {"sleep", CONST_ME_SLEEP}, - {"watercreature", CONST_ME_WATERCREATURE}, - {"groundshaker", CONST_ME_GROUNDSHAKER}, - {"hearts", CONST_ME_HEARTS}, - {"fireattack", CONST_ME_FIREATTACK}, - {"energyarea", CONST_ME_ENERGYAREA}, - {"smallclouds", CONST_ME_SMALLCLOUDS}, - {"holydamage", CONST_ME_HOLYDAMAGE}, - {"bigclouds", CONST_ME_BIGCLOUDS}, - {"icearea", CONST_ME_ICEAREA}, - {"icetornado", CONST_ME_ICETORNADO}, - {"iceattack", CONST_ME_ICEATTACK}, - {"stones", CONST_ME_STONES}, - {"smallplants", CONST_ME_SMALLPLANTS}, - {"carniphila", CONST_ME_CARNIPHILA}, - {"purpleenergy", CONST_ME_PURPLEENERGY}, - {"yellowenergy", CONST_ME_YELLOWENERGY}, - {"holyarea", CONST_ME_HOLYAREA}, - {"bigplants", CONST_ME_BIGPLANTS}, - {"cake", CONST_ME_CAKE}, - {"giantice", CONST_ME_GIANTICE}, - {"watersplash", CONST_ME_WATERSPLASH}, - {"plantattack", CONST_ME_PLANTATTACK}, - {"tutorialarrow", CONST_ME_TUTORIALARROW}, - {"tutorialsquare", CONST_ME_TUTORIALSQUARE}, - {"mirrorhorizontal", CONST_ME_MIRRORHORIZONTAL}, - {"mirrorvertical", CONST_ME_MIRRORVERTICAL}, - {"skullhorizontal", CONST_ME_SKULLHORIZONTAL}, - {"skullvertical", CONST_ME_SKULLVERTICAL}, - {"assassin", CONST_ME_ASSASSIN}, - {"stepshorizontal", CONST_ME_STEPSHORIZONTAL}, - {"bloodysteps", CONST_ME_BLOODYSTEPS}, - {"stepsvertical", CONST_ME_STEPSVERTICAL}, - {"yalaharighost", CONST_ME_YALAHARIGHOST}, - {"bats", CONST_ME_BATS}, - {"smoke", CONST_ME_SMOKE}, - {"insects", CONST_ME_INSECTS}, - {"dragonhead", CONST_ME_DRAGONHEAD}, - {"orcshaman", CONST_ME_ORCSHAMAN}, - {"orcshamanfire", CONST_ME_ORCSHAMAN_FIRE}, - {"thunder", CONST_ME_THUNDER}, - {"ferumbras", CONST_ME_FERUMBRAS}, - {"confettihorizontal", CONST_ME_CONFETTI_HORIZONTAL}, - {"confettivertical", CONST_ME_CONFETTI_VERTICAL}, - {"blacksmoke", CONST_ME_BLACKSMOKE}, - {"redsmoke", CONST_ME_REDSMOKE}, - {"yellowsmoke", CONST_ME_YELLOWSMOKE}, - {"greensmoke", CONST_ME_GREENSMOKE}, - {"purplesmoke", CONST_ME_PURPLESMOKE}, -}; - -ShootTypeNames shootTypeNames[] = { - {"spear", CONST_ANI_SPEAR}, - {"bolt", CONST_ANI_BOLT}, - {"arrow", CONST_ANI_ARROW}, - {"fire", CONST_ANI_FIRE}, - {"energy", CONST_ANI_ENERGY}, - {"poisonarrow", CONST_ANI_POISONARROW}, - {"burstarrow", CONST_ANI_BURSTARROW}, - {"throwingstar", CONST_ANI_THROWINGSTAR}, - {"throwingknife", CONST_ANI_THROWINGKNIFE}, - {"smallstone", CONST_ANI_SMALLSTONE}, - {"death", CONST_ANI_DEATH}, - {"largerock", CONST_ANI_LARGEROCK}, - {"snowball", CONST_ANI_SNOWBALL}, - {"powerbolt", CONST_ANI_POWERBOLT}, - {"poison", CONST_ANI_POISON}, - {"infernalbolt", CONST_ANI_INFERNALBOLT}, - {"huntingspear", CONST_ANI_HUNTINGSPEAR}, - {"enchantedspear", CONST_ANI_ENCHANTEDSPEAR}, - {"redstar", CONST_ANI_REDSTAR}, - {"greenstar", CONST_ANI_GREENSTAR}, - {"royalspear", CONST_ANI_ROYALSPEAR}, - {"sniperarrow", CONST_ANI_SNIPERARROW}, - {"onyxarrow", CONST_ANI_ONYXARROW}, - {"piercingbolt", CONST_ANI_PIERCINGBOLT}, - {"whirlwindsword", CONST_ANI_WHIRLWINDSWORD}, - {"whirlwindaxe", CONST_ANI_WHIRLWINDAXE}, - {"whirlwindclub", CONST_ANI_WHIRLWINDCLUB}, - {"etherealspear", CONST_ANI_ETHEREALSPEAR}, - {"ice", CONST_ANI_ICE}, - {"earth", CONST_ANI_EARTH}, - {"holy", CONST_ANI_HOLY}, - {"suddendeath", CONST_ANI_SUDDENDEATH}, - {"flasharrow", CONST_ANI_FLASHARROW}, - {"flammingarrow", CONST_ANI_FLAMMINGARROW}, - {"shiverarrow", CONST_ANI_SHIVERARROW}, - {"energyball", CONST_ANI_ENERGYBALL}, - {"smallice", CONST_ANI_SMALLICE}, - {"smallholy", CONST_ANI_SMALLHOLY}, - {"smallearth", CONST_ANI_SMALLEARTH}, - {"eartharrow", CONST_ANI_EARTHARROW}, - {"explosion", CONST_ANI_EXPLOSION}, - {"cake", CONST_ANI_CAKE}, - {"tarsalarrow", CONST_ANI_TARSALARROW}, - {"vortexbolt", CONST_ANI_VORTEXBOLT}, - {"prismaticbolt", CONST_ANI_PRISMATICBOLT}, - {"crystallinearrow", CONST_ANI_CRYSTALLINEARROW}, - {"drillbolt", CONST_ANI_DRILLBOLT}, - {"envenomedarrow", CONST_ANI_ENVENOMEDARROW}, - {"gloothspear", CONST_ANI_GLOOTHSPEAR}, - {"simplearrow", CONST_ANI_SIMPLEARROW}, -}; - -CombatTypeNames combatTypeNames[] = { - {"physical", COMBAT_PHYSICALDAMAGE}, - {"energy", COMBAT_ENERGYDAMAGE}, - {"earth", COMBAT_EARTHDAMAGE}, - {"fire", COMBAT_FIREDAMAGE}, - {"undefined", COMBAT_UNDEFINEDDAMAGE}, - {"lifedrain", COMBAT_LIFEDRAIN}, - {"manadrain", COMBAT_MANADRAIN}, - {"healing", COMBAT_HEALING}, - {"drown", COMBAT_DROWNDAMAGE}, - {"ice", COMBAT_ICEDAMAGE}, - {"holy", COMBAT_HOLYDAMAGE}, - {"death", COMBAT_DEATHDAMAGE}, -}; - -AmmoTypeNames ammoTypeNames[] = { - {"spear", AMMO_SPEAR}, - {"bolt", AMMO_BOLT}, - {"arrow", AMMO_ARROW}, - {"poisonarrow", AMMO_ARROW}, - {"burstarrow", AMMO_ARROW}, - {"throwingstar", AMMO_THROWINGSTAR}, - {"throwingknife", AMMO_THROWINGKNIFE}, - {"smallstone", AMMO_STONE}, - {"largerock", AMMO_STONE}, - {"snowball", AMMO_SNOWBALL}, - {"powerbolt", AMMO_BOLT}, - {"infernalbolt", AMMO_BOLT}, - {"huntingspear", AMMO_SPEAR}, - {"enchantedspear", AMMO_SPEAR}, - {"royalspear", AMMO_SPEAR}, - {"sniperarrow", AMMO_ARROW}, - {"onyxarrow", AMMO_ARROW}, - {"piercingbolt", AMMO_BOLT}, - {"etherealspear", AMMO_SPEAR}, - {"flasharrow", AMMO_ARROW}, - {"flammingarrow", AMMO_ARROW}, - {"shiverarrow", AMMO_ARROW}, - {"eartharrow", AMMO_ARROW}, -}; - -WeaponActionNames weaponActionNames[] = { - {"move", WEAPONACTION_MOVE}, - {"removecharge", WEAPONACTION_REMOVECHARGE}, - {"removecount", WEAPONACTION_REMOVECOUNT}, -}; - -SkullNames skullNames[] = { - {"none", SKULL_NONE}, - {"yellow", SKULL_YELLOW}, - {"green", SKULL_GREEN}, - {"white", SKULL_WHITE}, - {"red", SKULL_RED}, - {"black", SKULL_BLACK}, - {"orange", SKULL_ORANGE}, -}; - -MagicEffectClasses getMagicEffect(const std::string& strValue) -{ - for (size_t i = 0; i < sizeof(magicEffectNames) / sizeof(MagicEffectNames); ++i) { - if (strcasecmp(strValue.c_str(), magicEffectNames[i].name) == 0) { - return magicEffectNames[i].effect; - } - } - return CONST_ME_NONE; -} - -ShootType_t getShootType(const std::string& strValue) -{ - for (size_t i = 0, size = sizeof(shootTypeNames) / sizeof(ShootTypeNames); i < size; ++i) { - if (strcasecmp(strValue.c_str(), shootTypeNames[i].name) == 0) { - return shootTypeNames[i].shoot; - } - } - return CONST_ANI_NONE; -} - -CombatType_t getCombatType(const std::string& strValue) -{ - for (size_t i = 0, size = sizeof(combatTypeNames) / sizeof(CombatTypeNames); i < size; ++i) { - if (strcasecmp(strValue.c_str(), combatTypeNames[i].name) == 0) { - return combatTypeNames[i].combat; - } - } - return COMBAT_NONE; -} - -std::string getCombatName(CombatType_t combatType) -{ - for (size_t i = 0, size = sizeof(combatTypeNames) / sizeof(CombatTypeNames); i < size; ++i) { - if (combatTypeNames[i].combat == combatType) { - return combatTypeNames[i].name; - } - } - return "unknown"; -} - -Ammo_t getAmmoType(const std::string& strValue) -{ - for (size_t i = 0, size = sizeof(ammoTypeNames) / sizeof(AmmoTypeNames); i < size; ++i) { - if (strcasecmp(strValue.c_str(), ammoTypeNames[i].name) == 0) { - return ammoTypeNames[i].ammoType; - } - } - return AMMO_NONE; -} - -WeaponAction_t getWeaponAction(const std::string& strValue) -{ - for (size_t i = 0, size = sizeof(weaponActionNames) / sizeof(WeaponActionNames); i < size; ++i) { - if (strcasecmp(strValue.c_str(), weaponActionNames[i].name) == 0) { - return weaponActionNames[i].weaponAction; - } - } - return WEAPONACTION_NONE; -} - -Skulls_t getSkullType(const std::string& strValue) -{ - for (size_t i = 0, size = sizeof(skullNames) / sizeof(SkullNames); i < size; ++i) { - if (strcasecmp(strValue.c_str(), skullNames[i].name) == 0) { - return skullNames[i].skull; - } - } - return SKULL_NONE; -} - -std::string getSkillName(uint8_t skillid) -{ - switch (skillid) { - case SKILL_FIST: - return "fist fighting"; - - case SKILL_CLUB: - return "club fighting"; - - case SKILL_SWORD: - return "sword fighting"; - - case SKILL_AXE: - return "axe fighting"; - - case SKILL_DISTANCE: - return "distance fighting"; - - case SKILL_SHIELD: - return "shielding"; - - case SKILL_FISHING: - return "fishing"; - - case SKILL_MAGLEVEL: - return "magic level"; - - case SKILL_LEVEL: - return "level"; - - default: - return "unknown"; - } -} - -uint32_t adlerChecksum(const uint8_t* data, size_t length) -{ - if (length > NETWORKMESSAGE_MAXSIZE) { - return 0; - } - - const uint16_t adler = 65521; - - uint32_t a = 1, b = 0; - - while (length > 0) { - size_t tmp = length > 5552 ? 5552 : length; - length -= tmp; - - do { - a += *data++; - b += a; - } while (--tmp); - - a %= adler; - b %= adler; - } - - return (b << 16) | a; -} - -std::string ucfirst(std::string str) -{ - for (size_t i = 0; i < str.length(); ++i) { - if (str[i] != ' ') { - str[i] = toupper(str[i]); - break; - } - } - return str; -} - -std::string ucwords(std::string str) -{ - size_t strLength = str.length(); - if (strLength == 0) { - return str; - } - - str[0] = toupper(str.front()); - for (size_t i = 1; i < strLength; ++i) { - if (str[i - 1] == ' ') { - str[i] = toupper(str[i]); - } - } - - return str; -} - -bool booleanString(const std::string& str) -{ - if (str.empty()) { - return false; - } - - char ch = tolower(str.front()); - return ch != 'f' && ch != 'n' && ch != '0'; -} - -std::string getWeaponName(WeaponType_t weaponType) -{ - switch (weaponType) { - case WEAPON_SWORD: return "sword"; - case WEAPON_CLUB: return "club"; - case WEAPON_AXE: return "axe"; - case WEAPON_DISTANCE: return "distance"; - case WEAPON_WAND: return "wand"; - case WEAPON_AMMO: return "ammunition"; - default: return std::string(); - } -} - -size_t combatTypeToIndex(CombatType_t combatType) -{ - switch (combatType) { - case COMBAT_PHYSICALDAMAGE: - return 0; - case COMBAT_ENERGYDAMAGE: - return 1; - case COMBAT_EARTHDAMAGE: - return 2; - case COMBAT_FIREDAMAGE: - return 3; - case COMBAT_UNDEFINEDDAMAGE: - return 4; - case COMBAT_LIFEDRAIN: - return 5; - case COMBAT_MANADRAIN: - return 6; - case COMBAT_HEALING: - return 7; - case COMBAT_DROWNDAMAGE: - return 8; - case COMBAT_ICEDAMAGE: - return 9; - case COMBAT_HOLYDAMAGE: - return 10; - case COMBAT_DEATHDAMAGE: - return 11; - default: - return 0; - } -} - -CombatType_t indexToCombatType(size_t v) -{ - return static_cast(1 << v); -} - -uint8_t serverFluidToClient(uint8_t serverFluid) -{ - uint8_t size = sizeof(clientToServerFluidMap) / sizeof(uint8_t); - for (uint8_t i = 0; i < size; ++i) { - if (clientToServerFluidMap[i] == serverFluid) { - return i; - } - } - return 0; -} - -uint8_t clientFluidToServer(uint8_t clientFluid) -{ - uint8_t size = sizeof(clientToServerFluidMap) / sizeof(uint8_t); - if (clientFluid >= size) { - return 0; - } - return clientToServerFluidMap[clientFluid]; -} - -itemAttrTypes stringToItemAttribute(const std::string& str) -{ - if (str == "aid") { - return ITEM_ATTRIBUTE_ACTIONID; - } else if (str == "uid") { - return ITEM_ATTRIBUTE_UNIQUEID; - } else if (str == "description") { - return ITEM_ATTRIBUTE_DESCRIPTION; - } else if (str == "text") { - return ITEM_ATTRIBUTE_TEXT; - } else if (str == "date") { - return ITEM_ATTRIBUTE_DATE; - } else if (str == "writer") { - return ITEM_ATTRIBUTE_WRITER; - } else if (str == "name") { - return ITEM_ATTRIBUTE_NAME; - } else if (str == "article") { - return ITEM_ATTRIBUTE_ARTICLE; - } else if (str == "pluralname") { - return ITEM_ATTRIBUTE_PLURALNAME; - } else if (str == "weight") { - return ITEM_ATTRIBUTE_WEIGHT; - } else if (str == "attack") { - return ITEM_ATTRIBUTE_ATTACK; - } else if (str == "defense") { - return ITEM_ATTRIBUTE_DEFENSE; - } else if (str == "extradefense") { - return ITEM_ATTRIBUTE_EXTRADEFENSE; - } else if (str == "armor") { - return ITEM_ATTRIBUTE_ARMOR; - } else if (str == "hitchance") { - return ITEM_ATTRIBUTE_HITCHANCE; - } else if (str == "shootrange") { - return ITEM_ATTRIBUTE_SHOOTRANGE; - } else if (str == "owner") { - return ITEM_ATTRIBUTE_OWNER; - } else if (str == "duration") { - return ITEM_ATTRIBUTE_DURATION; - } else if (str == "decaystate") { - return ITEM_ATTRIBUTE_DECAYSTATE; - } else if (str == "corpseowner") { - return ITEM_ATTRIBUTE_CORPSEOWNER; - } else if (str == "charges") { - return ITEM_ATTRIBUTE_CHARGES; - } else if (str == "fluidtype") { - return ITEM_ATTRIBUTE_FLUIDTYPE; - } else if (str == "doorid") { - return ITEM_ATTRIBUTE_DOORID; - } - return ITEM_ATTRIBUTE_NONE; -} - -std::string getFirstLine(const std::string& str) -{ - std::string firstLine; - firstLine.reserve(str.length()); - for (const char c : str) { - if (c == '\n') { - break; - } - firstLine.push_back(c); - } - return firstLine; -} - -const char* getReturnMessage(ReturnValue value) -{ - switch (value) { - case RETURNVALUE_DESTINATIONOUTOFREACH: - return "Destination is out of reach."; - - case RETURNVALUE_NOTMOVEABLE: - return "You cannot move this object."; - - case RETURNVALUE_DROPTWOHANDEDITEM: - return "Drop the double-handed object first."; - - case RETURNVALUE_BOTHHANDSNEEDTOBEFREE: - return "Both hands need to be free."; - - case RETURNVALUE_CANNOTBEDRESSED: - return "You cannot dress this object there."; - - case RETURNVALUE_PUTTHISOBJECTINYOURHAND: - return "Put this object in your hand."; - - case RETURNVALUE_PUTTHISOBJECTINBOTHHANDS: - return "Put this object in both hands."; - - case RETURNVALUE_CANONLYUSEONEWEAPON: - return "You may only use one weapon."; - - case RETURNVALUE_TOOFARAWAY: - return "Too far away."; - - case RETURNVALUE_FIRSTGODOWNSTAIRS: - return "First go downstairs."; - - case RETURNVALUE_FIRSTGOUPSTAIRS: - return "First go upstairs."; - - case RETURNVALUE_NOTENOUGHCAPACITY: - return "This object is too heavy for you to carry."; - - case RETURNVALUE_CONTAINERNOTENOUGHROOM: - return "You cannot put more objects in this container."; - - case RETURNVALUE_NEEDEXCHANGE: - case RETURNVALUE_NOTENOUGHROOM: - return "There is not enough room."; - - case RETURNVALUE_CANNOTPICKUP: - return "You cannot take this object."; - - case RETURNVALUE_CANNOTTHROW: - return "You cannot throw there."; - - case RETURNVALUE_THEREISNOWAY: - return "There is no way."; - - case RETURNVALUE_THISISIMPOSSIBLE: - return "This is impossible."; - - case RETURNVALUE_PLAYERISPZLOCKED: - return "You can not enter a protection zone after attacking another player."; - - case RETURNVALUE_PLAYERISNOTINVITED: - return "You are not invited."; - - case RETURNVALUE_CREATUREDOESNOTEXIST: - return "Creature does not exist."; - - case RETURNVALUE_DEPOTISFULL: - return "You cannot put more items in this depot."; - - case RETURNVALUE_CANNOTUSETHISOBJECT: - return "You cannot use this object."; - - case RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE: - return "A player with this name is not online."; - - case RETURNVALUE_NOTREQUIREDLEVELTOUSERUNE: - return "You do not have the required magic level to use this rune."; - - case RETURNVALUE_YOUAREALREADYTRADING: - return "You are already trading."; - - case RETURNVALUE_THISPLAYERISALREADYTRADING: - return "This player is already trading."; - - case RETURNVALUE_YOUMAYNOTLOGOUTDURINGAFIGHT: - return "You may not logout during or immediately after a fight!"; - - case RETURNVALUE_DIRECTPLAYERSHOOT: - return "You are not allowed to shoot directly on players."; - - case RETURNVALUE_NOTENOUGHLEVEL: - return "You do not have enough level."; - - case RETURNVALUE_NOTENOUGHMAGICLEVEL: - return "You do not have enough magic level."; - - case RETURNVALUE_NOTENOUGHMANA: - return "You do not have enough mana."; - - case RETURNVALUE_NOTENOUGHSOUL: - return "You do not have enough soul."; - - case RETURNVALUE_YOUAREEXHAUSTED: - return "You are exhausted."; - - case RETURNVALUE_CANONLYUSETHISRUNEONCREATURES: - return "You can only use this rune on creatures."; - - case RETURNVALUE_PLAYERISNOTREACHABLE: - return "Player is not reachable."; - - case RETURNVALUE_CREATUREISNOTREACHABLE: - return "Creature is not reachable."; - - case RETURNVALUE_ACTIONNOTPERMITTEDINPROTECTIONZONE: - return "This action is not permitted in a protection zone."; - - case RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER: - return "You may not attack this player."; - - case RETURNVALUE_YOUMAYNOTATTACKTHISCREATURE: - return "You may not attack this creature."; - - case RETURNVALUE_YOUMAYNOTATTACKAPERSONINPROTECTIONZONE: - return "You may not attack a person in a protection zone."; - - case RETURNVALUE_YOUMAYNOTATTACKAPERSONWHILEINPROTECTIONZONE: - return "You may not attack a person while you are in a protection zone."; - - case RETURNVALUE_YOUCANONLYUSEITONCREATURES: - return "You can only use it on creatures."; - - case RETURNVALUE_TURNSECUREMODETOATTACKUNMARKEDPLAYERS: - return "Turn secure mode off if you really want to attack unmarked players."; - - case RETURNVALUE_YOUNEEDPREMIUMACCOUNT: - return "You need a premium account."; - - case RETURNVALUE_YOUNEEDTOLEARNTHISSPELL: - return "You need to learn this spell first."; - - case RETURNVALUE_YOURVOCATIONCANNOTUSETHISSPELL: - return "Your vocation cannot use this spell."; - - case RETURNVALUE_YOUNEEDAWEAPONTOUSETHISSPELL: - return "You need to equip a weapon to use this spell."; - - case RETURNVALUE_PLAYERISPZLOCKEDLEAVEPVPZONE: - return "You can not leave a pvp zone after attacking another player."; - - case RETURNVALUE_PLAYERISPZLOCKEDENTERPVPZONE: - return "You can not enter a pvp zone after attacking another player."; - - case RETURNVALUE_ACTIONNOTPERMITTEDINANOPVPZONE: - return "This action is not permitted in a non pvp zone."; - - case RETURNVALUE_YOUCANNOTLOGOUTHERE: - return "You can not logout here."; - - case RETURNVALUE_YOUNEEDAMAGICITEMTOCASTSPELL: - return "You need a magic item to cast this spell."; - - case RETURNVALUE_CANNOTCONJUREITEMHERE: - return "You cannot conjure items here."; - - case RETURNVALUE_YOUNEEDTOSPLITYOURSPEARS: - return "You need to split your spears first."; - - case RETURNVALUE_NAMEISTOOAMBIGIOUS: - return "Name is too ambigious."; - - case RETURNVALUE_CANONLYUSEONESHIELD: - return "You may use only one shield."; - - case RETURNVALUE_NOPARTYMEMBERSINRANGE: - return "No party members in range."; - - case RETURNVALUE_YOUARENOTTHEOWNER: - return "You are not the owner."; - - case RETURNVALUE_NOTENOUGHFISTLEVEL: - return "You do not have enough fist level"; - - case RETURNVALUE_NOTENOUGHCLUBLEVEL: - return "You do not have enough club level"; - - case RETURNVALUE_NOTENOUGHSWORDLEVEL: - return "You do not have enough sword level"; - - case RETURNVALUE_NOTENOUGHAXELEVEL: - return "You do not have enough axe level"; - - case RETURNVALUE_NOTENOUGHDISTANCELEVEL: - return "You do not have enough distance level"; - - case RETURNVALUE_NOTENOUGHSHIELDLEVEL: - return "You do not have enough shielding level"; - - case RETURNVALUE_NOTENOUGHFISHLEVEL: - return "You do not have enough fishing level"; - - default: // RETURNVALUE_NOTPOSSIBLE, etc - return "Sorry, not possible."; - } -} diff --git a/path_10_8/src/tools.h b/path_10_8/src/tools.h deleted file mode 100644 index fe70f9f86..000000000 --- a/path_10_8/src/tools.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TOOLS_H_5F9A9742DA194628830AA1C64909AE43 -#define FS_TOOLS_H_5F9A9742DA194628830AA1C64909AE43 - -#include - -#include "position.h" -#include "const.h" -#include "enums.h" - -void printXMLError(const std::string& where, const std::string& fileName, const pugi::xml_parse_result& result); - -std::string transformToSHA1(const std::string& input); - -void replaceString(std::string& str, const std::string& sought, const std::string& replacement); -void trim_right(std::string& source, char t); -void trim_left(std::string& source, char t); -void toLowerCaseString(std::string& source); -std::string asLowerCaseString(const std::string& source); -std::string asUpperCaseString(const std::string& source); - -typedef std::vector StringVec; -typedef std::vector IntegerVec; - -StringVec explodeString(const std::string& inString, const std::string& separator, int32_t limit = -1); -IntegerVec vectorAtoi(const StringVec& stringVector); -bool hasBitSet(uint32_t flag, uint32_t flags); - -std::mt19937& getRandomGenerator(); -int32_t uniform_random(int32_t minNumber, int32_t maxNumber); -int32_t normal_random(int32_t minNumber, int32_t maxNumber); -bool boolean_random(double probability = 0.5); - -Direction getDirection(const std::string& string); -Position getNextPosition(Direction direction, Position pos); -Direction getDirectionTo(const Position& from, const Position& to); - -std::string getFirstLine(const std::string& str); - -std::string formatDate(time_t time); -std::string formatDateShort(time_t time); -std::string convertIPToString(uint32_t ip); - -void trimString(std::string& str); - -MagicEffectClasses getMagicEffect(const std::string& strValue); -ShootType_t getShootType(const std::string& strValue); -Ammo_t getAmmoType(const std::string& strValue); -WeaponAction_t getWeaponAction(const std::string& strValue); -CombatType_t getCombatType(const std::string& strValue); -Skulls_t getSkullType(const std::string& strValue); -std::string getCombatName(CombatType_t combatType); - -std::string getSkillName(uint8_t skillid); - -uint32_t adlerChecksum(const uint8_t* data, size_t len); - -std::string ucfirst(std::string str); -std::string ucwords(std::string str); -bool booleanString(const std::string& str); - -std::string getWeaponName(WeaponType_t weaponType); - -size_t combatTypeToIndex(CombatType_t combatType); -CombatType_t indexToCombatType(size_t v); - -uint8_t serverFluidToClient(uint8_t serverFluid); -uint8_t clientFluidToServer(uint8_t clientFluid); - -itemAttrTypes stringToItemAttribute(const std::string& str); - -const char* getReturnMessage(ReturnValue value); - -inline int64_t OTSYS_TIME() -{ - return std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); -} - -#endif diff --git a/path_10_8/src/town.h b/path_10_8/src/town.h deleted file mode 100644 index 3d9b34acd..000000000 --- a/path_10_8/src/town.h +++ /dev/null @@ -1,98 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TOWN_H_3BE21D2293B44AA4A3D22D25BE1B9350 -#define FS_TOWN_H_3BE21D2293B44AA4A3D22D25BE1B9350 - -#include "position.h" - -class Town -{ - public: - explicit Town(uint32_t _id) : id(_id) {} - - const Position& getTemplePosition() const { - return templePosition; - } - const std::string& getName() const { - return name; - } - - void setTemplePos(Position pos) { - templePosition = pos; - } - void setName(std::string name) { - this->name = name; - } - uint32_t getID() const { - return id; - } - - private: - uint32_t id; - std::string name; - Position templePosition; -}; - -typedef std::map TownMap; - -class Towns -{ - public: - Towns() = default; - ~Towns() { - for (const auto& it : townMap) { - delete it.second; - } - } - - // non-copyable - Towns(const Towns&) = delete; - Towns& operator=(const Towns&) = delete; - - bool addTown(uint32_t townId, Town* town) { - return townMap.emplace(townId, town).second; - } - - Town* getTown(const std::string& townName) const { - for (const auto& it : townMap) { - if (strcasecmp(townName.c_str(), it.second->getName().c_str()) == 0) { - return it.second; - } - } - return nullptr; - } - - Town* getTown(uint32_t townId) const { - auto it = townMap.find(townId); - if (it == townMap.end()) { - return nullptr; - } - return it->second; - } - - const TownMap& getTowns() const { - return townMap; - } - - private: - TownMap townMap; -}; - -#endif diff --git a/path_10_8/src/trashholder.cpp b/path_10_8/src/trashholder.cpp deleted file mode 100644 index 7b688c102..000000000 --- a/path_10_8/src/trashholder.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "trashholder.h" -#include "game.h" - -extern Game g_game; - -ReturnValue TrashHolder::queryAdd(int32_t, const Thing&, uint32_t, uint32_t, Creature*) const -{ - return RETURNVALUE_NOERROR; -} - -ReturnValue TrashHolder::queryMaxCount(int32_t, const Thing&, uint32_t queryCount, uint32_t& maxQueryCount, uint32_t) const -{ - maxQueryCount = std::max(1, queryCount); - return RETURNVALUE_NOERROR; -} - -ReturnValue TrashHolder::queryRemove(const Thing&, uint32_t, uint32_t) const -{ - return RETURNVALUE_NOTPOSSIBLE; -} - -Cylinder* TrashHolder::queryDestination(int32_t&, const Thing&, Item**, uint32_t&) -{ - return this; -} - -void TrashHolder::addThing(Thing* thing) -{ - return addThing(0, thing); -} - -void TrashHolder::addThing(int32_t, Thing* thing) -{ - Item* item = thing->getItem(); - if (!item) { - return; - } - - if (item == this || !item->hasProperty(CONST_PROP_MOVEABLE)) { - return; - } - - const ItemType& it = Item::items[id]; - if (item->isHangable() && it.isGroundTile()) { - Tile* tile = dynamic_cast(getParent()); - if (tile && tile->hasFlag(TILESTATE_SUPPORTS_HANGABLE)) { - return; - } - } - - g_game.internalRemoveItem(item); - - if (it.magicEffect != CONST_ME_NONE) { - g_game.addMagicEffect(getPosition(), it.magicEffect); - } -} - -void TrashHolder::updateThing(Thing*, uint16_t, uint32_t) -{ - // -} - -void TrashHolder::replaceThing(uint32_t, Thing*) -{ - // -} - -void TrashHolder::removeThing(Thing*, uint32_t) -{ - // -} - -void TrashHolder::postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t) -{ - getParent()->postAddNotification(thing, oldParent, index, LINK_PARENT); -} - -void TrashHolder::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - getParent()->postRemoveNotification(thing, newParent, index, LINK_PARENT); -} diff --git a/path_10_8/src/trashholder.h b/path_10_8/src/trashholder.h deleted file mode 100644 index 45a7cbc96..000000000 --- a/path_10_8/src/trashholder.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_TRASHHOLDER_H_BA162024D67B4D388147F5EE06F33098 -#define FS_TRASHHOLDER_H_BA162024D67B4D388147F5EE06F33098 - -#include "item.h" -#include "cylinder.h" -#include "const.h" - -class TrashHolder final : public Item, public Cylinder -{ - public: - explicit TrashHolder(uint16_t itemId) : Item(itemId) {} - - TrashHolder* getTrashHolder() final { - return this; - } - const TrashHolder* getTrashHolder() const final { - return this; - } - - //cylinder implementations - ReturnValue queryAdd(int32_t index, const Thing& thing, uint32_t count, uint32_t flags, Creature* actor = nullptr) const final; - ReturnValue queryMaxCount(int32_t index, const Thing& thing, uint32_t count, uint32_t& maxQueryCount, uint32_t flags) const final; - ReturnValue queryRemove(const Thing& thing, uint32_t count, uint32_t flags) const final; - Cylinder* queryDestination(int32_t& index, const Thing& thing, Item** destItem, uint32_t& flags) final; - - void addThing(Thing* thing) final; - void addThing(int32_t index, Thing* thing) final; - - void updateThing(Thing* thing, uint16_t itemId, uint32_t count) final; - void replaceThing(uint32_t index, Thing* thing) final; - - void removeThing(Thing* thing, uint32_t count) final; - - void postAddNotification(Thing* thing, const Cylinder* oldParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; - void postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t link = LINK_OWNER) final; -}; - -#endif diff --git a/path_10_8/src/vocation.cpp b/path_10_8/src/vocation.cpp deleted file mode 100644 index d6a9dc137..000000000 --- a/path_10_8/src/vocation.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "vocation.h" - -#include "pugicast.h" -#include "tools.h" - -bool Vocations::loadFromXml() -{ - pugi::xml_document doc; - pugi::xml_parse_result result = doc.load_file("data/XML/vocations.xml"); - if (!result) { - printXMLError("Error - Vocations::loadFromXml", "data/XML/vocations.xml", result); - return false; - } - - for (auto vocationNode : doc.child("vocations").children()) { - pugi::xml_attribute attr; - if (!(attr = vocationNode.attribute("id"))) { - std::cout << "[Warning - Vocations::loadFromXml] Missing vocation id" << std::endl; - continue; - } - - uint16_t id = pugi::cast(attr.value()); - - auto res = vocationsMap.emplace(id, id); - Vocation& voc = res.first->second; - - if ((attr = vocationNode.attribute("name"))) { - voc.name = attr.as_string(); - } - - if ((attr = vocationNode.attribute("clientid"))) { - voc.clientId = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("description"))) { - voc.description = attr.as_string(); - } - - if ((attr = vocationNode.attribute("gaincap"))) { - voc.gainCap = pugi::cast(attr.value()) * 100; - } - - if ((attr = vocationNode.attribute("gainhp"))) { - voc.gainHP = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainmana"))) { - voc.gainMana = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainhpticks"))) { - voc.gainHealthTicks = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainhpamount"))) { - voc.gainHealthAmount = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainmanaticks"))) { - voc.gainManaTicks = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainmanaamount"))) { - voc.gainManaAmount = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("manamultiplier"))) { - voc.manaMultiplier = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("attackspeed"))) { - voc.attackSpeed = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("basespeed"))) { - voc.baseSpeed = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("soulmax"))) { - voc.soulMax = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("gainsoulticks"))) { - voc.gainSoulTicks = pugi::cast(attr.value()); - } - - if ((attr = vocationNode.attribute("fromvoc"))) { - voc.fromVocation = pugi::cast(attr.value()); - } - - for (auto childNode : vocationNode.children()) { - if (strcasecmp(childNode.name(), "skill") == 0) { - pugi::xml_attribute skillIdAttribute = childNode.attribute("id"); - if (skillIdAttribute) { - uint16_t skill_id = pugi::cast(skillIdAttribute.value()); - if (skill_id <= SKILL_LAST) { - voc.skillMultipliers[skill_id] = pugi::cast(childNode.attribute("multiplier").value()); - } else { - std::cout << "[Notice - Vocations::loadFromXml] No valid skill id: " << skill_id << " for vocation: " << voc.id << std::endl; - } - } else { - std::cout << "[Notice - Vocations::loadFromXml] Missing skill id for vocation: " << voc.id << std::endl; - } - } else if (strcasecmp(childNode.name(), "formula") == 0) { - pugi::xml_attribute meleeDamageAttribute = childNode.attribute("meleeDamage"); - if (meleeDamageAttribute) { - voc.meleeDamageMultiplier = pugi::cast(meleeDamageAttribute.value()); - } - - pugi::xml_attribute distDamageAttribute = childNode.attribute("distDamage"); - if (distDamageAttribute) { - voc.distDamageMultiplier = pugi::cast(distDamageAttribute.value()); - } - - pugi::xml_attribute defenseAttribute = childNode.attribute("defense"); - if (defenseAttribute) { - voc.defenseMultiplier = pugi::cast(defenseAttribute.value()); - } - - pugi::xml_attribute armorAttribute = childNode.attribute("armor"); - if (armorAttribute) { - voc.armorMultiplier = pugi::cast(armorAttribute.value()); - } - } - } - } - return true; -} - -Vocation* Vocations::getVocation(uint16_t id) -{ - auto it = vocationsMap.find(id); - if (it == vocationsMap.end()) { - std::cout << "[Warning - Vocations::getVocation] Vocation " << id << " not found." << std::endl; - return nullptr; - } - return &it->second; -} - -int32_t Vocations::getVocationId(const std::string& name) const -{ - for (const auto& it : vocationsMap) { - if (strcasecmp(it.second.name.c_str(), name.c_str()) == 0) { - return it.first; - } - } - return -1; -} - -uint16_t Vocations::getPromotedVocation(uint16_t vocationId) const -{ - for (const auto& it : vocationsMap) { - if (it.second.fromVocation == vocationId && it.first != vocationId) { - return it.first; - } - } - return VOCATION_NONE; -} - -uint32_t Vocation::skillBase[SKILL_LAST + 1] = {50, 50, 50, 50, 30, 100, 20}; - -Vocation::Vocation(uint16_t id) - : name("none"), id(id) -{ - gainHealthTicks = 6; - gainHealthAmount = 1; - gainManaTicks = 6; - gainManaAmount = 1; - gainSoulTicks = 120; - soulMax = 100; - - clientId = 0; - fromVocation = VOCATION_NONE; - - gainCap = 500; - gainMana = 5; - gainHP = 5; - attackSpeed = 1500; - baseSpeed = 220; - manaMultiplier = 4.0; - meleeDamageMultiplier = 1.0; - distDamageMultiplier = 1.0; - defenseMultiplier = 1.0; - armorMultiplier = 1.0; - skillMultipliers[0] = 1.5f; - skillMultipliers[1] = 2.0f; - skillMultipliers[2] = 2.0f; - skillMultipliers[3] = 2.0f; - skillMultipliers[4] = 2.0f; - skillMultipliers[5] = 1.5f; - skillMultipliers[6] = 1.1f; -} - -uint64_t Vocation::getReqSkillTries(uint8_t skill, uint16_t level) -{ - if (skill > SKILL_LAST) { - return 0; - } - - auto it = cacheSkill[skill].find(level); - if (it != cacheSkill[skill].end()) { - return it->second; - } - - uint64_t tries = static_cast(skillBase[skill] * std::pow(static_cast(skillMultipliers[skill]), level - 11)); - cacheSkill[skill][level] = tries; - return tries; -} - -uint64_t Vocation::getReqMana(uint32_t magLevel) -{ - auto it = cacheMana.find(magLevel); - if (it != cacheMana.end()) { - return it->second; - } - - uint64_t reqMana = static_cast(400 * std::pow(manaMultiplier, static_cast(magLevel) - 1)); - uint32_t modResult = reqMana % 20; - if (modResult < 10) { - reqMana -= modResult; - } else { - reqMana -= modResult + 20; - } - - cacheMana[magLevel] = reqMana; - return reqMana; -} diff --git a/path_10_8/src/vocation.h b/path_10_8/src/vocation.h deleted file mode 100644 index 8ddecbc46..000000000 --- a/path_10_8/src/vocation.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_VOCATION_H_ADCAA356C0DB44CEBA994A0D678EC92D -#define FS_VOCATION_H_ADCAA356C0DB44CEBA994A0D678EC92D - -#include "enums.h" -#include "item.h" - -class Vocation -{ - public: - Vocation(uint16_t id); - - const std::string& getVocName() const { - return name; - } - const std::string& getVocDescription() const { - return description; - } - uint64_t getReqSkillTries(uint8_t skill, uint16_t level); - uint64_t getReqMana(uint32_t magLevel); - - uint16_t getId() const { - return id; - } - - uint8_t getClientId() const { - return clientId; - } - - uint32_t getHPGain() const { - return gainHP; - } - uint32_t getManaGain() const { - return gainMana; - } - uint32_t getCapGain() const { - return gainCap; - } - - uint32_t getManaGainTicks() const { - return gainManaTicks; - } - uint32_t getManaGainAmount() const { - return gainManaAmount; - } - uint32_t getHealthGainTicks() const { - return gainHealthTicks; - } - uint32_t getHealthGainAmount() const { - return gainHealthAmount; - } - - uint8_t getSoulMax() const { - return soulMax; - } - uint16_t getSoulGainTicks() const { - return gainSoulTicks; - } - - uint32_t getAttackSpeed() const { - return attackSpeed; - } - uint32_t getBaseSpeed() const { - return baseSpeed; - } - - uint32_t getFromVocation() const { - return fromVocation; - } - - float meleeDamageMultiplier, distDamageMultiplier, defenseMultiplier, armorMultiplier; - - protected: - friend class Vocations; - - std::map cacheMana; - std::map cacheSkill[SKILL_LAST + 1]; - - std::string name; - std::string description; - - float skillMultipliers[SKILL_LAST + 1]; - float manaMultiplier; - - uint32_t gainHealthTicks; - uint32_t gainHealthAmount; - uint32_t gainManaTicks; - uint32_t gainManaAmount; - uint32_t gainCap; - uint32_t gainMana; - uint32_t gainHP; - uint32_t fromVocation; - uint32_t attackSpeed; - uint32_t baseSpeed; - uint16_t id; - - uint16_t gainSoulTicks; - - uint8_t soulMax; - uint8_t clientId; - - static uint32_t skillBase[SKILL_LAST + 1]; -}; - -class Vocations -{ - public: - bool loadFromXml(); - - Vocation* getVocation(uint16_t id); - int32_t getVocationId(const std::string& name) const; - uint16_t getPromotedVocation(uint16_t vocationId) const; - - private: - std::map vocationsMap; -}; - -#endif diff --git a/path_10_8/src/waitlist.cpp b/path_10_8/src/waitlist.cpp deleted file mode 100644 index 48cb94f8e..000000000 --- a/path_10_8/src/waitlist.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "configmanager.h" -#include "game.h" -#include "waitlist.h" - -extern ConfigManager g_config; -extern Game g_game; - -WaitListIterator WaitingList::findClient(const Player* player, uint32_t& slot) -{ - slot = 1; - for (WaitListIterator it = priorityWaitList.begin(), end = priorityWaitList.end(); it != end; ++it) { - if (it->playerGUID == player->getGUID()) { - return it; - } - ++slot; - } - - for (WaitListIterator it = waitList.begin(), end = waitList.end(); it != end; ++it) { - if (it->playerGUID == player->getGUID()) { - return it; - } - ++slot; - } - return waitList.end(); -} - -uint32_t WaitingList::getTime(uint32_t slot) -{ - if (slot < 5) { - return 5; - } else if (slot < 10) { - return 10; - } else if (slot < 20) { - return 20; - } else if (slot < 50) { - return 60; - } else { - return 120; - } -} - -uint32_t WaitingList::getTimeout(uint32_t slot) -{ - //timeout is set to 15 seconds longer than expected retry attempt - return getTime(slot) + 15; -} - -bool WaitingList::clientLogin(const Player* player) -{ - if (player->hasFlag(PlayerFlag_CanAlwaysLogin) || player->getAccountType() >= ACCOUNT_TYPE_GAMEMASTER) { - return true; - } - - uint32_t maxPlayers = static_cast(g_config.getNumber(ConfigManager::MAX_PLAYERS)); - if (maxPlayers == 0 || (priorityWaitList.empty() && waitList.empty() && g_game.getPlayersOnline() < maxPlayers)) { - return true; - } - - WaitingList::cleanupList(priorityWaitList); - WaitingList::cleanupList(waitList); - - uint32_t slot; - - WaitListIterator it = findClient(player, slot); - if (it != waitList.end()) { - if ((g_game.getPlayersOnline() + slot) <= maxPlayers) { - //should be able to login now - waitList.erase(it); - return true; - } - - //let them wait a bit longer - it->timeout = OTSYS_TIME() + (getTimeout(slot) * 1000); - return false; - } - - slot = priorityWaitList.size(); - if (player->isPremium()) { - priorityWaitList.emplace_back(OTSYS_TIME() + (getTimeout(slot + 1) * 1000), player->getGUID()); - } else { - slot += waitList.size(); - waitList.emplace_back(OTSYS_TIME() + (getTimeout(slot + 1) * 1000), player->getGUID()); - } - return false; -} - -uint32_t WaitingList::getClientSlot(const Player* player) -{ - uint32_t slot; - WaitListIterator it = findClient(player, slot); - if (it == waitList.end()) { - return 0; - } - return slot; -} - -void WaitingList::cleanupList(WaitList& list) -{ - int64_t time = OTSYS_TIME(); - - WaitListIterator it = list.begin(), end = list.end(); - while (it != end) { - if ((it->timeout - time) <= 0) { - it = list.erase(it); - } else { - ++it; - } - } -} diff --git a/path_10_8/src/waitlist.h b/path_10_8/src/waitlist.h deleted file mode 100644 index 9b7fe02e6..000000000 --- a/path_10_8/src/waitlist.h +++ /dev/null @@ -1,57 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_WAITLIST_H_7E4299E552E44F10BC4F4E50BF3D7241 -#define FS_WAITLIST_H_7E4299E552E44F10BC4F4E50BF3D7241 - -#include "player.h" - -struct Wait { - Wait(int64_t timeout, uint32_t playerGUID) : - timeout(timeout), playerGUID(playerGUID) {} - - int64_t timeout; - uint32_t playerGUID; -}; - -typedef std::list WaitList; -typedef WaitList::iterator WaitListIterator; - -class WaitingList -{ - public: - static WaitingList* getInstance() { - static WaitingList waitingList; - return &waitingList; - } - - bool clientLogin(const Player* player); - uint32_t getClientSlot(const Player* player); - static uint32_t getTime(uint32_t slot); - - protected: - WaitList priorityWaitList; - WaitList waitList; - - static uint32_t getTimeout(uint32_t slot); - WaitListIterator findClient(const Player* player, uint32_t& slot); - static void cleanupList(WaitList& list); -}; - -#endif diff --git a/path_10_8/src/weapons.cpp b/path_10_8/src/weapons.cpp deleted file mode 100644 index 0687e74e7..000000000 --- a/path_10_8/src/weapons.cpp +++ /dev/null @@ -1,949 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include "combat.h" -#include "configmanager.h" -#include "game.h" -#include "pugicast.h" -#include "weapons.h" - -extern Game g_game; -extern Vocations g_vocations; -extern ConfigManager g_config; -extern Weapons* g_weapons; - -Weapons::Weapons(): - m_scriptInterface("Weapon Interface") -{ - m_scriptInterface.initState(); -} - -Weapons::~Weapons() -{ - clear(); -} - -const Weapon* Weapons::getWeapon(const Item* item) const -{ - if (!item) { - return nullptr; - } - - auto it = weapons.find(item->getID()); - if (it == weapons.end()) { - return nullptr; - } - return it->second; -} - -void Weapons::clear() -{ - for (const auto& it : weapons) { - delete it.second; - } - weapons.clear(); - - m_scriptInterface.reInitState(); -} - -LuaScriptInterface& Weapons::getScriptInterface() -{ - return m_scriptInterface; -} - -std::string Weapons::getScriptBaseName() const -{ - return "weapons"; -} - -void Weapons::loadDefaults() -{ - for (size_t i = 100, size = Item::items.size(); i < size; ++i) { - const ItemType& it = Item::items.getItemType(i); - if (it.id == 0 || weapons.find(i) != weapons.end()) { - continue; - } - - switch (it.weaponType) { - case WEAPON_AXE: - case WEAPON_SWORD: - case WEAPON_CLUB: { - WeaponMelee* weapon = new WeaponMelee(&m_scriptInterface); - weapon->configureWeapon(it); - weapons[i] = weapon; - break; - } - - case WEAPON_AMMO: - case WEAPON_DISTANCE: { - if (it.weaponType == WEAPON_DISTANCE && it.ammoType != AMMO_NONE) { - continue; - } - - WeaponDistance* weapon = new WeaponDistance(&m_scriptInterface); - weapon->configureWeapon(it); - weapons[i] = weapon; - break; - } - - default: - break; - } - } -} - -Event* Weapons::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "melee") == 0) { - return new WeaponMelee(&m_scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "distance") == 0) { - return new WeaponDistance(&m_scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "wand") == 0) { - return new WeaponWand(&m_scriptInterface); - } - return nullptr; -} - -bool Weapons::registerEvent(Event* event, const pugi::xml_node&) -{ - Weapon* weapon = static_cast(event); //event is guaranteed to be a Weapon - - auto result = weapons.emplace(weapon->getID(), weapon); - if (!result.second) { - std::cout << "[Warning - Weapons::registerEvent] Duplicate registered item with id: " << weapon->getID() << std::endl; - } - return result.second; -} - -//monsters -int32_t Weapons::getMaxMeleeDamage(int32_t attackSkill, int32_t attackValue) -{ - return static_cast(std::ceil((attackSkill * (attackValue * 0.05)) + (attackValue * 0.5))); -} - -//players -int32_t Weapons::getMaxWeaponDamage(uint32_t level, int32_t attackSkill, int32_t attackValue, float attackFactor) -{ - return static_cast(std::ceil((2 * (attackValue * (attackSkill + 5.8) / 25 + (level - 1) / 10.)) / attackFactor)); -} - -Weapon::Weapon(LuaScriptInterface* _interface) : - Event(_interface) -{ - m_scripted = false; - id = 0; - level = 0; - magLevel = 0; - mana = 0; - manaPercent = 0; - soul = 0; - premium = false; - enabled = true; - wieldUnproperly = false; - swing = false; - breakChance = 0; - action = WEAPONACTION_NONE; - params.blockedByArmor = true; - params.blockedByShield = true; - params.combatType = COMBAT_PHYSICALDAMAGE; -} - -bool Weapon::configureEvent(const pugi::xml_node& node) -{ - pugi::xml_attribute attr; - if (!(attr = node.attribute("id"))) { - std::cout << "[Error - Weapon::configureEvent] Weapon without id." << std::endl; - return false; - } - id = pugi::cast(attr.value()); - - if ((attr = node.attribute("level"))) { - level = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("maglv")) || (attr = node.attribute("maglevel"))) { - magLevel = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("mana"))) { - mana = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("manapercent"))) { - manaPercent = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("soul"))) { - soul = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("prem"))) { - premium = attr.as_bool(); - } - - if ((attr = node.attribute("breakchance"))) { - breakChance = std::min(100, pugi::cast(attr.value())); - } - - if ((attr = node.attribute("action"))) { - action = getWeaponAction(attr.as_string()); - if (action == WEAPONACTION_NONE) { - std::cout << "[Warning - Weapon::configureEvent] Unknown action " << attr.as_string() << std::endl; - } - } - - if ((attr = node.attribute("enabled"))) { - enabled = attr.as_bool(); - } - - if ((attr = node.attribute("unproperly"))) { - wieldUnproperly = attr.as_bool(); - } - - if ((attr = node.attribute("swing"))) { - swing = attr.as_bool(); - } - - std::list vocStringList; - for (auto vocationNode : node.children()) { - if (!(attr = vocationNode.attribute("name"))) { - continue; - } - - int32_t vocationId = g_vocations.getVocationId(attr.as_string()); - if (vocationId != -1) { - vocWeaponMap[vocationId] = true; - int32_t promotedVocation = g_vocations.getPromotedVocation(vocationId); - if (promotedVocation != VOCATION_NONE) { - vocWeaponMap[promotedVocation] = true; - } - - if (vocationNode.attribute("showInDescription").as_bool(true)) { - vocStringList.push_back(asLowerCaseString(attr.as_string())); - } - } - } - - std::string vocationString; - for (const std::string& str : vocStringList) { - if (!vocationString.empty()) { - if (str != vocStringList.back()) { - vocationString.push_back(','); - vocationString.push_back(' '); - } else { - vocationString += " and "; - } - } - - vocationString += str; - vocationString.push_back('s'); - } - - uint32_t wieldInfo = 0; - if (getReqLevel() > 0) { - wieldInfo |= WIELDINFO_LEVEL; - } - - if (getReqMagLv() > 0) { - wieldInfo |= WIELDINFO_MAGLV; - } - - if (!vocationString.empty()) { - wieldInfo |= WIELDINFO_VOCREQ; - } - - if (isPremium()) { - wieldInfo |= WIELDINFO_PREMIUM; - } - - if (wieldInfo != 0) { - ItemType& it = Item::items.getItemType(id); - it.wieldInfo = wieldInfo; - it.vocationString = vocationString; - it.minReqLevel = getReqLevel(); - it.minReqMagicLevel = getReqMagLv(); - } - - configureWeapon(Item::items[id]); - return true; -} - -void Weapon::configureWeapon(const ItemType& it) -{ - id = it.id; -} - -std::string Weapon::getScriptEventName() const -{ - return "onUseWeapon"; -} - -int32_t Weapon::playerWeaponCheck(Player* player, Creature* target, uint8_t shootRange) const -{ - const Position& playerPos = player->getPosition(); - const Position& targetPos = target->getPosition(); - if (playerPos.z != targetPos.z) { - return 0; - } - - if (std::max(Position::getDistanceX(playerPos, targetPos), Position::getDistanceY(playerPos, targetPos)) > shootRange) { - return 0; - } - - if (!player->hasFlag(PlayerFlag_IgnoreWeaponCheck)) { - if (!enabled) { - return 0; - } - - if (player->getMana() < getManaCost(player)) { - return 0; - } - - if (player->getSoul() < soul) { - return 0; - } - - if (isPremium() && !player->isPremium()) { - return 0; - } - - if (!vocWeaponMap.empty()) { - if (vocWeaponMap.find(player->getVocationId()) == vocWeaponMap.end()) { - return 0; - } - } - - int32_t damageModifier = 100; - if (auto chance = g_config.getNumber(ConfigManager::CRITICAL_HIT_CHANCE)) { - if (boolean_random(static_cast(chance) / 100.0)) { - damageModifier += g_config.getNumber(ConfigManager::CRITICAL_HIT_EXTRA); - std::cout << "Critical hit!" << std::endl; - } - } - - if (player->getLevel() < getReqLevel()) { - damageModifier = (isWieldedUnproperly() ? damageModifier / 2 : 0); - } - - if (player->getMagicLevel() < getReqMagLv()) { - damageModifier = (isWieldedUnproperly() ? damageModifier / 2 : 0); - } - return damageModifier; - } - - return 100; -} - -bool Weapon::useWeapon(Player* player, Item* item, Creature* target) const -{ - int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); - if (damageModifier == 0) { - return false; - } - - internalUseWeapon(player, item, target, damageModifier); - return true; -} - -bool Weapon::useFist(Player* player, Creature* target) -{ - if (!Position::areInRange<1, 1>(player->getPosition(), target->getPosition())) { - return false; - } - - float attackFactor = player->getAttackFactor(); - int32_t attackSkill = player->getSkillLevel(SKILL_FIST); - int32_t attackValue = 7; - - int32_t maxDamage = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); - - CombatParams params; - params.combatType = COMBAT_PHYSICALDAMAGE; - params.blockedByArmor = true; - params.blockedByShield = true; - - CombatDamage damage; - damage.origin = ORIGIN_MELEE; - damage.primary.type = params.combatType; - damage.primary.value = -normal_random(0, maxDamage); - - Combat::doCombatHealth(player, target, damage, params); - if (!player->hasFlag(PlayerFlag_NotGainSkill) && player->getAddAttackSkill()) { - player->addSkillAdvance(SKILL_FIST, 1); - } - - return true; -} - -void Weapon::internalUseWeapon(Player* player, Item* item, Creature* target, int32_t damageModifier) const -{ - if (m_scripted) { - LuaVariant var; - var.type = VARIANT_NUMBER; - var.number = target->getID(); - executeUseWeapon(player, var); - } else { - CombatDamage damage; - WeaponType_t weaponType = item->getWeaponType(); - if (weaponType == WEAPON_AMMO || weaponType == WEAPON_DISTANCE) { - damage.origin = ORIGIN_RANGED; - } else { - damage.origin = ORIGIN_MELEE; - } - damage.primary.type = params.combatType; - damage.primary.value = (getWeaponDamage(player, target, item) * damageModifier) / 100; - damage.secondary.type = getElementType(); - damage.secondary.value = getElementDamage(player, target, item); - Combat::doCombatHealth(player, target, damage, params); - } - - onUsedWeapon(player, item, target->getTile()); -} - -void Weapon::internalUseWeapon(Player* player, Item* item, Tile* tile) const -{ - if (m_scripted) { - LuaVariant var; - var.type = VARIANT_TARGETPOSITION; - var.pos = tile->getPosition(); - executeUseWeapon(player, var); - } else { - Combat::postCombatEffects(player, tile->getPosition(), params); - g_game.addMagicEffect(tile->getPosition(), CONST_ME_POFF); - } - - onUsedWeapon(player, item, tile); -} - -void Weapon::onUsedWeapon(Player* player, Item* item, Tile* destTile) const -{ - if (!player->hasFlag(PlayerFlag_NotGainSkill)) { - skills_t skillType; - uint32_t skillPoint; - if (getSkillType(player, item, skillType, skillPoint)) { - player->addSkillAdvance(skillType, skillPoint); - } - } - - uint32_t manaCost = getManaCost(player); - if (manaCost != 0) { - player->addManaSpent(manaCost); - player->changeMana(-static_cast(manaCost)); - } - - if (!player->hasFlag(PlayerFlag_HasInfiniteSoul) && soul > 0) { - player->changeSoul(-static_cast(soul)); - } - - if (breakChance != 0 && uniform_random(1, 100) <= breakChance) { - decrementItemCount(item); - return; - } - - switch (action) { - case WEAPONACTION_REMOVECOUNT: - decrementItemCount(item); - break; - - case WEAPONACTION_REMOVECHARGE: { - uint16_t charges = item->getCharges(); - if (charges != 0) { - g_game.transformItem(item, item->getID(), charges - 1); - } - break; - } - - case WEAPONACTION_MOVE: - g_game.internalMoveItem(item->getParent(), destTile, INDEX_WHEREEVER, item, 1, nullptr, FLAG_NOLIMIT); - break; - - default: - break; - } -} - -uint32_t Weapon::getManaCost(const Player* player) const -{ - if (mana != 0) { - return mana; - } - - if (manaPercent == 0) { - return 0; - } - - return (player->getMaxMana() * manaPercent) / 100; -} - -bool Weapon::executeUseWeapon(Player* player, const LuaVariant& var) const -{ - //onUseWeapon(player, var) - if (!m_scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Weapon::executeUseWeapon] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = m_scriptInterface->getScriptEnv(); - env->setScriptId(m_scriptId, m_scriptInterface); - - lua_State* L = m_scriptInterface->getLuaState(); - - m_scriptInterface->pushFunction(m_scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - m_scriptInterface->pushVariant(L, var); - - return m_scriptInterface->callFunction(2); -} - -void Weapon::decrementItemCount(Item* item) const -{ - uint16_t count = item->getItemCount(); - if (count > 1) { - g_game.transformItem(item, item->getID(), count - 1); - } else { - g_game.internalRemoveItem(item); - } -} - -WeaponMelee::WeaponMelee(LuaScriptInterface* _interface) : - Weapon(_interface), elementType(COMBAT_NONE), elementDamage(0) -{ - params.blockedByArmor = true; - params.blockedByShield = true; - params.combatType = COMBAT_PHYSICALDAMAGE; -} - -void WeaponMelee::configureWeapon(const ItemType& it) -{ - if (it.abilities) { - elementType = it.abilities->elementType; - elementDamage = it.abilities->elementDamage; - params.aggressive = true; - params.useCharges = true; - } else { - elementType = COMBAT_NONE; - elementDamage = 0; - } - Weapon::configureWeapon(it); -} - -bool WeaponMelee::useWeapon(Player* player, Item* item, Creature* target) const -{ - int32_t damageModifier = playerWeaponCheck(player, target, item->getShootRange()); - if (damageModifier == 0) { - return false; - } - - internalUseWeapon(player, item, target, damageModifier); - return true; -} - -bool WeaponMelee::getSkillType(const Player* player, const Item* item, - skills_t& skill, uint32_t& skillpoint) const -{ - if (player->getAddAttackSkill() && player->getLastAttackBlockType() != BLOCK_IMMUNITY) { - skillpoint = 1; - } else { - skillpoint = 0; - } - - WeaponType_t weaponType = item->getWeaponType(); - switch (weaponType) { - case WEAPON_SWORD: { - skill = SKILL_SWORD; - return true; - } - - case WEAPON_CLUB: { - skill = SKILL_CLUB; - return true; - } - - case WEAPON_AXE: { - skill = SKILL_AXE; - return true; - } - - default: - break; - } - return false; -} - -int32_t WeaponMelee::getElementDamage(const Player* player, const Creature*, const Item* item) const -{ - if (elementType == COMBAT_NONE) { - return 0; - } - - int32_t attackSkill = player->getWeaponSkill(item); - int32_t attackValue = elementDamage; - float attackFactor = player->getAttackFactor(); - - int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); - return -normal_random(0, static_cast(maxValue * player->getVocation()->meleeDamageMultiplier)); -} - -int32_t WeaponMelee::getWeaponDamage(const Player* player, const Creature*, const Item* item, bool maxDamage /*= false*/) const -{ - int32_t attackSkill = player->getWeaponSkill(item); - int32_t attackValue = std::max(0, item->getAttack()); - float attackFactor = player->getAttackFactor(); - - int32_t maxValue = static_cast(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor) * player->getVocation()->meleeDamageMultiplier); - if (maxDamage) { - return -maxValue; - } - - return -normal_random(0, maxValue); -} - -WeaponDistance::WeaponDistance(LuaScriptInterface* _interface) : - Weapon(_interface), elementType(COMBAT_NONE), elementDamage(0) -{ - params.blockedByArmor = true; - params.combatType = COMBAT_PHYSICALDAMAGE; - swing = params.blockedByShield = false; -} - -void WeaponDistance::configureWeapon(const ItemType& it) -{ - params.distanceEffect = it.shootType; - - if (it.abilities) { - elementType = it.abilities->elementType; - elementDamage = it.abilities->elementDamage; - params.aggressive = true; - params.useCharges = true; - } else { - elementType = COMBAT_NONE; - elementDamage = 0; - } - - Weapon::configureWeapon(it); -} - -bool WeaponDistance::useWeapon(Player* player, Item* item, Creature* target) const -{ - int32_t damageModifier; - const ItemType& it = Item::items[id]; - if (it.weaponType == WEAPON_AMMO) { - Item* mainWeaponItem = player->getWeapon(true); - const Weapon* mainWeapon = g_weapons->getWeapon(mainWeaponItem); - if (mainWeapon) { - damageModifier = mainWeapon->playerWeaponCheck(player, target, mainWeaponItem->getShootRange()); - } else { - damageModifier = playerWeaponCheck(player, target, mainWeaponItem->getShootRange()); - } - } else { - damageModifier = playerWeaponCheck(player, target, item->getShootRange()); - } - - if (damageModifier == 0) { - return false; - } - - int32_t chance; - if (it.hitChance == 0) { - //hit chance is based on distance to target and distance skill - uint32_t skill = player->getSkillLevel(SKILL_DISTANCE); - const Position& playerPos = player->getPosition(); - const Position& targetPos = target->getPosition(); - uint32_t distance = std::max(Position::getDistanceX(playerPos, targetPos), Position::getDistanceY(playerPos, targetPos)); - - uint32_t maxHitChance; - if (it.maxHitChance != -1) { - maxHitChance = it.maxHitChance; - } else if (it.ammoType != AMMO_NONE) { - //hit chance on two-handed weapons is limited to 90% - maxHitChance = 90; - } else { - //one-handed is set to 75% - maxHitChance = 75; - } - - if (maxHitChance == 75) { - //chance for one-handed weapons - switch (distance) { - case 1: - case 5: - chance = std::min(skill, 74) + 1; - break; - case 2: - chance = static_cast(std::min(skill, 28) * 2.40f) + 8; - break; - case 3: - chance = static_cast(std::min(skill, 45) * 1.55f) + 6; - break; - case 4: - chance = static_cast(std::min(skill, 58) * 1.25f) + 3; - break; - case 6: - chance = static_cast(std::min(skill, 90) * 0.80f) + 3; - break; - case 7: - chance = static_cast(std::min(skill, 104) * 0.70f) + 2; - break; - default: - chance = it.hitChance; - break; - } - } else if (maxHitChance == 90) { - //formula for two-handed weapons - switch (distance) { - case 1: - case 5: - chance = static_cast(std::min(skill, 74) * 1.20f) + 1; - break; - case 2: - chance = static_cast(std::min(skill, 28) * 3.20f); - break; - case 3: - chance = std::min(skill, 45) * 2; - break; - case 4: - chance = static_cast(std::min(skill, 58) * 1.55f); - break; - case 6: - case 7: - chance = std::min(skill, 90); - break; - default: - chance = it.hitChance; - break; - } - } else if (maxHitChance == 100) { - switch (distance) { - case 1: - case 5: - chance = static_cast(std::min(skill, 73) * 1.35f) + 1; - break; - case 2: - chance = static_cast(std::min(skill, 30) * 3.20f) + 4; - break; - case 3: - chance = static_cast(std::min(skill, 48) * 2.05f) + 2; - break; - case 4: - chance = static_cast(std::min(skill, 65) * 1.50f) + 2; - break; - case 6: - chance = static_cast(std::min(skill, 87) * 1.20f) - 4; - break; - case 7: - chance = static_cast(std::min(skill, 90) * 1.10f) + 1; - break; - default: - chance = it.hitChance; - break; - } - } else { - chance = maxHitChance; - } - } else { - chance = it.hitChance; - } - - if (item->getWeaponType() == WEAPON_AMMO) { - Item* bow = player->getWeapon(true); - if (bow && bow->getHitChance() != 0) { - chance += bow->getHitChance(); - } - } - - if (chance >= uniform_random(1, 100)) { - Weapon::internalUseWeapon(player, item, target, damageModifier); - } else { - //miss target - Tile* destTile = target->getTile(); - - if (!Position::areInRange<1, 1, 0>(player->getPosition(), target->getPosition())) { - static std::vector> destList { - {-1, -1}, {0, -1}, {1, -1}, - {-1, 0}, {0, 0}, {1, 0}, - {-1, 1}, {0, 1}, {1, 1} - }; - std::shuffle(destList.begin(), destList.end(), getRandomGenerator()); - - Position destPos = target->getPosition(); - - for (const auto& dir : destList) { - // Blocking tiles or tiles without ground ain't valid targets for spears - Tile* tmpTile = g_game.map.getTile(destPos.x + dir.first, destPos.y + dir.second, destPos.z); - if (tmpTile && !tmpTile->hasProperty(CONST_PROP_IMMOVABLEBLOCKSOLID) && tmpTile->getGround() != nullptr) { - destTile = tmpTile; - break; - } - } - } - - Weapon::internalUseWeapon(player, item, destTile); - } - return true; -} - -int32_t WeaponDistance::getElementDamage(const Player* player, const Creature* target, const Item* item) const -{ - if (elementType == COMBAT_NONE) { - return 0; - } - - int32_t attackValue = elementDamage; - if (item->getWeaponType() == WEAPON_AMMO) { - Item* weapon = player->getWeapon(true); - if (weapon) { - attackValue += weapon->getAttack(); - } - } - - int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); - float attackFactor = player->getAttackFactor(); - - int32_t minValue = 0; - int32_t maxValue = Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor); - if (target) { - if (target->getPlayer()) { - minValue = static_cast(std::ceil(player->getLevel() * 0.1)); - } else { - minValue = static_cast(std::ceil(player->getLevel() * 0.2)); - } - } - - return -normal_random(minValue, static_cast(maxValue * player->getVocation()->distDamageMultiplier)); -} - -int32_t WeaponDistance::getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage /*= false*/) const -{ - int32_t attackValue = item->getAttack(); - - if (item->getWeaponType() == WEAPON_AMMO) { - Item* weapon = player->getWeapon(true); - if (weapon) { - attackValue += weapon->getAttack(); - } - } - - int32_t attackSkill = player->getSkillLevel(SKILL_DISTANCE); - float attackFactor = player->getAttackFactor(); - - int32_t maxValue = static_cast(Weapons::getMaxWeaponDamage(player->getLevel(), attackSkill, attackValue, attackFactor) * player->getVocation()->distDamageMultiplier); - if (maxDamage) { - return -maxValue; - } - - int32_t minValue; - if (target) { - if (target->getPlayer()) { - minValue = static_cast(std::ceil(player->getLevel() * 0.1)); - } else { - minValue = static_cast(std::ceil(player->getLevel() * 0.2)); - } - } else { - minValue = 0; - } - return -normal_random(minValue, maxValue); -} - -bool WeaponDistance::getSkillType(const Player* player, const Item*, skills_t& skill, uint32_t& skillpoint) const -{ - skill = SKILL_DISTANCE; - - if (player->getAddAttackSkill()) { - switch (player->getLastAttackBlockType()) { - case BLOCK_NONE: { - skillpoint = 2; - break; - } - - case BLOCK_DEFENSE: - case BLOCK_ARMOR: { - skillpoint = 1; - break; - } - - default: - skillpoint = 0; - break; - } - } else { - skillpoint = 0; - } - return true; -} - -WeaponWand::WeaponWand(LuaScriptInterface* _interface) : - Weapon(_interface) -{ - minChange = 0; - maxChange = 0; -} - -bool WeaponWand::configureEvent(const pugi::xml_node& node) -{ - if (!Weapon::configureEvent(node)) { - return false; - } - - pugi::xml_attribute attr; - if ((attr = node.attribute("min"))) { - minChange = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("max"))) { - maxChange = pugi::cast(attr.value()); - } - - if ((attr = node.attribute("type"))) { - std::string tmpStrValue = asLowerCaseString(attr.as_string()); - if (tmpStrValue == "earth") { - params.combatType = COMBAT_EARTHDAMAGE; - } else if (tmpStrValue == "ice") { - params.combatType = COMBAT_ICEDAMAGE; - } else if (tmpStrValue == "energy") { - params.combatType = COMBAT_ENERGYDAMAGE; - } else if (tmpStrValue == "fire") { - params.combatType = COMBAT_FIREDAMAGE; - } else if (tmpStrValue == "death") { - params.combatType = COMBAT_DEATHDAMAGE; - } else if (tmpStrValue == "holy") { - params.combatType = COMBAT_HOLYDAMAGE; - } else { - std::cout << "[Warning - WeaponWand::configureEvent] Type \"" << attr.as_string() << "\" does not exist." << std::endl; - } - } - return true; -} - -void WeaponWand::configureWeapon(const ItemType& it) -{ - params.distanceEffect = it.shootType; - - Weapon::configureWeapon(it); -} - -int32_t WeaponWand::getWeaponDamage(const Player*, const Creature*, const Item*, bool maxDamage /*= false*/) const -{ - if (maxDamage) { - return -maxChange; - } - return -normal_random(minChange, maxChange); -} diff --git a/path_10_8/src/weapons.h b/path_10_8/src/weapons.h deleted file mode 100644 index 1b1608ab1..000000000 --- a/path_10_8/src/weapons.h +++ /dev/null @@ -1,201 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_WEAPONS_H_69D1993478AA42948E24C0B90B8F5BF5 -#define FS_WEAPONS_H_69D1993478AA42948E24C0B90B8F5BF5 - -#include "luascript.h" -#include "player.h" -#include "baseevents.h" -#include "combat.h" -#include "const.h" - -class Weapon; -class WeaponMelee; -class WeaponDistance; -class WeaponWand; - -class Weapons final : public BaseEvents -{ - public: - Weapons(); - ~Weapons(); - - // non-copyable - Weapons(const Weapons&) = delete; - Weapons& operator=(const Weapons&) = delete; - - void loadDefaults(); - const Weapon* getWeapon(const Item* item) const; - - static int32_t getMaxMeleeDamage(int32_t attackSkill, int32_t attackValue); - static int32_t getMaxWeaponDamage(uint32_t level, int32_t attackSkill, int32_t attackValue, float attackFactor); - - protected: - void clear() final; - LuaScriptInterface& getScriptInterface() final; - std::string getScriptBaseName() const final; - Event* getEvent(const std::string& nodeName) final; - bool registerEvent(Event* event, const pugi::xml_node& node) final; - - std::map weapons; - - LuaScriptInterface m_scriptInterface; -}; - -class Weapon : public Event -{ - public: - explicit Weapon(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) override; - bool loadFunction(const pugi::xml_attribute&) final { - return true; - } - virtual void configureWeapon(const ItemType& it); - virtual bool interruptSwing() const { - return false; - } - - int32_t playerWeaponCheck(Player* player, Creature* target, uint8_t shootRange) const; - static bool useFist(Player* player, Creature* target); - virtual bool useWeapon(Player* player, Item* item, Creature* target) const; - - virtual int32_t getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage = false) const = 0; - virtual int32_t getElementDamage(const Player* player, const Creature* target, const Item* item) const = 0; - virtual CombatType_t getElementType() const = 0; - - uint16_t getID() const { - return id; - } - - uint32_t getReqLevel() const { - return level; - } - uint32_t getReqMagLv() const { - return magLevel; - } - bool isPremium() const { - return premium; - } - bool isWieldedUnproperly() const { - return wieldUnproperly; - } - - protected: - std::string getScriptEventName() const final; - - bool executeUseWeapon(Player* player, const LuaVariant& var) const; - void internalUseWeapon(Player* player, Item* item, Creature* target, int32_t damageModifier) const; - void internalUseWeapon(Player* player, Item* item, Tile* tile) const; - - void onUsedWeapon(Player* player, Item* item, Tile* destTile) const; - virtual bool getSkillType(const Player*, const Item*, skills_t&, uint32_t&) const { - return false; - } - - uint32_t getManaCost(const Player* player) const; - - CombatParams params; - - uint32_t level; - uint32_t magLevel; - uint32_t mana; - uint32_t manaPercent; - uint32_t soul; - uint16_t id; - WeaponAction_t action; - uint8_t breakChance; - bool enabled; - bool premium; - bool wieldUnproperly; - bool swing; - - private: - void decrementItemCount(Item* item) const; - - std::map vocWeaponMap; - friend class Combat; -}; - -class WeaponMelee final : public Weapon -{ - public: - explicit WeaponMelee(LuaScriptInterface* _interface); - - void configureWeapon(const ItemType& it) final; - - bool useWeapon(Player* player, Item* item, Creature* target) const final; - - int32_t getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage = false) const final; - int32_t getElementDamage(const Player* player, const Creature* target, const Item* item) const final; - CombatType_t getElementType() const final { return elementType; } - - protected: - bool getSkillType(const Player* player, const Item* item, skills_t& skill, uint32_t& skillpoint) const final; - - CombatType_t elementType; - uint16_t elementDamage; -}; - -class WeaponDistance final : public Weapon -{ - public: - explicit WeaponDistance(LuaScriptInterface* _interface); - - void configureWeapon(const ItemType& it) final; - bool interruptSwing() const final { - return true; - } - - bool useWeapon(Player* player, Item* item, Creature* target) const final; - - int32_t getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage = false) const final; - int32_t getElementDamage(const Player* player, const Creature* target, const Item* item) const final; - CombatType_t getElementType() const final { return elementType; } - - protected: - bool getSkillType(const Player* player, const Item* item, skills_t& skill, uint32_t& skillpoint) const final; - - CombatType_t elementType; - uint16_t elementDamage; -}; - -class WeaponWand final : public Weapon -{ - public: - explicit WeaponWand(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - void configureWeapon(const ItemType& it) final; - - int32_t getWeaponDamage(const Player* player, const Creature* target, const Item* item, bool maxDamage = false) const final; - int32_t getElementDamage(const Player*, const Creature*, const Item*) const final { return 0; } - CombatType_t getElementType() const final { return COMBAT_NONE; } - - protected: - bool getSkillType(const Player*, const Item*, skills_t&, uint32_t&) const final { - return false; - } - - int32_t minChange; - int32_t maxChange; -}; - -#endif diff --git a/path_10_8/src/wildcardtree.cpp b/path_10_8/src/wildcardtree.cpp deleted file mode 100644 index 542da0669..000000000 --- a/path_10_8/src/wildcardtree.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#include "otpch.h" - -#include - -#include "wildcardtree.h" - -WildcardTreeNode* WildcardTreeNode::getChild(char ch) -{ - auto it = children.find(ch); - if (it == children.end()) { - return nullptr; - } - return &it->second; -} - -const WildcardTreeNode* WildcardTreeNode::getChild(char ch) const -{ - auto it = children.find(ch); - if (it == children.end()) { - return nullptr; - } - return &it->second; -} - -WildcardTreeNode* WildcardTreeNode::addChild(char ch, bool breakpoint) -{ - WildcardTreeNode* child = getChild(ch); - if (child) { - if (breakpoint && !child->breakpoint) { - child->breakpoint = true; - } - } else { - auto pair = children.emplace(ch, breakpoint); - child = &pair.first->second; - } - return child; -} - -void WildcardTreeNode::insert(const std::string& str) -{ - WildcardTreeNode* cur = this; - - size_t length = str.length() - 1; - for (size_t pos = 0; pos < length; ++pos) { - cur = cur->addChild(str[pos], false); - } - - cur->addChild(str[length], true); -} - -void WildcardTreeNode::remove(const std::string& str) -{ - WildcardTreeNode* cur = this; - - std::stack path; - path.push(cur); - size_t len = str.length(); - for (size_t pos = 0; pos < len; ++pos) { - cur = cur->getChild(str[pos]); - if (!cur) { - return; - } - path.push(cur); - } - - cur->breakpoint = false; - - do { - cur = path.top(); - path.pop(); - - if (!cur->children.empty() || cur->breakpoint || path.empty()) { - break; - } - - cur = path.top(); - - auto it = cur->children.find(str[--len]); - if (it != cur->children.end()) { - cur->children.erase(it); - } - } while (true); -} - -ReturnValue WildcardTreeNode::findOne(const std::string& query, std::string& result) const -{ - const WildcardTreeNode* cur = this; - for (size_t pos = 0; pos < query.length(); ++pos) { - cur = cur->getChild(query[pos]); - if (!cur) { - return RETURNVALUE_PLAYERWITHTHISNAMEISNOTONLINE; - } - } - - result = query; - - do { - size_t size = cur->children.size(); - if (size == 0) { - return RETURNVALUE_NOERROR; - } else if (size > 1 || cur->breakpoint) { - return RETURNVALUE_NAMEISTOOAMBIGIOUS; - } - - auto it = cur->children.begin(); - result += it->first; - cur = &it->second; - } while (true); -} diff --git a/path_10_8/src/wildcardtree.h b/path_10_8/src/wildcardtree.h deleted file mode 100644 index ed8eaddce..000000000 --- a/path_10_8/src/wildcardtree.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * The Forgotten Server - a free and open-source MMORPG server emulator - * Copyright (C) 2016 Mark Samman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ - -#ifndef FS_WILDCARDTREE_H_054C9BA46A1D4EA4B7C77ECE60ED4DEB -#define FS_WILDCARDTREE_H_054C9BA46A1D4EA4B7C77ECE60ED4DEB - -#include "enums.h" - -class WildcardTreeNode -{ - public: - WildcardTreeNode(bool breakpoint) : breakpoint(breakpoint) {} - WildcardTreeNode(WildcardTreeNode&& other) : children(std::move(other.children)), breakpoint(other.breakpoint) {} - - // non-copyable - WildcardTreeNode(const WildcardTreeNode&) = delete; - WildcardTreeNode& operator=(const WildcardTreeNode&) = delete; - - WildcardTreeNode* getChild(char ch); - const WildcardTreeNode* getChild(char ch) const; - WildcardTreeNode* addChild(char ch, bool breakpoint); - - void insert(const std::string& str); - void remove(const std::string& str); - - ReturnValue findOne(const std::string& query, std::string& result) const; - - private: - std::map children; - bool breakpoint; -}; - -#endif diff --git a/path_10_8/vc14/TheForgottenServer.rc b/path_10_8/vc14/TheForgottenServer.rc deleted file mode 100644 index 5147602ee..000000000 --- a/path_10_8/vc14/TheForgottenServer.rc +++ /dev/null @@ -1 +0,0 @@ -MAINICON ICON "TheForgottenServer.ico" \ No newline at end of file diff --git a/path_10_8/vc14/arch32.props b/path_10_8/vc14/arch32.props deleted file mode 100644 index d2adc41ef..000000000 --- a/path_10_8/vc14/arch32.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - $(TFS_LIBS) - true - - - - \ No newline at end of file diff --git a/path_10_8/vc14/arch64.props b/path_10_8/vc14/arch64.props deleted file mode 100644 index 6c086a54a..000000000 --- a/path_10_8/vc14/arch64.props +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - $(TFS_LIBS64) - - - - \ No newline at end of file diff --git a/path_10_8/vc14/debug.props b/path_10_8/vc14/debug.props deleted file mode 100644 index ab4fb7de3..000000000 --- a/path_10_8/vc14/debug.props +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - true - - - - false - false - EnableFastChecks - MultiThreadedDebugDLL - $(IntDir)\obj_d\ - - - $(TFS_LIBDEPS_D) - - - - - diff --git a/path_10_8/vc14/release.props b/path_10_8/vc14/release.props deleted file mode 100644 index 1a6520d97..000000000 --- a/path_10_8/vc14/release.props +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - false - - - - Full - $(IntDir)\obj_r\ - - - UseLinkTimeCodeGeneration - - - - - diff --git a/path_10_8/vc14/settings.props b/path_10_8/vc14/settings.props deleted file mode 100644 index 191f4f40a..000000000 --- a/path_10_8/vc14/settings.props +++ /dev/null @@ -1,73 +0,0 @@ - - - - - $(TFSSDKDir)\LuaJIT\ - $(TFSSDKDir)\mpir\ - $(TFSSDKDir)\mysql-connector-c\ - _CRT_SECURE_NO_WARNINGS; - $(BOOST_ROOT);$(LUA_DIR)\include;$(GMP_DIR)\include;$(MYSQLC_DIR)\include - $(BOOST_ROOT)\lib32-msvc-14.0;$(LUA_DIR)\lib;$(GMP_DIR)\lib;$(MYSQLC_DIR)\lib - $(BOOST_ROOT)\lib64-msvc-14.0;$(LUA_DIR)\lib64;$(GMP_DIR)\lib64;$(MYSQLC_DIR)\lib64 - lua51.lib;mpir.lib;libmysql.lib - lua51.lib;mpir.lib;libmysql.lib - - - false - - - - $(TFS_INCLUDES) - Level3 - true - true - Use - otpch.h - MultiThreadedDLL - - - $(TFS_LIBDEPS) - Default - - - $(PREPROCESSOR_DEFS) - - - - - $(LUA_DIR) - true - - - $(GMP_DIR) - true - - - $(MYSQLC_DIR) - true - - - $(PREPROCESSOR_DEFS) - true - - - $(TFS_INCLUDES) - true - - - $(TFS_LIBS) - true - - - $(TFS_LIBS64) - true - - - $(TFS_LIBDEPS) - true - - - $(TFS_LIBDEPS_D) - - - \ No newline at end of file diff --git a/path_10_8/vc14/theforgottenserver.ico b/path_10_8/vc14/theforgottenserver.ico deleted file mode 100644 index 78af5e576..000000000 Binary files a/path_10_8/vc14/theforgottenserver.ico and /dev/null differ diff --git a/path_10_8/vc14/theforgottenserver.sln b/path_10_8/vc14/theforgottenserver.sln deleted file mode 100644 index 4c37956c6..000000000 --- a/path_10_8/vc14/theforgottenserver.sln +++ /dev/null @@ -1,28 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "theforgottenserver", "theforgottenserver.vcxproj", "{A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Debug|x64 = Debug|x64 - Release|Win32 = Release|Win32 - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Debug|Win32.ActiveCfg = Debug|Win32 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Debug|Win32.Build.0 = Debug|Win32 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Debug|x64.ActiveCfg = Debug|x64 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Debug|x64.Build.0 = Debug|x64 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Release|Win32.ActiveCfg = Release|Win32 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Release|Win32.Build.0 = Release|Win32 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Release|x64.ActiveCfg = Release|x64 - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E}.Release|x64.Build.0 = Release|x64 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/path_10_8/vc14/theforgottenserver.vcxproj b/path_10_8/vc14/theforgottenserver.vcxproj deleted file mode 100644 index 8021e3c3d..000000000 --- a/path_10_8/vc14/theforgottenserver.vcxproj +++ /dev/null @@ -1,302 +0,0 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - Win32Proj - {A10F9657-129F-0FEF-14CB-CEE0B0E5AA3E} - - - - Application - true - v140 - - - Application - true - v140 - - - Application - false - v140 - - - Application - false - v140 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - _CONSOLE;$(PREPROCESSOR_DEFS);%(PreprocessorDefinitions) - ProgramDatabase - Disabled - - - MachineX86 - true - Console - - - - - _CONSOLE;$(PREPROCESSOR_DEFS);%(PreprocessorDefinitions) - ProgramDatabase - - - true - Console - - - - - NDEBUG;_CONSOLE;$(PREPROCESSOR_DEFS);%(PreprocessorDefinitions) - MultiThreadedDLL - ProgramDatabase - - - MachineX86 - true - Console - true - true - - - - - NDEBUG;_CONSOLE;$(PREPROCESSOR_DEFS);%(PreprocessorDefinitions) - MultiThreadedDLL - ProgramDatabase - Level4 - - - true - Console - true - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create - Create - Create - Create - otpch.h - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/path_10_9/.gitignore b/path_10_9/.gitignore index bf2b4e1e8..5400463dd 100644 --- a/path_10_9/.gitignore +++ b/path_10_9/.gitignore @@ -52,6 +52,7 @@ ipch/ *.aps *.ncb *.opensdf +*.opendb *.sdf *.cachefile diff --git a/path_10_9/config.lua b/path_10_9/config.lua index 927cc2be0..6d4a5c0c9 100644 --- a/path_10_9/config.lua +++ b/path_10_9/config.lua @@ -5,11 +5,11 @@ hotkeyAimbotEnabled = true protectionLevel = 1 killsToRedSkull = 3 killsToBlackSkull = 6 -pzLocked = 60000 +pzLocked = 60 * 1000 removeChargesFromRunes = true timeToDecreaseFrags = 24 * 60 * 60 * 1000 whiteSkullTime = 15 * 60 * 1000 -stairJumpExhaustion = 2000 +stairJumpExhaustion = 2 * 1000 experienceByKillingPlayers = false expFromPlayersLevelRange = 75 @@ -25,7 +25,7 @@ motd = "Welcome to The Forgotten Server!" onePlayerOnlinePerAccount = true allowClones = false serverName = "Forgotten" -statusTimeout = 5000 +statusTimeout = 5 * 1000 replaceKickOnLogin = true maxPacketsPerSecond = 25 @@ -38,7 +38,7 @@ deathLosePercent = -1 -- Houses -- NOTE: set housePriceEachSQM to -1 to disable the ingame buy house functionality housePriceEachSQM = 1000 -houseRentPeriod = "never" +houseRentPeriod = "weekly" -- Item Usage timeBetweenActions = 200 @@ -68,7 +68,7 @@ allowChangeOutfit = true freePremium = false kickIdlePlayerAfterMinutes = 15 maxMessageBuffer = 4 -emoteSpells = false +emoteSpells = true classicEquipmentSlots = false -- Rates @@ -94,10 +94,10 @@ convertUnsafeScripts = true -- NOTE: defaultPriority only works on Windows and sets process -- priority, valid values are: "normal", "above-normal", "high" defaultPriority = "high" -startupDatabaseOptimization = false +startupDatabaseOptimization = true -- Status server information -ownerName = "" -ownerEmail = "" -url = "https://otland.net/" -location = "Sweden" +ownerName = "Mattyx14" +ownerEmail = "darkylive@live.com.mx" +url = "http://darkkonia.sytes.net/" +location = "Mexico" diff --git a/path_10_9/data/XML/mounts.xml b/path_10_9/data/XML/mounts.xml index dceb65d4f..d0e0901f7 100644 --- a/path_10_9/data/XML/mounts.xml +++ b/path_10_9/data/XML/mounts.xml @@ -74,4 +74,20 @@ + + + + + + + + + + + + + + + + diff --git a/path_10_9/data/XML/outfits.xml b/path_10_9/data/XML/outfits.xml index 0b2cc48eb..854fe86ce 100644 --- a/path_10_9/data/XML/outfits.xml +++ b/path_10_9/data/XML/outfits.xml @@ -35,6 +35,7 @@ + @@ -45,6 +46,13 @@ + + + + + + + @@ -81,6 +89,7 @@ + @@ -91,4 +100,11 @@ + + + + + + + diff --git a/path_10_9/data/actions/actions.xml b/path_10_9/data/actions/actions.xml index c39a360bc..a77aa1c66 100644 --- a/path_10_9/data/actions/actions.xml +++ b/path_10_9/data/actions/actions.xml @@ -4,6 +4,7 @@ + diff --git a/path_10_9/data/actions/scripts/other/doors.lua b/path_10_9/data/actions/scripts/other/doors.lua index d1fdbe1d6..0374d46a9 100644 --- a/path_10_9/data/actions/scripts/other/doors.lua +++ b/path_10_9/data/actions/scripts/other/doors.lua @@ -16,6 +16,9 @@ function onUse(player, item, fromPosition, target, toPosition, isHotkey) player:sendTextMessage(MESSAGE_INFO_DESCR, "Only the worthy may pass.") end return true + elseif isInArray(blockDoors, itemId) then + player:sendTextMessage(MESSAGE_STATUS_SMALL, "It is locked.") + return true elseif isInArray(keys, itemId) then if target.actionid > 0 then if item.actionid == target.actionid and doors[target.itemid] then diff --git a/path_10_9/data/actions/scripts/quests/system.lua b/path_10_9/data/actions/scripts/quests/system.lua new file mode 100644 index 000000000..9f37e462e --- /dev/null +++ b/path_10_9/data/actions/scripts/quests/system.lua @@ -0,0 +1,87 @@ +local specialQuests = {} +local questsExperience = {} +local questLog = {} + +function onUse(player, item, fromPosition, target, toPosition, isHotkey) + local storage = specialQuests[item.actionid] + if not storage then + storage = item.uid + if storage > 65535 then + return false + end + end + + if player:getStorageValue(storage) > 0 then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'The ' .. ItemType(item.itemid):getName() .. ' is empty.') + return true + end + + local items, reward = {} + local size = item:isContainer() and item:getSize() or 0 + if size == 0 then + reward = item:clone() + else + local container = Container(item.uid) + for i = 0, container:getSize() - 1 do + items[#items + 1] = container:getItem(i):clone() + end + end + + size = #items + if size == 1 then + reward = items[1]:clone() + end + + local result = '' + if reward then + local ret = ItemType(reward.itemid) + if ret:isRune() then + result = ret:getArticle() .. ' ' .. ret:getName() .. ' (' .. reward.type .. ' charges)' + elseif ret:isStackable() and reward:getCount() > 1 then + result = reward:getCount() .. ' ' .. ret:getPluralName() + elseif ret:getArticle() ~= '' then + result = ret:getArticle() .. ' ' .. ret:getName() + else + result = ret:getName() + end + else + if size > 20 then + reward = Game.createItem(item.itemid, 1) + elseif size > 8 then + reward = Game.createItem(1988, 1) + else + reward = Game.createItem(1987, 1) + end + + for i = 1, size do + local tmp = items[i] + if reward:addItemEx(tmp) ~= RETURNVALUE_NOERROR then + print('[Warning] QuestSystem:', 'Could not add quest reward to container') + end + end + local ret = ItemType(reward.itemid) + result = ret:getArticle() .. ' ' .. ret:getName() + end + + if player:addItemEx(reward) ~= RETURNVALUE_NOERROR then + local weight = reward:getWeight() + if player:getFreeCapacity() < weight then + player:sendCancelMessage(string.format('You have found %s weighing %.2f oz. You have no capacity.', result, (weight / 100))) + else + player:sendCancelMessage('You have found ' .. result .. ', but you have no room to take it.') + end + return true + end + + if questsExperience[storage] then + player:addExperience(questsExperience[storage], true) + end + + if questLog[storage] then + player:setStorageValue(questLog[storage], 1) + end + + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You have found ' .. result .. '.') + player:setStorageValue(storage, 1) + return true +end diff --git a/path_10_9/data/actions/scripts/tools/shovel.lua b/path_10_9/data/actions/scripts/tools/shovel.lua index 3bacc66d8..d5fcd9b4e 100644 --- a/path_10_9/data/actions/scripts/tools/shovel.lua +++ b/path_10_9/data/actions/scripts/tools/shovel.lua @@ -1,5 +1,14 @@ local holes = {468, 481, 483} +local others = {7932} function onUse(player, item, fromPosition, target, toPosition, isHotkey) + local targetId = target.itemid, target.actionid + if isInArray(others, targetId) then + target:transform(targetId + 1) + target:decay() + + return true + end + if toPosition.x == CONTAINER_POSITION then return false end diff --git a/path_10_9/data/creaturescripts/creaturescripts.xml b/path_10_9/data/creaturescripts/creaturescripts.xml index 86e2c8c3a..18f666513 100644 --- a/path_10_9/data/creaturescripts/creaturescripts.xml +++ b/path_10_9/data/creaturescripts/creaturescripts.xml @@ -2,10 +2,13 @@ - + + + + diff --git a/path_10_9/data/creaturescripts/scripts/advance_save.lua b/path_10_9/data/creaturescripts/scripts/advance_save.lua new file mode 100644 index 000000000..b4095a9d0 --- /dev/null +++ b/path_10_9/data/creaturescripts/scripts/advance_save.lua @@ -0,0 +1,25 @@ +local config = { + heal = true, + save = true, + effect = false +} + +function onAdvance(player, skill, oldLevel, newLevel) + if skill ~= SKILL_LEVEL or newLevel <= oldLevel then + return true + end + + if config.effect then + player:getPosition():sendMagicEffect(math.random(CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_BLUE)) + player:say('LEVEL UP!', TALKTYPE_MONSTER_SAY) + end + + if config.heal then + player:addHealth(player:getMaxHealth()) + end + + if config.save then + player:save() + end + return true +end diff --git a/path_10_9/data/creaturescripts/scripts/firstitems.lua b/path_10_9/data/creaturescripts/scripts/firstitems.lua index 9530f4657..38a9ec889 100644 --- a/path_10_9/data/creaturescripts/scripts/firstitems.lua +++ b/path_10_9/data/creaturescripts/scripts/firstitems.lua @@ -1,12 +1,52 @@ -local firstItems = {2050, 2382} +-- Without Rookgaard +local config = { + [1] = { + --equipment spellbook, wand of vortex, magician's robe, mage hat, studded legs, leather boots, scarf + items = {{2175, 1}, {2190, 1}, {8819, 1}, {8820, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, + --container rope, shovel, mana potion + container = {{2120, 1}, {2554, 1}, {7620, 1}} + }, + [2] = { + --equipment spellbook, snakebite rod, magician's robe, mage hat, studded legs, leather boots scarf + items = {{2175, 1}, {2182, 1}, {8819, 1}, {8820, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, + --container rope, shovel, mana potion + container = {{2120, 1}, {2554, 1}, {7620, 1}} + }, + [3] = { + --equipment dwrven shield, 5 spear, ranger's cloak, ranger legs scarf, legion helmet + items = {{2525, 1}, {2389, 5}, {2660, 1}, {8923, 1}, {2643, 1}, {2661, 1}, {2480, 1}}, + --container rope, shovel, health potion, bow, 50 arrow + container = {{2120, 1}, {2554, 1}, {7618, 1}, {2456, 1}, {2544, 50}} + }, + [4] = { + --equipment dwarven shield, steel axe, brass armor, brass helmet, brass legs scarf + items = {{2525, 1}, {8601, 1}, {2465, 1}, {2460, 1}, {2478, 1}, {2643, 1}, {2661, 1}}, + --container jagged sword, daramian mace, rope, shovel, health potion + container = {{8602, 1}, {2439, 1}, {2120, 1}, {2554, 1}, {7618, 1}} + } +} function onLogin(player) - if player:getLastLoginSaved() == 0 then - for i = 1, #firstItems do - player:addItem(firstItems[i], 1) - end - player:addItem(player:getSex() == 0 and 2651 or 2650, 1) - player:addItem(1987, 1):addItem(2674, 1) + local targetVocation = config[player:getVocation():getId()] + if not targetVocation then + return true + end + + if player:getLastLoginSaved() ~= 0 then + return true + end + + for i = 1, #targetVocation.items do + player:addItem(targetVocation.items[i][1], targetVocation.items[i][2]) + end + + local backpack = player:addItem(1988) + if not backpack then + return true + end + + for i = 1, #targetVocation.container do + backpack:addItem(targetVocation.container[i][1], targetVocation.container[i][2]) end return true end diff --git a/path_10_9/data/events/events.xml b/path_10_9/data/events/events.xml index 77ba759da..446a6b09a 100644 --- a/path_10_9/data/events/events.xml +++ b/path_10_9/data/events/events.xml @@ -16,12 +16,16 @@ - + - + + + + + diff --git a/path_10_9/data/events/scripts/player.lua b/path_10_9/data/events/scripts/player.lua index a75ddce4d..08e53173c 100644 --- a/path_10_9/data/events/scripts/player.lua +++ b/path_10_9/data/events/scripts/player.lua @@ -86,6 +86,32 @@ function Player:onLookInShop(itemType, count) end function Player:onMoveItem(item, count, fromPosition, toPosition) + if toPosition.x ~= CONTAINER_POSITION then + return true + end + + if item:getTopParent() == self and bit.band(toPosition.y, 0x40) == 0 then + local itemType, moveItem = ItemType(item:getId()) + if bit.band(itemType:getSlotPosition(), SLOTP_TWO_HAND) ~= 0 and toPosition.y == CONST_SLOT_LEFT then + moveItem = self:getSlotItem(CONST_SLOT_RIGHT) + elseif itemType:getWeaponType() == WEAPON_SHIELD and toPosition.y == CONST_SLOT_RIGHT then + moveItem = self:getSlotItem(CONST_SLOT_LEFT) + if moveItem and bit.band(ItemType(moveItem:getId()):getSlotPosition(), SLOTP_TWO_HAND) == 0 then + return true + end + end + + if moveItem then + local parent = item:getParent() + if parent:getSize() == parent:getCapacity() then + self:sendTextMessage(MESSAGE_STATUS_SMALL, Game.getReturnMessage(RETURNVALUE_CONTAINERNOTENOUGHROOM)) + return false + else + return moveItem:moveTo(parent) + end + end + end + return true end @@ -180,3 +206,7 @@ function Player:onGainSkillTries(skill, tries) end return tries * configManager.getNumber(configKeys.RATE_SKILL) end + +function Player:onSave(GUID) + return true +end diff --git a/path_10_9/data/global.lua b/path_10_9/data/global.lua index 23101bc5b..5f5268fc7 100644 --- a/path_10_9/data/global.lua +++ b/path_10_9/data/global.lua @@ -4,12 +4,13 @@ STORAGEVALUE_PROMOTION = 30018 ropeSpots = {384, 418, 8278, 8592, 13189, 14435, 14436, 15635, 19518} -doors = {[1209] = 1211, [1210] = 1211, [1212] = 1214, [1213] = 1214, [1219] = 1220, [1221] = 1222, [1231] = 1233, [1232] = 1233, [1234] = 1236, [1235] = 1236, [1237] = 1238, [1239] = 1240, [1249] = 1251, [1250] = 1251, [1252] = 1254, [1253] = 1254, [1539] = 1540, [1541] = 1542, [3535] = 3537, [3536] = 3537, [3538] = 3539, [3544] = 3546, [3545] = 3546, [3547] = 3548, [4913] = 4915, [4914] = 4915, [4916] = 4918, [4917] = 4918, [5082] = 5083, [5084] = 5085, [5098] = 5100, [5099] = 5100, [5101] = 5102, [5107] = 5109, [5108] = 5109, [5110] = 5111, [5116] = 5118, [5117] = 5118, [5119] = 5120, [5125] = 5127, [5126] = 5127, [5128] = 5129, [5134] = 5136, [5135] = 5136, [5137] = 5139, [5138] = 5139, [5140] = 5142, [5141] = 5142, [5143] = 5145, [5144] = 5145, [5278] = 5280, [5279] = 5280, [5281] = 5283, [5282] = 5283, [5284] = 5285, [5286] = 5287, [5515] = 5516, [5517] = 5518, [5732] = 5734, [5733] = 5734, [5735] = 5737, [5736] = 5737, [6192] = 6194, [6193] = 6194, [6195] = 6197, [6196] = 6197, [6198] = 6199, [6200] = 6201, [6249] = 6251, [6250] = 6251, [6252] = 6254, [6253] = 6254, [6255] = 6256, [6257] = 6258, [6795] = 6796, [6797] = 6798, [6799] = 6800, [6801] = 6802, [6891] = 6893, [6892] = 6893, [6894] = 6895, [6900] = 6902, [6901] = 6902, [6903] = 6904, [7033] = 7035, [7034] = 7035, [7036] = 7037, [7042] = 7044, [7043] = 7044, [7045] = 7046, [7054] = 7055, [7056] = 7057, [8541] = 8543, [8542] = 8543, [8544] = 8546, [8545] = 8546, [8547] = 8548, [8549] = 8550, [9165] = 9167, [9166] = 9167, [9168] = 9170, [9169] = 9170, [9171] = 9172, [9173] = 9174, [9267] = 9269, [9268] = 9269, [9270] = 9272, [9271] = 9272, [9273] = 9274, [9275] = 9276, [10276] = 10277, [10274] = 10275, [10268] = 10270, [10269] = 10270, [10271] = 10273, [10272] = 10273, [10471] = 10472, [10480] = 10481, [10477] = 10479, [10478] = 10479, [10468] = 10470, [10469] = 10470, [10775] = 10777, [10776] = 10777, [12092] = 12094, [12093] = 12094, [12188] = 12190, [12189] = 12190, [19840] = 19842, [19841] = 19842, [19843] = 19844, [19980] = 19982, [19981] = 19982, [19983] = 19984, [20273] = 20275, [20274] = 20275, [20276] = 20277, [17235] = 17236, [18208] = 18209, [13022] = 13023, [10784] = 10786, [10785] = 10786, [12099] = 12101, [12100] = 12101, [12197] = 12199, [12198] = 12199, [19849] = 19851, [19850] = 19851, [19852] = 19853, [19989] = 19991, [19990] = 19991, [19992] = 19993, [20282] = 20284, [20283] = 20284, [20285] = 20286, [17237] = 17238, [13020] = 13021, [10780] = 10781, [12095] = 12096, [12195] = 12196, [19845] = 19846, [19985] = 19986, [20278] = 20279, [10789] = 10790, [12102] = 12103, [12204] = 12205, [19854] = 19855, [19994] = 19995, [20287] = 20288, [10782] = 10783, [12097] = 12098, [12193] = 12194, [19847] = 19848, [19987] = 19988, [20280] = 20281, [10791] = 10792, [12104] = 12105, [12202] = 12203, [19856] = 19857, [19996] = 19997, [20289] = 20290} +doors = {[1210] = 1211, [1213] = 1214, [1219] = 1220, [1221] = 1222, [1231] = 1233, [1232] = 1233, [1234] = 1236, [1235] = 1236, [1237] = 1238, [1239] = 1240, [1249] = 1251, [1250] = 1251, [1252] = 1254, [1253] = 1254, [1539] = 1540, [1541] = 1542, [3535] = 3537, [3536] = 3537, [3538] = 3539, [3544] = 3546, [3545] = 3546, [3547] = 3548, [4913] = 4915, [4914] = 4915, [4916] = 4918, [4917] = 4918, [5082] = 5083, [5084] = 5085, [5098] = 5100, [5099] = 5100, [5101] = 5102, [5107] = 5109, [5108] = 5109, [5110] = 5111, [5116] = 5118, [5117] = 5118, [5119] = 5120, [5125] = 5127, [5126] = 5127, [5128] = 5129, [5134] = 5136, [5135] = 5136, [5137] = 5139, [5138] = 5139, [5140] = 5142, [5141] = 5142, [5143] = 5145, [5144] = 5145, [5278] = 5280, [5279] = 5280, [5281] = 5283, [5282] = 5283, [5284] = 5285, [5286] = 5287, [5515] = 5516, [5517] = 5518, [5732] = 5734, [5733] = 5734, [5735] = 5737, [5736] = 5737, [6192] = 6194, [6193] = 6194, [6195] = 6197, [6196] = 6197, [6198] = 6199, [6200] = 6201, [6249] = 6251, [6250] = 6251, [6252] = 6254, [6253] = 6254, [6255] = 6256, [6257] = 6258, [6795] = 6796, [6797] = 6798, [6799] = 6800, [6801] = 6802, [6891] = 6893, [6892] = 6893, [6894] = 6895, [6900] = 6902, [6901] = 6902, [6903] = 6904, [7033] = 7035, [7034] = 7035, [7036] = 7037, [7042] = 7044, [7043] = 7044, [7045] = 7046, [7054] = 7055, [7056] = 7057, [8541] = 8543, [8542] = 8543, [8544] = 8546, [8545] = 8546, [8547] = 8548, [8549] = 8550, [9165] = 9167, [9166] = 9167, [9168] = 9170, [9169] = 9170, [9171] = 9172, [9173] = 9174, [9267] = 9269, [9268] = 9269, [9270] = 9272, [9271] = 9272, [9273] = 9274, [9275] = 9276, [10276] = 10277, [10274] = 10275, [10268] = 10270, [10269] = 10270, [10271] = 10273, [10272] = 10273, [10471] = 10472, [10480] = 10481, [10477] = 10479, [10478] = 10479, [10468] = 10470, [10469] = 10470, [10775] = 10777, [10776] = 10777, [12092] = 12094, [12093] = 12094, [12188] = 12190, [12189] = 12190, [19840] = 19842, [19841] = 19842, [19843] = 19844, [19980] = 19982, [19981] = 19982, [19983] = 19984, [20273] = 20275, [20274] = 20275, [20276] = 20277, [17235] = 17236, [18208] = 18209, [13022] = 13023, [10784] = 10786, [10785] = 10786, [12099] = 12101, [12100] = 12101, [12197] = 12199, [12198] = 12199, [19849] = 19851, [19850] = 19851, [19852] = 19853, [19989] = 19991, [19990] = 19991, [19992] = 19993, [20282] = 20284, [20283] = 20284, [20285] = 20286, [17237] = 17238, [13020] = 13021, [10780] = 10781, [12095] = 12096, [12195] = 12196, [19845] = 19846, [19985] = 19986, [20278] = 20279, [10789] = 10790, [12102] = 12103, [12204] = 12205, [19854] = 19855, [19994] = 19995, [20287] = 20288, [10782] = 10783, [12097] = 12098, [12193] = 12194, [19847] = 19848, [19987] = 19988, [20280] = 20281, [10791] = 10792, [12104] = 12105, [12202] = 12203, [19856] = 19857, [19996] = 19997, [20289] = 20290} verticalOpenDoors = {1211, 1220, 1224, 1228, 1233, 1238, 1242, 1246, 1251, 1256, 1260, 1540, 3546, 3548, 3550, 3552, 4915, 5083, 5109, 5111, 5113, 5115, 5127, 5129, 5131, 5133, 5142, 5145, 5283, 5285, 5289, 5293, 5516, 5737, 5749, 6194, 6199, 6203, 6207, 6251, 6256, 6260, 6264, 6798, 6802, 6902, 6904, 6906, 6908, 7044, 7046, 7048, 7050, 7055, 8543, 8548, 8552, 8556, 9167, 9172, 9269, 9274, 9274, 9269, 9278, 9282, 10270, 10275, 10279, 10283, 10479, 10481, 10485, 10483, 10786, 12101, 12199, 19851, 19853, 19991, 19993, 20284, 20286, 17238, 13021, 10790, 12103, 12205, 19855, 19995, 20288, 10792, 12105, 12203, 19857, 19997, 20290} horizontalOpenDoors = {1214, 1222, 1226, 1230, 1236, 1240, 1244, 1248, 1254, 1258, 1262, 1542, 3537, 3539, 3541, 3543, 4918, 5085, 5100, 5102, 5104, 5106, 5118, 5120, 5122, 5124, 5136, 5139, 5280, 5287, 5291, 5295, 5518, 5734, 5746, 6197, 6201, 6205, 6209, 6254, 6258, 6262, 6266, 6796, 6800, 6893, 6895, 6897, 6899, 7035, 7037, 7039, 7041, 7057, 8546, 8550, 8554, 8558, 9170, 9174, 9272, 9276, 9280, 9284, 10273, 10277, 10281, 10285, 10470, 10472, 10476, 10474, 10777, 12094, 12190, 19842, 19844, 19982, 19984, 20275, 20277, 17236, 18209, 13023, 10781, 12096, 12196, 19846, 19986, 20279, 10783, 12098, 12194, 19848, 19988, 20281} openSpecialDoors = {1224, 1226, 1228, 1230, 1242, 1244, 1246, 1248, 1256, 1258, 1260, 1262, 3541, 3543, 3550, 3552, 5104, 5106, 5113, 5115, 5122, 5124, 5131, 5133, 5289, 5291, 5293, 5295, 6203, 6205, 6207, 6209, 6260, 6262, 6264, 6266, 6897, 6899, 6906, 6908, 7039, 7041, 7048, 7050, 8552, 8554, 8556, 8558, 9176, 9178, 9180, 9182, 9278, 9280, 9282, 9284, 10279, 10281, 10283, 10285, 10474, 10476, 10483, 10485, 10781, 12096, 12196, 19846, 19986, 20279, 10783, 12098, 12194, 19848, 19988, 20281, 10790, 12103, 12205, 19855, 19995, 20288, 10792, 12105, 12203, 19857, 19997, 20290} questDoors = {1223, 1225, 1241, 1243, 1255, 1257, 3542, 3551, 5105, 5114, 5123, 5132, 5288, 5290, 5745, 5748, 6202, 6204, 6259, 6261, 6898, 6907, 7040, 7049, 8551, 8553, 9175, 9177, 9277, 9279, 10278, 10280, 10475, 10484, 10782, 12097, 12193, 19847, 19987, 20280, 10791, 12104, 12202, 19856, 19996, 20289} levelDoors = {1227, 1229, 1245, 1247, 1259, 1261, 3540, 3549, 5103, 5112, 5121, 5130, 5292, 5294, 6206, 6208, 6263, 6265, 6896, 6905, 7038, 7047, 8555, 8557, 9179, 9181, 9281, 9283, 10282, 10284, 10473, 10482, 10780, 10789, 10780, 12095, 12195, 19845, 19985, 20278, 10789, 12102, 12204, 19854, 19994, 20287} +blockDoors = {1209, 1212,} keys = {2086, 2087, 2088, 2089, 2090, 2091, 2092, 10032} function getDistanceBetween(firstPosition, secondPosition) diff --git a/path_10_9/data/globalevents/globalevents.xml b/path_10_9/data/globalevents/globalevents.xml index 942d72a71..8012f11aa 100644 --- a/path_10_9/data/globalevents/globalevents.xml +++ b/path_10_9/data/globalevents/globalevents.xml @@ -2,8 +2,8 @@ - - + + + + diff --git a/path_10_9/data/globalevents/scripts/cleanmap.lua b/path_10_9/data/globalevents/scripts/cleanmap.lua new file mode 100644 index 000000000..bc69435f4 --- /dev/null +++ b/path_10_9/data/globalevents/scripts/cleanmap.lua @@ -0,0 +1,10 @@ +local function saveServer() + cleanMap() + broadcastMessage("Clean map completed and the next clean at on 2 hours.", MESSAGE_STATUS_CONSOLE_RED) +end + +function onThink(interval) + broadcastMessage("Cleaning map in 5 minutes.", MESSAGE_STATUS_WARNING) + addEvent(saveServer, 5 * 60 * 1000) + return true +end diff --git a/path_10_9/data/globalevents/scripts/serversave.lua b/path_10_9/data/globalevents/scripts/serversave.lua index 3a6c2f59e..e943e74d5 100644 --- a/path_10_9/data/globalevents/scripts/serversave.lua +++ b/path_10_9/data/globalevents/scripts/serversave.lua @@ -1,33 +1,4 @@ -local shutdownAtServerSave = false -local cleanMapAtServerSave = false - -local function serverSave() - if shutdownAtServerSave then - Game.setGameState(GAME_STATE_SHUTDOWN) - else - Game.setGameState(GAME_STATE_CLOSED) - - if cleanMapAtServerSave then - cleanMap() - end - - Game.setGameState(GAME_STATE_NORMAL) - end -end - -local function secondServerSaveWarning() - broadcastMessage("Server is saving game in one minute. Please logout.", MESSAGE_STATUS_WARNING) - addEvent(serverSave, 60000) -end - -local function firstServerSaveWarning() - broadcastMessage("Server is saving game in 3 minutes. Please logout.", MESSAGE_STATUS_WARNING) - addEvent(secondServerSaveWarning, 120000) -end - -function onTime(interval) - broadcastMessage("Server is saving game in 5 minutes. Please logout.", MESSAGE_STATUS_WARNING) - Game.setGameState(GAME_STATE_STARTUP) - addEvent(firstServerSaveWarning, 120000) - return not shutdownAtServerSave +function onThink(interval) + saveServer() + return true end diff --git a/path_10_9/data/items/items.otb b/path_10_9/data/items/items.otb index b372c1099..7953a709b 100644 Binary files a/path_10_9/data/items/items.otb and b/path_10_9/data/items/items.otb differ diff --git a/path_10_9/data/items/items.xml b/path_10_9/data/items/items.xml index facd820ae..91421c34b 100644 --- a/path_10_9/data/items/items.xml +++ b/path_10_9/data/items/items.xml @@ -220,15 +220,19 @@ - + + + + + - + @@ -285,7 +289,7 @@ - + @@ -297,7 +301,7 @@ - + @@ -353,7 +357,7 @@ - + @@ -365,7 +369,7 @@ - + @@ -6788,7 +6792,7 @@ - + @@ -6822,7 +6826,7 @@ - + @@ -7950,7 +7954,7 @@ - + @@ -7958,7 +7962,7 @@ - + @@ -7966,7 +7970,7 @@ - + @@ -7974,13 +7978,13 @@ - + - + @@ -7993,7 +7997,7 @@ - + @@ -8014,14 +8018,15 @@ - + + - + @@ -8167,7 +8172,7 @@ - + @@ -8179,7 +8184,7 @@ - + @@ -8325,7 +8330,7 @@ - + @@ -8359,7 +8364,7 @@ - + @@ -8393,7 +8398,7 @@ - + @@ -8427,7 +8432,7 @@ - + @@ -8461,7 +8466,7 @@ - + @@ -8473,7 +8478,7 @@ - + @@ -8485,7 +8490,7 @@ - + @@ -8497,7 +8502,7 @@ - + @@ -8526,7 +8531,7 @@ - + @@ -8538,7 +8543,7 @@ - + @@ -9075,7 +9080,7 @@ - + @@ -9086,7 +9091,7 @@ - + @@ -10586,7 +10591,7 @@ - + @@ -10598,7 +10603,7 @@ - + @@ -10661,7 +10666,7 @@ - + @@ -10673,7 +10678,7 @@ - + @@ -11704,7 +11709,7 @@ - + @@ -11738,7 +11743,7 @@ - + @@ -11828,7 +11833,7 @@ - + @@ -11862,7 +11867,7 @@ - + @@ -15224,7 +15229,10 @@ - + + + + @@ -16650,7 +16658,7 @@ - + @@ -16658,7 +16666,7 @@ - + @@ -16727,7 +16735,7 @@ - + @@ -16735,7 +16743,7 @@ - + @@ -18241,7 +18249,7 @@ - + @@ -18253,7 +18261,7 @@ - + @@ -18592,7 +18600,7 @@ - + @@ -18626,7 +18634,7 @@ - + @@ -19036,7 +19044,7 @@ - + @@ -19064,7 +19072,7 @@ - + @@ -20266,10 +20274,24 @@ + + + + + + + + + + + + + + @@ -20294,7 +20316,7 @@ - + @@ -20305,6 +20327,9 @@ + + + @@ -20355,6 +20380,8 @@ + + @@ -20366,7 +20393,7 @@ - + @@ -20393,7 +20420,7 @@ - + @@ -20435,7 +20462,7 @@ - + @@ -20463,7 +20490,7 @@ - + @@ -20489,12 +20516,15 @@ + + + @@ -20525,6 +20555,7 @@ + @@ -20534,6 +20565,7 @@ + @@ -20558,6 +20590,7 @@ + @@ -20895,6 +20928,22 @@ + + + + + + + + + + + + + + + + @@ -21550,6 +21599,7 @@ + @@ -22398,15 +22448,21 @@ + - + + + + + + - + @@ -22592,6 +22648,7 @@ + @@ -22656,6 +22713,9 @@ + + + @@ -22677,6 +22737,19 @@ + + + + + + + + + + + + + @@ -23052,19 +23125,36 @@ + + + + - - - + + + + + + + + + + + + + + + + @@ -25653,7 +25743,7 @@ - + @@ -25751,6 +25841,7 @@ + @@ -25792,13 +25883,19 @@ - + + + + + + + @@ -26129,7 +26226,7 @@ - + @@ -26163,7 +26260,7 @@ - + @@ -26301,7 +26398,7 @@ - + @@ -26335,7 +26432,7 @@ - + @@ -28675,6 +28772,13 @@ + + + + + + + @@ -28687,6 +28791,7 @@ + @@ -28740,6 +28845,7 @@ + @@ -29117,6 +29223,7 @@ + @@ -29183,6 +29290,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -29381,6 +29514,20 @@ + + + + + + + + + + + + + + @@ -29461,6 +29608,10 @@ + + + + @@ -29472,18 +29623,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -29684,6 +29859,7 @@ + @@ -29692,6 +29868,7 @@ + @@ -29768,6 +29945,7 @@ + @@ -30003,6 +30181,11 @@ + + + + + @@ -30105,7 +30288,7 @@ - + @@ -30198,6 +30381,7 @@ + @@ -30213,6 +30397,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -30233,14 +30450,849 @@ - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/path_10_9/data/lib/custom/custom.lua b/path_10_9/data/lib/custom/custom.lua new file mode 100644 index 000000000..3a1167657 --- /dev/null +++ b/path_10_9/data/lib/custom/custom.lua @@ -0,0 +1,85 @@ +function isNumber(str) + return tonumber(str) ~= nil +end + +function getAccountNumberByPlayerName(name) + local player = Player(name) + if player ~= nil then + return player:getAccountId() + end + + local resultId = db.storeQuery("SELECT `account_id` FROM `players` WHERE `name` = " .. db.escapeString(name)) + if resultId ~= false then + local accountId = result.getNumber(resultId, "account_id") + result.free(resultId) + return accountId + end + return 0 +end + +function getMoneyCount(string) + local b, e = string:find("%d+") + local money = b and e and tonumber(string:sub(b, e)) or -1 + if isValidMoney(money) then + return money + end + return -1 +end + +function getMoneyWeight(money) + local gold = money + local crystal = math.floor(gold / 10000) + gold = gold - crystal * 10000 + local platinum = math.floor(gold / 100) + gold = gold - platinum * 100 + return (ItemType(2160):getWeight() * crystal) + (ItemType(2152):getWeight() * platinum) + (ItemType(2148):getWeight() * gold) +end + +function getRealDate() + local month = tonumber(os.date("%m", os.time())) + local day = tonumber(os.date("%d", os.time())) + + if month < 10 then + month = '0' .. month + end + if day < 10 then + day = '0' .. day + end + return day .. '/' .. month +end + +function getRealTime() + local hours = tonumber(os.date("%H", os.time())) + local minutes = tonumber(os.date("%M", os.time())) + + if hours < 10 then + hours = '0' .. hours + end + if minutes < 10 then + minutes = '0' .. minutes + end + return hours .. ':' .. minutes +end + +function isValidMoney(money) + return isNumber(money) and money > 0 and money < 4294967296 +end + +function iterateArea(func, from, to) + for z = from.z, to.z do + for y = from.y, to.y do + for x = from.x, to.x do + func(Position(x, y, z)) + end + end + end +end + +function playerExists(name) + local resultId = db.storeQuery('SELECT `name` FROM `players` WHERE `name` = ' .. db.escapeString(name)) + if resultId then + result.free(resultId) + return true + end + return false +end diff --git a/path_10_9/data/lib/custom/storages.lua b/path_10_9/data/lib/custom/storages.lua new file mode 100644 index 000000000..0cbf79c31 --- /dev/null +++ b/path_10_9/data/lib/custom/storages.lua @@ -0,0 +1,5 @@ +-- STORAGES -- +-- (HIGHLY RECOMMENDED -> ONE mission per STORAGE) -- +-- Sort it in Values - + +Storage = {} diff --git a/path_10_9/data/lib/lib.lua b/path_10_9/data/lib/lib.lua index 5a0e2b553..2ffc31da5 100644 --- a/path_10_9/data/lib/lib.lua +++ b/path_10_9/data/lib/lib.lua @@ -3,3 +3,7 @@ dofile('data/lib/core/core.lua') -- Compatibility library for our old Lua API dofile('data/lib/compat/compat.lua') + +-- Custom +dofile('data/lib/custom/custom.lua') +dofile('data/lib/custom/storages.lua') diff --git a/path_10_9/data/logs/DarkKonia commands.log b/path_10_9/data/logs/DarkKonia commands.log new file mode 100644 index 000000000..d710052b4 --- /dev/null +++ b/path_10_9/data/logs/DarkKonia commands.log @@ -0,0 +1,4 @@ +[18/01/2016 13:23] /reload npc +[18/01/2016 13:23] /reload movements +[18/01/2016 13:24] /reload npc +[18/01/2016 13:25] /reload movements diff --git a/path_10_9/data/monster/monsters.xml b/path_10_9/data/monster/monsters.xml index 680330387..167b6a794 100644 --- a/path_10_9/data/monster/monsters.xml +++ b/path_10_9/data/monster/monsters.xml @@ -28,6 +28,14 @@ + + + + + + + + @@ -71,26 +79,33 @@ + + + + + - + + + - + @@ -116,142 +131,184 @@ + - - - + - - + - + + + + - + + - + + - - + + + + + + + + - + - + + + + + + + - - + + + + - + + + - + - + + - + + + - + - + + - + + + + - + + + + + + - - + + - + + - + + - + - + + + + + + + + + + - - + - + - + - + + + - - - + + @@ -263,11 +320,9 @@ - - + - @@ -291,50 +346,47 @@ - + + + - - + + - - + + - + - - - + - - + - - - + @@ -345,18 +397,19 @@ - + + - - + + - + + + - - @@ -364,11 +417,9 @@ - - - - + + @@ -379,6 +430,7 @@ + @@ -394,8 +446,14 @@ + + + - + + + + @@ -414,13 +472,16 @@ - + + - + + + @@ -442,12 +503,13 @@ - + + @@ -455,32 +517,27 @@ - - - - - + + - - - + + - @@ -500,9 +557,14 @@ - + + + + + + @@ -523,7 +585,7 @@ - + @@ -535,7 +597,6 @@ - @@ -549,7 +610,6 @@ - @@ -562,26 +622,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - @@ -597,6 +679,10 @@ + + + + @@ -606,6 +692,7 @@ + @@ -621,6 +708,7 @@ + @@ -628,38 +716,46 @@ + + + + + + - + + - + + - + + + - - - + @@ -675,13 +771,9 @@ + - - - - - @@ -715,42 +807,57 @@ + + + + + + + + + + + + + + - - - - - - + + + + + + + @@ -764,32 +871,32 @@ + + + + + - + - - - - - - + @@ -798,8 +905,8 @@ - + @@ -807,13 +914,14 @@ + - - - - + + + + diff --git a/path_10_9/data/movements/movements.xml b/path_10_9/data/movements/movements.xml index 25569d019..073465488 100644 --- a/path_10_9/data/movements/movements.xml +++ b/path_10_9/data/movements/movements.xml @@ -27,6 +27,7 @@ + @@ -192,6 +193,8 @@ + + diff --git a/path_10_9/data/movements/scripts/citizen.lua b/path_10_9/data/movements/scripts/citizen.lua index 94e882d5e..541cfa3a6 100644 --- a/path_10_9/data/movements/scripts/citizen.lua +++ b/path_10_9/data/movements/scripts/citizen.lua @@ -7,6 +7,7 @@ function onStepIn(creature, item, position, fromPosition) local town = Town(item.actionid - 30020) player:setTown(town) + player:sendTextMessage(MESSAGE_INFO_DESCR, "You are the newest resident of " .. town:getName(town) .. ".") end return true end diff --git a/path_10_9/data/npc/Eryn.xml b/path_10_9/data/npc/Eryn.xml index 93622cdbf..3ee6f7476 100644 --- a/path_10_9/data/npc/Eryn.xml +++ b/path_10_9/data/npc/Eryn.xml @@ -3,7 +3,7 @@ - + diff --git a/path_10_9/data/npc/Naji.xml b/path_10_9/data/npc/Naji.xml new file mode 100644 index 000000000..7aa02a4f0 --- /dev/null +++ b/path_10_9/data/npc/Naji.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/path_10_9/data/npc/lib/npc.lua b/path_10_9/data/npc/lib/npc.lua index 8161efeab..c6d3e2cf6 100644 --- a/path_10_9/data/npc/lib/npc.lua +++ b/path_10_9/data/npc/lib/npc.lua @@ -1,5 +1,6 @@ -- Including the Advanced NPC System dofile('data/npc/lib/npcsystem/npcsystem.lua') +dofile('data/npc/lib/npcsystem/customModules.lua') function msgcontains(message, keyword) local message, keyword = message:lower(), keyword:lower() diff --git a/path_10_9/data/npc/lib/npcsystem/customModules.lua b/path_10_9/data/npc/lib/npcsystem/customModules.lua new file mode 100644 index 000000000..f44c8a8b0 --- /dev/null +++ b/path_10_9/data/npc/lib/npcsystem/customModules.lua @@ -0,0 +1,192 @@ +-- Custom Modules, created to help us in this datapack +local travelDiscounts = { + ['postman'] = {price = 10, storage = 12460, value = 3}, + ['new frontier'] = {price = 50, storage = 12133, value = 1} +} + +function StdModule.travelDiscount(player, discounts) + local discountPrice, discount = 0 + if type(discounts) == 'string' then + discount = travelDiscounts[discounts] + if discount and player:getStorageValue(discount.storage) >= discount.value then + return discount.price + end + else + for i = 1, #discounts do + discount = travelDiscounts[discounts[i]] + if discount and player:getStorageValue(discount.storage) >= discount.value then + discountPrice = discountPrice + discount.price + end + end + end + + return discountPrice +end + +function StdModule.kick(cid, message, keywords, parameters, node) + local npcHandler = parameters.npcHandler + if npcHandler == nil then + error("StdModule.travel called without any npcHandler instance.") + end + + if not npcHandler:isFocused(cid) then + return false + end + + npcHandler:releaseFocus(cid) + npcHandler:say(parameters.text or "Off with you!", cid) + + local destination = parameters.destination + if type(destination) == 'table' then + destination = destination[math.random(#destination)] + end + + Player(cid):teleportTo(destination, true) + + npcHandler:resetNpc(cid) + return true +end + +local GreetModule = {} +function GreetModule.greet(cid, message, keywords, parameters) + if not parameters.npcHandler:isInRange(cid) then + return true + end + + if parameters.npcHandler:isFocused(cid) then + return true + end + + local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() } + parameters.npcHandler:say(parameters.npcHandler:parseMessage(parameters.text, parseInfo), cid, true) + parameters.npcHandler:addFocus(cid) + return true +end + +function GreetModule.farewell(cid, message, keywords, parameters) + if not parameters.npcHandler:isFocused(cid) then + return false + end + + local parseInfo = { [TAG_PLAYERNAME] = Player(cid):getName() } + parameters.npcHandler:say(parameters.npcHandler:parseMessage(parameters.text, parseInfo), cid, true) + parameters.npcHandler:resetNpc(cid) + parameters.npcHandler:releaseFocus(cid) + return true +end + +-- Adds a keyword which acts as a greeting word +function KeywordHandler:addGreetKeyword(keys, parameters, condition, action) + local keys = keys + keys.callback = FocusModule.messageMatcherDefault + return self:addKeyword(keys, GreetModule.greet, parameters, condition, action) +end + +-- Adds a keyword which acts as a farewell word +function KeywordHandler:addFarewellKeyword(keys, parameters, condition, action) + local keys = keys + keys.callback = FocusModule.messageMatcherDefault + return self:addKeyword(keys, GreetModule.farewell, parameters, condition, action) +end + +-- Adds a keyword which acts as a spell word +function KeywordHandler:addSpellKeyword(keys, parameters) + local keys = keys + keys.callback = FocusModule.messageMatcherDefault + + local npcHandler, spellName, price, vocationId = parameters.npcHandler, parameters.spellName, parameters.price, parameters.vocation + local spellKeyword = self:addKeyword(keys, StdModule.say, {npcHandler = npcHandler, text = string.format("Do you want to learn the spell '%s' for %s?", spellName, price > 0 and price .. ' gold' or 'free')}, + function(player) + local baseVocationId = player:getVocation():getBase():getId() + if type(vocationId) == 'table' then + return isInArray(vocationId, baseVocationId) + else + return vocationId == baseVocationId + end + end + ) + + spellKeyword:addChildKeyword({'yes'}, StdModule.learnSpell, {npcHandler = npcHandler, spellName = spellName, level = parameters.level, price = price}) + spellKeyword:addChildKeyword({'no'}, StdModule.say, {npcHandler = npcHandler, text = 'Maybe next time.', reset = true}) +end + +local hints = { + [-1] = 'If you don\'t know the meaning of an icon on the right side, move the mouse cursor on it and wait a moment.', + [0] = 'Send private messages to other players by right-clicking on the player or the player\'s name and select \'Message to ....\'. You can also open a \'private message channel\' and type in the name of the player.', + [1] = 'Use the shortcuts \'SHIFT\' to look, \'CTRL\' for use and \'ALT\' for attack when clicking on an object or player.', + [2] = 'If you already know where you want to go, click on the automap and your character will walk there automatically if the location is reachable and not too far away.', + [3] = 'To open or close skills, battle or VIP list, click on the corresponding button to the right.', + [4] = '\'Capacity\' restricts the amount of things you can carry with you. It raises with each level.', + [5] = 'Always have a look on your health bar. If you see that you do not regenerate health points anymore, eat something.', + [6] = 'Always eat as much food as possible. This way, you\'ll regenerate health points for a longer period of time.', + [7] = 'After you have killed a monster, you have 10 seconds in which the corpse is not moveable and no one else but you can loot it.', + [8] = 'Be careful when you approach three or more monsters because you only can block the attacks of two. In such a situation even a few rats can do severe damage or even kill you.', + [9] = 'There are many ways to gather food. Many creatures drop food but you can also pick blueberries or bake your own bread. If you have a fishing rod and worms in your inventory, you can also try to catch a fish.', + [10] = {'Baking bread is rather complex. First of all you need a scythe to harvest wheat. Then you use the wheat with a millstone to get flour. ...', 'This can be be used on water to get dough, which can be used on an oven to bake bread. Use milk instead of water to get cake dough.'}, + [11] = 'Dying hurts! Better run away than risk your life. You are going to lose experience and skill points when you die.', + [12] = 'When you switch to \'Offensive Fighting\', you deal out more damage but you also get hurt more easily.', + [13] = 'When you are on low health and need to run away from a monster, switch to \'Defensive Fighting\' and the monster will hit you less severely.', + [14] = 'Many creatures try to run away from you. Select \'Chase Opponent\' to follow them.', + [15] = 'The deeper you enter a dungeon, the more dangerous it will be. Approach every dungeon with utmost care or an unexpected creature might kill you. This will result in losing experience and skill points.', + [16] = 'Due to the perspective, some objects in Tibia are not located at the spot they seem to appear (ladders, windows, lamps). Try clicking on the floor tile the object would lie on.', + [17] = 'If you want to trade an item with another player, right-click on the item and select \'Trade with ...\', then click on the player with whom you want to trade.', + [18] = 'Stairs, ladders and dungeon entrances are marked as yellow dots on the automap.', + [19] = 'You can get food by killing animals or monsters. You can also pick blueberries or bake your own bread. If you are too lazy or own too much money, you can also buy food.', + [20] = 'Quest containers can be recognised easily. They don\'t open up regularly but display a message \'You have found ....\'. They can only be opened once.', + [21] = 'Better run away than risk to die. You\'ll lose experience and skill points each time you die.', + [22] = 'You can form a party by right-clicking on a player and selecting \'Invite to Party\'. The party leader can also enable \'Shared Experience\' by right-clicking on him- or herself.', + [23] = 'You can assign spells, the use of items, or random text to \'hotkeys\'. You find them under \'Options\'.', + [24] = 'You can also follow other players. Just right-click on the player and select \'Follow\'.', + [25] = 'You can found a party with your friends by right-clicking on a player and selecting \'Invite to Party\'. If you are invited to a party, right-click on yourself and select \'Join Party\'.', + [26] = 'Only found parties with people you trust. You can attack people in your party without getting a skull. This is helpful for training your skills, but can be abused to kill people without having to fear negative consequences.', + [27] = 'The leader of a party has the option to distribute gathered experience among all players in the party. If you are the leader, right-click on yourself and select \'Enable Shared Experience\'.', + [28] = 'There is nothing more I can tell you. If you are still in need of some {hints}, I can repeat them for you.' +} + +-- VoiceModule +VoiceModule = { + voices = nil, + voiceCount = 0, + lastVoice = 0, + timeout = nil, + chance = nil, + npcHandler = nil +} + +-- Creates a new instance of VoiceModule +function VoiceModule:new(voices, timeout, chance) + local obj = {} + setmetatable(obj, self) + self.__index = self + + obj.voices = voices + for i = 1, #obj.voices do + local voice = obj.voices[i] + if voice.yell then + voice.yell = nil + voice.talktype = TALKTYPE_YELL + else + voice.talktype = TALKTYPE_SAY + end + end + + obj.voiceCount = #voices + obj.timeout = timeout or 10 + obj.chance = chance or 25 + return obj +end + +function VoiceModule:init(handler) + return true +end + +function VoiceModule:callbackOnThink() + if self.lastVoice < os.time() then + self.lastVoice = os.time() + self.timeout + if math.random(100) < self.chance then + local voice = self.voices[math.random(self.voiceCount)] + Npc():say(voice.text, voice.talktype) + end + end + return true +end diff --git a/path_10_9/data/npc/scripts/bank.lua b/path_10_9/data/npc/scripts/bank.lua new file mode 100644 index 000000000..e20f20a92 --- /dev/null +++ b/path_10_9/data/npc/scripts/bank.lua @@ -0,0 +1,323 @@ +local keywordHandler = KeywordHandler:new() +local npcHandler = NpcHandler:new(keywordHandler) +NpcSystem.parseParameters(npcHandler) + +local count = {} +local transfer = {} + +function onCreatureAppear(cid) npcHandler:onCreatureAppear(cid) end +function onCreatureDisappear(cid) npcHandler:onCreatureDisappear(cid) end +function onCreatureSay(cid, type, msg) npcHandler:onCreatureSay(cid, type, msg) end +function onThink() npcHandler:onThink() end + +local voices = { {text = 'It\'s a wise idea to store your money in your bank account.'} } +npcHandler:addModule(VoiceModule:new(voices)) + +local function greetCallback(cid) + count[cid], transfer[cid] = nil, nil + return true +end + +local function creatureSayCallback(cid, type, msg) + if not npcHandler:isFocused(cid) then + return false + end + local player = Player(cid) +---------------------------- help ------------------------ + if msgcontains(msg, 'bank account') then + npcHandler:say({ + 'Every Tibian has one. The big advantage is that you can access your money in every branch of the Tibian Bank! ...', + 'Would you like to know more about the {basic} functions of your bank account, the {advanced} functions, or are you already bored, perhaps?' + }, cid) + npcHandler.topic[cid] = 0 + return true +---------------------------- balance --------------------- + elseif msgcontains(msg, 'balance') then + npcHandler.topic[cid] = 0 + if player:getBankBalance() >= 100000000 then + npcHandler:say('I think you must be one of the richest inhabitants in the world! Your account balance is ' .. player:getBankBalance() .. ' gold.', cid) + return true + elseif player:getBankBalance() >= 10000000 then + npcHandler:say('You have made ten millions and it still grows! Your account balance is ' .. player:getBankBalance() .. ' gold.', cid) + return true + elseif player:getBankBalance() >= 1000000 then + npcHandler:say('Wow, you have reached the magic number of a million gp!!! Your account balance is ' .. player:getBankBalance() .. ' gold!', cid) + return true + elseif player:getBankBalance() >= 100000 then + npcHandler:say('You certainly have made a pretty penny. Your account balance is ' .. player:getBankBalance() .. ' gold.', cid) + return true + else + npcHandler:say('Your account balance is ' .. player:getBankBalance() .. ' gold.', cid) + return true + end +---------------------------- deposit --------------------- + elseif msgcontains(msg, 'deposit') then + count[cid] = player:getMoney() + if count[cid] < 1 then + npcHandler:say('You do not have enough gold.', cid) + npcHandler.topic[cid] = 0 + return false + end + if msgcontains(msg, 'all') then + count[cid] = player:getMoney() + npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid) + npcHandler.topic[cid] = 2 + return true + else + if string.match(msg,'%d+') then + count[cid] = getMoneyCount(msg) + if count[cid] < 1 then + npcHandler:say('You do not have enough gold.', cid) + npcHandler.topic[cid] = 0 + return false + end + npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid) + npcHandler.topic[cid] = 2 + return true + else + npcHandler:say('Please tell me how much gold it is you would like to deposit.', cid) + npcHandler.topic[cid] = 1 + return true + end + end + if not isValidMoney(count[cid]) then + npcHandler:say('Sorry, but you can\'t deposit that much.', cid) + npcHandler.topic[cid] = 0 + return false + end + elseif npcHandler.topic[cid] == 1 then + count[cid] = getMoneyCount(msg) + if isValidMoney(count[cid]) then + npcHandler:say('Would you really like to deposit ' .. count[cid] .. ' gold?', cid) + npcHandler.topic[cid] = 2 + return true + else + npcHandler:say('You do not have enough gold.', cid) + npcHandler.topic[cid] = 0 + return true + end + elseif npcHandler.topic[cid] == 2 then + if msgcontains(msg, 'yes') then + if player:getMoney() >= tonumber(count[cid]) then + player:depositMoney(count[cid]) + npcHandler:say('Alright, we have added the amount of ' .. count[cid] .. ' gold to your {balance}. You can {withdraw} your money anytime you want to.', cid) + else + npcHandler:say('You do not have enough gold.', cid) + end + elseif msgcontains(msg, 'no') then + npcHandler:say('As you wish. Is there something else I can do for you?', cid) + end + npcHandler.topic[cid] = 0 + return true +---------------------------- withdraw -------------------- + elseif msgcontains(msg, 'withdraw') then + if string.match(msg,'%d+') then + count[cid] = getMoneyCount(msg) + if isValidMoney(count[cid]) then + npcHandler:say('Are you sure you wish to withdraw ' .. count[cid] .. ' gold from your bank account?', cid) + npcHandler.topic[cid] = 7 + else + npcHandler:say('There is not enough gold on your account.', cid) + npcHandler.topic[cid] = 0 + end + return true + else + npcHandler:say('Please tell me how much gold you would like to withdraw.', cid) + npcHandler.topic[cid] = 6 + return true + end + elseif npcHandler.topic[cid] == 6 then + count[cid] = getMoneyCount(msg) + if isValidMoney(count[cid]) then + npcHandler:say('Are you sure you wish to withdraw ' .. count[cid] .. ' gold from your bank account?', cid) + npcHandler.topic[cid] = 7 + else + npcHandler:say('There is not enough gold on your account.', cid) + npcHandler.topic[cid] = 0 + end + return true + elseif npcHandler.topic[cid] == 7 then + if msgcontains(msg, 'yes') then + if player:getFreeCapacity() >= getMoneyWeight(count[cid]) then + if not player:withdrawMoney(count[cid]) then + npcHandler:say('There is not enough gold on your account.', cid) + else + npcHandler:say('Here you are, ' .. count[cid] .. ' gold. Please let me know if there is something else I can do for you.', cid) + end + else + npcHandler:say('Whoah, hold on, you have no room in your inventory to carry all those coins. I don\'t want you to drop it on the floor, maybe come back with a cart!', cid) + end + npcHandler.topic[cid] = 0 + elseif msgcontains(msg, 'no') then + npcHandler:say('The customer is king! Come back anytime you want to if you wish to {withdraw} your money.', cid) + npcHandler.topic[cid] = 0 + end + return true +---------------------------- transfer -------------------- + elseif msgcontains(msg, 'transfer') then + npcHandler:say('Please tell me the amount of gold you would like to transfer.', cid) + npcHandler.topic[cid] = 11 + elseif npcHandler.topic[cid] == 11 then + count[cid] = getMoneyCount(msg) + if player:getBankBalance() < count[cid] then + npcHandler:say('There is not enough gold on your account.', cid) + npcHandler.topic[cid] = 0 + return true + end + if isValidMoney(count[cid]) then + npcHandler:say('Who would you like transfer ' .. count[cid] .. ' gold to?', cid) + npcHandler.topic[cid] = 12 + else + npcHandler:say('There is not enough gold on your account.', cid) + npcHandler.topic[cid] = 0 + end + elseif npcHandler.topic[cid] == 12 then + transfer[cid] = msg + if player:getName() == transfer[cid] then + npcHandler:say('Fill in this field with person who receives your gold!', cid) + npcHandler.topic[cid] = 0 + return true + end + if playerExists(transfer[cid]) then + npcHandler:say('So you would like to transfer ' .. count[cid] .. ' gold to ' .. transfer[cid] .. '?', cid) + npcHandler.topic[cid] = 13 + else + npcHandler:say('This player does not exist.', cid) + npcHandler.topic[cid] = 0 + end + elseif npcHandler.topic[cid] == 13 then + if msgcontains(msg, 'yes') then + if not player:transferMoneyTo(transfer[cid], count[cid]) then + npcHandler:say('You cannot transfer money to this account.', cid) + else + npcHandler:say('Very well. You have transferred ' .. count[cid] .. ' gold to ' .. transfer[cid] ..'.', cid) + transfer[cid] = nil + end + elseif msgcontains(msg, 'no') then + npcHandler:say('Alright, is there something else I can do for you?', cid) + end + npcHandler.topic[cid] = 0 +---------------------------- money exchange -------------- + elseif msgcontains(msg, 'change gold') then + npcHandler:say('How many platinum coins would you like to get?', cid) + npcHandler.topic[cid] = 14 + elseif npcHandler.topic[cid] == 14 then + if getMoneyCount(msg) < 1 then + npcHandler:say('Sorry, you do not have enough gold coins.', cid) + npcHandler.topic[cid] = 0 + else + count[cid] = getMoneyCount(msg) + npcHandler:say('So you would like me to change ' .. count[cid] * 100 .. ' of your gold coins into ' .. count[cid] .. ' platinum coins?', cid) + npcHandler.topic[cid] = 15 + end + elseif npcHandler.topic[cid] == 15 then + if msgcontains(msg, 'yes') then + if player:removeItem(2148, count[cid] * 100) then + player:addItem(2152, count[cid]) + npcHandler:say('Here you are.', cid) + else + npcHandler:say('Sorry, you do not have enough gold coins.', cid) + end + else + npcHandler:say('Well, can I help you with something else?', cid) + end + npcHandler.topic[cid] = 0 + elseif msgcontains(msg, 'change platinum') then + npcHandler:say('Would you like to change your platinum coins into gold or crystal?', cid) + npcHandler.topic[cid] = 16 + elseif npcHandler.topic[cid] == 16 then + if msgcontains(msg, 'gold') then + npcHandler:say('How many platinum coins would you like to change into gold?', cid) + npcHandler.topic[cid] = 17 + elseif msgcontains(msg, 'crystal') then + npcHandler:say('How many crystal coins would you like to get?', cid) + npcHandler.topic[cid] = 19 + else + npcHandler:say('Well, can I help you with something else?', cid) + npcHandler.topic[cid] = 0 + end + elseif npcHandler.topic[cid] == 17 then + if getMoneyCount(msg) < 1 then + npcHandler:say('Sorry, you do not have enough platinum coins.', cid) + npcHandler.topic[cid] = 0 + else + count[cid] = getMoneyCount(msg) + npcHandler:say('So you would like me to change ' .. count[cid] .. ' of your platinum coins into ' .. count[cid] * 100 .. ' gold coins for you?', cid) + npcHandler.topic[cid] = 18 + end + elseif npcHandler.topic[cid] == 18 then + if msgcontains(msg, 'yes') then + if player:removeItem(2152, count[cid]) then + player:addItem(2148, count[cid] * 100) + npcHandler:say('Here you are.', cid) + else + npcHandler:say('Sorry, you do not have enough platinum coins.', cid) + end + else + npcHandler:say('Well, can I help you with something else?', cid) + end + npcHandler.topic[cid] = 0 + elseif npcHandler.topic[cid] == 19 then + if getMoneyCount(msg) < 1 then + npcHandler:say('Sorry, you do not have enough platinum coins.', cid) + npcHandler.topic[cid] = 0 + else + count[cid] = getMoneyCount(msg) + npcHandler:say('So you would like me to change ' .. count[cid] * 100 .. ' of your platinum coins into ' .. count[cid] .. ' crystal coins for you?', cid) + npcHandler.topic[cid] = 20 + end + elseif npcHandler.topic[cid] == 20 then + if msgcontains(msg, 'yes') then + if player:removeItem(2152, count[cid] * 100) then + player:addItem(2160, count[cid]) + npcHandler:say('Here you are.', cid) + else + npcHandler:say('Sorry, you do not have enough platinum coins.', cid) + end + else + npcHandler:say('Well, can I help you with something else?', cid) + end + npcHandler.topic[cid] = 0 + elseif msgcontains(msg, 'change crystal') then + npcHandler:say('How many crystal coins would you like to change into platinum?', cid) + npcHandler.topic[cid] = 21 + elseif npcHandler.topic[cid] == 21 then + if getMoneyCount(msg) < 1 then + npcHandler:say('Sorry, you do not have enough crystal coins.', cid) + npcHandler.topic[cid] = 0 + else + count[cid] = getMoneyCount(msg) + npcHandler:say('So you would like me to change ' .. count[cid] .. ' of your crystal coins into ' .. count[cid] * 100 .. ' platinum coins for you?', cid) + npcHandler.topic[cid] = 22 + end + elseif npcHandler.topic[cid] == 22 then + if msgcontains(msg, 'yes') then + if player:removeItem(2160, count[cid]) then + player:addItem(2152, count[cid] * 100) + npcHandler:say('Here you are.', cid) + else + npcHandler:say('Sorry, you do not have enough crystal coins.', cid) + end + else + npcHandler:say('Well, can I help you with something else?', cid) + end + npcHandler.topic[cid] = 0 + end + return true +end + +keywordHandler:addKeyword({'money'}, StdModule.say, {npcHandler = npcHandler, text = 'We can {change} money for you. You can also access your {bank account}.'}) +keywordHandler:addKeyword({'change'}, StdModule.say, {npcHandler = npcHandler, text = 'There are three different coin types in Tibia: 100 gold coins equal 1 platinum coin, 100 platinum coins equal 1 crystal coin. So if you\'d like to change 100 gold into 1 platinum, simply say \'{change gold}\' and then \'1 platinum\'.'}) +keywordHandler:addKeyword({'bank'}, StdModule.say, {npcHandler = npcHandler, text = 'We can {change} money for you. You can also access your {bank account}.'}) +keywordHandler:addKeyword({'advanced'}, StdModule.say, {npcHandler = npcHandler, text = 'Your bank account will be used automatically when you want to {rent} a house or place an offer on an item on the {market}. Let me know if you want to know about how either one works.'}) +keywordHandler:addKeyword({'help'}, StdModule.say, {npcHandler = npcHandler, text = 'You can check the {balance} of your bank account, {deposit} money or {withdraw} it. You can also {transfer} money to other characters, provided that they have a vocation.'}) +keywordHandler:addKeyword({'functions'}, StdModule.say, {npcHandler = npcHandler, text = 'You can check the {balance} of your bank account, {deposit} money or {withdraw} it. You can also {transfer} money to other characters, provided that they have a vocation.'}) +keywordHandler:addKeyword({'basic'}, StdModule.say, {npcHandler = npcHandler, text = 'You can check the {balance} of your bank account, {deposit} money or {withdraw} it. You can also {transfer} money to other characters, provided that they have a vocation.'}) +keywordHandler:addKeyword({'job'}, StdModule.say, {npcHandler = npcHandler, text = 'I work in this bank. I can change money for you and help you with your bank account.'}) +keywordHandler:addKeyword({'name'}, StdModule.say, {npcHandler = npcHandler, text = "My name is Naji. My mother gave me that name because she knew a Paladin with that name. I'm a spare timer hunter by myself, you know! I want to join the {Paw and Fur - hunting elite}!"}) +keywordHandler:addKeyword({'paw and fur'}, StdModule.say, {npcHandler = npcHandler, text = "The Paw and Fur - Hunting Elite is a newly founded hunting society in Port Hope. It is said that they send you on hunting mission. Sounds great if you ask me."}) + +npcHandler:setMessage(MESSAGE_GREET, 'Welcome to the Tibian {bank}, |PLAYERNAME|! What can I do for you?') +npcHandler:setCallback(CALLBACK_GREET, greetCallback) +npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback) +npcHandler:addModule(FocusModule:new()) diff --git a/path_10_9/data/spells/lib/spells.lua b/path_10_9/data/spells/lib/spells.lua index 2bf763d8b..bf1c9e98d 100644 --- a/path_10_9/data/spells/lib/spells.lua +++ b/path_10_9/data/spells/lib/spells.lua @@ -1,7 +1,7 @@ --Pre-made areas --Waves -AREA_SHORTWAVE3 = { +AREA_WAVE3 = { {1, 1, 1}, {1, 1, 1}, {0, 3, 0} diff --git a/path_10_9/data/spells/scripts/attack/strong ice wave.lua b/path_10_9/data/spells/scripts/attack/strong ice wave.lua index 60819fad2..5beee5409 100644 --- a/path_10_9/data/spells/scripts/attack/strong ice wave.lua +++ b/path_10_9/data/spells/scripts/attack/strong ice wave.lua @@ -1,7 +1,7 @@ local combat = Combat() combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ICEDAMAGE) combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setArea(createCombatArea(AREA_SHORTWAVE3)) +combat:setArea(createCombatArea(AREA_WAVE3)) function onGetFormulaValues(player, level, maglevel) local min = (level / 5) + (maglevel * 4.5) + 20 diff --git a/path_10_9/data/spells/scripts/healing/mass healing.lua b/path_10_9/data/spells/scripts/healing/mass healing.lua index eb921babf..0b984503e 100644 --- a/path_10_9/data/spells/scripts/healing/mass healing.lua +++ b/path_10_9/data/spells/scripts/healing/mass healing.lua @@ -8,11 +8,11 @@ local healMonsters = false function onTargetCreature(creature, target) local player = creature:getPlayer() - local min = ((player:getLevel() / 5) + (player:getMagicLevel() * 4.6) + 100) - local max = ((player:getLevel() / 5) + (player:getMagicLevel() * 9.6) + 125) + local min = (player:getLevel() / 5) + (player:getMagicLevel() * 4.6) + 100 + local max = (player:getLevel() / 5) + (player:getMagicLevel() * 9.6) + 125 - local master = target:getMaster() if not healMonsters then + local master = target:getMaster() if target:isMonster() and not master or master and master:isMonster() then return true end diff --git a/path_10_9/data/spells/scripts/monster/devourer paralyze.lua b/path_10_9/data/spells/scripts/monster/devourer paralyze.lua new file mode 100644 index 000000000..4af621800 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/devourer paralyze.lua @@ -0,0 +1,17 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_POISONAREA) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 20000) +condition:setFormula(-0.55, 0, -0.75, 0) +combat:setCondition(condition) + + +local area = createCombatArea(AREA_SQUARE1X1) + combat:setArea(area) + combat:setCondition(condition) + + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/devourer wave.lua b/path_10_9/data/spells/scripts/monster/devourer wave.lua new file mode 100644 index 000000000..54f6809e9 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/devourer wave.lua @@ -0,0 +1,19 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_POISONDAMAGE) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLPLANTS) + + arr = { + {0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} + } + +local area = createCombatArea(arr) +combat:setArea(area) + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_8/data/spells/scripts/monster/forest fury skill reducer.lua b/path_10_9/data/spells/scripts/monster/dipthrah skill reducer.lua similarity index 57% rename from path_10_8/data/spells/scripts/monster/forest fury skill reducer.lua rename to path_10_9/data/spells/scripts/monster/dipthrah skill reducer.lua index 422fde6a9..558a02843 100644 --- a/path_10_8/data/spells/scripts/monster/forest fury skill reducer.lua +++ b/path_10_9/data/spells/scripts/monster/dipthrah skill reducer.lua @@ -1,12 +1,14 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HOLYAREA) + +local area = createCombatArea(AREA_CIRCLE3X3) +combat:setArea(area) + local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) +condition:setParameter(CONDITION_PARAM_TICKS, 6000) +condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 50) condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 50) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_LARGEROCK) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) +condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) combat:setCondition(condition) function onCastSpell(creature, variant) diff --git a/path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua b/path_10_9/data/spells/scripts/monster/dreadbeast skill increaser.lua similarity index 59% rename from path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua rename to path_10_9/data/spells/scripts/monster/dreadbeast skill increaser.lua index e8e2b0be8..e526e53e0 100644 --- a/path_10_8/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua +++ b/path_10_9/data/spells/scripts/monster/dreadbeast skill increaser.lua @@ -1,10 +1,9 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_YELLOWENERGY) + local condition = Condition(CONDITION_ATTRIBUTES) condition:setParameter(CONDITION_PARAM_TICKS, 6000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 45) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) -combat:setArea(createCombatArea(AREA_CROSS1X1)) +condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 130) combat:setCondition(condition) function onCastSpell(creature, variant) diff --git a/path_10_8/data/spells/scripts/monster/diabolic imp skill reducer.lua b/path_10_9/data/spells/scripts/monster/dreadbeast skill reducer.lua similarity index 68% rename from path_10_8/data/spells/scripts/monster/diabolic imp skill reducer.lua rename to path_10_9/data/spells/scripts/monster/dreadbeast skill reducer.lua index 00b3193c4..02a67c438 100644 --- a/path_10_8/data/spells/scripts/monster/diabolic imp skill reducer.lua +++ b/path_10_9/data/spells/scripts/monster/dreadbeast skill reducer.lua @@ -1,13 +1,14 @@ local combat = {} for i = 70, 80 do - local condition = Condition(CONDITION_ATTRIBUTES) - condition:setParameter(CONDITION_PARAM_TICKS, 6000) - condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, i) - combat[i] = Combat() + combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_YELLOWENERGY) combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) - combat[i]:setArea(createCombatArea(AREA_BEAM1)) + + local condition = Condition(CONDITION_ATTRIBUTES) + condition:setParameter(CONDITION_PARAM_TICKS, 20000) + condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, i) + condition:setParameter(CONDITION_PARAM_SKILL_FISTPERCENT, i) combat[i]:setCondition(condition) end diff --git a/path_10_8/data/spells/scripts/monster/cliff strider skill reducer.lua b/path_10_9/data/spells/scripts/monster/energized raging mage skill reducer.lua similarity index 70% rename from path_10_8/data/spells/scripts/monster/cliff strider skill reducer.lua rename to path_10_9/data/spells/scripts/monster/energized raging mage skill reducer.lua index e60f3b996..6c4ff36ea 100644 --- a/path_10_8/data/spells/scripts/monster/cliff strider skill reducer.lua +++ b/path_10_9/data/spells/scripts/monster/energized raging mage skill reducer.lua @@ -1,10 +1,12 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) + +local area = createCombatArea(AREA_CROSS6X6) +combat:setArea(area) + local condition = Condition(CONDITION_ATTRIBUTES) condition:setParameter(CONDITION_PARAM_TICKS, 6000) condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 50) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) -combat:setArea(createCombatArea(AREA_CIRCLE2X2)) combat:setCondition(condition) function onCastSpell(creature, variant) diff --git a/path_10_9/data/spells/scripts/monster/frazzlemaw paralyze.lua b/path_10_9/data/spells/scripts/monster/frazzlemaw paralyze.lua new file mode 100644 index 000000000..3106180e7 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/frazzlemaw paralyze.lua @@ -0,0 +1,30 @@ + local combat = Combat() + combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED) + + local condition = Condition(CONDITION_PARALYZE) + condition:setParameter(CONDITION_PARAM_TICKS, 20000) + condition:setFormula(-0.6, 0, -0.8, 0) + combat:setCondition(condition) + + arr = { + {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}, + {0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 3, 1, 1, 1, 1, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 1, 1, 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, 0, 0, 0, 0, 0} + } + + local area = createCombatArea(arr) + combat:setArea(area) + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/glooth anemone summon.lua b/path_10_9/data/spells/scripts/monster/glooth anemone summon.lua new file mode 100644 index 000000000..43e8d773b --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/glooth anemone summon.lua @@ -0,0 +1,22 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_NONE) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) + +local area = createCombatArea(AREA_SQUARE1X1) +combat:setArea(area) + +local maxsummons = 1 + +function onCastSpell(creature, variant) + local summoncount = creature:getSummons() + if #summoncount < 1 then + for i = 1, maxsummons - #summoncount do + local mid = Game.createMonster("Glooth Blob", creature:getPosition()) + if not mid then + return + end + mid:setMaster(creature) + end + end + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/hellgorak skill reducer.lua b/path_10_9/data/spells/scripts/monster/hellgorak skill reducer.lua new file mode 100644 index 000000000..0c4238394 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/hellgorak skill reducer.lua @@ -0,0 +1,34 @@ +local combat = {} + +for i = 20, 40 do + combat[i] = Combat() + combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_POFF) + + local condition = Condition(CONDITION_ATTRIBUTES) + condition:setParameter(CONDITION_PARAM_TICKS, 20000) + condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, i) + + arr = { + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0} + } + + local area = createCombatArea(arr) + combat[i]:setArea(area) + combat[i]:setCondition(condition) +end + +function onCastSpell(creature, variant) + return combat[math.random(20, 40)]:execute(creature, variant) +end diff --git a/path_10_8/data/spells/scripts/monster/warlock skill reducer.lua b/path_10_9/data/spells/scripts/monster/infernalist skill reducer.lua similarity index 59% rename from path_10_8/data/spells/scripts/monster/warlock skill reducer.lua rename to path_10_9/data/spells/scripts/monster/infernalist skill reducer.lua index 49dbbad2c..27208c4c9 100644 --- a/path_10_8/data/spells/scripts/monster/warlock skill reducer.lua +++ b/path_10_9/data/spells/scripts/monster/infernalist skill reducer.lua @@ -1,12 +1,11 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA) +combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH) + local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) +condition:setParameter(CONDITION_PARAM_TICKS, 6000) condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 50) - -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ICEAREA) -combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ICE) -combat:setArea(createCombatArea(AREA_BEAM1)) +condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) combat:setCondition(condition) function onCastSpell(creature, variant) diff --git a/path_10_9/data/spells/scripts/monster/medusa paralyze.lua b/path_10_9/data/spells/scripts/monster/medusa paralyze.lua new file mode 100644 index 000000000..5a08677ca --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/medusa paralyze.lua @@ -0,0 +1,32 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_POFF) +combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_EARTH) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 20000) +condition:setFormula(-0.45, 0, -0.5, 0) +combat:setCondition(condition) + +arr = { + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}, + {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0}, + {0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0} +} + +local area = createCombatArea(arr) +combat:setArea(area) +combat:setCondition(condition) + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_8/data/spells/scripts/monster/lizard magistratus curse.lua b/path_10_9/data/spells/scripts/monster/metal gargoyle curse.lua similarity index 67% rename from path_10_8/data/spells/scripts/monster/lizard magistratus curse.lua rename to path_10_9/data/spells/scripts/monster/metal gargoyle curse.lua index b5b3276b5..eebd81402 100644 --- a/path_10_8/data/spells/scripts/monster/lizard magistratus curse.lua +++ b/path_10_9/data/spells/scripts/monster/metal gargoyle curse.lua @@ -1,10 +1,9 @@ local combat = {} -for i = 2, 3 do +for i = 2, 2 do combat[i] = Combat() combat[i]:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) - combat[i]:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SMALLCLOUDS) - combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_DEATH) + combat[i]:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH) local condition = Condition(CONDITION_CURSED) condition:setParameter(CONDITION_PARAM_DELAYED, true) @@ -20,5 +19,5 @@ for i = 2, 3 do end function onCastSpell(creature, variant) - return combat[math.random(2, 3)]:execute(creature, variant) + return combat[math.random(2, 2)]:execute(creature, variant) end diff --git a/path_10_9/data/spells/scripts/monster/minotaur amazon paralyze.lua b/path_10_9/data/spells/scripts/monster/minotaur amazon paralyze.lua new file mode 100644 index 000000000..130fd1811 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/minotaur amazon paralyze.lua @@ -0,0 +1,23 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, 3) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 10000) +condition:setFormula(-0.4, 0, -0.7, 0) +combat:setCondition(condition) + + arr = { + {0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} + } + +local area = createCombatArea(arr) + combat:setArea(area) + combat:setCondition(condition) + + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/mooh'tah master skill reducer.lua b/path_10_9/data/spells/scripts/monster/mooh'tah master skill reducer.lua new file mode 100644 index 000000000..049fe8599 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/mooh'tah master skill reducer.lua @@ -0,0 +1,12 @@ + local combat = Combat() + combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_STUN) + combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_SUDDENDEATH) + + local condition = Condition(CONDITION_ATTRIBUTES) + condition:setParameter(CONDITION_PARAM_TICKS, 3000) + condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, -100) + combat:setCondition(condition) + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/rot elemental paralyze.lua b/path_10_9/data/spells/scripts/monster/rot elemental paralyze.lua new file mode 100644 index 000000000..2450159e4 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/rot elemental paralyze.lua @@ -0,0 +1,17 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_SOUND_GREEN) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 20000) +condition:setFormula(-0.45, 0, -0.65, 0) +combat:setCondition(condition) + + +local area = createCombatArea(AREA_CIRCLE2X2) + combat:setArea(area) + combat:setCondition(condition) + + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_8/data/spells/scripts/monster/quara constrictor electrify.lua b/path_10_9/data/spells/scripts/monster/rustheap golem electrify.lua similarity index 69% rename from path_10_8/data/spells/scripts/monster/quara constrictor electrify.lua rename to path_10_9/data/spells/scripts/monster/rustheap golem electrify.lua index 83eb0c4eb..1cedb5de8 100644 --- a/path_10_8/data/spells/scripts/monster/quara constrictor electrify.lua +++ b/path_10_9/data/spells/scripts/monster/rustheap golem electrify.lua @@ -1,13 +1,16 @@ local combat = Combat() combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_ENERGYDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_ENERGYHIT) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) combat:setParameter(COMBAT_PARAM_DISTANCEEFFECT, CONST_ANI_ENERGY) local condition = Condition(CONDITION_ENERGY) condition:setParameter(CONDITION_PARAM_DELAYED, true) -condition:addDamage(3, 10000, -25) +condition:addDamage(17, 10000, -25) combat:setCondition(condition) +local area = createCombatArea(AREA_SQUARE1X1) +combat:setArea(area) + function onCastSpell(creature, variant) return combat:execute(creature, variant) end diff --git a/path_10_9/data/spells/scripts/monster/rustheap golem wave.lua b/path_10_9/data/spells/scripts/monster/rustheap golem wave.lua new file mode 100644 index 000000000..12c0b1ebc --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/rustheap golem wave.lua @@ -0,0 +1,18 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_LIFEDRAIN) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_BLACKSMOKE) + + arr = { + {0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} + } + +local area = createCombatArea(arr) + combat:setArea(area) + + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/seacrest serpent wave.lua b/path_10_9/data/spells/scripts/monster/seacrest serpent wave.lua new file mode 100644 index 000000000..3c21e65b8 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/seacrest serpent wave.lua @@ -0,0 +1,19 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_WATERSPLASH) + + arr = { + {0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} + } + +local area = createCombatArea(arr) +combat:setArea(area) + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_8/data/spells/scripts/support/blood rage.lua b/path_10_9/data/spells/scripts/monster/smokeue.lua similarity index 55% rename from path_10_8/data/spells/scripts/support/blood rage.lua rename to path_10_9/data/spells/scripts/monster/smokeue.lua index 3daa31f24..7128d6a20 100644 --- a/path_10_8/data/spells/scripts/support/blood rage.lua +++ b/path_10_9/data/spells/scripts/monster/smokeue.lua @@ -1,12 +1,13 @@ local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_GREEN) -combat:setParameter(COMBAT_PARAM_AGGRESSIVE, false) +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GROUNDSHAKER) + +local area = createCombatArea(AREA_CROSS5X5) +combat:setArea(area) local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 10000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 135) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, -100) condition:setParameter(CONDITION_PARAM_BUFF_SPELL, true) +condition:setParameter(CONDITION_PARAM_TICKS, 10000) +condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 40) combat:setCondition(condition) function onCastSpell(creature, variant) diff --git a/path_10_9/data/spells/scripts/monster/walker skill reducer.lua b/path_10_9/data/spells/scripts/monster/walker skill reducer.lua new file mode 100644 index 000000000..73553dde4 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/walker skill reducer.lua @@ -0,0 +1,71 @@ +local mage = {1, 2, 5, 6} +local paladin = {3, 7} +local knight = {4, 8} + +local combat = {} + +for i = 45, 60 do + combat[i] = Combat() + + local condition1 = Condition(CONDITION_ATTRIBUTES) + condition1:setParameter(CONDITION_PARAM_TICKS, 7000) + condition1:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, i) + condition1:setParameter(CONDITION_PARAM_SKILL_FISTPERCENT, i) + condition1:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, i) + + local condition2 = Condition(CONDITION_ATTRIBUTES) + condition2:setParameter(CONDITION_PARAM_TICKS, 7000) + condition2:setParameter(CONDITION_PARAM_STAT_MAGICPOINTSPERCENT, i) + + local condition3 = Condition(CONDITION_ATTRIBUTES) + condition3:setParameter(CONDITION_PARAM_TICKS, 7000) + condition3:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, i) + condition3:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, i) + + local area = createCombatArea(AREA_CIRCLE3X3) + combat[i]:setArea(area) + + +function onTargetTile(creature, pos) + local creatureTable = {} + local n, i = Tile({x=pos.x, y=pos.y, z=pos.z}).creatures, 1 + if n ~= 0 then + local v = getThingfromPos({x=pos.x, y=pos.y, z=pos.z, stackpos=i}).uid + while v ~= 0 do + if isCreature(v) == true then + table.insert(creatureTable, v) + if n == #creatureTable then + break + end + end + i = i + 1 + v = getThingfromPos({x=pos.x, y=pos.y, z=pos.z, stackpos=i}).uid + end + end + if #creatureTable ~= nil and #creatureTable > 0 then + for r = 1, #creatureTable do + if creatureTable[r] ~= creature then + local player = Player(creatureTable[r]) + + if isPlayer(creatureTable[r]) == true and isInArray(mage, player:getVocation():getId()) then + player:addCondition(condition2) + elseif isPlayer(creatureTable[r]) == true and isInArray(paladin, player:getVocation():getId()) then + player:addCondition(condition3) + elseif isPlayer(creatureTable[r]) == true and isInArray(knight, player:getVocation():getId()) then + player:addCondition(condition1) + elseif isMonster(creatureTable[r]) == true then + end + end + end + end + pos:sendMagicEffect(CONST_ME_MAGIC_RED) + return true +end + +combat[i]:setCallback(CALLBACK_PARAM_TARGETTILE, "onTargetTile") + +end + +function onCastSpell(creature, variant) + return combat[math.random(45, 60)]:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/monster/worm priestess paralyze.lua b/path_10_9/data/spells/scripts/monster/worm priestess paralyze.lua new file mode 100644 index 000000000..d7efefcc3 --- /dev/null +++ b/path_10_9/data/spells/scripts/monster/worm priestess paralyze.lua @@ -0,0 +1,22 @@ +local combat = Combat() +combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_HITAREA) + +local condition = Condition(CONDITION_PARALYZE) +condition:setParameter(CONDITION_PARAM_TICKS, 10000) +condition:setFormula(-0.4, 0, -0.7, 0) +combat:setCondition(condition) + + arr = { + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0}, + {0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0} + } + +local area = createCombatArea(arr) + combat:setArea(area) + combat:setCondition(condition) + + +function onCastSpell(creature, variant) + return combat:execute(creature, variant) +end diff --git a/path_10_9/data/spells/scripts/support/sharpshooter.lua b/path_10_9/data/spells/scripts/support/sharpshooter.lua index e1168cbb7..52fe14626 100644 --- a/path_10_9/data/spells/scripts/support/sharpshooter.lua +++ b/path_10_9/data/spells/scripts/support/sharpshooter.lua @@ -9,7 +9,7 @@ skill:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, -100) skill:setParameter(CONDITION_PARAM_BUFF_SPELL, true) combat:setCondition(skill) -local speed = Condition(CONDITION_HASTE) +local speed = Condition(CONDITION_PARALYZE) speed:setParameter(CONDITION_PARAM_TICKS, 10000) speed:setFormula(-0.7, 56, -0.7, 56) combat:setCondition(speed) diff --git a/path_10_9/data/spells/spells.xml b/path_10_9/data/spells/spells.xml index 513eca9d3..be08678da 100644 --- a/path_10_9/data/spells/spells.xml +++ b/path_10_9/data/spells/spells.xml @@ -1,75 +1,75 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -79,65 +79,65 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -147,29 +147,29 @@ - + - + - + - + - + - + @@ -179,11 +179,11 @@ - + - + @@ -193,41 +193,41 @@ - + - + - + - + - + - + - + - + - + @@ -235,23 +235,23 @@ - + - + - + - + @@ -261,7 +261,7 @@ - + @@ -271,7 +271,7 @@ - + @@ -279,11 +279,11 @@ - + - + @@ -291,7 +291,7 @@ - + @@ -301,210 +301,210 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + - - + + - - - - + + + + - + - + @@ -512,60 +512,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - - + @@ -573,113 +573,113 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -687,7 +687,7 @@ - + @@ -695,7 +695,7 @@ - + @@ -703,23 +703,23 @@ - + - + - + - + - + @@ -727,11 +727,11 @@ - + - + @@ -792,4 +792,20 @@ + + + + + + + + + + + + + + + + diff --git a/path_10_9/data/talkactions/scripts/addon.lua b/path_10_9/data/talkactions/scripts/addon.lua new file mode 100644 index 000000000..50681a10a --- /dev/null +++ b/path_10_9/data/talkactions/scripts/addon.lua @@ -0,0 +1,181 @@ +local config = { + ["citizen"] = { + male = 128, + female = 136, + addon = 3, + items = { + {5878,100} + } + }, + ["hunter"] = { + male = 129, + female = 137, + addon = 3, + items = { + {5876, 100}, {5948, 100} + } + }, + ["mage"] = { + male = 130, + female = 138, + addon = 3, + items = { + {2160, 1000} + } + }, + ["knight"] = { + male = 131, + female = 139, + addon = 3, + items = { + {5880, 100}, {5893, 100} + } + }, + ["summoner"] = { + male = 133, + female = 141, + addon = 3, + items = { + {2160,1000} + } + }, + ["warrior"] = { + male = 134, + female = 142, + addon = 3, + items = { + {5925, 100}, {5899, 100}, {5919, 1}, {5880, 100} + } + }, + ["barbarian"] = { + male = 147, + female = 143, + addon = 3, + items = { + {5911, 50}, {5910, 50}, {5879, 100} + } + }, + ["druid"] = { + male = 148, + female = 144, + addon = 3, + items = { + {5896, 50}, {5897, 50} + } + }, + ["wizard"] = { + male = 149, + female = 145, + addon = 3, + items = { + {2536, 1}, {2492, 1}, {2488, 1}, {2123, 1}, {5922, 50} + } + }, + ["oriental"] = { + male = 150, + female = 146, + addon = 3, + items = { + {5883, 100}, {5895, 100}, {5912, 100} + } + }, + ["pirate"] = { + male = 151, + female = 155, + addon = 3, + items = { + {6098, 100}, {6126, 100}, {6097, 100} + } + }, + ["assassin"] = { + male = 152, + female = 156, + addon = 3, + items = { + {5898, 30}, {5882, 10}, {5881, 30}, {5895, 20}, {5905, 10} + } + }, + ["beggar"] = { + male = 153, + female = 157, + addon = 3, + items = { + {5878, 50}, {2743, 30}, {5913, 20}, {5894, 10} + } + }, + ["shaman"] = { + male = 154, + female = 158, + addon = 3, + items = { + {3955, 5}, {5810, 5}, {3966, 5}, {3967, 5} + } + }, + ["norseman"] = { + male = 251, + female = 252, + addon = 3, + items = { + {7290, 15} + } + }, + ["nightmare"] = { + male = 268, + female = 269, + addon = 3, + items = { + {6500, 200} + } + }, + ["jester"] = { + male = 273, + female = 270, + addon = 3, + items = { + {2160, 25} + } + }, + ["brotherhood"] = { + male = 278, + female = 279, + addon = 3, + items = { + {6500, 200} + } + } +} + +function onSay(player, words, param) + local v = config[param:lower()] + if not v then + return false + end + + local outfit = player:getSex() == PLAYERSEX_FEMALE and v["female"] or v["male"] + if player:hasOutfit(outfit, 3) then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have already obtained the " .. param .. " addons.") + return false + end + + local text = "" + for i = 1, #v["items"] do + local itemType = ItemType(v["items"][i][1]) + text = text .. (i ~= 1 and (i == #v["items"] and " and " or ", ") or "") .. (v["items"][i][2] > 1 and v["items"][i][2] or itemType:getArticle()) .. " " .. (v["items"][i][2] > 1 and itemType:getPluralName() or itemType:getName()) + end + + for i = 1, #v["items"] do + if player:getItemCount(v["items"][i][1]) < v["items"][i][2] then + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You need " .. text .. " for the whole " .. param .. " outfit.") + return false + end + end + + for i = 1, #v["items"] do + player:removeItem(unpack(v["items"][i])) + end + player:addOutfitAddon(v["female"], 3) + player:addOutfitAddon(v["male"], 3) + player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Enjoy your new addons to your " .. param .. " outfit!") + player:getPosition():sendMagicEffect(CONST_ME_FIREWORK_YELLOW) + return false +end diff --git a/path_10_9/data/talkactions/scripts/alladdons.lua b/path_10_9/data/talkactions/scripts/alladdons.lua new file mode 100644 index 000000000..e474dc914 --- /dev/null +++ b/path_10_9/data/talkactions/scripts/alladdons.lua @@ -0,0 +1,45 @@ +local looktypes = { + 128, 136, 129, 137, 130, 138, 131, 139, 132, 140, 133, 141, 134, 142, + 143, 147, 144, 148, 145, 149, 146, 150, 151, 155, 152, 156, 153, 157, + 154, 158, 251, 252, 268, 269, 273, 270, 278, 279, 289, 288, 325, 324, + 335, 336, 366, 367, 328, 329, 430, 431, 432, 433, 463, 464, 465, 466, + 471, 472, 512, 513, 514, 516, 541, 542, 574, 575, 577, 578, 618, 620, + 632, 635, 636, 664, 666, 683, 694, 696, 698, 724, 732, 745, 749, 759, + 845, 852, 610, 619, 633, 634, 637, 665, 667, 684, 695, 697, 699, 725, + 733, 746, 750, 760, 846, 853, +} + +function onSay(player, words, param) + if not player:getGroup():getAccess() then + return true + end + + local target + if param == '' then + target = player:getTarget() + if not target then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Gives players the ability to wear all addons. Usage: /addons ') + return false + end + else + target = Player(param) + end + + if not target then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Player ' .. param .. ' is currently not online.') + return false + end + + if player:getAccountType() < ACCOUNT_TYPE_GOD then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Cannot perform action.') + return false + end + + for i = 1, #looktypes do + target:addOutfitAddon(looktypes[i], 3) + end + + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'All addons unlocked for ' .. target:getName() .. '.') + target:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, '[Server] All addons unlocked.') + return false +end diff --git a/path_10_9/data/talkactions/scripts/allmounts.lua b/path_10_9/data/talkactions/scripts/allmounts.lua new file mode 100644 index 000000000..837465c16 --- /dev/null +++ b/path_10_9/data/talkactions/scripts/allmounts.lua @@ -0,0 +1,34 @@ +function onSay(player, words, param) + if not player:getGroup():getAccess() then + return true + end + + local target + if param == '' then + target = player:getTarget() + if not target then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Unlocks all mounts for certain player. Usage: /mounts ') + return false + end + else + target = Player(param) + end + + if not target then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Player ' .. param .. ' is not currently online.') + return false + end + + if player:getAccountType() < ACCOUNT_TYPE_GOD then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Cannot perform action.') + return false + end + + for i = 1, 90 do + target:addMount(i) + end + + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'All mounts unlocked for: ' .. target:getName()) + target:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, '[Server] All mounts unlocked.') + return false +end diff --git a/path_10_9/data/talkactions/scripts/save.lua b/path_10_9/data/talkactions/scripts/save.lua new file mode 100644 index 000000000..f1949517a --- /dev/null +++ b/path_10_9/data/talkactions/scripts/save.lua @@ -0,0 +1,19 @@ +local savingEvent = 0 + +function onSay(player, words, param) + if player:getGroup():getAccess() then + if isNumber(param) then + stopEvent(savingEvent) + save(tonumber(param) * 60 * 1000) + else + saveServer() + end + end +end + +function save(delay) + saveServer() + if delay > 0 then + savingEvent = addEvent(save, delay, delay) + end +end diff --git a/path_10_9/data/talkactions/scripts/teleport_to_pos.lua b/path_10_9/data/talkactions/scripts/teleport_to_pos.lua new file mode 100644 index 000000000..2b0f31a20 --- /dev/null +++ b/path_10_9/data/talkactions/scripts/teleport_to_pos.lua @@ -0,0 +1,27 @@ +function onSay(player, words, param) + if not player:getGroup():getAccess() then + return true + end + + if param == '' then + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Command param required.") + return false + end + + local tile = param:split(",") + local pos + if tile[2] and tile[3] then + pos = Position(tile[1], tile[2], tile[3]) + else + player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Invalid param specified.") + return false + end + + local tmp = player:getPosition() + if player:teleportTo(pos) and not player:isInGhostMode() then + tmp:sendMagicEffect(CONST_ME_POFF) + pos:sendMagicEffect(CONST_ME_TELEPORT) + end + + return false +end diff --git a/path_10_9/data/talkactions/talkactions.xml b/path_10_9/data/talkactions/talkactions.xml index 486868cc9..05f0f35d7 100644 --- a/path_10_9/data/talkactions/talkactions.xml +++ b/path_10_9/data/talkactions/talkactions.xml @@ -33,18 +33,27 @@ + + + + + + - - - - - + diff --git a/path_10_9/src/actions.cpp b/path_10_9/src/actions.cpp index 9d98352ec..dcb19f3a6 100644 --- a/path_10_9/src/actions.cpp +++ b/path_10_9/src/actions.cpp @@ -263,11 +263,7 @@ Action* Actions::getAction(const Item* item) } //rune items - Action* runeSpell = g_spells->getRuneSpell(item->getID()); - if (runeSpell) { - return runeSpell; - } - return nullptr; + return g_spells->getRuneSpell(item->getID()); } ReturnValue Actions::internalUseItem(Player* player, const Position& pos, uint8_t index, Item* item, bool isHotkey) diff --git a/path_10_9/src/chat.cpp b/path_10_9/src/chat.cpp index e6b22653c..2f4e0b82a 100644 --- a/path_10_9/src/chat.cpp +++ b/path_10_9/src/chat.cpp @@ -22,7 +22,6 @@ #include "chat.h" #include "game.h" #include "pugicast.h" -#include "player.h" #include "scheduler.h" extern Chat* g_chat; diff --git a/path_10_9/src/game.cpp b/path_10_9/src/game.cpp index d44f6e2eb..84cd7fa42 100644 --- a/path_10_9/src/game.cpp +++ b/path_10_9/src/game.cpp @@ -26,29 +26,16 @@ #include "creature.h" #include "monster.h" #include "game.h" -#include "tile.h" -#include "house.h" #include "actions.h" -#include "combat.h" #include "iologindata.h" #include "iomarket.h" -#include "chat.h" #include "talkaction.h" #include "spells.h" #include "configmanager.h" -#include "ban.h" -#include "raids.h" -#include "database.h" #include "server.h" -#include "ioguild.h" -#include "quests.h" #include "globalevent.h" -#include "mounts.h" #include "bed.h" #include "scheduler.h" -#include "monster.h" -#include "spawn.h" -#include "connection.h" #include "events.h" #include "databasetasks.h" @@ -1422,9 +1409,9 @@ Item* Game::findItemOfType(Cylinder* cylinder, uint16_t itemId, return item; } - Container* tmpContainer = item->getContainer(); - if (tmpContainer) { - containers.push_back(tmpContainer); + Container* subContainer = item->getContainer(); + if (subContainer) { + containers.push_back(subContainer); } } } @@ -1437,7 +1424,7 @@ bool Game::removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0* return false; } - if (money <= 0) { + if (money == 0) { return true; } @@ -1492,50 +1479,52 @@ bool Game::removeMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0* for (const auto& moneyEntry : moneyMap) { Item* item = moneyEntry.second; - if (moneyEntry.first > money) { + if (moneyEntry.first >= money) { uint32_t worth = moneyEntry.first / item->getItemCount(); uint32_t removeCount = (money / worth) + 1; addMoney(cylinder, (worth * removeCount) - money, flags); internalRemoveItem(item, removeCount); - money = 0; - } else { - internalRemoveItem(item); - money -= moneyEntry.first; - } - - if (money == 0) { return true; } + + internalRemoveItem(item); + money -= moneyEntry.first; } return false; } void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) { - uint32_t crys = money / 10000; - money -= crys * 10000; - while (crys > 0) { - Item* remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, std::min(100, crys)); + if (money == 0) { + return; + } + + uint32_t crystalCoins = money / 10000; + money -= crystalCoins * 10000; + while (crystalCoins > 0) { + const uint16_t count = std::min(100, crystalCoins); + + Item* remaindItem = Item::CreateItem(ITEM_CRYSTAL_COIN, count); ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); if (ret != RETURNVALUE_NOERROR) { internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); } - crys -= std::min(100, crys); + crystalCoins -= count; } - uint16_t plat = money / 100; - if (plat != 0) { - Item* remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, plat); + uint16_t platinumCoins = money / 100; + if (platinumCoins != 0) { + Item* remaindItem = Item::CreateItem(ITEM_PLATINUM_COIN, platinumCoins); ReturnValue ret = internalAddItem(cylinder, remaindItem, INDEX_WHEREEVER, flags); if (ret != RETURNVALUE_NOERROR) { internalAddItem(cylinder->getTile(), remaindItem, INDEX_WHEREEVER, FLAG_NOLIMIT); } - money -= plat * 100; + money -= platinumCoins * 100; } if (money != 0) { diff --git a/path_10_9/src/iomapserialize.cpp b/path_10_9/src/iomapserialize.cpp index d4390b0dd..dddd4d696 100644 --- a/path_10_9/src/iomapserialize.cpp +++ b/path_10_9/src/iomapserialize.cpp @@ -20,7 +20,6 @@ #include "otpch.h" #include "iomapserialize.h" -#include "house.h" #include "game.h" #include "bed.h" diff --git a/path_10_9/src/item.cpp b/path_10_9/src/item.cpp index c28072af3..0fb631bf6 100644 --- a/path_10_9/src/item.cpp +++ b/path_10_9/src/item.cpp @@ -26,13 +26,10 @@ #include "mailbox.h" #include "house.h" #include "game.h" -#include "luascript.h" #include "bed.h" #include "actions.h" -#include "combat.h" #include "spells.h" -#include "vocation.h" extern Game g_game; extern Spells* g_spells; @@ -819,35 +816,29 @@ std::string Item::getDescription(const ItemType& it, int32_t lookDistance, if (it.isRune()) { if (it.runeLevel > 0 || it.runeMagLevel > 0) { - int32_t tmpSubType = subType; - - if (item) { - tmpSubType = item->getSubType(); - } - - s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used by "; - if (RuneSpell* rune = g_spells->getRuneSpell(it.id)) { - const VocSpellMap& vocMap = rune->getVocMap(); - if (vocMap.empty()) { - s << "players"; - } else { - std::vector showVocMap; - - // vocations listed are mostly unpromoted ones and the promoted version, with the latter hidden from - // description, so probably always `total / 2` is the amount of vocations to be shown. - showVocMap.reserve(vocMap.size() / 2); + int32_t tmpSubType = subType; + if (item) { + tmpSubType = item->getSubType(); + } + s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used by "; - for (const auto& voc : vocMap) { - if (voc.second) { - showVocMap.push_back(g_vocations.getVocation(voc.first)); - } + const VocSpellMap& vocMap = rune->getVocMap(); + std::vector showVocMap; + + // vocations are usually listed with the unpromoted and promoted version, the latter being + // hidden from description, so `total / 2` is most likely the amount of vocations to be shown. + showVocMap.reserve(vocMap.size() / 2); + for (const auto& voc : vocMap) { + if (voc.second) { + showVocMap.push_back(g_vocations.getVocation(voc.first)); } + } + if (!showVocMap.empty()) { auto vocIt = showVocMap.begin(), vocLast = (showVocMap.end() - 1); while (vocIt != vocLast) { s << asLowerCaseString((*vocIt)->getVocName()) << "s"; - if (++vocIt == vocLast) { s << " and "; } else { @@ -855,6 +846,8 @@ std::string Item::getDescription(const ItemType& it, int32_t lookDistance, } } s << asLowerCaseString((*vocLast)->getVocName()) << "s"; + } else { + s << "players"; } s << " with"; @@ -1360,7 +1353,7 @@ std::string Item::getDescription(const ItemType& it, int32_t lookDistance, s << "premium "; } - if (it.wieldInfo & WIELDINFO_VOCREQ) { + if (!it.vocationString.empty()) { s << it.vocationString; } else { s << "players"; diff --git a/path_10_9/src/items.cpp b/path_10_9/src/items.cpp index 1e75b5dbe..b244f3225 100644 --- a/path_10_9/src/items.cpp +++ b/path_10_9/src/items.cpp @@ -949,6 +949,14 @@ void Items::parseItemNode(const pugi::xml_node& itemNode, uint16_t id) Abilities& abilities = it.getAbilities(); abilities.elementDamage = pugi::cast(valueAttribute.value()); abilities.elementType = COMBAT_ENERGYDAMAGE; + } else if (tmpStrValue == "elementdeath") { + Abilities& abilities = it.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_DEATHDAMAGE; + } else if (tmpStrValue == "elementholy") { + Abilities& abilities = it.getAbilities(); + abilities.elementDamage = pugi::cast(valueAttribute.value()); + abilities.elementType = COMBAT_HOLYDAMAGE; } else if (tmpStrValue == "walkstack") { it.walkStack = valueAttribute.as_bool(); } else if (tmpStrValue == "blocking") { diff --git a/path_10_9/src/networkmessage.cpp b/path_10_9/src/networkmessage.cpp index fb6fb2219..ecd8afa10 100644 --- a/path_10_9/src/networkmessage.cpp +++ b/path_10_9/src/networkmessage.cpp @@ -23,10 +23,6 @@ #include "container.h" #include "creature.h" -#include "player.h" - -#include "position.h" -#include "rsa.h" int32_t NetworkMessage::decodeHeader() { diff --git a/path_10_9/src/npc.cpp b/path_10_9/src/npc.cpp index 61bb65f5c..a53548698 100644 --- a/path_10_9/src/npc.cpp +++ b/path_10_9/src/npc.cpp @@ -21,12 +21,7 @@ #include "npc.h" #include "game.h" -#include "tools.h" -#include "position.h" -#include "player.h" -#include "spawn.h" #include "pugicast.h" -#include "luascript.h" extern Game g_game; extern LuaEnvironment g_luaEnvironment; diff --git a/path_10_9/src/player.cpp b/path_10_9/src/player.cpp index 52553267e..3439e6e31 100644 --- a/path_10_9/src/player.cpp +++ b/path_10_9/src/player.cpp @@ -31,7 +31,6 @@ #include "iologindata.h" #include "monster.h" #include "movement.h" -#include "outputmessage.h" #include "scheduler.h" #include "weapons.h" diff --git a/path_10_9/src/protocollogin.cpp b/path_10_9/src/protocollogin.cpp index a34aa8150..2a4aea8b1 100644 --- a/path_10_9/src/protocollogin.cpp +++ b/path_10_9/src/protocollogin.cpp @@ -17,12 +17,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include "otpch.h" #include "protocollogin.h" #include "outputmessage.h" -#include "rsa.h" #include "tasks.h" #include "configmanager.h" @@ -92,7 +92,9 @@ void ProtocolLogin::getCharacterList(const std::string& accountName, const std:: output->addByte(0); output->addByte(g_config.getBoolean(ConfigManager::FREE_PREMIUM) || account.premiumDays > 0); - output->add(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : (time(nullptr) + (account.premiumDays * 86400))); + auto time = std::chrono::system_clock::now() + std::chrono::hours(account.premiumDays * 24); + std::chrono::seconds timestamp = std::chrono::duration_cast(time.time_since_epoch()); + output->add(g_config.getBoolean(ConfigManager::FREE_PREMIUM) ? 0 : timestamp.count()); send(output); diff --git a/path_10_9/src/protocolold.cpp b/path_10_9/src/protocolold.cpp index a68e857b2..319f40247 100644 --- a/path_10_9/src/protocolold.cpp +++ b/path_10_9/src/protocolold.cpp @@ -21,7 +21,6 @@ #include "protocolold.h" #include "outputmessage.h" -#include "tasks.h" #include "game.h" diff --git a/path_10_9/src/protocolstatus.cpp b/path_10_9/src/protocolstatus.cpp index 18e517acf..afb1a722b 100644 --- a/path_10_9/src/protocolstatus.cpp +++ b/path_10_9/src/protocolstatus.cpp @@ -22,11 +22,7 @@ #include "protocolstatus.h" #include "configmanager.h" #include "game.h" -#include "connection.h" -#include "networkmessage.h" #include "outputmessage.h" -#include "tools.h" -#include "tasks.h" extern ConfigManager g_config; extern Game g_game; diff --git a/path_10_9/src/tile.cpp b/path_10_9/src/tile.cpp index b707aa759..e20a1fdf1 100644 --- a/path_10_9/src/tile.cpp +++ b/path_10_9/src/tile.cpp @@ -29,7 +29,6 @@ #include "mailbox.h" #include "monster.h" #include "movement.h" -#include "player.h" #include "teleport.h" #include "trashholder.h"