diff --git a/path_10_9/src/definitions.h b/path_10_9/src/definitions.h index 1e40a6240..7a84e7006 100644 --- a/path_10_9/src/definitions.h +++ b/path_10_9/src/definitions.h @@ -23,7 +23,7 @@ #define STATUS_SERVER_NAME "OTX Server" #define STATUS_SERVER_VERSION "3" #define MINOR_VERSION "4" -#define REVISION_VERSION "-" +#define REVISION_VERSION "612" #define SOFTWARE_CODENAME "LORD ZEDD" #define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" #define GIT_REPO "https://github.com/mattyx14/otxserver/" diff --git a/path_7_s/.editorconfig b/path_7_s/.editorconfig deleted file mode 100644 index 26b3599ca..000000000 --- a/path_7_s/.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_7_s/.gitattributes b/path_7_s/.gitattributes deleted file mode 100644 index 109adf08d..000000000 --- a/path_7_s/.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_7_s/.gitignore b/path_7_s/.gitignore deleted file mode 100644 index 5400463dd..000000000 --- a/path_7_s/.gitignore +++ /dev/null @@ -1,172 +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 -*.opendb -*.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_7_s/.travis.yml b/path_7_s/.travis.yml deleted file mode 100644 index f0741bfa5..000000000 --- a/path_7_s/.travis.yml +++ /dev/null @@ -1,23 +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 - - libpugixml-dev -before_script: - - mkdir build && cd build - - cmake -DCMAKE_BUILD_TYPE=Release -DUSE_LUAJIT=${LUAJIT} .. -script: make -j2 diff --git a/path_7_s/CMakeLists.txt b/path_7_s/CMakeLists.txt deleted file mode 100644 index ae6fdcaba..000000000 --- a/path_7_s/CMakeLists.txt +++ /dev/null @@ -1,53 +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(PugiXML 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} ${PUGIXML_INCLUDE_DIR} ${GMP_INCLUDE_DIR}) -target_link_libraries(tfs ${MYSQL_CLIENT_LIBS} ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${PUGIXML_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_7_s/cmake/FindCXX11.cmake b/path_7_s/cmake/FindCXX11.cmake deleted file mode 100644 index 1702e8dfb..000000000 --- a/path_7_s/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_7_s/cmake/FindGMP.cmake b/path_7_s/cmake/FindGMP.cmake deleted file mode 100644 index 80805443f..000000000 --- a/path_7_s/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_7_s/cmake/FindLua.cmake b/path_7_s/cmake/FindLua.cmake deleted file mode 100644 index 57a48ebca..000000000 --- a/path_7_s/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_7_s/cmake/FindLuaJIT.cmake b/path_7_s/cmake/FindLuaJIT.cmake deleted file mode 100644 index e626a5a1d..000000000 --- a/path_7_s/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_7_s/cmake/FindMySQL.cmake b/path_7_s/cmake/FindMySQL.cmake deleted file mode 100644 index 5e378d5b4..000000000 --- a/path_7_s/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_7_s/cmake/FindPugiXML.cmake b/path_7_s/cmake/FindPugiXML.cmake deleted file mode 100644 index 4f09e0b55..000000000 --- a/path_7_s/cmake/FindPugiXML.cmake +++ /dev/null @@ -1,7 +0,0 @@ -find_path(PUGIXML_INCLUDE_DIR NAMES pugixml.hpp) -find_library(PUGIXML_LIBRARIES NAMES pugixml) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PugiXML REQUIRED_VARS PUGIXML_INCLUDE_DIR PUGIXML_LIBRARIES) - -mark_as_advanced(PUGIXML_INCLUDE_DIR PUGIXML_LIBRARIES) diff --git a/path_7_s/cmake/cotire.cmake b/path_7_s/cmake/cotire.cmake deleted file mode 100644 index a4fb533c6..000000000 --- a/path_7_s/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_7_s/config.lua b/path_7_s/config.lua deleted file mode 100644 index 28ab78597..000000000 --- a/path_7_s/config.lua +++ /dev/null @@ -1,102 +0,0 @@ --- Combat settings --- NOTE: valid values for worldType are: "pvp", "no-pvp" and "pvp-enforced" -worldType = "pvp" -hotkeyAimbotEnabled = true -protectionLevel = 1 -killsToRedSkull = 3 -pzLocked = 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 Forgotten Server!" -onePlayerOnlinePerAccount = true -allowClones = false -serverName = "Forgotten" -statusTimeout = 5 * 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 = "weekly" - --- Item Usage -timeBetweenActions = 200 -timeBetweenExActions = 1000 - --- Map --- NOTE: set mapName WITHOUT .otbm at the end -mapName = "forgotten" -mapAuthor = "Komic" - --- MySQL -mysqlHost = "127.0.0.1" -mysqlUser = "forgottenserver" -mysqlPass = "" -mysqlDatabase = "forgottenserver" -mysqlPort = 3306 -mysqlSock = "" - --- Misc. -allowChangeOutfit = true -freePremium = false -kickIdlePlayerAfterMinutes = 15 -maxMessageBuffer = 4 -emoteSpells = true -classicEquipmentSlots = false - --- 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 - --- Rates --- NOTE: rateExp is not used if you have enabled stages in data/XML/stages.xml -rateExp = 5 -rateSkill = 3 -rateLoot = 2 -rateMagic = 3 -rateSpawn = 1 - --- 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 = "http://darkkonia.sytes.net/" -location = "Mexico" diff --git a/path_7_s/data/XML/commands.xml b/path_7_s/data/XML/commands.xml deleted file mode 100644 index 9b1630aaa..000000000 --- a/path_7_s/data/XML/commands.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/path_7_s/data/XML/groups.xml b/path_7_s/data/XML/groups.xml deleted file mode 100644 index cd5ed0486..000000000 --- a/path_7_s/data/XML/groups.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_7_s/data/XML/outfits.xml b/path_7_s/data/XML/outfits.xml deleted file mode 100644 index 4f82f5a2c..000000000 --- a/path_7_s/data/XML/outfits.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/XML/quests.xml b/path_7_s/data/XML/quests.xml deleted file mode 100644 index 4633d44f7..000000000 --- a/path_7_s/data/XML/quests.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/path_7_s/data/XML/stages.xml b/path_7_s/data/XML/stages.xml deleted file mode 100644 index 06b639c0e..000000000 --- a/path_7_s/data/XML/stages.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_7_s/data/XML/vocations.xml b/path_7_s/data/XML/vocations.xml deleted file mode 100644 index 6ddebd0c9..000000000 --- a/path_7_s/data/XML/vocations.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/actions/actions.xml b/path_7_s/data/actions/actions.xml deleted file mode 100644 index 4aa067b12..000000000 --- a/path_7_s/data/actions/actions.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/actions/lib/actions.lua b/path_7_s/data/actions/lib/actions.lua deleted file mode 100644 index e6092fd66..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/blueberrybush.lua b/path_7_s/data/actions/scripts/other/blueberrybush.lua deleted file mode 100644 index a471e0c2f..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/changegold.lua b/path_7_s/data/actions/scripts/other/changegold.lua deleted file mode 100644 index 6af63855a..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/constructionkits.lua b/path_7_s/data/actions/scripts/other/constructionkits.lua deleted file mode 100644 index e65a42302..000000000 --- a/path_7_s/data/actions/scripts/other/constructionkits.lua +++ /dev/null @@ -1,28 +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, -} - -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_7_s/data/actions/scripts/other/createbread.lua b/path_7_s/data/actions/scripts/other/createbread.lua deleted file mode 100644 index f58eb1a0b..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/decayto.lua b/path_7_s/data/actions/scripts/other/decayto.lua deleted file mode 100644 index ee8543e86..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/destroy.lua b/path_7_s/data/actions/scripts/other/destroy.lua deleted file mode 100644 index 0499f62cc..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/dice.lua b/path_7_s/data/actions/scripts/other/dice.lua deleted file mode 100644 index 86505a5dc..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/doors.lua b/path_7_s/data/actions/scripts/other/doors.lua deleted file mode 100644 index 0374d46a9..000000000 --- a/path_7_s/data/actions/scripts/other/doors.lua +++ /dev/null @@ -1,68 +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(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 - 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_7_s/data/actions/scripts/other/fireworksrocket.lua b/path_7_s/data/actions/scripts/other/fireworksrocket.lua deleted file mode 100644 index 57ce7989d..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/fluids.lua b/path_7_s/data/actions/scripts/other/fluids.lua deleted file mode 100644 index c01f40334..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/food.lua b/path_7_s/data/actions/scripts/other/food.lua deleted file mode 100644 index 005fa5545..000000000 --- a/path_7_s/data/actions/scripts/other/food.lua +++ /dev/null @@ -1,80 +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) -} - -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_7_s/data/actions/scripts/other/music.lua b/path_7_s/data/actions/scripts/other/music.lua deleted file mode 100644 index a6bdb61ab..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/partyhat.lua b/path_7_s/data/actions/scripts/other/partyhat.lua deleted file mode 100644 index 6e41b5871..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/partytrumpet.lua b/path_7_s/data/actions/scripts/other/partytrumpet.lua deleted file mode 100644 index 8e178c67a..000000000 --- a/path_7_s/data/actions/scripts/other/partytrumpet.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(6573) - item:decay() - player:say("TOOOOOOT!", TALKTYPE_MONSTER_SAY) - fromPosition:sendMagicEffect(CONST_ME_SOUND_BLUE) - return true -end diff --git a/path_7_s/data/actions/scripts/other/piggybank.lua b/path_7_s/data/actions/scripts/other/piggybank.lua deleted file mode 100644 index 07f5d93ad..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/potions.lua b/path_7_s/data/actions/scripts/other/potions.lua deleted file mode 100644 index 9a59245b7..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/skilltrainer.lua b/path_7_s/data/actions/scripts/other/skilltrainer.lua deleted file mode 100644 index 8e995faff..000000000 --- a/path_7_s/data/actions/scripts/other/skilltrainer.lua +++ /dev/null @@ -1,27 +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:getActionId()] - if not skill then - return false - end - - 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_7_s/data/actions/scripts/other/spellbook.lua b/path_7_s/data/actions/scripts/other/spellbook.lua deleted file mode 100644 index 5c7da6c00..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/surprisebag.lua b/path_7_s/data/actions/scripts/other/surprisebag.lua deleted file mode 100644 index 4727e0537..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/teleport.lua b/path_7_s/data/actions/scripts/other/teleport.lua deleted file mode 100644 index 8cb599463..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/trap.lua b/path_7_s/data/actions/scripts/other/trap.lua deleted file mode 100644 index 9d4554707..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/watch.lua b/path_7_s/data/actions/scripts/other/watch.lua deleted file mode 100644 index 88b7df4ea..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/other/windows.lua b/path_7_s/data/actions/scripts/other/windows.lua deleted file mode 100644 index 3a701b46e..000000000 --- a/path_7_s/data/actions/scripts/other/windows.lua +++ /dev/null @@ -1,43 +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, -} - -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_7_s/data/actions/scripts/quests/annihilator.lua b/path_7_s/data/actions/scripts/quests/annihilator.lua deleted file mode 100644 index 70066e1dd..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/quests/quests.lua b/path_7_s/data/actions/scripts/quests/quests.lua deleted file mode 100644 index 0463324a8..000000000 --- a/path_7_s/data/actions/scripts/quests/quests.lua +++ /dev/null @@ -1,42 +0,0 @@ -local annihilatorReward = {1990, 2400, 2431, 2494} -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item.uid <= 1250 or item.uid >= 12660 then - return false - end - - local itemType = ItemType(item.uid) - if itemType:getId() == 0 then - return false - end - - 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_7_s/data/actions/scripts/quests/system.lua b/path_7_s/data/actions/scripts/quests/system.lua deleted file mode 100644 index 9f37e462e..000000000 --- a/path_7_s/data/actions/scripts/quests/system.lua +++ /dev/null @@ -1,87 +0,0 @@ -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_7_s/data/actions/scripts/tools/fishing.lua b/path_7_s/data/actions/scripts/tools/fishing.lua deleted file mode 100644 index d50d11631..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/tools/machete.lua b/path_7_s/data/actions/scripts/tools/machete.lua deleted file mode 100644 index daf0ed3da..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/tools/pick.lua b/path_7_s/data/actions/scripts/tools/pick.lua deleted file mode 100644 index 7ef688b5f..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/tools/rope.lua b/path_7_s/data/actions/scripts/tools/rope.lua deleted file mode 100644 index 5b0b80d4c..000000000 --- a/path_7_s/data/actions/scripts/tools/rope.lua +++ /dev/null @@ -1,24 +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 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local tile = Tile(toPosition) - if isInArray(ropeSpots, tile:getGround():getId()) 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_7_s/data/actions/scripts/tools/scythe.lua b/path_7_s/data/actions/scripts/tools/scythe.lua deleted file mode 100644 index 3d2f7c18f..000000000 --- a/path_7_s/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_7_s/data/actions/scripts/tools/shovel.lua b/path_7_s/data/actions/scripts/tools/shovel.lua deleted file mode 100644 index 3bacc66d8..000000000 --- a/path_7_s/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_7_s/data/chatchannels/chatchannels.xml b/path_7_s/data/chatchannels/chatchannels.xml deleted file mode 100644 index dc7922473..000000000 --- a/path_7_s/data/chatchannels/chatchannels.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_7_s/data/chatchannels/scripts/advertising-rook.lua b/path_7_s/data/chatchannels/scripts/advertising-rook.lua deleted file mode 100644 index 6c92b4ef8..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/advertising.lua b/path_7_s/data/chatchannels/scripts/advertising.lua deleted file mode 100644 index 0f90e3340..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/englishchat.lua b/path_7_s/data/chatchannels/scripts/englishchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/gamemaster.lua b/path_7_s/data/chatchannels/scripts/gamemaster.lua deleted file mode 100644 index b3050cc53..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/help.lua b/path_7_s/data/chatchannels/scripts/help.lua deleted file mode 100644 index 54e7de61e..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/tutor.lua b/path_7_s/data/chatchannels/scripts/tutor.lua deleted file mode 100644 index 8db26a8ba..000000000 --- a/path_7_s/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_7_s/data/chatchannels/scripts/worldchat.lua b/path_7_s/data/chatchannels/scripts/worldchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/creaturescripts.xml b/path_7_s/data/creaturescripts/creaturescripts.xml deleted file mode 100644 index 18f666513..000000000 --- a/path_7_s/data/creaturescripts/creaturescripts.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/path_7_s/data/creaturescripts/lib/creaturescripts.lua b/path_7_s/data/creaturescripts/lib/creaturescripts.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_7_s/data/creaturescripts/lib/creaturescripts.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_7_s/data/creaturescripts/scripts/advance_save.lua b/path_7_s/data/creaturescripts/scripts/advance_save.lua deleted file mode 100644 index b4095a9d0..000000000 --- a/path_7_s/data/creaturescripts/scripts/advance_save.lua +++ /dev/null @@ -1,25 +0,0 @@ -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_7_s/data/creaturescripts/scripts/droploot.lua b/path_7_s/data/creaturescripts/scripts/droploot.lua deleted file mode 100644 index 371c48a59..000000000 --- a/path_7_s/data/creaturescripts/scripts/droploot.lua +++ /dev/null @@ -1,43 +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) - local hasSkull = isInArray({SKULL_RED, SKULL_BLACK}, player:getSkull()) - if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not hasSkull 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 - local lossPercent = player:getLossPercent() - for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do - local item = player:getSlotItem(i) - if item then - if hasSkull or math.random(item:isContainer() and 100 or 1000) <= lossPercent 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_7_s/data/creaturescripts/scripts/extendedopcode.lua b/path_7_s/data/creaturescripts/scripts/extendedopcode.lua deleted file mode 100644 index 7fa2d42e6..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/scripts/firstitems.lua b/path_7_s/data/creaturescripts/scripts/firstitems.lua deleted file mode 100644 index f778c7878..000000000 --- a/path_7_s/data/creaturescripts/scripts/firstitems.lua +++ /dev/null @@ -1,52 +0,0 @@ --- Without Rookgaard -local config = { - [1] = { - --equipment spellbook, wand of vortex, studded legs, leather boots, scarf - items = {{2175, 1}, {2190, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - --container rope, shovel - container = {{2120, 1}, {2554, 1}} - }, - [2] = { - --equipment spellbook, snakebite rod, studded legs, leather boots scarf - items = {{2175, 1}, {2182, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - --container rope, shovel - container = {{2120, 1}, {2554, 1}} - }, - [3] = { - --equipment dwrven shield, 5 spear, ranger's cloak, scarf, legion helmet - items = {{2525, 1}, {2389, 5}, {2660, 1}, {2643, 1}, {2661, 1}, {2480, 1}}, - --container rope, shovel, bow, 50 arrow - container = {{2120, 1}, {2554, 1}, {2456, 1}, {2544, 50}} - }, - [4] = { - --equipment dwarven shield, orcish axe, brass armor, brass helmet, brass legs scarf - items = {{2525, 1}, {2428, 1}, {2465, 1}, {2460, 1}, {2478, 1}, {2643, 1}, {2661, 1}}, - --container spike sword, daramian mace, rope, shovel, health potion - container = {{2383, 1}, {2439, 1}, {2120, 1}, {2554, 1}} - } -} - -function onLogin(player) - 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_7_s/data/creaturescripts/scripts/login.lua b/path_7_s/data/creaturescripts/scripts/login.lua deleted file mode 100644 index 6c414c1bb..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/scripts/logout.lua b/path_7_s/data/creaturescripts/scripts/logout.lua deleted file mode 100644 index 5a5bfe4eb..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/scripts/offlinetraining.lua b/path_7_s/data/creaturescripts/scripts/offlinetraining.lua deleted file mode 100644 index 98e37aeae..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/scripts/playerdeath.lua b/path_7_s/data/creaturescripts/scripts/playerdeath.lua deleted file mode 100644 index 159dbc720..000000000 --- a/path_7_s/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_7_s/data/creaturescripts/scripts/regeneratestamina.lua b/path_7_s/data/creaturescripts/scripts/regeneratestamina.lua deleted file mode 100644 index 04409058b..000000000 --- a/path_7_s/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_7_s/data/events/events.xml b/path_7_s/data/events/events.xml deleted file mode 100644 index 7b6bdc7f5..000000000 --- a/path_7_s/data/events/events.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/events/scripts/creature.lua b/path_7_s/data/events/scripts/creature.lua deleted file mode 100644 index 17116ec37..000000000 --- a/path_7_s/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_7_s/data/events/scripts/monster.lua b/path_7_s/data/events/scripts/monster.lua deleted file mode 100644 index 5afd8d131..000000000 --- a/path_7_s/data/events/scripts/monster.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Monster:onSpawn(position, isStartup) - return true -end diff --git a/path_7_s/data/events/scripts/party.lua b/path_7_s/data/events/scripts/party.lua deleted file mode 100644 index bbb4cfa29..000000000 --- a/path_7_s/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_7_s/data/events/scripts/player.lua b/path_7_s/data/events/scripts/player.lua deleted file mode 100644 index 4e6072ca7..000000000 --- a/path_7_s/data/events/scripts/player.lua +++ /dev/null @@ -1,215 +0,0 @@ -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) - 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 - -function Player:onMoveCreature(creature, fromPosition, toPosition) - return true -end - -function Player:onTurn(direction) - if self:getGroup():getAccess() and self:getDirection() == direction then - local nextPosition = self:getPosition() - nextPosition:getNextPosition(direction) - - self:teleportTo(nextPosition, true) - end - - 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_7_s/data/global.lua b/path_7_s/data/global.lua deleted file mode 100644 index d5f0a5300..000000000 --- a/path_7_s/data/global.lua +++ /dev/null @@ -1,70 +0,0 @@ -dofile('data/lib/lib.lua') - -ddos = {}; -ddos.enabled = false; -ddos.broadcasted = false - -STORAGEVALUE_PROMOTION = 30018 - -ropeSpots = {384, 418} - -doors = { - [1209] = 1211, [1210] = 1211, [1212] = 1214, [1213] = 1214, [1214] = 1212, [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, -} - -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} -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} -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} -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} -levelDoors = {1227, 1229, 1245, 1247, 1259, 1261, 3540, 3549, 5103, 5112, 5121, 5130, 5292, 5294, 6206, 6208, 6263, 6265, 6896, 6905, 7038, 7047} -keys = {2086, 2087, 2088, 2089, 2090, 2091, 2092} - -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_7_s/data/globalevents/globalevents.xml b/path_7_s/data/globalevents/globalevents.xml deleted file mode 100644 index 8012f11aa..000000000 --- a/path_7_s/data/globalevents/globalevents.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_7_s/data/globalevents/lib/globalevents.lua b/path_7_s/data/globalevents/lib/globalevents.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_7_s/data/globalevents/lib/globalevents.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_7_s/data/globalevents/scripts/cleanmap.lua b/path_7_s/data/globalevents/scripts/cleanmap.lua deleted file mode 100644 index bc69435f4..000000000 --- a/path_7_s/data/globalevents/scripts/cleanmap.lua +++ /dev/null @@ -1,10 +0,0 @@ -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_7_s/data/globalevents/scripts/ddos.lua b/path_7_s/data/globalevents/scripts/ddos.lua deleted file mode 100644 index c629eaffd..000000000 --- a/path_7_s/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_7_s/data/globalevents/scripts/record.lua b/path_7_s/data/globalevents/scripts/record.lua deleted file mode 100644 index 47d6b79ef..000000000 --- a/path_7_s/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_7_s/data/globalevents/scripts/serversave.lua b/path_7_s/data/globalevents/scripts/serversave.lua deleted file mode 100644 index e943e74d5..000000000 --- a/path_7_s/data/globalevents/scripts/serversave.lua +++ /dev/null @@ -1,4 +0,0 @@ -function onThink(interval) - saveServer() - return true -end diff --git a/path_7_s/data/globalevents/scripts/startup.lua b/path_7_s/data/globalevents/scripts/startup.lua deleted file mode 100644 index bb2542118..000000000 --- a/path_7_s/data/globalevents/scripts/startup.lua +++ /dev/null @@ -1,38 +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()) - - -- 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_7_s/data/items/items.otb b/path_7_s/data/items/items.otb deleted file mode 100644 index fe4446714..000000000 Binary files a/path_7_s/data/items/items.otb and /dev/null differ diff --git a/path_7_s/data/items/items.xml b/path_7_s/data/items/items.xml deleted file mode 100644 index 38396a37d..000000000 --- a/path_7_s/data/items/items.xml +++ /dev/null @@ -1,15278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/lib/compat/compat.lua b/path_7_s/data/lib/compat/compat.lua deleted file mode 100644 index 16dddf5dc..000000000 --- a/path_7_s/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(message, position, color) return Game.sendAnimatedText(message, position, color) 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:getHouse() ~= nil - 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_7_s/data/lib/core/constants.lua b/path_7_s/data/lib/core/constants.lua deleted file mode 100644 index 9d1f90bc1..000000000 --- a/path_7_s/data/lib/core/constants.lua +++ /dev/null @@ -1 +0,0 @@ -CONTAINER_POSITION = 0xFFFF diff --git a/path_7_s/data/lib/core/container.lua b/path_7_s/data/lib/core/container.lua deleted file mode 100644 index 65343eb7f..000000000 --- a/path_7_s/data/lib/core/container.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Container.isContainer(self) - return true -end diff --git a/path_7_s/data/lib/core/core.lua b/path_7_s/data/lib/core/core.lua deleted file mode 100644 index 1b78513f1..000000000 --- a/path_7_s/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_7_s/data/lib/core/creature.lua b/path_7_s/data/lib/core/creature.lua deleted file mode 100644 index e0fd78578..000000000 --- a/path_7_s/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_7_s/data/lib/core/game.lua b/path_7_s/data/lib/core/game.lua deleted file mode 100644 index 4e0c5d8aa..000000000 --- a/path_7_s/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_7_s/data/lib/core/item.lua b/path_7_s/data/lib/core/item.lua deleted file mode 100644 index 7980d5ae1..000000000 --- a/path_7_s/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_7_s/data/lib/core/itemtype.lua b/path_7_s/data/lib/core/itemtype.lua deleted file mode 100644 index c94ba7f1b..000000000 --- a/path_7_s/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_7_s/data/lib/core/player.lua b/path_7_s/data/lib/core/player.lua deleted file mode 100644 index db09d6816..000000000 --- a/path_7_s/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 - -local lossPercent = { - [0] = 100, - [1] = 70, - [2] = 45, - [3] = 25, - [4] = 10, - [5] = 0 -} - -function Player.getLossPercent(self) - local blessings = 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_7_s/data/lib/core/position.lua b/path_7_s/data/lib/core/position.lua deleted file mode 100644 index 572c6a29f..000000000 --- a/path_7_s/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_7_s/data/lib/core/teleport.lua b/path_7_s/data/lib/core/teleport.lua deleted file mode 100644 index 89302688e..000000000 --- a/path_7_s/data/lib/core/teleport.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Teleport.isTeleport(self) - return true -end diff --git a/path_7_s/data/lib/core/tile.lua b/path_7_s/data/lib/core/tile.lua deleted file mode 100644 index e2e26c4ba..000000000 --- a/path_7_s/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_7_s/data/lib/custom/custom.lua b/path_7_s/data/lib/custom/custom.lua deleted file mode 100644 index 3a1167657..000000000 --- a/path_7_s/data/lib/custom/custom.lua +++ /dev/null @@ -1,85 +0,0 @@ -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_7_s/data/lib/custom/storages.lua b/path_7_s/data/lib/custom/storages.lua deleted file mode 100644 index 0cbf79c31..000000000 --- a/path_7_s/data/lib/custom/storages.lua +++ /dev/null @@ -1,5 +0,0 @@ --- STORAGES -- --- (HIGHLY RECOMMENDED -> ONE mission per STORAGE) -- --- Sort it in Values - - -Storage = {} diff --git a/path_7_s/data/lib/lib.lua b/path_7_s/data/lib/lib.lua deleted file mode 100644 index 2ffc31da5..000000000 --- a/path_7_s/data/lib/lib.lua +++ /dev/null @@ -1,9 +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') - --- Custom -dofile('data/lib/custom/custom.lua') -dofile('data/lib/custom/storages.lua') diff --git a/path_7_s/data/logs/.gitignore b/path_7_s/data/logs/.gitignore deleted file mode 100644 index 5e7d2734c..000000000 --- a/path_7_s/data/logs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/path_7_s/data/migrations/0.lua b/path_7_s/data/migrations/0.lua deleted file mode 100644 index 0fb3ff971..000000000 --- a/path_7_s/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_7_s/data/migrations/1.lua b/path_7_s/data/migrations/1.lua deleted file mode 100644 index c3e6f22fb..000000000 --- a/path_7_s/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_7_s/data/migrations/10.lua b/path_7_s/data/migrations/10.lua deleted file mode 100644 index 9e1357e73..000000000 --- a/path_7_s/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_7_s/data/migrations/11.lua b/path_7_s/data/migrations/11.lua deleted file mode 100644 index 69b1691cb..000000000 --- a/path_7_s/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_7_s/data/migrations/12.lua b/path_7_s/data/migrations/12.lua deleted file mode 100644 index 6e168586b..000000000 --- a/path_7_s/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_7_s/data/migrations/13.lua b/path_7_s/data/migrations/13.lua deleted file mode 100644 index 7b123b40f..000000000 --- a/path_7_s/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_7_s/data/migrations/14.lua b/path_7_s/data/migrations/14.lua deleted file mode 100644 index 632bbaf09..000000000 --- a/path_7_s/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_7_s/data/migrations/15.lua b/path_7_s/data/migrations/15.lua deleted file mode 100644 index f04796b66..000000000 --- a/path_7_s/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_7_s/data/migrations/16.lua b/path_7_s/data/migrations/16.lua deleted file mode 100644 index 45e742227..000000000 --- a/path_7_s/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_7_s/data/migrations/17.lua b/path_7_s/data/migrations/17.lua deleted file mode 100644 index e26bdd430..000000000 --- a/path_7_s/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_7_s/data/migrations/18.lua b/path_7_s/data/migrations/18.lua deleted file mode 100644 index d0ffd9c0c..000000000 --- a/path_7_s/data/migrations/18.lua +++ /dev/null @@ -1,3 +0,0 @@ -function onUpdateDatabase() - return false -end diff --git a/path_7_s/data/migrations/2.lua b/path_7_s/data/migrations/2.lua deleted file mode 100644 index 942a1cd76..000000000 --- a/path_7_s/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_7_s/data/migrations/3.lua b/path_7_s/data/migrations/3.lua deleted file mode 100644 index c93e34d54..000000000 --- a/path_7_s/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_7_s/data/migrations/4.lua b/path_7_s/data/migrations/4.lua deleted file mode 100644 index 069a6432d..000000000 --- a/path_7_s/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_7_s/data/migrations/5.lua b/path_7_s/data/migrations/5.lua deleted file mode 100644 index 82ba621a6..000000000 --- a/path_7_s/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_7_s/data/migrations/6.lua b/path_7_s/data/migrations/6.lua deleted file mode 100644 index f98946764..000000000 --- a/path_7_s/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_7_s/data/migrations/7.lua b/path_7_s/data/migrations/7.lua deleted file mode 100644 index 1fd4a1196..000000000 --- a/path_7_s/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_7_s/data/migrations/8.lua b/path_7_s/data/migrations/8.lua deleted file mode 100644 index d2d9f1750..000000000 --- a/path_7_s/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_7_s/data/migrations/9.lua b/path_7_s/data/migrations/9.lua deleted file mode 100644 index 33022ee08..000000000 --- a/path_7_s/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_7_s/data/monster/Amazons/amazon.xml b/path_7_s/data/monster/Amazons/amazon.xml deleted file mode 100644 index 9bc831a04..000000000 --- a/path_7_s/data/monster/Amazons/amazon.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Amazons/valkyrie.xml b/path_7_s/data/monster/Amazons/valkyrie.xml deleted file mode 100644 index b36103999..000000000 --- a/path_7_s/data/monster/Amazons/valkyrie.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Annelids/carrion worm.xml b/path_7_s/data/monster/Annelids/carrion worm.xml deleted file mode 100644 index 19b2bce4a..000000000 --- a/path_7_s/data/monster/Annelids/carrion worm.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Annelids/rotworm.xml b/path_7_s/data/monster/Annelids/rotworm.xml deleted file mode 100644 index 0506dd91b..000000000 --- a/path_7_s/data/monster/Annelids/rotworm.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Apes/kongra.xml b/path_7_s/data/monster/Apes/kongra.xml deleted file mode 100644 index 4fde32524..000000000 --- a/path_7_s/data/monster/Apes/kongra.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Apes/merlkin.xml b/path_7_s/data/monster/Apes/merlkin.xml deleted file mode 100644 index 3b2794a3f..000000000 --- a/path_7_s/data/monster/Apes/merlkin.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Apes/sibang.xml b/path_7_s/data/monster/Apes/sibang.xml deleted file mode 100644 index 1f62e4dfb..000000000 --- a/path_7_s/data/monster/Apes/sibang.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Apes/yeti.xml b/path_7_s/data/monster/Apes/yeti.xml deleted file mode 100644 index 5faa737f6..000000000 --- a/path_7_s/data/monster/Apes/yeti.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/crystal spider.xml b/path_7_s/data/monster/Arachnids/crystal spider.xml deleted file mode 100644 index 80575371b..000000000 --- a/path_7_s/data/monster/Arachnids/crystal spider.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/giant spider.xml b/path_7_s/data/monster/Arachnids/giant spider.xml deleted file mode 100644 index 0e235e35a..000000000 --- a/path_7_s/data/monster/Arachnids/giant spider.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/poison spider.xml b/path_7_s/data/monster/Arachnids/poison spider.xml deleted file mode 100644 index 07e543df9..000000000 --- a/path_7_s/data/monster/Arachnids/poison spider.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/scorpion.xml b/path_7_s/data/monster/Arachnids/scorpion.xml deleted file mode 100644 index 8f74aae3f..000000000 --- a/path_7_s/data/monster/Arachnids/scorpion.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/spider.xml b/path_7_s/data/monster/Arachnids/spider.xml deleted file mode 100644 index 3bd0faf05..000000000 --- a/path_7_s/data/monster/Arachnids/spider.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arachnids/tarantula.xml b/path_7_s/data/monster/Arachnids/tarantula.xml deleted file mode 100644 index 5f5a3c10c..000000000 --- a/path_7_s/data/monster/Arachnids/tarantula.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/achad.xml b/path_7_s/data/monster/Arena/greenhorn/achad.xml deleted file mode 100644 index e4e722b1e..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/achad.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/axeitus headbanger.xml b/path_7_s/data/monster/Arena/greenhorn/axeitus headbanger.xml deleted file mode 100644 index d77f18405..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/axeitus headbanger.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/bloodpaw.xml b/path_7_s/data/monster/Arena/greenhorn/bloodpaw.xml deleted file mode 100644 index b8b9fe98a..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/bloodpaw.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/bovinus.xml b/path_7_s/data/monster/Arena/greenhorn/bovinus.xml deleted file mode 100644 index 84f832d78..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/bovinus.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/colerian the barbarian.xml b/path_7_s/data/monster/Arena/greenhorn/colerian the barbarian.xml deleted file mode 100644 index 35e9462db..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/colerian the barbarian.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/cursed gladiator.xml b/path_7_s/data/monster/Arena/greenhorn/cursed gladiator.xml deleted file mode 100644 index a3230bae8..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/cursed gladiator.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/frostfur.xml b/path_7_s/data/monster/Arena/greenhorn/frostfur.xml deleted file mode 100644 index 570d82689..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/frostfur.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/orcus the cruel.xml b/path_7_s/data/monster/Arena/greenhorn/orcus the cruel.xml deleted file mode 100644 index 5ae4f278d..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/orcus the cruel.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/rocky.xml b/path_7_s/data/monster/Arena/greenhorn/rocky.xml deleted file mode 100644 index d0f33ebe0..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/rocky.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/greenhorn/the hairy one.xml b/path_7_s/data/monster/Arena/greenhorn/the hairy one.xml deleted file mode 100644 index b2b227f87..000000000 --- a/path_7_s/data/monster/Arena/greenhorn/the hairy one.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/avalanche.xml b/path_7_s/data/monster/Arena/scrapper/avalanche.xml deleted file mode 100644 index 632efc88e..000000000 --- a/path_7_s/data/monster/Arena/scrapper/avalanche.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/drasilla.xml b/path_7_s/data/monster/Arena/scrapper/drasilla.xml deleted file mode 100644 index 0597feec6..000000000 --- a/path_7_s/data/monster/Arena/scrapper/drasilla.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/grimgor guteater.xml b/path_7_s/data/monster/Arena/scrapper/grimgor guteater.xml deleted file mode 100644 index 44ab725ef..000000000 --- a/path_7_s/data/monster/Arena/scrapper/grimgor guteater.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/kreebosh the exile.xml b/path_7_s/data/monster/Arena/scrapper/kreebosh the exile.xml deleted file mode 100644 index 354033c29..000000000 --- a/path_7_s/data/monster/Arena/scrapper/kreebosh the exile.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/slim.xml b/path_7_s/data/monster/Arena/scrapper/slim.xml deleted file mode 100644 index 757e45d4a..000000000 --- a/path_7_s/data/monster/Arena/scrapper/slim.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/spirit of earth.xml b/path_7_s/data/monster/Arena/scrapper/spirit of earth.xml deleted file mode 100644 index 0e3b90359..000000000 --- a/path_7_s/data/monster/Arena/scrapper/spirit of earth.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/spirit of fire.xml b/path_7_s/data/monster/Arena/scrapper/spirit of fire.xml deleted file mode 100644 index 2fa56ed7a..000000000 --- a/path_7_s/data/monster/Arena/scrapper/spirit of fire.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/spirit of water.xml b/path_7_s/data/monster/Arena/scrapper/spirit of water.xml deleted file mode 100644 index ea45271cb..000000000 --- a/path_7_s/data/monster/Arena/scrapper/spirit of water.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/the dark dancer.xml b/path_7_s/data/monster/Arena/scrapper/the dark dancer.xml deleted file mode 100644 index 56f55b449..000000000 --- a/path_7_s/data/monster/Arena/scrapper/the dark dancer.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/scrapper/the hag.xml b/path_7_s/data/monster/Arena/scrapper/the hag.xml deleted file mode 100644 index 0893946bd..000000000 --- a/path_7_s/data/monster/Arena/scrapper/the hag.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/darakan the executioner.xml b/path_7_s/data/monster/Arena/warlord/darakan the executioner.xml deleted file mode 100644 index 289db40e4..000000000 --- a/path_7_s/data/monster/Arena/warlord/darakan the executioner.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/deathbringer.xml b/path_7_s/data/monster/Arena/warlord/deathbringer.xml deleted file mode 100644 index 843622990..000000000 --- a/path_7_s/data/monster/Arena/warlord/deathbringer.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml b/path_7_s/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml deleted file mode 100644 index e22f6f3ec..000000000 --- a/path_7_s/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/gnorre chyllson.xml b/path_7_s/data/monster/Arena/warlord/gnorre chyllson.xml deleted file mode 100644 index 0f48e5165..000000000 --- a/path_7_s/data/monster/Arena/warlord/gnorre chyllson.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/norgle glacierbeard.xml b/path_7_s/data/monster/Arena/warlord/norgle glacierbeard.xml deleted file mode 100644 index a3fbd82bd..000000000 --- a/path_7_s/data/monster/Arena/warlord/norgle glacierbeard.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/svoren the mad.xml b/path_7_s/data/monster/Arena/warlord/svoren the mad.xml deleted file mode 100644 index 7dc8b7b3b..000000000 --- a/path_7_s/data/monster/Arena/warlord/svoren the mad.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/the masked marauder.xml b/path_7_s/data/monster/Arena/warlord/the masked marauder.xml deleted file mode 100644 index dfbe0f8a0..000000000 --- a/path_7_s/data/monster/Arena/warlord/the masked marauder.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/the obliverator.xml b/path_7_s/data/monster/Arena/warlord/the obliverator.xml deleted file mode 100644 index d41561c45..000000000 --- a/path_7_s/data/monster/Arena/warlord/the obliverator.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/the pit lord.xml b/path_7_s/data/monster/Arena/warlord/the pit lord.xml deleted file mode 100644 index 0ecb6d5d5..000000000 --- a/path_7_s/data/monster/Arena/warlord/the pit lord.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Arena/warlord/webster.xml b/path_7_s/data/monster/Arena/warlord/webster.xml deleted file mode 100644 index 7b5c07443..000000000 --- a/path_7_s/data/monster/Arena/warlord/webster.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Barbarians/barbarian bloodwalker.xml b/path_7_s/data/monster/Barbarians/barbarian bloodwalker.xml deleted file mode 100644 index 38fe831de..000000000 --- a/path_7_s/data/monster/Barbarians/barbarian bloodwalker.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Barbarians/barbarian brutetamer.xml b/path_7_s/data/monster/Barbarians/barbarian brutetamer.xml deleted file mode 100644 index 6d556cc40..000000000 --- a/path_7_s/data/monster/Barbarians/barbarian brutetamer.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Barbarians/barbarian headsplitter.xml b/path_7_s/data/monster/Barbarians/barbarian headsplitter.xml deleted file mode 100644 index 176abc9d6..000000000 --- a/path_7_s/data/monster/Barbarians/barbarian headsplitter.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Barbarians/barbarian skullhunter.xml b/path_7_s/data/monster/Barbarians/barbarian skullhunter.xml deleted file mode 100644 index efa9e6f6e..000000000 --- a/path_7_s/data/monster/Barbarians/barbarian skullhunter.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bears/bear.xml b/path_7_s/data/monster/Bears/bear.xml deleted file mode 100644 index e07bfaa17..000000000 --- a/path_7_s/data/monster/Bears/bear.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bears/panda.xml b/path_7_s/data/monster/Bears/panda.xml deleted file mode 100644 index d7a9f0637..000000000 --- a/path_7_s/data/monster/Bears/panda.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bears/polar bear.xml b/path_7_s/data/monster/Bears/polar bear.xml deleted file mode 100644 index aaa41711f..000000000 --- a/path_7_s/data/monster/Bears/polar bear.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bio-Elementals/carniphila.xml b/path_7_s/data/monster/Bio-Elementals/carniphila.xml deleted file mode 100644 index 726db41b6..000000000 --- a/path_7_s/data/monster/Bio-Elementals/carniphila.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bio-Elementals/defiler.xml b/path_7_s/data/monster/Bio-Elementals/defiler.xml deleted file mode 100644 index f79b2f940..000000000 --- a/path_7_s/data/monster/Bio-Elementals/defiler.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bio-Elementals/slime.xml b/path_7_s/data/monster/Bio-Elementals/slime.xml deleted file mode 100644 index 4267d221c..000000000 --- a/path_7_s/data/monster/Bio-Elementals/slime.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bio-Elementals/son of verminor.xml b/path_7_s/data/monster/Bio-Elementals/son of verminor.xml deleted file mode 100644 index 4f03ba841..000000000 --- a/path_7_s/data/monster/Bio-Elementals/son of verminor.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bio-Elementals/spit nettle.xml b/path_7_s/data/monster/Bio-Elementals/spit nettle.xml deleted file mode 100644 index e55d0584a..000000000 --- a/path_7_s/data/monster/Bio-Elementals/spit nettle.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/chicken.xml b/path_7_s/data/monster/Birds/chicken.xml deleted file mode 100644 index 527c7e1b2..000000000 --- a/path_7_s/data/monster/Birds/chicken.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/flamingo.xml b/path_7_s/data/monster/Birds/flamingo.xml deleted file mode 100644 index 27e1ba97c..000000000 --- a/path_7_s/data/monster/Birds/flamingo.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/parrot.xml b/path_7_s/data/monster/Birds/parrot.xml deleted file mode 100644 index 446d6b47d..000000000 --- a/path_7_s/data/monster/Birds/parrot.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/penguin.xml b/path_7_s/data/monster/Birds/penguin.xml deleted file mode 100644 index 82e7d4b48..000000000 --- a/path_7_s/data/monster/Birds/penguin.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/seagull.xml b/path_7_s/data/monster/Birds/seagull.xml deleted file mode 100644 index 6ac3624f8..000000000 --- a/path_7_s/data/monster/Birds/seagull.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Birds/terror bird.xml b/path_7_s/data/monster/Birds/terror bird.xml deleted file mode 100644 index 28353a3a7..000000000 --- a/path_7_s/data/monster/Birds/terror bird.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bonelords/beholder.xml b/path_7_s/data/monster/Bonelords/beholder.xml deleted file mode 100644 index 24e6deee9..000000000 --- a/path_7_s/data/monster/Bonelords/beholder.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bonelords/braindeath.xml b/path_7_s/data/monster/Bonelords/braindeath.xml deleted file mode 100644 index a2f8bd9ad..000000000 --- a/path_7_s/data/monster/Bonelords/braindeath.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bonelords/elder beholder.xml b/path_7_s/data/monster/Bonelords/elder beholder.xml deleted file mode 100644 index 53768ce4f..000000000 --- a/path_7_s/data/monster/Bonelords/elder beholder.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bonelords/eye of the seven.xml b/path_7_s/data/monster/Bonelords/eye of the seven.xml deleted file mode 100644 index 44e24ca79..000000000 --- a/path_7_s/data/monster/Bonelords/eye of the seven.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bonelords/gazer.xml b/path_7_s/data/monster/Bonelords/gazer.xml deleted file mode 100644 index 430e26091..000000000 --- a/path_7_s/data/monster/Bonelords/gazer.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/annihilon.xml b/path_7_s/data/monster/Bosses/annihilon.xml deleted file mode 100644 index 1aa9ed4ca..000000000 --- a/path_7_s/data/monster/Bosses/annihilon.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/apprentice sheng.xml b/path_7_s/data/monster/Bosses/apprentice sheng.xml deleted file mode 100644 index 06db7e042..000000000 --- a/path_7_s/data/monster/Bosses/apprentice sheng.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/barbaria.xml b/path_7_s/data/monster/Bosses/barbaria.xml deleted file mode 100644 index 1505de6c1..000000000 --- a/path_7_s/data/monster/Bosses/barbaria.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/bones.xml b/path_7_s/data/monster/Bosses/bones.xml deleted file mode 100644 index f7401c9c5..000000000 --- a/path_7_s/data/monster/Bosses/bones.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/brutus bloodbeard.xml b/path_7_s/data/monster/Bosses/brutus bloodbeard.xml deleted file mode 100644 index 387ff18ac..000000000 --- a/path_7_s/data/monster/Bosses/brutus bloodbeard.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/countess sorrow.xml b/path_7_s/data/monster/Bosses/countess sorrow.xml deleted file mode 100644 index 3e67e1513..000000000 --- a/path_7_s/data/monster/Bosses/countess sorrow.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/deadeye devious.xml b/path_7_s/data/monster/Bosses/deadeye devious.xml deleted file mode 100644 index a550a0f85..000000000 --- a/path_7_s/data/monster/Bosses/deadeye devious.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/demodras.xml b/path_7_s/data/monster/Bosses/demodras.xml deleted file mode 100644 index 839d64565..000000000 --- a/path_7_s/data/monster/Bosses/demodras.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/dharalion.xml b/path_7_s/data/monster/Bosses/dharalion.xml deleted file mode 100644 index 83850d8a0..000000000 --- a/path_7_s/data/monster/Bosses/dharalion.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/dire penguin.xml b/path_7_s/data/monster/Bosses/dire penguin.xml deleted file mode 100644 index 42887ee23..000000000 --- a/path_7_s/data/monster/Bosses/dire penguin.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/dracola.xml b/path_7_s/data/monster/Bosses/dracola.xml deleted file mode 100644 index b7bddf66d..000000000 --- a/path_7_s/data/monster/Bosses/dracola.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/fernfang.xml b/path_7_s/data/monster/Bosses/fernfang.xml deleted file mode 100644 index 0f9f9d904..000000000 --- a/path_7_s/data/monster/Bosses/fernfang.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/ferumbras.xml b/path_7_s/data/monster/Bosses/ferumbras.xml deleted file mode 100644 index 402b0cf18..000000000 --- a/path_7_s/data/monster/Bosses/ferumbras.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/fluffy.xml b/path_7_s/data/monster/Bosses/fluffy.xml deleted file mode 100644 index ef1c3d23a..000000000 --- a/path_7_s/data/monster/Bosses/fluffy.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/foreman kneebiter.xml b/path_7_s/data/monster/Bosses/foreman kneebiter.xml deleted file mode 100644 index 4f74bdd40..000000000 --- a/path_7_s/data/monster/Bosses/foreman kneebiter.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/general murius.xml b/path_7_s/data/monster/Bosses/general murius.xml deleted file mode 100644 index b3fd507b8..000000000 --- a/path_7_s/data/monster/Bosses/general murius.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/ghazbaran.xml b/path_7_s/data/monster/Bosses/ghazbaran.xml deleted file mode 100644 index 81a367e8d..000000000 --- a/path_7_s/data/monster/Bosses/ghazbaran.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/golgordan.xml b/path_7_s/data/monster/Bosses/golgordan.xml deleted file mode 100644 index 6c485946d..000000000 --- a/path_7_s/data/monster/Bosses/golgordan.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/grorlam.xml b/path_7_s/data/monster/Bosses/grorlam.xml deleted file mode 100644 index 0c53f7c7f..000000000 --- a/path_7_s/data/monster/Bosses/grorlam.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/hairman the huge.xml b/path_7_s/data/monster/Bosses/hairman the huge.xml deleted file mode 100644 index bd25ebc64..000000000 --- a/path_7_s/data/monster/Bosses/hairman the huge.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/handmaiden.xml b/path_7_s/data/monster/Bosses/handmaiden.xml deleted file mode 100644 index 5ebd42598..000000000 --- a/path_7_s/data/monster/Bosses/handmaiden.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/hellgorak.xml b/path_7_s/data/monster/Bosses/hellgorak.xml deleted file mode 100644 index eabafede5..000000000 --- a/path_7_s/data/monster/Bosses/hellgorak.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/koshei the deathless.xml b/path_7_s/data/monster/Bosses/koshei the deathless.xml deleted file mode 100644 index bed77fdf9..000000000 --- a/path_7_s/data/monster/Bosses/koshei the deathless.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/latrivan.xml b/path_7_s/data/monster/Bosses/latrivan.xml deleted file mode 100644 index 953eaa744..000000000 --- a/path_7_s/data/monster/Bosses/latrivan.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/lethal lissy.xml b/path_7_s/data/monster/Bosses/lethal lissy.xml deleted file mode 100644 index c176579b8..000000000 --- a/path_7_s/data/monster/Bosses/lethal lissy.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/mad technomancer.xml b/path_7_s/data/monster/Bosses/mad technomancer.xml deleted file mode 100644 index f97163ec8..000000000 --- a/path_7_s/data/monster/Bosses/mad technomancer.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/madareth.xml b/path_7_s/data/monster/Bosses/madareth.xml deleted file mode 100644 index 8296fee60..000000000 --- a/path_7_s/data/monster/Bosses/madareth.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/man in the cave.xml b/path_7_s/data/monster/Bosses/man in the cave.xml deleted file mode 100644 index bb59b88fe..000000000 --- a/path_7_s/data/monster/Bosses/man in the cave.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/massacre.xml b/path_7_s/data/monster/Bosses/massacre.xml deleted file mode 100644 index eee4188b8..000000000 --- a/path_7_s/data/monster/Bosses/massacre.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/minishabaal.xml b/path_7_s/data/monster/Bosses/minishabaal.xml deleted file mode 100644 index fa6917683..000000000 --- a/path_7_s/data/monster/Bosses/minishabaal.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/morgaroth.xml b/path_7_s/data/monster/Bosses/morgaroth.xml deleted file mode 100644 index 759b6c2cb..000000000 --- a/path_7_s/data/monster/Bosses/morgaroth.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/mr. punish.xml b/path_7_s/data/monster/Bosses/mr. punish.xml deleted file mode 100644 index 3dc5c5e8e..000000000 --- a/path_7_s/data/monster/Bosses/mr. punish.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/munster.xml b/path_7_s/data/monster/Bosses/munster.xml deleted file mode 100644 index 0f2755869..000000000 --- a/path_7_s/data/monster/Bosses/munster.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/necropharus.xml b/path_7_s/data/monster/Bosses/necropharus.xml deleted file mode 100644 index 97fce3af6..000000000 --- a/path_7_s/data/monster/Bosses/necropharus.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/orshabaal.xml b/path_7_s/data/monster/Bosses/orshabaal.xml deleted file mode 100644 index 93255a541..000000000 --- a/path_7_s/data/monster/Bosses/orshabaal.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/ron the ripper.xml b/path_7_s/data/monster/Bosses/ron the ripper.xml deleted file mode 100644 index 4a3a50d35..000000000 --- a/path_7_s/data/monster/Bosses/ron the ripper.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the abomination.xml b/path_7_s/data/monster/Bosses/the abomination.xml deleted file mode 100644 index f6a99b018..000000000 --- a/path_7_s/data/monster/Bosses/the abomination.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the evil eye.xml b/path_7_s/data/monster/Bosses/the evil eye.xml deleted file mode 100644 index b2305017c..000000000 --- a/path_7_s/data/monster/Bosses/the evil eye.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the handmaiden.xml b/path_7_s/data/monster/Bosses/the handmaiden.xml deleted file mode 100644 index 1cd2e7118..000000000 --- a/path_7_s/data/monster/Bosses/the handmaiden.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the horned fox.xml b/path_7_s/data/monster/Bosses/the horned fox.xml deleted file mode 100644 index f5ad9f314..000000000 --- a/path_7_s/data/monster/Bosses/the horned fox.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the imperor.xml b/path_7_s/data/monster/Bosses/the imperor.xml deleted file mode 100644 index 0af978dfd..000000000 --- a/path_7_s/data/monster/Bosses/the imperor.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the old widow.xml b/path_7_s/data/monster/Bosses/the old widow.xml deleted file mode 100644 index 5900fd4a0..000000000 --- a/path_7_s/data/monster/Bosses/the old widow.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/the plasmother.xml b/path_7_s/data/monster/Bosses/the plasmother.xml deleted file mode 100644 index 39da9d0d9..000000000 --- a/path_7_s/data/monster/Bosses/the plasmother.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/thul.xml b/path_7_s/data/monster/Bosses/thul.xml deleted file mode 100644 index acc7ff2b9..000000000 --- a/path_7_s/data/monster/Bosses/thul.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/tibia bug.xml b/path_7_s/data/monster/Bosses/tibia bug.xml deleted file mode 100644 index e9f178905..000000000 --- a/path_7_s/data/monster/Bosses/tibia bug.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/tiquandas revenge.xml b/path_7_s/data/monster/Bosses/tiquandas revenge.xml deleted file mode 100644 index cd5402461..000000000 --- a/path_7_s/data/monster/Bosses/tiquandas revenge.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/undead minion.xml b/path_7_s/data/monster/Bosses/undead minion.xml deleted file mode 100644 index 910cc10d8..000000000 --- a/path_7_s/data/monster/Bosses/undead minion.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/ungreez.xml b/path_7_s/data/monster/Bosses/ungreez.xml deleted file mode 100644 index cd8959c2a..000000000 --- a/path_7_s/data/monster/Bosses/ungreez.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/ushuriel.xml b/path_7_s/data/monster/Bosses/ushuriel.xml deleted file mode 100644 index bf5c87d81..000000000 --- a/path_7_s/data/monster/Bosses/ushuriel.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/xenia.xml b/path_7_s/data/monster/Bosses/xenia.xml deleted file mode 100644 index 184a4a11c..000000000 --- a/path_7_s/data/monster/Bosses/xenia.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Bosses/zugurosh.xml b/path_7_s/data/monster/Bosses/zugurosh.xml deleted file mode 100644 index 1605a313e..000000000 --- a/path_7_s/data/monster/Bosses/zugurosh.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/dog.xml b/path_7_s/data/monster/Canines/dog.xml deleted file mode 100644 index 01aeee631..000000000 --- a/path_7_s/data/monster/Canines/dog.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/hellhound.xml b/path_7_s/data/monster/Canines/hellhound.xml deleted file mode 100644 index e37291b29..000000000 --- a/path_7_s/data/monster/Canines/hellhound.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/husky.xml b/path_7_s/data/monster/Canines/husky.xml deleted file mode 100644 index 04d71532e..000000000 --- a/path_7_s/data/monster/Canines/husky.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/war wolf.xml b/path_7_s/data/monster/Canines/war wolf.xml deleted file mode 100644 index c6f944fab..000000000 --- a/path_7_s/data/monster/Canines/war wolf.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/winter wolf.xml b/path_7_s/data/monster/Canines/winter wolf.xml deleted file mode 100644 index 115d77ad1..000000000 --- a/path_7_s/data/monster/Canines/winter wolf.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Canines/wolf.xml b/path_7_s/data/monster/Canines/wolf.xml deleted file mode 100644 index 757de4588..000000000 --- a/path_7_s/data/monster/Canines/wolf.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Chakoyas/chakoya toolshaper.xml b/path_7_s/data/monster/Chakoyas/chakoya toolshaper.xml deleted file mode 100644 index 9f7e1b42c..000000000 --- a/path_7_s/data/monster/Chakoyas/chakoya toolshaper.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Chakoyas/chakoya tribewarden.xml b/path_7_s/data/monster/Chakoyas/chakoya tribewarden.xml deleted file mode 100644 index 5f9321947..000000000 --- a/path_7_s/data/monster/Chakoyas/chakoya tribewarden.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Chakoyas/chakoya windcaller.xml b/path_7_s/data/monster/Chakoyas/chakoya windcaller.xml deleted file mode 100644 index cc51c8928..000000000 --- a/path_7_s/data/monster/Chakoyas/chakoya windcaller.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Crustaceans/blood crab.xml b/path_7_s/data/monster/Crustaceans/blood crab.xml deleted file mode 100644 index 10d162785..000000000 --- a/path_7_s/data/monster/Crustaceans/blood crab.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Crustaceans/crab.xml b/path_7_s/data/monster/Crustaceans/crab.xml deleted file mode 100644 index 5403d1636..000000000 --- a/path_7_s/data/monster/Crustaceans/crab.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Cryo-Elementals/ice golem.xml b/path_7_s/data/monster/Cryo-Elementals/ice golem.xml deleted file mode 100644 index 0962c095c..000000000 --- a/path_7_s/data/monster/Cryo-Elementals/ice golem.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/dark torturer.xml b/path_7_s/data/monster/Demons/dark torturer.xml deleted file mode 100644 index 0f582c466..000000000 --- a/path_7_s/data/monster/Demons/dark torturer.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/demon (dcq).xml b/path_7_s/data/monster/Demons/demon (dcq).xml deleted file mode 100644 index bbd092cd0..000000000 --- a/path_7_s/data/monster/Demons/demon (dcq).xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/demon.xml b/path_7_s/data/monster/Demons/demon.xml deleted file mode 100644 index af718370c..000000000 --- a/path_7_s/data/monster/Demons/demon.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/destroyer.xml b/path_7_s/data/monster/Demons/destroyer.xml deleted file mode 100644 index 0b5bf1083..000000000 --- a/path_7_s/data/monster/Demons/destroyer.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/diabolic imp.xml b/path_7_s/data/monster/Demons/diabolic imp.xml deleted file mode 100644 index 1a96ea904..000000000 --- a/path_7_s/data/monster/Demons/diabolic imp.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/fire devil.xml b/path_7_s/data/monster/Demons/fire devil.xml deleted file mode 100644 index d100e1f91..000000000 --- a/path_7_s/data/monster/Demons/fire devil.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/fury.xml b/path_7_s/data/monster/Demons/fury.xml deleted file mode 100644 index d31ee4413..000000000 --- a/path_7_s/data/monster/Demons/fury.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/hand of cursed fate.xml b/path_7_s/data/monster/Demons/hand of cursed fate.xml deleted file mode 100644 index 4714dad9d..000000000 --- a/path_7_s/data/monster/Demons/hand of cursed fate.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/juggernaut.xml b/path_7_s/data/monster/Demons/juggernaut.xml deleted file mode 100644 index 2a7869622..000000000 --- a/path_7_s/data/monster/Demons/juggernaut.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/nightmare.xml b/path_7_s/data/monster/Demons/nightmare.xml deleted file mode 100644 index 80388860a..000000000 --- a/path_7_s/data/monster/Demons/nightmare.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Demons/plaguesmith.xml b/path_7_s/data/monster/Demons/plaguesmith.xml deleted file mode 100644 index e645c6e66..000000000 --- a/path_7_s/data/monster/Demons/plaguesmith.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Djinns/blue djinn.xml b/path_7_s/data/monster/Djinns/blue djinn.xml deleted file mode 100644 index a9cbbb51d..000000000 --- a/path_7_s/data/monster/Djinns/blue djinn.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Djinns/efreet.xml b/path_7_s/data/monster/Djinns/efreet.xml deleted file mode 100644 index 5238a43b2..000000000 --- a/path_7_s/data/monster/Djinns/efreet.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Djinns/green djinn.xml b/path_7_s/data/monster/Djinns/green djinn.xml deleted file mode 100644 index 20e7b6cff..000000000 --- a/path_7_s/data/monster/Djinns/green djinn.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Djinns/marid.xml b/path_7_s/data/monster/Djinns/marid.xml deleted file mode 100644 index b3efa30cf..000000000 --- a/path_7_s/data/monster/Djinns/marid.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dragons/dragon lord.xml b/path_7_s/data/monster/Dragons/dragon lord.xml deleted file mode 100644 index c2ee427a1..000000000 --- a/path_7_s/data/monster/Dragons/dragon lord.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dragons/dragon.xml b/path_7_s/data/monster/Dragons/dragon.xml deleted file mode 100644 index a1e28f685..000000000 --- a/path_7_s/data/monster/Dragons/dragon.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dragons/frost dragon.xml b/path_7_s/data/monster/Dragons/frost dragon.xml deleted file mode 100644 index d100c2420..000000000 --- a/path_7_s/data/monster/Dragons/frost dragon.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dragons/undead dragon.xml b/path_7_s/data/monster/Dragons/undead dragon.xml deleted file mode 100644 index 1bc920ca1..000000000 --- a/path_7_s/data/monster/Dragons/undead dragon.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dwarves/dwarf geomancer.xml b/path_7_s/data/monster/Dwarves/dwarf geomancer.xml deleted file mode 100644 index 0b75f1778..000000000 --- a/path_7_s/data/monster/Dwarves/dwarf geomancer.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dwarves/dwarf guard.xml b/path_7_s/data/monster/Dwarves/dwarf guard.xml deleted file mode 100644 index 09a64a240..000000000 --- a/path_7_s/data/monster/Dwarves/dwarf guard.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dwarves/dwarf soldier.xml b/path_7_s/data/monster/Dwarves/dwarf soldier.xml deleted file mode 100644 index 99cc9a6ee..000000000 --- a/path_7_s/data/monster/Dwarves/dwarf soldier.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dwarves/dwarf.xml b/path_7_s/data/monster/Dwarves/dwarf.xml deleted file mode 100644 index 877fbafec..000000000 --- a/path_7_s/data/monster/Dwarves/dwarf.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dworcs/dworc fleshhunter.xml b/path_7_s/data/monster/Dworcs/dworc fleshhunter.xml deleted file mode 100644 index f0ba931c1..000000000 --- a/path_7_s/data/monster/Dworcs/dworc fleshhunter.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dworcs/dworc venomsniper.xml b/path_7_s/data/monster/Dworcs/dworc venomsniper.xml deleted file mode 100644 index 3c746df7a..000000000 --- a/path_7_s/data/monster/Dworcs/dworc venomsniper.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Dworcs/dworc voodoomaster.xml b/path_7_s/data/monster/Dworcs/dworc voodoomaster.xml deleted file mode 100644 index 32f8145d9..000000000 --- a/path_7_s/data/monster/Dworcs/dworc voodoomaster.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Elves/elf arcanist.xml b/path_7_s/data/monster/Elves/elf arcanist.xml deleted file mode 100644 index 5952a8efe..000000000 --- a/path_7_s/data/monster/Elves/elf arcanist.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Elves/elf scout.xml b/path_7_s/data/monster/Elves/elf scout.xml deleted file mode 100644 index f5f86962c..000000000 --- a/path_7_s/data/monster/Elves/elf scout.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Elves/elf.xml b/path_7_s/data/monster/Elves/elf.xml deleted file mode 100644 index bf6774cba..000000000 --- a/path_7_s/data/monster/Elves/elf.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Felines/lion.xml b/path_7_s/data/monster/Felines/lion.xml deleted file mode 100644 index c0071f15d..000000000 --- a/path_7_s/data/monster/Felines/lion.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Felines/tiger.xml b/path_7_s/data/monster/Felines/tiger.xml deleted file mode 100644 index c9ff06a63..000000000 --- a/path_7_s/data/monster/Felines/tiger.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/azure frog.xml b/path_7_s/data/monster/Frogs/azure frog.xml deleted file mode 100644 index 1649336bd..000000000 --- a/path_7_s/data/monster/Frogs/azure frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/coral frog.xml b/path_7_s/data/monster/Frogs/coral frog.xml deleted file mode 100644 index eb8e8715d..000000000 --- a/path_7_s/data/monster/Frogs/coral frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/crimson frog.xml b/path_7_s/data/monster/Frogs/crimson frog.xml deleted file mode 100644 index f57f2bf45..000000000 --- a/path_7_s/data/monster/Frogs/crimson frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/green frog.xml b/path_7_s/data/monster/Frogs/green frog.xml deleted file mode 100644 index d73285982..000000000 --- a/path_7_s/data/monster/Frogs/green frog.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/orchid frog.xml b/path_7_s/data/monster/Frogs/orchid frog.xml deleted file mode 100644 index d4cbde37f..000000000 --- a/path_7_s/data/monster/Frogs/orchid frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Frogs/toad.xml b/path_7_s/data/monster/Frogs/toad.xml deleted file mode 100644 index a636024c9..000000000 --- a/path_7_s/data/monster/Frogs/toad.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Geo-Elementals/gargoyle.xml b/path_7_s/data/monster/Geo-Elementals/gargoyle.xml deleted file mode 100644 index 84ce7dc92..000000000 --- a/path_7_s/data/monster/Geo-Elementals/gargoyle.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Geo-Elementals/stone golem.xml b/path_7_s/data/monster/Geo-Elementals/stone golem.xml deleted file mode 100644 index 3d6d9093e..000000000 --- a/path_7_s/data/monster/Geo-Elementals/stone golem.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ghosts/ghost.xml b/path_7_s/data/monster/Ghosts/ghost.xml deleted file mode 100644 index 9ab423dc4..000000000 --- a/path_7_s/data/monster/Ghosts/ghost.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ghosts/phantasm summon.xml b/path_7_s/data/monster/Ghosts/phantasm summon.xml deleted file mode 100644 index e471f7de1..000000000 --- a/path_7_s/data/monster/Ghosts/phantasm summon.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ghosts/phantasm.xml b/path_7_s/data/monster/Ghosts/phantasm.xml deleted file mode 100644 index a2c293b0b..000000000 --- a/path_7_s/data/monster/Ghosts/phantasm.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ghosts/spectre.xml b/path_7_s/data/monster/Ghosts/spectre.xml deleted file mode 100644 index 75bfa1631..000000000 --- a/path_7_s/data/monster/Ghosts/spectre.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Giants/behemoth.xml b/path_7_s/data/monster/Giants/behemoth.xml deleted file mode 100644 index 039ff41b0..000000000 --- a/path_7_s/data/monster/Giants/behemoth.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Giants/cyclops.xml b/path_7_s/data/monster/Giants/cyclops.xml deleted file mode 100644 index dabfb5266..000000000 --- a/path_7_s/data/monster/Giants/cyclops.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Giants/frost giant.xml b/path_7_s/data/monster/Giants/frost giant.xml deleted file mode 100644 index 9f95dbe2e..000000000 --- a/path_7_s/data/monster/Giants/frost giant.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Giants/frost giantess.xml b/path_7_s/data/monster/Giants/frost giantess.xml deleted file mode 100644 index dec2fc7ab..000000000 --- a/path_7_s/data/monster/Giants/frost giantess.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Glires/cave rat.xml b/path_7_s/data/monster/Glires/cave rat.xml deleted file mode 100644 index c0963db4f..000000000 --- a/path_7_s/data/monster/Glires/cave rat.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Glires/rabbit.xml b/path_7_s/data/monster/Glires/rabbit.xml deleted file mode 100644 index af8ad673f..000000000 --- a/path_7_s/data/monster/Glires/rabbit.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Glires/rat.xml b/path_7_s/data/monster/Glires/rat.xml deleted file mode 100644 index 174750406..000000000 --- a/path_7_s/data/monster/Glires/rat.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Glires/silver rabbit.xml b/path_7_s/data/monster/Glires/silver rabbit.xml deleted file mode 100644 index 75f99a821..000000000 --- a/path_7_s/data/monster/Glires/silver rabbit.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Goblins/demon (goblin).xml b/path_7_s/data/monster/Goblins/demon (goblin).xml deleted file mode 100644 index 10205c559..000000000 --- a/path_7_s/data/monster/Goblins/demon (goblin).xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Goblins/goblin.xml b/path_7_s/data/monster/Goblins/goblin.xml deleted file mode 100644 index 2f0f7c45d..000000000 --- a/path_7_s/data/monster/Goblins/goblin.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/ancient scarab.xml b/path_7_s/data/monster/Insects/ancient scarab.xml deleted file mode 100644 index 797c8dacd..000000000 --- a/path_7_s/data/monster/Insects/ancient scarab.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/blue butterfly.xml b/path_7_s/data/monster/Insects/blue butterfly.xml deleted file mode 100644 index 5c4e0205d..000000000 --- a/path_7_s/data/monster/Insects/blue butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/bug.xml b/path_7_s/data/monster/Insects/bug.xml deleted file mode 100644 index 2cde49f13..000000000 --- a/path_7_s/data/monster/Insects/bug.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/butterfly.xml b/path_7_s/data/monster/Insects/butterfly.xml deleted file mode 100644 index 26582b97b..000000000 --- a/path_7_s/data/monster/Insects/butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/larva.xml b/path_7_s/data/monster/Insects/larva.xml deleted file mode 100644 index 521d0ceb4..000000000 --- a/path_7_s/data/monster/Insects/larva.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/pink butterfly.xml b/path_7_s/data/monster/Insects/pink butterfly.xml deleted file mode 100644 index 4dc00c20a..000000000 --- a/path_7_s/data/monster/Insects/pink butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/purple butterfly.xml b/path_7_s/data/monster/Insects/purple butterfly.xml deleted file mode 100644 index e3c81b3bf..000000000 --- a/path_7_s/data/monster/Insects/purple butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/red butterfly.xml b/path_7_s/data/monster/Insects/red butterfly.xml deleted file mode 100644 index 0ff74de94..000000000 --- a/path_7_s/data/monster/Insects/red butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/scarab.xml b/path_7_s/data/monster/Insects/scarab.xml deleted file mode 100644 index cd2d3db34..000000000 --- a/path_7_s/data/monster/Insects/scarab.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/wasp.xml b/path_7_s/data/monster/Insects/wasp.xml deleted file mode 100644 index 967d2755a..000000000 --- a/path_7_s/data/monster/Insects/wasp.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Insects/yellow butterfly.xml b/path_7_s/data/monster/Insects/yellow butterfly.xml deleted file mode 100644 index 1b38da032..000000000 --- a/path_7_s/data/monster/Insects/yellow butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Lizards/lizard noble.xml b/path_7_s/data/monster/Lizards/lizard noble.xml deleted file mode 100644 index 22fd37a77..000000000 --- a/path_7_s/data/monster/Lizards/lizard noble.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Lizards/lizard sentinel.xml b/path_7_s/data/monster/Lizards/lizard sentinel.xml deleted file mode 100644 index 2be80bb33..000000000 --- a/path_7_s/data/monster/Lizards/lizard sentinel.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Lizards/lizard snakecharmer.xml b/path_7_s/data/monster/Lizards/lizard snakecharmer.xml deleted file mode 100644 index 583efa593..000000000 --- a/path_7_s/data/monster/Lizards/lizard snakecharmer.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Lizards/lizard templar.xml b/path_7_s/data/monster/Lizards/lizard templar.xml deleted file mode 100644 index 93a1075db..000000000 --- a/path_7_s/data/monster/Lizards/lizard templar.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Lizards/wyvern.xml b/path_7_s/data/monster/Lizards/wyvern.xml deleted file mode 100644 index b74579f39..000000000 --- a/path_7_s/data/monster/Lizards/wyvern.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Minotaurs/minotaur archer.xml b/path_7_s/data/monster/Minotaurs/minotaur archer.xml deleted file mode 100644 index 5080e2987..000000000 --- a/path_7_s/data/monster/Minotaurs/minotaur archer.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Minotaurs/minotaur guard.xml b/path_7_s/data/monster/Minotaurs/minotaur guard.xml deleted file mode 100644 index d0b283bf7..000000000 --- a/path_7_s/data/monster/Minotaurs/minotaur guard.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Minotaurs/minotaur mage.xml b/path_7_s/data/monster/Minotaurs/minotaur mage.xml deleted file mode 100644 index 46fbeef15..000000000 --- a/path_7_s/data/monster/Minotaurs/minotaur mage.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Minotaurs/minotaur.xml b/path_7_s/data/monster/Minotaurs/minotaur.xml deleted file mode 100644 index a7e8d34f7..000000000 --- a/path_7_s/data/monster/Minotaurs/minotaur.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Mammals/badger.xml b/path_7_s/data/monster/Misc/Misc Mammals/badger.xml deleted file mode 100644 index 2ad3a8f67..000000000 --- a/path_7_s/data/monster/Misc/Misc Mammals/badger.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Mammals/bat.xml b/path_7_s/data/monster/Misc/Misc Mammals/bat.xml deleted file mode 100644 index 855d0c09c..000000000 --- a/path_7_s/data/monster/Misc/Misc Mammals/bat.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Mammals/hyaena.xml b/path_7_s/data/monster/Misc/Misc Mammals/hyaena.xml deleted file mode 100644 index e5131f099..000000000 --- a/path_7_s/data/monster/Misc/Misc Mammals/hyaena.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Mammals/skunk.xml b/path_7_s/data/monster/Misc/Misc Mammals/skunk.xml deleted file mode 100644 index 19125c596..000000000 --- a/path_7_s/data/monster/Misc/Misc Mammals/skunk.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Reptiles/crocodile.xml b/path_7_s/data/monster/Misc/Misc Reptiles/crocodile.xml deleted file mode 100644 index 3c84a4a4c..000000000 --- a/path_7_s/data/monster/Misc/Misc Reptiles/crocodile.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Reptiles/hydra.xml b/path_7_s/data/monster/Misc/Misc Reptiles/hydra.xml deleted file mode 100644 index fde9a0f54..000000000 --- a/path_7_s/data/monster/Misc/Misc Reptiles/hydra.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Reptiles/thornback tortoise.xml b/path_7_s/data/monster/Misc/Misc Reptiles/thornback tortoise.xml deleted file mode 100644 index 0a9ec4f2a..000000000 --- a/path_7_s/data/monster/Misc/Misc Reptiles/thornback tortoise.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Misc/Misc Reptiles/tortoise.xml b/path_7_s/data/monster/Misc/Misc Reptiles/tortoise.xml deleted file mode 100644 index 269dd63d0..000000000 --- a/path_7_s/data/monster/Misc/Misc Reptiles/tortoise.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Monks/dark monk.xml b/path_7_s/data/monster/Monks/dark monk.xml deleted file mode 100644 index ea9c9e051..000000000 --- a/path_7_s/data/monster/Monks/dark monk.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Monks/monk.xml b/path_7_s/data/monster/Monks/monk.xml deleted file mode 100644 index cdd846e2e..000000000 --- a/path_7_s/data/monster/Monks/monk.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Myriapods/centipede.xml b/path_7_s/data/monster/Myriapods/centipede.xml deleted file mode 100644 index 726ab1b5b..000000000 --- a/path_7_s/data/monster/Myriapods/centipede.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Necromancers/necromancer.xml b/path_7_s/data/monster/Necromancers/necromancer.xml deleted file mode 100644 index 2ad8e284d..000000000 --- a/path_7_s/data/monster/Necromancers/necromancer.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Necromancers/priestess.xml b/path_7_s/data/monster/Necromancers/priestess.xml deleted file mode 100644 index 4f46d4406..000000000 --- a/path_7_s/data/monster/Necromancers/priestess.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc berserker.xml b/path_7_s/data/monster/Orcs/orc berserker.xml deleted file mode 100644 index 132d5a177..000000000 --- a/path_7_s/data/monster/Orcs/orc berserker.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc leader.xml b/path_7_s/data/monster/Orcs/orc leader.xml deleted file mode 100644 index 509c569d3..000000000 --- a/path_7_s/data/monster/Orcs/orc leader.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc rider.xml b/path_7_s/data/monster/Orcs/orc rider.xml deleted file mode 100644 index 610edd475..000000000 --- a/path_7_s/data/monster/Orcs/orc rider.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc shaman.xml b/path_7_s/data/monster/Orcs/orc shaman.xml deleted file mode 100644 index 6fe3a973e..000000000 --- a/path_7_s/data/monster/Orcs/orc shaman.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc spearman.xml b/path_7_s/data/monster/Orcs/orc spearman.xml deleted file mode 100644 index df38336ad..000000000 --- a/path_7_s/data/monster/Orcs/orc spearman.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc warlord.xml b/path_7_s/data/monster/Orcs/orc warlord.xml deleted file mode 100644 index 05dcc386a..000000000 --- a/path_7_s/data/monster/Orcs/orc warlord.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc warrior.xml b/path_7_s/data/monster/Orcs/orc warrior.xml deleted file mode 100644 index 3fa512fba..000000000 --- a/path_7_s/data/monster/Orcs/orc warrior.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Orcs/orc.xml b/path_7_s/data/monster/Orcs/orc.xml deleted file mode 100644 index 8ccd47fac..000000000 --- a/path_7_s/data/monster/Orcs/orc.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/assassin.xml b/path_7_s/data/monster/Outlaws/assassin.xml deleted file mode 100644 index 3fd101219..000000000 --- a/path_7_s/data/monster/Outlaws/assassin.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/bandit.xml b/path_7_s/data/monster/Outlaws/bandit.xml deleted file mode 100644 index 509ce5b79..000000000 --- a/path_7_s/data/monster/Outlaws/bandit.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/black knight.xml b/path_7_s/data/monster/Outlaws/black knight.xml deleted file mode 100644 index eb9cec97f..000000000 --- a/path_7_s/data/monster/Outlaws/black knight.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/hero.xml b/path_7_s/data/monster/Outlaws/hero.xml deleted file mode 100644 index 9ab624a1a..000000000 --- a/path_7_s/data/monster/Outlaws/hero.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/hunter.xml b/path_7_s/data/monster/Outlaws/hunter.xml deleted file mode 100644 index 4439004b1..000000000 --- a/path_7_s/data/monster/Outlaws/hunter.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/nomad.xml b/path_7_s/data/monster/Outlaws/nomad.xml deleted file mode 100644 index 5e473d030..000000000 --- a/path_7_s/data/monster/Outlaws/nomad.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/smuggler.xml b/path_7_s/data/monster/Outlaws/smuggler.xml deleted file mode 100644 index 53114186c..000000000 --- a/path_7_s/data/monster/Outlaws/smuggler.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/stalker.xml b/path_7_s/data/monster/Outlaws/stalker.xml deleted file mode 100644 index b9d6987e4..000000000 --- a/path_7_s/data/monster/Outlaws/stalker.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Outlaws/wild warrior.xml b/path_7_s/data/monster/Outlaws/wild warrior.xml deleted file mode 100644 index 9ab80a3d5..000000000 --- a/path_7_s/data/monster/Outlaws/wild warrior.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/ashmunrah.xml b/path_7_s/data/monster/Pharaohs/ashmunrah.xml deleted file mode 100644 index 409147e3f..000000000 --- a/path_7_s/data/monster/Pharaohs/ashmunrah.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/dipthrah.xml b/path_7_s/data/monster/Pharaohs/dipthrah.xml deleted file mode 100644 index ba8a9ecf4..000000000 --- a/path_7_s/data/monster/Pharaohs/dipthrah.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/mahrdis.xml b/path_7_s/data/monster/Pharaohs/mahrdis.xml deleted file mode 100644 index 1325b0ee1..000000000 --- a/path_7_s/data/monster/Pharaohs/mahrdis.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/morguthis.xml b/path_7_s/data/monster/Pharaohs/morguthis.xml deleted file mode 100644 index 1dba1a91c..000000000 --- a/path_7_s/data/monster/Pharaohs/morguthis.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/omruc.xml b/path_7_s/data/monster/Pharaohs/omruc.xml deleted file mode 100644 index 31b24e6b9..000000000 --- a/path_7_s/data/monster/Pharaohs/omruc.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/rahemos.xml b/path_7_s/data/monster/Pharaohs/rahemos.xml deleted file mode 100644 index 02ee5128a..000000000 --- a/path_7_s/data/monster/Pharaohs/rahemos.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/superior death minion.xml b/path_7_s/data/monster/Pharaohs/superior death minion.xml deleted file mode 100644 index 868b7aa43..000000000 --- a/path_7_s/data/monster/Pharaohs/superior death minion.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/thalas.xml b/path_7_s/data/monster/Pharaohs/thalas.xml deleted file mode 100644 index 38e7843c0..000000000 --- a/path_7_s/data/monster/Pharaohs/thalas.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pharaohs/vashresamun.xml b/path_7_s/data/monster/Pharaohs/vashresamun.xml deleted file mode 100644 index 06bfd40e5..000000000 --- a/path_7_s/data/monster/Pharaohs/vashresamun.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate buccaneer.xml b/path_7_s/data/monster/Pirates/pirate buccaneer.xml deleted file mode 100644 index e465d94d4..000000000 --- a/path_7_s/data/monster/Pirates/pirate buccaneer.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate corsair.xml b/path_7_s/data/monster/Pirates/pirate corsair.xml deleted file mode 100644 index d70c73a03..000000000 --- a/path_7_s/data/monster/Pirates/pirate corsair.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate cutthroat.xml b/path_7_s/data/monster/Pirates/pirate cutthroat.xml deleted file mode 100644 index 5468ea8ad..000000000 --- a/path_7_s/data/monster/Pirates/pirate cutthroat.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate ghost.xml b/path_7_s/data/monster/Pirates/pirate ghost.xml deleted file mode 100644 index 6e44799a3..000000000 --- a/path_7_s/data/monster/Pirates/pirate ghost.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate marauder.xml b/path_7_s/data/monster/Pirates/pirate marauder.xml deleted file mode 100644 index c03d63f4e..000000000 --- a/path_7_s/data/monster/Pirates/pirate marauder.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pirates/pirate skeleton.xml b/path_7_s/data/monster/Pirates/pirate skeleton.xml deleted file mode 100644 index 68a1b3431..000000000 --- a/path_7_s/data/monster/Pirates/pirate skeleton.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pyro-Elementals/fire elemental.xml b/path_7_s/data/monster/Pyro-Elementals/fire elemental.xml deleted file mode 100644 index bdaa4960e..000000000 --- a/path_7_s/data/monster/Pyro-Elementals/fire elemental.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Pyro-Elementals/hellfire fighter.xml b/path_7_s/data/monster/Pyro-Elementals/hellfire fighter.xml deleted file mode 100644 index 26000938f..000000000 --- a/path_7_s/data/monster/Pyro-Elementals/hellfire fighter.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara constrictor scout.xml b/path_7_s/data/monster/Quaras/quara constrictor scout.xml deleted file mode 100644 index 7f800452b..000000000 --- a/path_7_s/data/monster/Quaras/quara constrictor scout.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara constrictor.xml b/path_7_s/data/monster/Quaras/quara constrictor.xml deleted file mode 100644 index 2b8273a9a..000000000 --- a/path_7_s/data/monster/Quaras/quara constrictor.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara hydromancer scout.xml b/path_7_s/data/monster/Quaras/quara hydromancer scout.xml deleted file mode 100644 index 748ac5f59..000000000 --- a/path_7_s/data/monster/Quaras/quara hydromancer scout.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara hydromancer.xml b/path_7_s/data/monster/Quaras/quara hydromancer.xml deleted file mode 100644 index a9f9e79ed..000000000 --- a/path_7_s/data/monster/Quaras/quara hydromancer.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara mantassin scout.xml b/path_7_s/data/monster/Quaras/quara mantassin scout.xml deleted file mode 100644 index 5b487938f..000000000 --- a/path_7_s/data/monster/Quaras/quara mantassin scout.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara mantassin.xml b/path_7_s/data/monster/Quaras/quara mantassin.xml deleted file mode 100644 index a2e2350a1..000000000 --- a/path_7_s/data/monster/Quaras/quara mantassin.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara pincher scout.xml b/path_7_s/data/monster/Quaras/quara pincher scout.xml deleted file mode 100644 index 3ab6a824f..000000000 --- a/path_7_s/data/monster/Quaras/quara pincher scout.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara pincher.xml b/path_7_s/data/monster/Quaras/quara pincher.xml deleted file mode 100644 index 1764e261e..000000000 --- a/path_7_s/data/monster/Quaras/quara pincher.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara predator scout.xml b/path_7_s/data/monster/Quaras/quara predator scout.xml deleted file mode 100644 index af6a7b06a..000000000 --- a/path_7_s/data/monster/Quaras/quara predator scout.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Quaras/quara predator.xml b/path_7_s/data/monster/Quaras/quara predator.xml deleted file mode 100644 index 5116d2ef5..000000000 --- a/path_7_s/data/monster/Quaras/quara predator.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Serpents/cobra.xml b/path_7_s/data/monster/Serpents/cobra.xml deleted file mode 100644 index 97595d636..000000000 --- a/path_7_s/data/monster/Serpents/cobra.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Serpents/serpent spawn.xml b/path_7_s/data/monster/Serpents/serpent spawn.xml deleted file mode 100644 index 144ff66df..000000000 --- a/path_7_s/data/monster/Serpents/serpent spawn.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Serpents/snake.xml b/path_7_s/data/monster/Serpents/snake.xml deleted file mode 100644 index e2ee57d95..000000000 --- a/path_7_s/data/monster/Serpents/snake.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Skeletons/betrayed wraith.xml b/path_7_s/data/monster/Skeletons/betrayed wraith.xml deleted file mode 100644 index 2b66cfba7..000000000 --- a/path_7_s/data/monster/Skeletons/betrayed wraith.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Skeletons/bonebeast.xml b/path_7_s/data/monster/Skeletons/bonebeast.xml deleted file mode 100644 index ac0a16340..000000000 --- a/path_7_s/data/monster/Skeletons/bonebeast.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Skeletons/demon skeleton.xml b/path_7_s/data/monster/Skeletons/demon skeleton.xml deleted file mode 100644 index 0430dcf12..000000000 --- a/path_7_s/data/monster/Skeletons/demon skeleton.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Skeletons/lost soul.xml b/path_7_s/data/monster/Skeletons/lost soul.xml deleted file mode 100644 index e9994c0ca..000000000 --- a/path_7_s/data/monster/Skeletons/lost soul.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Skeletons/skeleton.xml b/path_7_s/data/monster/Skeletons/skeleton.xml deleted file mode 100644 index 3a3af0e21..000000000 --- a/path_7_s/data/monster/Skeletons/skeleton.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Sorcerers/dark magician.xml b/path_7_s/data/monster/Sorcerers/dark magician.xml deleted file mode 100644 index 2962964c7..000000000 --- a/path_7_s/data/monster/Sorcerers/dark magician.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Sorcerers/ice witch.xml b/path_7_s/data/monster/Sorcerers/ice witch.xml deleted file mode 100644 index 61dab10ba..000000000 --- a/path_7_s/data/monster/Sorcerers/ice witch.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Sorcerers/warlock.xml b/path_7_s/data/monster/Sorcerers/warlock.xml deleted file mode 100644 index 1d5e6ffb8..000000000 --- a/path_7_s/data/monster/Sorcerers/warlock.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Sorcerers/witch.xml b/path_7_s/data/monster/Sorcerers/witch.xml deleted file mode 100644 index 0b806166b..000000000 --- a/path_7_s/data/monster/Sorcerers/witch.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/a carved stone tile.xml b/path_7_s/data/monster/Traps/a carved stone tile.xml deleted file mode 100644 index 690f38569..000000000 --- a/path_7_s/data/monster/Traps/a carved stone tile.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/deathslicer.xml b/path_7_s/data/monster/Traps/deathslicer.xml deleted file mode 100644 index aea09d36b..000000000 --- a/path_7_s/data/monster/Traps/deathslicer.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/flamethrower.xml b/path_7_s/data/monster/Traps/flamethrower.xml deleted file mode 100644 index 835522c57..000000000 --- a/path_7_s/data/monster/Traps/flamethrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/hell hole.xml b/path_7_s/data/monster/Traps/hell hole.xml deleted file mode 100644 index a5880b72e..000000000 --- a/path_7_s/data/monster/Traps/hell hole.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/lavahole.xml b/path_7_s/data/monster/Traps/lavahole.xml deleted file mode 100644 index 2f9f24bc6..000000000 --- a/path_7_s/data/monster/Traps/lavahole.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/magic pillar.xml b/path_7_s/data/monster/Traps/magic pillar.xml deleted file mode 100644 index 8c19b2915..000000000 --- a/path_7_s/data/monster/Traps/magic pillar.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/magicthrower.xml b/path_7_s/data/monster/Traps/magicthrower.xml deleted file mode 100644 index 50304607b..000000000 --- a/path_7_s/data/monster/Traps/magicthrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/pillar.xml b/path_7_s/data/monster/Traps/pillar.xml deleted file mode 100644 index d1560821f..000000000 --- a/path_7_s/data/monster/Traps/pillar.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/plaguethrower.xml b/path_7_s/data/monster/Traps/plaguethrower.xml deleted file mode 100644 index b661e3baf..000000000 --- a/path_7_s/data/monster/Traps/plaguethrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Traps/shredderthrower.xml b/path_7_s/data/monster/Traps/shredderthrower.xml deleted file mode 100644 index 1a3128caf..000000000 --- a/path_7_s/data/monster/Traps/shredderthrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Trolls/frost troll.xml b/path_7_s/data/monster/Trolls/frost troll.xml deleted file mode 100644 index 41d695482..000000000 --- a/path_7_s/data/monster/Trolls/frost troll.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Trolls/swamp troll.xml b/path_7_s/data/monster/Trolls/swamp troll.xml deleted file mode 100644 index b1204ba36..000000000 --- a/path_7_s/data/monster/Trolls/swamp troll.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Trolls/troll.xml b/path_7_s/data/monster/Trolls/troll.xml deleted file mode 100644 index bc4011b35..000000000 --- a/path_7_s/data/monster/Trolls/troll.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/banshee.xml b/path_7_s/data/monster/Undead Humanoids/banshee.xml deleted file mode 100644 index ce6685ac3..000000000 --- a/path_7_s/data/monster/Undead Humanoids/banshee.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/blightwalker.xml b/path_7_s/data/monster/Undead Humanoids/blightwalker.xml deleted file mode 100644 index 771d6d8c7..000000000 --- a/path_7_s/data/monster/Undead Humanoids/blightwalker.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/crypt shambler.xml b/path_7_s/data/monster/Undead Humanoids/crypt shambler.xml deleted file mode 100644 index ffacd4c72..000000000 --- a/path_7_s/data/monster/Undead Humanoids/crypt shambler.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/ghoul.xml b/path_7_s/data/monster/Undead Humanoids/ghoul.xml deleted file mode 100644 index 798290bd2..000000000 --- a/path_7_s/data/monster/Undead Humanoids/ghoul.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/lich.xml b/path_7_s/data/monster/Undead Humanoids/lich.xml deleted file mode 100644 index b546cec8c..000000000 --- a/path_7_s/data/monster/Undead Humanoids/lich.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Undead Humanoids/mummy.xml b/path_7_s/data/monster/Undead Humanoids/mummy.xml deleted file mode 100644 index f8f709cdf..000000000 --- a/path_7_s/data/monster/Undead Humanoids/mummy.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/black sheep.xml b/path_7_s/data/monster/Ungulates/black sheep.xml deleted file mode 100644 index 86524152e..000000000 --- a/path_7_s/data/monster/Ungulates/black sheep.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/deer.xml b/path_7_s/data/monster/Ungulates/deer.xml deleted file mode 100644 index 20976abbc..000000000 --- a/path_7_s/data/monster/Ungulates/deer.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/elephant.xml b/path_7_s/data/monster/Ungulates/elephant.xml deleted file mode 100644 index 6d0a77419..000000000 --- a/path_7_s/data/monster/Ungulates/elephant.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/mammoth.xml b/path_7_s/data/monster/Ungulates/mammoth.xml deleted file mode 100644 index 5d1a02e3b..000000000 --- a/path_7_s/data/monster/Ungulates/mammoth.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/pig.xml b/path_7_s/data/monster/Ungulates/pig.xml deleted file mode 100644 index 92f963145..000000000 --- a/path_7_s/data/monster/Ungulates/pig.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Ungulates/sheep.xml b/path_7_s/data/monster/Ungulates/sheep.xml deleted file mode 100644 index 3acfa1c9d..000000000 --- a/path_7_s/data/monster/Ungulates/sheep.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Voodoo Cultists/acolyte of the cult.xml b/path_7_s/data/monster/Voodoo Cultists/acolyte of the cult.xml deleted file mode 100644 index de9cc37b7..000000000 --- a/path_7_s/data/monster/Voodoo Cultists/acolyte of the cult.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Voodoo Cultists/adept of the cult.xml b/path_7_s/data/monster/Voodoo Cultists/adept of the cult.xml deleted file mode 100644 index 4c69f4f58..000000000 --- a/path_7_s/data/monster/Voodoo Cultists/adept of the cult.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Voodoo Cultists/enlightened of the cult.xml b/path_7_s/data/monster/Voodoo Cultists/enlightened of the cult.xml deleted file mode 100644 index e46e9ac8b..000000000 --- a/path_7_s/data/monster/Voodoo Cultists/enlightened of the cult.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/Voodoo Cultists/novice of the cult.xml b/path_7_s/data/monster/Voodoo Cultists/novice of the cult.xml deleted file mode 100644 index 1a613993f..000000000 --- a/path_7_s/data/monster/Voodoo Cultists/novice of the cult.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/bats/bat.xml b/path_7_s/data/monster/bats/bat.xml deleted file mode 100644 index 855d0c09c..000000000 --- a/path_7_s/data/monster/bats/bat.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/monsters.xml b/path_7_s/data/monster/monsters.xml deleted file mode 100644 index 2ea948950..000000000 --- a/path_7_s/data/monster/monsters.xml +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/monster/vampires/vampire.xml b/path_7_s/data/monster/vampires/vampire.xml deleted file mode 100644 index d1ff32418..000000000 --- a/path_7_s/data/monster/vampires/vampire.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/movements/lib/movements.lua b/path_7_s/data/movements/lib/movements.lua deleted file mode 100644 index b081a0ffe..000000000 --- a/path_7_s/data/movements/lib/movements.lua +++ /dev/null @@ -1,2 +0,0 @@ --- Nothing -- - diff --git a/path_7_s/data/movements/movements.xml b/path_7_s/data/movements/movements.xml deleted file mode 100644 index 4e86ef5c4..000000000 --- a/path_7_s/data/movements/movements.xml +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/movements/scripts/citizen.lua b/path_7_s/data/movements/scripts/citizen.lua deleted file mode 100644 index 541cfa3a6..000000000 --- a/path_7_s/data/movements/scripts/citizen.lua +++ /dev/null @@ -1,13 +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) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are the newest resident of " .. town:getName(town) .. ".") - end - return true -end diff --git a/path_7_s/data/movements/scripts/closingdoor.lua b/path_7_s/data/movements/scripts/closingdoor.lua deleted file mode 100644 index 83904ae06..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/decay.lua b/path_7_s/data/movements/scripts/decay.lua deleted file mode 100644 index 9a48822b2..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/dough.lua b/path_7_s/data/movements/scripts/dough.lua deleted file mode 100644 index a0b371fa4..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/drowning.lua b/path_7_s/data/movements/scripts/drowning.lua deleted file mode 100644 index ee5a6979d..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/snow.lua b/path_7_s/data/movements/scripts/snow.lua deleted file mode 100644 index 8a07bbfa3..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/swimming.lua b/path_7_s/data/movements/scripts/swimming.lua deleted file mode 100644 index f11af1a6c..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/tiles.lua b/path_7_s/data/movements/scripts/tiles.lua deleted file mode 100644 index cdb765677..000000000 --- a/path_7_s/data/movements/scripts/tiles.lua +++ /dev/null @@ -1,56 +0,0 @@ -local increasing = {[416] = 417, [426] = 425, [446] = 447, [3216] = 3217, [3202] = 3215} -local decreasing = {[417] = 416, [425] = 426, [447] = 446, [3217] = 3216, [3215] = 3202} - -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_7_s/data/movements/scripts/trap.lua b/path_7_s/data/movements/scripts/trap.lua deleted file mode 100644 index e8a49f7a5..000000000 --- a/path_7_s/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_7_s/data/movements/scripts/walkback.lua b/path_7_s/data/movements/scripts/walkback.lua deleted file mode 100644 index 30b00f21f..000000000 --- a/path_7_s/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_7_s/data/npc/Alice.xml b/path_7_s/data/npc/Alice.xml deleted file mode 100644 index 5f02ca5ea..000000000 --- a/path_7_s/data/npc/Alice.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_7_s/data/npc/Deruno.xml b/path_7_s/data/npc/Deruno.xml deleted file mode 100644 index 3015d5fff..000000000 --- a/path_7_s/data/npc/Deruno.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_7_s/data/npc/Dimral.xml b/path_7_s/data/npc/Dimral.xml deleted file mode 100644 index 287660d3f..000000000 --- a/path_7_s/data/npc/Dimral.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_7_s/data/npc/Donald.xml b/path_7_s/data/npc/Donald.xml deleted file mode 100644 index 91e5bd147..000000000 --- a/path_7_s/data/npc/Donald.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_7_s/data/npc/Eryn.xml b/path_7_s/data/npc/Eryn.xml deleted file mode 100644 index 93622cdbf..000000000 --- a/path_7_s/data/npc/Eryn.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_7_s/data/npc/Naji.xml b/path_7_s/data/npc/Naji.xml deleted file mode 100644 index 7aa02a4f0..000000000 --- a/path_7_s/data/npc/Naji.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_7_s/data/npc/Riona.xml b/path_7_s/data/npc/Riona.xml deleted file mode 100644 index 13a1df43f..000000000 --- a/path_7_s/data/npc/Riona.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_7_s/data/npc/Soya.xml b/path_7_s/data/npc/Soya.xml deleted file mode 100644 index 3f9ad1381..000000000 --- a/path_7_s/data/npc/Soya.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_7_s/data/npc/The Forgotten King.xml b/path_7_s/data/npc/The Forgotten King.xml deleted file mode 100644 index 5f34703f6..000000000 --- a/path_7_s/data/npc/The Forgotten King.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_7_s/data/npc/The Oracle.xml b/path_7_s/data/npc/The Oracle.xml deleted file mode 100644 index 8aec9e74f..000000000 --- a/path_7_s/data/npc/The Oracle.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_7_s/data/npc/Tyoric.xml b/path_7_s/data/npc/Tyoric.xml deleted file mode 100644 index 38f6114b1..000000000 --- a/path_7_s/data/npc/Tyoric.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_7_s/data/npc/lib/npc.lua b/path_7_s/data/npc/lib/npc.lua deleted file mode 100644 index c6d3e2cf6..000000000 --- a/path_7_s/data/npc/lib/npc.lua +++ /dev/null @@ -1,131 +0,0 @@ --- 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() - 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_7_s/data/npc/lib/npcsystem/customModules.lua b/path_7_s/data/npc/lib/npcsystem/customModules.lua deleted file mode 100644 index f44c8a8b0..000000000 --- a/path_7_s/data/npc/lib/npcsystem/customModules.lua +++ /dev/null @@ -1,192 +0,0 @@ --- 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_7_s/data/npc/lib/npcsystem/keywordhandler.lua b/path_7_s/data/npc/lib/npcsystem/keywordhandler.lua deleted file mode 100644 index ea4f5d3ad..000000000 --- a/path_7_s/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_7_s/data/npc/lib/npcsystem/modules.lua b/path_7_s/data/npc/lib/npcsystem/modules.lua deleted file mode 100644 index a127d198a..000000000 --- a/path_7_s/data/npc/lib/npcsystem/modules.lua +++ /dev/null @@ -1,1193 +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) - 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_7_s/data/npc/lib/npcsystem/npchandler.lua b/path_7_s/data/npc/lib/npcsystem/npchandler.lua deleted file mode 100644 index d867ca5c1..000000000 --- a/path_7_s/data/npc/lib/npcsystem/npchandler.lua +++ /dev/null @@ -1,595 +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 - 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() - 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) 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 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_SAY, ((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:gsub("|PLAYERNAME|", player:getName()), TALKTYPE_SAY) - end - end, self.talkDelayTime * 1000, Npc():getId(), message, focus) - end -end diff --git a/path_7_s/data/npc/lib/npcsystem/npcsystem.lua b/path_7_s/data/npc/lib/npcsystem/npcsystem.lua deleted file mode 100644 index 15d7f5fa4..000000000 --- a/path_7_s/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_7_s/data/npc/scripts/The Oracle.lua b/path_7_s/data/npc/scripts/The Oracle.lua deleted file mode 100644 index 6619adda1..000000000 --- a/path_7_s/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_7_s/data/npc/scripts/bank.lua b/path_7_s/data/npc/scripts/bank.lua deleted file mode 100644 index e20f20a92..000000000 --- a/path_7_s/data/npc/scripts/bank.lua +++ /dev/null @@ -1,323 +0,0 @@ -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_7_s/data/npc/scripts/bless.lua b/path_7_s/data/npc/scripts/bless.lua deleted file mode 100644 index eb3fc5ac3..000000000 --- a/path_7_s/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_7_s/data/npc/scripts/default.lua b/path_7_s/data/npc/scripts/default.lua deleted file mode 100644 index 36d042db2..000000000 --- a/path_7_s/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_7_s/data/npc/scripts/promotion.lua b/path_7_s/data/npc/scripts/promotion.lua deleted file mode 100644 index e565d5703..000000000 --- a/path_7_s/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_7_s/data/npc/scripts/runes.lua b/path_7_s/data/npc/scripts/runes.lua deleted file mode 100644 index 84915f2d8..000000000 --- a/path_7_s/data/npc/scripts/runes.lua +++ /dev/null @@ -1,123 +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: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 cosmic energy', 'cosmic energy'}, 2189, 10000, 'wand of cosmic energy') -shopModule:addBuyableItem({'wand of inferno', 'inferno'}, 2187, 15000, 'wand of inferno') - -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({'terra rod', 'terra'}, 2181, 10000, 'terra rod') -shopModule:addBuyableItem({'hailstorm rod', 'hailstorm'}, 2183, 15000, 'hailstorm rod') - -shopModule:addSellableItem({'wand of vortex', 'vortex'}, 2190, 250, 'wand of vortex') -shopModule:addSellableItem({'wand of dragonbreath', 'dragonbreath'}, 2191, 500, 'wand of dragonbreath') -shopModule:addSellableItem({'wand of decay', 'decay'}, 2188, 2500, 'wand of decay') -shopModule:addSellableItem({'wand of cosmic energy', 'cosmic energy'}, 2189, 5000, 'wand of cosmic energy') -shopModule:addSellableItem({'wand of inferno', 'inferno'},2187, 7500, 'wand of inferno') - -shopModule:addSellableItem({'snakebite rod', 'snakebite'}, 2182, 250,'snakebite rod') -shopModule:addSellableItem({'moonlight rod', 'moonlight'}, 2186, 500, 'moonlight rod') -shopModule:addSellableItem({'necrotic rod', 'necrotic'}, 2185, 2500, 'necrotic rod') -shopModule:addSellableItem({'terra rod', 'terra'}, 2181, 5000, 'terra rod') -shopModule:addSellableItem({'hailstorm rod', 'hailstorm'}, 2183, 7500, 'hailstorm 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_7_s/data/raids/raids.xml b/path_7_s/data/raids/raids.xml deleted file mode 100644 index e61a5a6e4..000000000 --- a/path_7_s/data/raids/raids.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/path_7_s/data/raids/testraid.xml b/path_7_s/data/raids/testraid.xml deleted file mode 100644 index ebfe9d0c9..000000000 --- a/path_7_s/data/raids/testraid.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/reports/.gitignore b/path_7_s/data/reports/.gitignore deleted file mode 100644 index eb67fe0af..000000000 --- a/path_7_s/data/reports/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Ignore user generated reports -* -!.gitignore diff --git a/path_7_s/data/spells/lib/spells.lua b/path_7_s/data/spells/lib/spells.lua deleted file mode 100644 index bf1c9e98d..000000000 --- a/path_7_s/data/spells/lib/spells.lua +++ /dev/null @@ -1,250 +0,0 @@ ---Pre-made areas - ---Waves -AREA_WAVE3 = { -{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_7_s/data/spells/scripts/attack/berserk.lua b/path_7_s/data/spells/scripts/attack/berserk.lua deleted file mode 100644 index 9afe6025f..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/energy beam.lua b/path_7_s/data/spells/scripts/attack/energy beam.lua deleted file mode 100644 index 47b8c177d..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/energy bomb.lua b/path_7_s/data/spells/scripts/attack/energy bomb.lua deleted file mode 100644 index 78726107d..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/energy field.lua b/path_7_s/data/spells/scripts/attack/energy field.lua deleted file mode 100644 index f026a05ed..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/energy strike.lua b/path_7_s/data/spells/scripts/attack/energy strike.lua deleted file mode 100644 index 73b623338..000000000 --- a/path_7_s/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_ENERGYHIT) -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_7_s/data/spells/scripts/attack/energy wall.lua b/path_7_s/data/spells/scripts/attack/energy wall.lua deleted file mode 100644 index 9888b87d8..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/energy wave.lua b/path_7_s/data/spells/scripts/attack/energy wave.lua deleted file mode 100644 index 714d38025..000000000 --- a/path_7_s/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_TELEPORT) -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_7_s/data/spells/scripts/attack/envenom.lua b/path_7_s/data/spells/scripts/attack/envenom.lua deleted file mode 100644 index e2901383f..000000000 --- a/path_7_s/data/spells/scripts/attack/envenom.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_7_s/data/spells/scripts/attack/ethereal spear.lua b/path_7_s/data/spells/scripts/attack/ethereal spear.lua deleted file mode 100644 index d97832f5a..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/explosion.lua b/path_7_s/data/spells/scripts/attack/explosion.lua deleted file mode 100644 index ddb1dc5a3..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fierce berserk.lua b/path_7_s/data/spells/scripts/attack/fierce berserk.lua deleted file mode 100644 index 1f051ba06..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fire bomb.lua b/path_7_s/data/spells/scripts/attack/fire bomb.lua deleted file mode 100644 index eba9401f8..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fire field.lua b/path_7_s/data/spells/scripts/attack/fire field.lua deleted file mode 100644 index 59b2aa7e4..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fire wall.lua b/path_7_s/data/spells/scripts/attack/fire wall.lua deleted file mode 100644 index 8935419a6..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fire wave.lua b/path_7_s/data/spells/scripts/attack/fire wave.lua deleted file mode 100644 index 98b7f4bc0..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/fireball.lua b/path_7_s/data/spells/scripts/attack/fireball.lua deleted file mode 100644 index 1a29dd5c5..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/flame strike.lua b/path_7_s/data/spells/scripts/attack/flame strike.lua deleted file mode 100644 index 924eb1580..000000000 --- a/path_7_s/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_FIREAREA) -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_7_s/data/spells/scripts/attack/force strike.lua b/path_7_s/data/spells/scripts/attack/force strike.lua deleted file mode 100644 index 7b5c0e9bb..000000000 --- a/path_7_s/data/spells/scripts/attack/force strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -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_7_s/data/spells/scripts/attack/great energy beam.lua b/path_7_s/data/spells/scripts/attack/great energy beam.lua deleted file mode 100644 index 5a40cd6fe..000000000 --- a/path_7_s/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_BEAM8)) - -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_7_s/data/spells/scripts/attack/great fireball.lua b/path_7_s/data/spells/scripts/attack/great fireball.lua deleted file mode 100644 index 2c9291ae3..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/groundshaker.lua b/path_7_s/data/spells/scripts/attack/groundshaker.lua deleted file mode 100644 index bb9995407..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/heavy magic missile.lua b/path_7_s/data/spells/scripts/attack/heavy magic missile.lua deleted file mode 100644 index 6e6f6dea9..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/light magic missile.lua b/path_7_s/data/spells/scripts/attack/light magic missile.lua deleted file mode 100644 index 977d302cd..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/poison bomb.lua b/path_7_s/data/spells/scripts/attack/poison bomb.lua deleted file mode 100644 index ec5522574..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/poison field.lua b/path_7_s/data/spells/scripts/attack/poison field.lua deleted file mode 100644 index f4e9e6224..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/poison storm.lua b/path_7_s/data/spells/scripts/attack/poison storm.lua deleted file mode 100644 index c243d508c..000000000 --- a/path_7_s/data/spells/scripts/attack/poison storm.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -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_7_s/data/spells/scripts/attack/poison wall.lua b/path_7_s/data/spells/scripts/attack/poison wall.lua deleted file mode 100644 index a9b8460ae..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/soul fire.lua b/path_7_s/data/spells/scripts/attack/soul fire.lua deleted file mode 100644 index 74ee7015c..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/attack/sudden death.lua b/path_7_s/data/spells/scripts/attack/sudden death.lua deleted file mode 100644 index a2dd09f3f..000000000 --- a/path_7_s/data/spells/scripts/attack/sudden death.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -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 * 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_7_s/data/spells/scripts/attack/ultimate explosion.lua b/path_7_s/data/spells/scripts/attack/ultimate explosion.lua deleted file mode 100644 index efd08b292..000000000 --- a/path_7_s/data/spells/scripts/attack/ultimate explosion.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -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_7_s/data/spells/scripts/attack/whirlwind throw.lua b/path_7_s/data/spells/scripts/attack/whirlwind throw.lua deleted file mode 100644 index 508062132..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/custom/apocalypse.lua b/path_7_s/data/spells/scripts/custom/apocalypse.lua deleted file mode 100644 index 70dead24b..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/custom/combustion.lua b/path_7_s/data/spells/scripts/custom/combustion.lua deleted file mode 100644 index ca9cb5aa7..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/custom/drunk.lua b/path_7_s/data/spells/scripts/custom/drunk.lua deleted file mode 100644 index 3c19aea0c..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/custom/magic prison.lua b/path_7_s/data/spells/scripts/custom/magic prison.lua deleted file mode 100644 index ee5bfba68..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/custom/polymorph.lua b/path_7_s/data/spells/scripts/custom/polymorph.lua deleted file mode 100644 index 27efef382..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/cure poison rune.lua b/path_7_s/data/spells/scripts/healing/cure poison rune.lua deleted file mode 100644 index f272fb983..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/cure poison.lua b/path_7_s/data/spells/scripts/healing/cure poison.lua deleted file mode 100644 index b50548e72..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/heal friend.lua b/path_7_s/data/spells/scripts/healing/heal friend.lua deleted file mode 100644 index 621628afc..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/intense healing rune.lua b/path_7_s/data/spells/scripts/healing/intense healing rune.lua deleted file mode 100644 index 53fa135aa..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/intense healing.lua b/path_7_s/data/spells/scripts/healing/intense healing.lua deleted file mode 100644 index 2a61b871c..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/light healing.lua b/path_7_s/data/spells/scripts/healing/light healing.lua deleted file mode 100644 index bd3a0908d..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/mass healing.lua b/path_7_s/data/spells/scripts/healing/mass healing.lua deleted file mode 100644 index 0b984503e..000000000 --- a/path_7_s/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 - - if not healMonsters then - local master = target:getMaster() - 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_7_s/data/spells/scripts/healing/ultimate healing rune.lua b/path_7_s/data/spells/scripts/healing/ultimate healing rune.lua deleted file mode 100644 index 5aac4c00f..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/healing/ultimate healing.lua b/path_7_s/data/spells/scripts/healing/ultimate healing.lua deleted file mode 100644 index ec18d9ed9..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua b/path_7_s/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua deleted file mode 100644 index 8d7ff3758..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/betrayed wraith skill reducer.lua b/path_7_s/data/spells/scripts/monster/betrayed wraith skill reducer.lua deleted file mode 100644 index a6d972a52..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/choking fear drown.lua b/path_7_s/data/spells/scripts/monster/choking fear drown.lua deleted file mode 100644 index 42b7ad8eb..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/cliff strider electrify.lua b/path_7_s/data/spells/scripts/monster/cliff strider electrify.lua deleted file mode 100644 index 7231acef3..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/cliff strider skill reducer.lua b/path_7_s/data/spells/scripts/monster/cliff strider skill reducer.lua deleted file mode 100644 index e60f3b996..000000000 --- a/path_7_s/data/spells/scripts/monster/cliff strider 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, 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) - return combat:execute(creature, variant) -end diff --git a/path_7_s/data/spells/scripts/monster/dark torturer skill reducer.lua b/path_7_s/data/spells/scripts/monster/dark torturer skill reducer.lua deleted file mode 100644 index 559cec088..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/deepling spellsinger skill reducer.lua b/path_7_s/data/spells/scripts/monster/deepling spellsinger skill reducer.lua deleted file mode 100644 index cb0d443d2..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/demon outcast skill reducer.lua b/path_7_s/data/spells/scripts/monster/demon outcast skill reducer.lua deleted file mode 100644 index e36bbc78a..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/diabolic imp skill reducer.lua b/path_7_s/data/spells/scripts/monster/diabolic imp skill reducer.lua deleted file mode 100644 index 00b3193c4..000000000 --- a/path_7_s/data/spells/scripts/monster/diabolic imp skill reducer.lua +++ /dev/null @@ -1,16 +0,0 @@ -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_DISTANCEEFFECT, CONST_ANI_ENERGY) - combat[i]:setArea(createCombatArea(AREA_BEAM1)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(70, 80)]:execute(creature, variant) -end diff --git a/path_7_s/data/spells/scripts/monster/dipthrah skill reducer.lua b/path_7_s/data/spells/scripts/monster/dipthrah skill reducer.lua deleted file mode 100644 index feb2df27a..000000000 --- a/path_7_s/data/spells/scripts/monster/dipthrah skill reducer.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) - -local area = createCombatArea(AREA_CIRCLE3X3) -combat:setArea(area) - -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 6000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 50) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 50) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) -combat:setCondition(condition) - -function onCastSpell(creature, var) - return combat:execute(creature, var) -end diff --git a/path_7_s/data/spells/scripts/monster/djinn cancel invisibility.lua b/path_7_s/data/spells/scripts/monster/djinn cancel invisibility.lua deleted file mode 100644 index 61128bc97..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/djinn electrify.lua b/path_7_s/data/spells/scripts/monster/djinn electrify.lua deleted file mode 100644 index 83eb0c4eb..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/energy elemental electrify.lua b/path_7_s/data/spells/scripts/monster/energy elemental electrify.lua deleted file mode 100644 index 0d479c47a..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua b/path_7_s/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua deleted file mode 100644 index 3790028db..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua b/path_7_s/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua deleted file mode 100644 index e8e2b0be8..000000000 --- a/path_7_s/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua +++ /dev/null @@ -1,12 +0,0 @@ -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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_7_s/data/spells/scripts/monster/feversleep skill reducer.lua b/path_7_s/data/spells/scripts/monster/feversleep skill reducer.lua deleted file mode 100644 index f4b62f910..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/forest fury skill reducer.lua b/path_7_s/data/spells/scripts/monster/forest fury skill reducer.lua deleted file mode 100644 index 422fde6a9..000000000 --- a/path_7_s/data/spells/scripts/monster/forest fury skill reducer.lua +++ /dev/null @@ -1,14 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_7_s/data/spells/scripts/monster/fury skill reducer.lua b/path_7_s/data/spells/scripts/monster/fury skill reducer.lua deleted file mode 100644 index 2f0534660..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/hellfire fighter soulfire.lua b/path_7_s/data/spells/scripts/monster/hellfire fighter soulfire.lua deleted file mode 100644 index 8ae590fdd..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/hellspawn soulfire.lua b/path_7_s/data/spells/scripts/monster/hellspawn soulfire.lua deleted file mode 100644 index 1c7f144e2..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/ice golem skill reducer.lua b/path_7_s/data/spells/scripts/monster/ice golem skill reducer.lua deleted file mode 100644 index d7bc670f0..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/lava golem soulfire.lua b/path_7_s/data/spells/scripts/monster/lava golem soulfire.lua deleted file mode 100644 index 69aacb1e3..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/magma crawler soulfire.lua b/path_7_s/data/spells/scripts/monster/magma crawler soulfire.lua deleted file mode 100644 index 68135f908..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/massive energy elemental electrify.lua b/path_7_s/data/spells/scripts/monster/massive energy elemental electrify.lua deleted file mode 100644 index 1bbd62614..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/massive fire elemental soulfire.lua b/path_7_s/data/spells/scripts/monster/massive fire elemental soulfire.lua deleted file mode 100644 index 1c759518a..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/phantasm drown.lua b/path_7_s/data/spells/scripts/monster/phantasm drown.lua deleted file mode 100644 index bc13da129..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/pirate corsair skill reducer.lua b/path_7_s/data/spells/scripts/monster/pirate corsair skill reducer.lua deleted file mode 100644 index 7435ff606..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/quara constrictor electrify.lua b/path_7_s/data/spells/scripts/monster/quara constrictor electrify.lua deleted file mode 100644 index 83eb0c4eb..000000000 --- a/path_7_s/data/spells/scripts/monster/quara constrictor 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_7_s/data/spells/scripts/monster/sea serpent drown.lua b/path_7_s/data/spells/scripts/monster/sea serpent drown.lua deleted file mode 100644 index c0af07d2a..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/shock head skill reducer 1.lua b/path_7_s/data/spells/scripts/monster/shock head skill reducer 1.lua deleted file mode 100644 index a7733c502..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/shock head skill reducer 2.lua b/path_7_s/data/spells/scripts/monster/shock head skill reducer 2.lua deleted file mode 100644 index f70279d7f..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/silencer skill reducer.lua b/path_7_s/data/spells/scripts/monster/silencer skill reducer.lua deleted file mode 100644 index 5e2cc3d9d..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/souleater drown.lua b/path_7_s/data/spells/scripts/monster/souleater drown.lua deleted file mode 100644 index aa1c8c820..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/spectre drown.lua b/path_7_s/data/spells/scripts/monster/spectre drown.lua deleted file mode 100644 index d1eda5fa3..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/stampor skill reducer.lua b/path_7_s/data/spells/scripts/monster/stampor skill reducer.lua deleted file mode 100644 index 5e2594633..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/vulcongra soulfire.lua b/path_7_s/data/spells/scripts/monster/vulcongra soulfire.lua deleted file mode 100644 index d56c65ec5..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/war golem electrify.lua b/path_7_s/data/spells/scripts/monster/war golem electrify.lua deleted file mode 100644 index 630922952..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/war golem skill reducer.lua b/path_7_s/data/spells/scripts/monster/war golem skill reducer.lua deleted file mode 100644 index af28828b6..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/warlock skill reducer.lua b/path_7_s/data/spells/scripts/monster/warlock skill reducer.lua deleted file mode 100644 index 49dbbad2c..000000000 --- a/path_7_s/data/spells/scripts/monster/warlock skill reducer.lua +++ /dev/null @@ -1,14 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) -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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_7_s/data/spells/scripts/monster/werewolf skill reducer.lua b/path_7_s/data/spells/scripts/monster/werewolf skill reducer.lua deleted file mode 100644 index ceaa58e67..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/monster/young sea serpent drown.lua b/path_7_s/data/spells/scripts/monster/young sea serpent drown.lua deleted file mode 100644 index 93d9fb5b5..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/animate dead rune.lua b/path_7_s/data/spells/scripts/support/animate dead rune.lua deleted file mode 100644 index daa1dca62..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/cancel invisibility.lua b/path_7_s/data/spells/scripts/support/cancel invisibility.lua deleted file mode 100644 index 1137dce45..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/challenge.lua b/path_7_s/data/spells/scripts/support/challenge.lua deleted file mode 100644 index 348a3a7ad..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/destroy field rune.lua b/path_7_s/data/spells/scripts/support/destroy field rune.lua deleted file mode 100644 index d6ccc1162..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/disintegrate rune.lua b/path_7_s/data/spells/scripts/support/disintegrate rune.lua deleted file mode 100644 index e1f510c8d..000000000 --- a/path_7_s/data/spells/scripts/support/disintegrate rune.lua +++ /dev/null @@ -1,24 +0,0 @@ -local corpseIds = {3058, 3059, 3060, 3061, 3064, 3065, 3066} -local removalLimit = 500 - -function onCastSpell(creature, variant, isHotkey) - local position = variant:getPosition() - local tile = Tile(position) - if tile then - local items = tile:getItems() - if items then - for i, item in ipairs(items) do - if item:getType():isMovable() and item:getUniqueId() > 65535 and item:getActionId() == 0 and not isInArray(corpseIds, item:getId()) then - item:remove() - end - - if i == removalLimit then - break - end - end - end - end - - position:sendMagicEffect(CONST_ME_POFF) - return true -end diff --git a/path_7_s/data/spells/scripts/support/food.lua b/path_7_s/data/spells/scripts/support/food.lua deleted file mode 100644 index 4b7a37081..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/great light.lua b/path_7_s/data/spells/scripts/support/great light.lua deleted file mode 100644 index 8eea28af1..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/haste.lua b/path_7_s/data/spells/scripts/support/haste.lua deleted file mode 100644 index 51aca5baa..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/invisible.lua b/path_7_s/data/spells/scripts/support/invisible.lua deleted file mode 100644 index c5d1eec86..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/light.lua b/path_7_s/data/spells/scripts/support/light.lua deleted file mode 100644 index 591bf912b..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/magic rope.lua b/path_7_s/data/spells/scripts/support/magic rope.lua deleted file mode 100644 index 012311df6..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/magic shield.lua b/path_7_s/data/spells/scripts/support/magic shield.lua deleted file mode 100644 index adf714704..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/magic wall rune.lua b/path_7_s/data/spells/scripts/support/magic wall rune.lua deleted file mode 100644 index 79c26ee0c..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/paralyze rune.lua b/path_7_s/data/spells/scripts/support/paralyze rune.lua deleted file mode 100644 index 4e76c6b35..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/strong haste.lua b/path_7_s/data/spells/scripts/support/strong haste.lua deleted file mode 100644 index 3a02eadc6..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/ultimate light.lua b/path_7_s/data/spells/scripts/support/ultimate light.lua deleted file mode 100644 index cea27680f..000000000 --- a/path_7_s/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_7_s/data/spells/scripts/support/wild growth rune.lua b/path_7_s/data/spells/scripts/support/wild growth rune.lua deleted file mode 100644 index 1ab7d6004..000000000 --- a/path_7_s/data/spells/scripts/support/wild growth 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_WILDGROWTH) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_7_s/data/spells/spells.xml b/path_7_s/data/spells/spells.xml deleted file mode 100644 index ea71ad595..000000000 --- a/path_7_s/data/spells/spells.xml +++ /dev/null @@ -1,486 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/talkactions/lib/talkactions.lua b/path_7_s/data/talkactions/lib/talkactions.lua deleted file mode 100644 index 585eb19d6..000000000 --- a/path_7_s/data/talkactions/lib/talkactions.lua +++ /dev/null @@ -1 +0,0 @@ --- Nothing -- diff --git a/path_7_s/data/talkactions/scripts/add_skill.lua b/path_7_s/data/talkactions/scripts/add_skill.lua deleted file mode 100644 index 613ed0e5d..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/add_tutor.lua b/path_7_s/data/talkactions/scripts/add_tutor.lua deleted file mode 100644 index 621b6e8df..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/addon.lua b/path_7_s/data/talkactions/scripts/addon.lua deleted file mode 100644 index 50681a10a..000000000 --- a/path_7_s/data/talkactions/scripts/addon.lua +++ /dev/null @@ -1,181 +0,0 @@ -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_7_s/data/talkactions/scripts/alladdons.lua b/path_7_s/data/talkactions/scripts/alladdons.lua deleted file mode 100644 index 255da61da..000000000 --- a/path_7_s/data/talkactions/scripts/alladdons.lua +++ /dev/null @@ -1,41 +0,0 @@ -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 -} - -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_7_s/data/talkactions/scripts/allmounts.lua b/path_7_s/data/talkactions/scripts/allmounts.lua deleted file mode 100644 index 5e27a9dce..000000000 --- a/path_7_s/data/talkactions/scripts/allmounts.lua +++ /dev/null @@ -1,34 +0,0 @@ -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, 12 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_7_s/data/talkactions/scripts/animationeffect.lua b/path_7_s/data/talkactions/scripts/animationeffect.lua deleted file mode 100644 index ba55558ce..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/ban.lua b/path_7_s/data/talkactions/scripts/ban.lua deleted file mode 100644 index fc46763f0..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/broadcast.lua b/path_7_s/data/talkactions/scripts/broadcast.lua deleted file mode 100644 index 1b7a1420b..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/buyhouse.lua b/path_7_s/data/talkactions/scripts/buyhouse.lua deleted file mode 100644 index 58e0c4545..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/buyprem.lua b/path_7_s/data/talkactions/scripts/buyprem.lua deleted file mode 100644 index 1aa4f5f0e..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/chameleon.lua b/path_7_s/data/talkactions/scripts/chameleon.lua deleted file mode 100644 index d3fcbe2f7..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/changesex.lua b/path_7_s/data/talkactions/scripts/changesex.lua deleted file mode 100644 index 3b71fe0cc..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/clean.lua b/path_7_s/data/talkactions/scripts/clean.lua deleted file mode 100644 index 0d5f7aa95..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/closeserver.lua b/path_7_s/data/talkactions/scripts/closeserver.lua deleted file mode 100644 index 2f7c95ec3..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/create_item.lua b/path_7_s/data/talkactions/scripts/create_item.lua deleted file mode 100644 index 1a7bf4148..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/deathlist.lua b/path_7_s/data/talkactions/scripts/deathlist.lua deleted file mode 100644 index c1066a960..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/down.lua b/path_7_s/data/talkactions/scripts/down.lua deleted file mode 100644 index 460e0c490..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/ghost.lua b/path_7_s/data/talkactions/scripts/ghost.lua deleted file mode 100644 index 2ba455bd9..000000000 --- a/path_7_s/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_POFF) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are visible again.") - position.x = position.x + 1 - position:sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_7_s/data/talkactions/scripts/hide.lua b/path_7_s/data/talkactions/scripts/hide.lua deleted file mode 100644 index 1e84352f2..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/info.lua b/path_7_s/data/talkactions/scripts/info.lua deleted file mode 100644 index 8969b1cae..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/ipban.lua b/path_7_s/data/talkactions/scripts/ipban.lua deleted file mode 100644 index 1a393e2a9..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/kick.lua b/path_7_s/data/talkactions/scripts/kick.lua deleted file mode 100644 index 67f8ec4aa..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/kills.lua b/path_7_s/data/talkactions/scripts/kills.lua deleted file mode 100644 index 98dd37cc9..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/leavehouse.lua b/path_7_s/data/talkactions/scripts/leavehouse.lua deleted file mode 100644 index 18938cc7c..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/looktype.lua b/path_7_s/data/talkactions/scripts/looktype.lua deleted file mode 100644 index 1a1b11dc9..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/magiceffect.lua b/path_7_s/data/talkactions/scripts/magiceffect.lua deleted file mode 100644 index ebc26b3ec..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/mccheck.lua b/path_7_s/data/talkactions/scripts/mccheck.lua deleted file mode 100644 index 13ffbc970..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/online.lua b/path_7_s/data/talkactions/scripts/online.lua deleted file mode 100644 index da1c1a4bd..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/openserver.lua b/path_7_s/data/talkactions/scripts/openserver.lua deleted file mode 100644 index c3896e728..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/owner.lua b/path_7_s/data/talkactions/scripts/owner.lua deleted file mode 100644 index d56f4897b..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/place_monster.lua b/path_7_s/data/talkactions/scripts/place_monster.lua deleted file mode 100644 index 8446c0b01..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/place_npc.lua b/path_7_s/data/talkactions/scripts/place_npc.lua deleted file mode 100644 index aaf6ef6e5..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/place_summon.lua b/path_7_s/data/talkactions/scripts/place_summon.lua deleted file mode 100644 index f511d2083..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/position.lua b/path_7_s/data/talkactions/scripts/position.lua deleted file mode 100644 index 299ce6e56..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/remove_tutor.lua b/path_7_s/data/talkactions/scripts/remove_tutor.lua deleted file mode 100644 index 27b0bdb1b..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/removething.lua b/path_7_s/data/talkactions/scripts/removething.lua deleted file mode 100644 index 8216e03ba..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/save.lua b/path_7_s/data/talkactions/scripts/save.lua deleted file mode 100644 index f1949517a..000000000 --- a/path_7_s/data/talkactions/scripts/save.lua +++ /dev/null @@ -1,19 +0,0 @@ -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_7_s/data/talkactions/scripts/serverinfo.lua b/path_7_s/data/talkactions/scripts/serverinfo.lua deleted file mode 100644 index 6b26b9814..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/teleport_creature_here.lua b/path_7_s/data/talkactions/scripts/teleport_creature_here.lua deleted file mode 100644 index ea3691991..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/teleport_home.lua b/path_7_s/data/talkactions/scripts/teleport_home.lua deleted file mode 100644 index 64852301d..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/teleport_ntiles.lua b/path_7_s/data/talkactions/scripts/teleport_ntiles.lua deleted file mode 100644 index 28cbccb0f..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/teleport_to_creature.lua b/path_7_s/data/talkactions/scripts/teleport_to_creature.lua deleted file mode 100644 index 17a7da995..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/teleport_to_pos.lua b/path_7_s/data/talkactions/scripts/teleport_to_pos.lua deleted file mode 100644 index 2b0f31a20..000000000 --- a/path_7_s/data/talkactions/scripts/teleport_to_pos.lua +++ /dev/null @@ -1,27 +0,0 @@ -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_7_s/data/talkactions/scripts/teleport_to_town.lua b/path_7_s/data/talkactions/scripts/teleport_to_town.lua deleted file mode 100644 index 87cdfae39..000000000 --- a/path_7_s/data/talkactions/scripts/teleport_to_town.lua +++ /dev/null @@ -1,18 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local town = Town(param) - if town == nil then - town = Town(tonumber(param)) - end - - if town == nil then - player:sendCancelMessage("Town not found.") - return false - end - - player:teleportTo(town:getTemplePosition()) - return false -end diff --git a/path_7_s/data/talkactions/scripts/unban.lua b/path_7_s/data/talkactions/scripts/unban.lua deleted file mode 100644 index b65c4c705..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/up.lua b/path_7_s/data/talkactions/scripts/up.lua deleted file mode 100644 index c48bfd726..000000000 --- a/path_7_s/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_7_s/data/talkactions/scripts/uptime.lua b/path_7_s/data/talkactions/scripts/uptime.lua deleted file mode 100644 index 7c0e291ed..000000000 --- a/path_7_s/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_7_s/data/talkactions/talkactions.xml b/path_7_s/data/talkactions/talkactions.xml deleted file mode 100644 index ae85082af..000000000 --- a/path_7_s/data/talkactions/talkactions.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/weapons/lib/weapons.lua b/path_7_s/data/weapons/lib/weapons.lua deleted file mode 100644 index e69de29bb..000000000 diff --git a/path_7_s/data/weapons/scripts/burst_arrow.lua b/path_7_s/data/weapons/scripts/burst_arrow.lua deleted file mode 100644 index eb8290173..000000000 --- a/path_7_s/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_7_s/data/weapons/scripts/poison_arrow.lua b/path_7_s/data/weapons/scripts/poison_arrow.lua deleted file mode 100644 index 2e0f64a62..000000000 --- a/path_7_s/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_7_s/data/weapons/scripts/viper_star.lua b/path_7_s/data/weapons/scripts/viper_star.lua deleted file mode 100644 index 023325818..000000000 --- a/path_7_s/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_7_s/data/weapons/weapons.xml b/path_7_s/data/weapons/weapons.xml deleted file mode 100644 index f47b10cb1..000000000 --- a/path_7_s/data/weapons/weapons.xml +++ /dev/null @@ -1,426 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/world/forgotten-house.xml b/path_7_s/data/world/forgotten-house.xml deleted file mode 100644 index 4279d5650..000000000 --- a/path_7_s/data/world/forgotten-house.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/world/forgotten-spawn.xml b/path_7_s/data/world/forgotten-spawn.xml deleted file mode 100644 index d97e97c92..000000000 --- a/path_7_s/data/world/forgotten-spawn.xml +++ /dev/null @@ -1,1544 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_7_s/data/world/forgotten.otbm b/path_7_s/data/world/forgotten.otbm deleted file mode 100644 index 517c3c0a7..000000000 Binary files a/path_7_s/data/world/forgotten.otbm and /dev/null differ diff --git a/path_7_s/schema.sql b/path_7_s/schema.sql deleted file mode 100644 index 804f1c746..000000000 --- a/path_7_s/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_7_s/src/CMakeLists.txt b/path_7_s/src/CMakeLists.txt deleted file mode 100644 index da0aa5ed3..000000000 --- a/path_7_s/src/CMakeLists.txt +++ /dev/null @@ -1,75 +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}/definitions.h - ${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}/ioguild.cpp - ${CMAKE_CURRENT_LIST_DIR}/iologindata.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomap.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomapserialize.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}/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}/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_7_s/src/account.h b/path_7_s/src/account.h deleted file mode 100644 index 870e65018..000000000 --- a/path_7_s/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; - uint32_t 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_7_s/src/actions.cpp b/path_7_s/src/actions.cpp deleted file mode 100644 index bbe3183c3..000000000 --- a/path_7_s/src/actions.cpp +++ /dev/null @@ -1,523 +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() : - scriptInterface("Action Interface") -{ - 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); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Actions::getScriptInterface() -{ - return 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(&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 - return g_spells->getRuneSpell(item->getID()); -} - -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; - } - - bed->sleep(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()); - 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 { - std::cout << "[Warning - Action::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - 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; -} - -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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Action::executeUse] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(6); -} diff --git a/path_7_s/src/actions.h b/path_7_s/src/actions.h deleted file mode 100644 index dd6ca3c29..000000000 --- a/path_7_s/src/actions.h +++ /dev/null @@ -1,125 +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; - - 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 scriptInterface; -}; - -#endif diff --git a/path_7_s/src/ban.cpp b/path_7_s/src/ban.cpp deleted file mode 100644 index ebe974fd4..000000000 --- a/path_7_s/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_7_s/src/ban.h b/path_7_s/src/ban.h deleted file mode 100644 index 994507dd6..000000000 --- a/path_7_s/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_7_s/src/baseevents.cpp b/path_7_s/src/baseevents.cpp deleted file mode 100644 index db3f645c3..000000000 --- a/path_7_s/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() -{ - loaded = false; -} - -bool BaseEvents::loadFromXml() -{ - if (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; - } - - 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() -{ - loaded = false; - clear(); - return loadFromXml(); -} - -Event::Event(LuaScriptInterface* _interface) -{ - scriptInterface = _interface; - scriptId = 0; - scripted = false; -} - -Event::Event(const Event* copy) -{ - scriptInterface = copy->scriptInterface; - scriptId = copy->scriptId; - scripted = copy->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 (scriptId != 0) { - std::cout << "[Failure - Event::checkScript] scriptid = " << 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 (!scriptInterface || scriptId != 0) { - std::cout << "Failure: [Event::loadScript] scriptInterface == nullptr. scriptid = " << scriptId << std::endl; - return false; - } - - if (scriptInterface->loadFile(scriptFile) == -1) { - std::cout << "[Warning - Event::loadScript] Can not load script. " << scriptFile << std::endl; - std::cout << scriptInterface->getLastLuaError() << std::endl; - return false; - } - - int32_t id = scriptInterface->getEvent(getScriptEventName()); - if (id == -1) { - std::cout << "[Warning - Event::loadScript] Event " << getScriptEventName() << " not found. " << scriptFile << std::endl; - return false; - } - - scripted = true; - scriptId = id; - return true; -} - -CallBack::CallBack() -{ - scriptId = 0; - scriptInterface = nullptr; - loaded = false; -} - -bool CallBack::loadCallBack(LuaScriptInterface* _interface, const std::string& name) -{ - if (!_interface) { - std::cout << "Failure: [CallBack::loadCallBack] scriptInterface == nullptr" << std::endl; - return false; - } - - scriptInterface = _interface; - - int32_t id = scriptInterface->getEvent(name.c_str()); - if (id == -1) { - std::cout << "[Warning - CallBack::loadCallBack] Event " << name << " not found." << std::endl; - return false; - } - - callbackName = name; - scriptId = id; - loaded = true; - return true; -} diff --git a/path_7_s/src/baseevents.h b/path_7_s/src/baseevents.h deleted file mode 100644 index ccffcfbaf..000000000 --- a/path_7_s/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 scripted; - } - - protected: - virtual std::string getScriptEventName() const = 0; - - bool scripted; - int32_t scriptId; - LuaScriptInterface* scriptInterface; -}; - -class BaseEvents -{ - public: - BaseEvents(); - virtual ~BaseEvents() = default; - - bool loadFromXml(); - bool reload(); - bool isLoaded() const { - return 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 loaded; -}; - -class CallBack -{ - public: - CallBack(); - - bool loadCallBack(LuaScriptInterface* _interface, const std::string& name); - - protected: - int32_t scriptId; - LuaScriptInterface* scriptInterface; - - bool loaded; - - std::string callbackName; -}; - -#endif diff --git a/path_7_s/src/bed.cpp b/path_7_s/src/bed.cpp deleted file mode 100644 index 196421450..000000000 --- a/path_7_s/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_7_s/src/bed.h b/path_7_s/src/bed.h deleted file mode 100644 index e65dd72aa..000000000 --- a/path_7_s/src/bed.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_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; - } - - 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_7_s/src/chat.cpp b/path_7_s/src/chat.cpp deleted file mode 100644 index 9f3365d29..000000000 --- a/path_7_s/src/chat.cpp +++ /dev/null @@ -1,605 +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 "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()); -} - -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); -} - -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()))); - } - } - - 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); - - 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* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CanJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(canJoinEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(canJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnJoinEvent(const Player& player) -{ - if (onJoinEvent == -1) { - return true; - } - - //onJoin(player) - LuaScriptInterface* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onJoinEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(onJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnLeaveEvent(const Player& player) -{ - if (onLeaveEvent == -1) { - return true; - } - - //onLeave(player) - LuaScriptInterface* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnLeaveChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onLeaveEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(onLeaveEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return 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* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnSpeakChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onSpeakEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - 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 = 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!"); - } - 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_7_s/src/chat.h b/path_7_s/src/chat.h deleted file mode 100644 index 8b03ffb44..000000000 --- a/path_7_s/src/chat.h +++ /dev/null @@ -1,167 +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* getInvitedUsers() 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 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_7_s/src/combat.cpp b/path_7_s/src/combat.cpp deleted file mode 100644 index d2423e478..000000000 --- a/path_7_s/src/combat.cpp +++ /dev/null @@ -1,1408 +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->hasFlag(TILESTATE_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; - } - - 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 | 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()) { - 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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ValueCallback::getMinMaxValues] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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; - 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!"); - } - - scriptInterface->resetScriptEnv(); -} - -//**********************************************************// - -void TileCallback::onTileCombat(Creature* creature, Tile* tile) const -{ - //onTileCombat(creature, pos) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TileCallback::onTileCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - LuaScriptInterface::pushPosition(L, tile->getPosition()); - - scriptInterface->callFunction(2); -} - -//**********************************************************// - -void TargetCallback::onTargetCombat(Creature* creature, Creature* target) const -{ - //onTargetCombat(creature, target) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TargetCallback::onTargetCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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!"); - } - - 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_7_s/src/combat.h b/path_7_s/src/combat.h deleted file mode 100644 index 0e38330e7..000000000 --- a/path_7_s/src/combat.h +++ /dev/null @@ -1,383 +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_7_s/src/commands.cpp b/path_7_s/src/commands.cpp deleted file mode 100644 index eb922ccb9..000000000 --- a/path_7_s/src/commands.cpp +++ /dev/null @@ -1,344 +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() -{ - // set up command map - for (uint32_t i = 0; i < sizeof(defined_commands) / sizeof(defined_commands[0]); i++) { - commandMap[defined_commands[i].name] = new Command(defined_commands[i].f, 1, ACCOUNT_TYPE_GOD, true); - } -} - -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; - } - - 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) { - command->groupId = pugi::cast(groupAttribute.value()); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing group for command " << it->first << std::endl; - } - - pugi::xml_attribute acctypeAttribute = commandNode.attribute("acctype"); - if (acctypeAttribute) { - command->accountType = static_cast(pugi::cast(acctypeAttribute.value())); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing acctype for command " << it->first << std::endl; - } - - pugi::xml_attribute logAttribute = commandNode.attribute("log"); - if (logAttribute) { - command->log = booleanString(logAttribute.as_string()); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing log for command " << it->first << std::endl; - } - g_game.addCommandTag(it->first.front()); - } - return true; -} - -bool Commands::reload() -{ - for (const auto& it : commandMap) { - Command* command = it.second; - command->groupId = 1; - command->accountType = ACCOUNT_TYPE_GOD; - command->log = true; - } - - 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->log) { - 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) -{ - // Always reload the global libraries - g_luaEnvironment.loadFile("data/global.lua"); - - 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 == "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") { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded globals."); - } 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_7_s/src/commands.h b/path_7_s/src/commands.h deleted file mode 100644 index 7da91eb79..000000000 --- a/path_7_s/src/commands.h +++ /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. - */ - -#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; -}; - -typedef void (Commands::*CommandFunc)(Player&, const std::string&); - -struct Command { - Command(CommandFunc f, uint32_t groupId, AccountType_t accountType, bool log) - : f(f), groupId(groupId), accountType(accountType), log(log) {} - - CommandFunc f; - uint32_t groupId; - AccountType_t accountType; - bool log; -}; - -struct s_defcommands { - const char* name; - CommandFunc f; -}; - -#endif diff --git a/path_7_s/src/condition.cpp b/path_7_s/src/condition.cpp deleted file mode 100644 index 547afaabd..000000000 --- a/path_7_s/src/condition.cpp +++ /dev/null @@ -1,1632 +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_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_STATUS_SMALL, "You were healed for " + healString); - player->sendTextMessage(message); - - std::ostringstream strHealthGain; - strHealthGain << realHealthGain; - g_game.addAnimatedText(strHealthGain.str(), player->getPosition(), TEXTCOLOR_MAYABLUE); - - SpectatorVec list; - g_game.map.getSpectators(list, player->getPosition(), false, true); - list.erase(player); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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; - - 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); -} diff --git a/path_7_s/src/condition.h b/path_7_s/src/condition.h deleted file mode 100644 index c3eb5e4b5..000000000 --- a/path_7_s/src/condition.h +++ /dev/null @@ -1,379 +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; -}; - -#endif diff --git a/path_7_s/src/configmanager.cpp b/path_7_s/src/configmanager.cpp deleted file mode 100644 index 11d11b7d0..000000000 --- a/path_7_s/src/configmanager.cpp +++ /dev/null @@ -1,207 +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 -#undef lua_strlen -#define lua_strlen lua_rawlen -#endif - -extern Game g_game; - -ConfigManager::ConfigManager() - : integer(), boolean() -{ - 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); - - } - - 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[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); - - 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[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[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_7_s/src/configmanager.h b/path_7_s/src/configmanager.h deleted file mode 100644 index 27677e8aa..000000000 --- a/path_7_s/src/configmanager.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_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, - EMOTE_SPELLS, - STAMINA_SYSTEM, - WARN_UNSAFE_SCRIPTS, - CONVERT_UNSAFE_SCRIPTS, - CLASSIC_EQUIPMENT_SLOTS, - - 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, - 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, - 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_7_s/src/connection.cpp b/path_7_s/src/connection.cpp deleted file mode 100644 index 3890c97a2..000000000 --- a/path_7_s/src/connection.cpp +++ /dev/null @@ -1,295 +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; - } - - if (!receivedFirst) { - // First message received - receivedFirst = true; - - if (!protocol) { - // Game protocol has already been created at this point - protocol = service_port->make_protocol(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_7_s/src/connection.h b/path_7_s/src/connection.h deleted file mode 100644 index b2c242cb6..000000000 --- a/path_7_s/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_7_s/src/const.h b/path_7_s/src/const.h deleted file mode 100644 index 5a3898228..000000000 --- a/path_7_s/src/const.h +++ /dev/null @@ -1,468 +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_LAST = CONST_ME_PLANTATTACK, -}; - -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_LAST = CONST_ANI_CAKE, - - // 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 = 4, - TALKTYPE_CHANNEL_Y = 5, - TALKTYPE_RVR_CHANNEL = 6, - TALKTYPE_RVR_ANSWER = 7, - TALKTYPE_RVR_CONTINUE = 8, - TALKTYPE_BROADCAST = 9, - TALKTYPE_CHANNEL_R1 = 10, //red - #c text - TALKTYPE_PRIVATE_RED = 11, //@name@text - TALKTYPE_CHANNEL_O = 12, //@name@text - TALKTYPE_CHANNEL_R2 = 14, //#d - TALKTYPE_MONSTER_SAY = 16, - TALKTYPE_MONSTER_YELL = 17, -}; - -enum MessageClasses : uint8_t { - MESSAGE_STATUS_CONSOLE_YELLOW = 1, /*Yellow message in the console*/ - MESSAGE_STATUS_CONSOLE_LIGHTBLUE = 4, /*Light blue message in the console*/ - MESSAGE_STATUS_CONSOLE_ORANGE = 17, /*Orange message 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_EVENT_DEFAULT = 20, /*White message at the bottom of the game window and in the console*/ - MESSAGE_STATUS_DEFAULT = 21, /*White message at the bottom of the game window and in the console*/ - MESSAGE_INFO_DESCR = 22, /*Green message in game window and in the console*/ - MESSAGE_STATUS_SMALL = 23, /*White message at the bottom of the game window"*/ - MESSAGE_STATUS_CONSOLE_BLUE = 24, /*Blue message in the console*/ - MESSAGE_STATUS_CONSOLE_RED = 25, /*Red 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 = 155, - 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, -}; - -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, -}; - -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, -}; - -enum item_t : uint16_t { - 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 = ITEM_MAGICWALL, - - ITEM_WILDGROWTH = 1499, - ITEM_WILDGROWTH_PERSISTENT = 2721, - ITEM_WILDGROWTH_SAFE = ITEM_WILDGROWTH, - - ITEM_BAG = 1987, - - ITEM_GOLD_COIN = 2148, - ITEM_PLATINUM_COIN = 2152, - ITEM_CRYSTAL_COIN = 2160, - - ITEM_DEPOT = 2594, - ITEM_LOCKER = 2589, - - 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, - PlayerFlag_CanAnswerRuleViolations = static_cast(1) << 38, -}; - -#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 - -#define IS_IN_KEYRANGE(key, range) (key >= PSTRG_##range##_START && ((key - PSTRG_##range##_START) <= PSTRG_##range##_SIZE)) - -#endif diff --git a/path_7_s/src/container.cpp b/path_7_s/src/container.cpp deleted file mode 100644 index 0ef3e0c10..000000000 --- a/path_7_s/src/container.cpp +++ /dev/null @@ -1,705 +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; -} - -Container::Container(uint16_t _type, uint16_t _size) : Item(_type) -{ - maxSize = _size; - totalWeight = 0; - serializationCount = 0; - unlocked = true; -} - -Container::~Container() -{ - 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 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; - } - - 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_7_s/src/container.h b/path_7_s/src/container.h deleted file mode 100644 index 783bc1ca8..000000000 --- a/path_7_s/src/container.h +++ /dev/null @@ -1,170 +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; - } - - //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; - - friend class ContainerIterator; - friend class IOMapSerialize; -}; - -#endif diff --git a/path_7_s/src/creature.cpp b/path_7_s/src/creature.cpp deleted file mode 100644 index ce9ed0620..000000000 --- a/path_7_s/src/creature.cpp +++ /dev/null @@ -1,1639 +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; - moveLocked = 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); - - std::ostringstream strExp; - strExp << gainExp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_WHITE_EXP); -} - -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_7_s/src/creature.h b/path_7_s/src/creature.h deleted file mode 100644 index 5ecb83973..000000000 --- a/path_7_s/src/creature.h +++ /dev/null @@ -1,582 +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; - } - - bool isMoveLocked() const { - return moveLocked; - } - void setMoveLocked(bool locked) { - moveLocked = locked; - } - - 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; - } - - 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; - bool moveLocked; - - //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_7_s/src/creatureevent.cpp b/path_7_s/src/creatureevent.cpp deleted file mode 100644 index 161aafe78..000000000 --- a/path_7_s/src/creatureevent.cpp +++ /dev/null @@ -1,559 +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() : - scriptInterface("CreatureScript Interface") -{ - scriptInterface.initState(); -} - -CreatureEvents::~CreatureEvents() -{ - for (const auto& it : creatureEvents) { - delete it.second; - } -} - -void CreatureEvents::clear() -{ - //clear creature events - for (const auto& it : creatureEvents) { - it.second->clearEvent(); - } - - //clear lua state - scriptInterface.reInitState(); -} - -LuaScriptInterface& CreatureEvents::getScriptInterface() -{ - return 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(&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 - creatureEvents[creatureEvent->getName()] = creatureEvent; - return true; - } -} - -CreatureEvent* CreatureEvents::getEventByName(const std::string& name, bool forceLoaded /*= true*/) -{ - CreatureEventList::iterator it = creatureEvents.find(name); - if (it != 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 : 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 : 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 : 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) -{ - type = CREATURE_EVENT_NONE; - loaded = 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; - } - - eventName = nameAttribute.as_string(); - - pugi::xml_attribute typeAttribute = node.attribute("type"); - if (!typeAttribute) { - std::cout << "[Error - CreatureEvent::configureEvent] Missing type for creature event: " << eventName << std::endl; - return false; - } - - std::string tmpStr = asLowerCaseString(typeAttribute.as_string()); - if (tmpStr == "login") { - type = CREATURE_EVENT_LOGIN; - } else if (tmpStr == "logout") { - type = CREATURE_EVENT_LOGOUT; - } else if (tmpStr == "think") { - type = CREATURE_EVENT_THINK; - } else if (tmpStr == "preparedeath") { - type = CREATURE_EVENT_PREPAREDEATH; - } else if (tmpStr == "death") { - type = CREATURE_EVENT_DEATH; - } else if (tmpStr == "kill") { - type = CREATURE_EVENT_KILL; - } else if (tmpStr == "advance") { - type = CREATURE_EVENT_ADVANCE; - } else if (tmpStr == "textedit") { - type = CREATURE_EVENT_TEXTEDIT; - } else if (tmpStr == "healthchange") { - type = CREATURE_EVENT_HEALTHCHANGE; - } else if (tmpStr == "manachange") { - type = CREATURE_EVENT_MANACHANGE; - } else if (tmpStr == "extendedopcode") { - type = CREATURE_EVENT_EXTENDED_OPCODE; - } else { - std::cout << "[Error - CreatureEvent::configureEvent] Invalid type for creature event: " << eventName << std::endl; - return false; - } - - loaded = true; - return true; -} - -std::string CreatureEvent::getScriptEventName() const -{ - //Depending on the type script event name is different - switch (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_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) -{ - scriptId = creatureEvent->scriptId; - scriptInterface = creatureEvent->scriptInterface; - scripted = creatureEvent->scripted; - loaded = creatureEvent->loaded; -} - -void CreatureEvent::clearEvent() -{ - scriptId = 0; - scriptInterface = nullptr; - scripted = false; - loaded = false; -} - -bool CreatureEvent::executeOnLogin(Player* player) -{ - //onLogin(player) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogin] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnLogout(Player* player) -{ - //onLogout(player) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogout] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnThink(Creature* creature, uint32_t interval) -{ - //onThink(creature, interval) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnThink] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, interval); - - return scriptInterface->callFunction(2); -} - -bool CreatureEvent::executeOnPrepareDeath(Creature* creature, Creature* killer) -{ - //onPrepareDeath(creature, killer) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnPrepareDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(6); -} - -bool CreatureEvent::executeAdvance(Player* player, skills_t skill, uint32_t oldLevel, - uint32_t newLevel) -{ - //onAdvance(player, skill, oldLevel, newLevel) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeAdvance] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(4); -} - -void CreatureEvent::executeOnKill(Creature* creature, Creature* target) -{ - //onKill(creature, target) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnKill] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setCreatureMetatable(L, -1, target); - scriptInterface->callVoidFunction(2); -} - -bool CreatureEvent::executeTextEdit(Player* player, Item* item, const std::string& text) -{ - //onTextEdit(player, item, text) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeTextEdit] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushString(L, text); - - return scriptInterface->callFunction(3); -} - -void CreatureEvent::executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage) -{ - //onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeHealthChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(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 (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; - } - } - - scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeManaChange(Creature* creature, Creature* attacker, int32_t& manaChange, CombatOrigin origin) -{ - //onManaChange(creature, attacker, manaChange, origin) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeManaChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(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 (scriptInterface->protectedCall(L, 4, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(L, -1)); - } else { - manaChange = LuaScriptInterface::getNumber(L, -1); - } - lua_pop(L, 1); - - scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer) -{ - //onExtendedOpcode(player, opcode, buffer) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeExtendedOpcode] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, opcode); - LuaScriptInterface::pushString(L, buffer); - - scriptInterface->callVoidFunction(3); -} diff --git a/path_7_s/src/creatureevent.h b/path_7_s/src/creatureevent.h deleted file mode 100644 index a96ce8edd..000000000 --- a/path_7_s/src/creatureevent.h +++ /dev/null @@ -1,117 +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_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 creatureEvents; - - LuaScriptInterface scriptInterface; -}; - -class CreatureEvent final : public Event -{ - public: - explicit CreatureEvent(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - - CreatureEventType_t getEventType() const { - return type; - } - const std::string& getName() const { - return eventName; - } - bool isLoaded() const { - return loaded; - } - - 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); - 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 eventName; - CreatureEventType_t type; - bool loaded; -}; - -#endif diff --git a/path_7_s/src/cylinder.cpp b/path_7_s/src/cylinder.cpp deleted file mode 100644 index 4d4a22ede..000000000 --- a/path_7_s/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_7_s/src/cylinder.h b/path_7_s/src/cylinder.h deleted file mode 100644 index 2c61889ea..000000000 --- a/path_7_s/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_7_s/src/database.cpp b/path_7_s/src/database.cpp deleted file mode 100644 index a10524ff3..000000000 --- a/path_7_s/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_7_s/src/database.h b/path_7_s/src/database.h deleted file mode 100644 index d3f2c8b8e..000000000 --- a/path_7_s/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_7_s/src/databasemanager.cpp b/path_7_s/src/databasemanager.cpp deleted file mode 100644 index 2940f201e..000000000 --- a/path_7_s/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_7_s/src/databasemanager.h b/path_7_s/src/databasemanager.h deleted file mode 100644 index 128827578..000000000 --- a/path_7_s/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_7_s/src/databasetasks.cpp b/path_7_s/src/databasetasks.cpp deleted file mode 100644 index f479500dc..000000000 --- a/path_7_s/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_7_s/src/databasetasks.h b/path_7_s/src/databasetasks.h deleted file mode 100644 index 1d8738f40..000000000 --- a/path_7_s/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_7_s/src/definitions.h b/path_7_s/src/definitions.h deleted file mode 100644 index 44c6deea0..000000000 --- a/path_7_s/src/definitions.h +++ /dev/null @@ -1,84 +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 "3" -#define REVISION_VERSION "-" -#define SOFTWARE_CODENAME "-" -#define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" -#define GIT_REPO "https://github.com/mattyx14/otxserver/" - -#define CLIENT_VERSION_MIN 811 -#define CLIENT_VERSION_MAX 811 -#define CLIENT_VERSION_STR "8.11" - -#ifndef __FUNCTION__ -#define __FUNCTION__ __func__ -#endif - -#ifndef _USE_MATH_DEFINES -#define _USE_MATH_DEFINES -#endif - -#include -#include -#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 -#pragma warning(disable:4996) -#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 - -typedef std::vector> IPList; - -#endif diff --git a/path_7_s/src/depotchest.cpp b/path_7_s/src/depotchest.cpp deleted file mode 100644 index 64e8c4710..000000000 --- a/path_7_s/src/depotchest.cpp +++ /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. - */ - -#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) -{ - if (parent != nullptr) { - parent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void DepotChest::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - if (parent != nullptr) { - parent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} diff --git a/path_7_s/src/depotchest.h b/path_7_s/src/depotchest.h deleted file mode 100644 index 1e1b267eb..000000000 --- a/path_7_s/src/depotchest.h +++ /dev/null @@ -1,56 +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* getRealParent() const { - return parent; - } - - private: - uint32_t maxDepotItems; -}; - -#endif - diff --git a/path_7_s/src/depotlocker.cpp b/path_7_s/src/depotlocker.cpp deleted file mode 100644 index 64b58f795..000000000 --- a/path_7_s/src/depotlocker.cpp +++ /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. - */ - -#include "otpch.h" - -#include "depotlocker.h" - -DepotLocker::DepotLocker(uint16_t _type) : - Container(_type) -{ - depotId = 0; - maxSize = 30; -} - -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 index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor/* = nullptr*/) const -{ - return Container::queryAdd(index, thing, count, flags, actor); -} - -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); - } -} diff --git a/path_7_s/src/depotlocker.h b/path_7_s/src/depotlocker.h deleted file mode 100644 index 5ed614196..000000000 --- a/path_7_s/src/depotlocker.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_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 -#define FS_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 - -#include "container.h" - -class DepotLocker final : public Container -{ - public: - explicit DepotLocker(uint16_t _type); - - DepotLocker* getDepotLocker() final { - return this; - } - const DepotLocker* getDepotLocker() const final { - return this; - } - - //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_7_s/src/enums.h b/path_7_s/src/enums.h deleted file mode 100644 index b512e65e5..000000000 --- a/path_7_s/src/enums.h +++ /dev/null @@ -1,444 +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 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 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_NONE = 0, - - CLIENTOS_LINUX = 1, - CLIENTOS_WINDOWS = 2, - CLIENTOS_FLASH = 3, - - CLIENTOS_OTCLIENT_LINUX = 10, - CLIENTOS_OTCLIENT_WINDOWS = 11, - CLIENTOS_OTCLIENT_MAC = 12, -}; - -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 = 0, - - 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, -}; - -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 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; - lookHead = 0; - lookBody = 0; - lookLegs = 0; - lookFeet = 0; - lookAddons = 0; - } - - uint16_t lookType; - uint16_t lookTypeEx; - 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; - } -}; - -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; - } -}; - -#endif diff --git a/path_7_s/src/events.cpp b/path_7_s/src/events.cpp deleted file mode 100644 index 8830581c0..000000000 --- a/path_7_s/src/events.cpp +++ /dev/null @@ -1,758 +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 - playerOnLook = -1; - playerOnLookInBattleList = -1; - playerOnLookInTrade = -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 == "onLook") { - playerOnLook = event; - } else if (methodName == "onLookInBattleList") { - playerOnLookInBattleList = event; - } else if (methodName == "onLookInTrade") { - playerOnLookInTrade = 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 -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::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_7_s/src/events.h b/path_7_s/src/events.h deleted file mode 100644 index 0c5288b22..000000000 --- a/path_7_s/src/events.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_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 - 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 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 playerOnLook; - int32_t playerOnLookInBattleList; - int32_t playerOnLookInTrade; - 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_7_s/src/fileloader.cpp b/path_7_s/src/fileloader.cpp deleted file mode 100644 index 1fa6fea2f..000000000 --- a/path_7_s/src/fileloader.cpp +++ /dev/null @@ -1,419 +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() : cached_data() -{ - file = nullptr; - root = nullptr; - buffer = new uint8_t[1024]; - buffer_size = 1024; - lastError = ERROR_NONE; - - //cache - cache_size = 0; - cache_index = NO_VALID_CACHE; - cache_offset = NO_VALID_CACHE; -} - -FileLoader::~FileLoader() -{ - if (file) { - fclose(file); - file = nullptr; - } - - NodeStruct::clearNet(root); - delete[] buffer; - - for (int32_t i = 0; i < CACHE_BLOCKS; i++) { - delete[] cached_data[i].data; - } -} - -bool FileLoader::openFile(const char* filename, const char* accept_identifier) -{ - file = fopen(filename, "rb"); - if (!file) { - lastError = ERROR_CAN_NOT_OPEN; - return false; - } - - char identifier[4]; - if (fread(identifier, 1, 4, file) < 4) { - fclose(file); - file = nullptr; - 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(file); - file = nullptr; - lastError = ERROR_INVALID_FILE_VERSION; - return false; - } - - fseek(file, 0, SEEK_END); - int32_t file_size = ftell(file); - cache_size = std::min(32768, std::max(file_size / 20, 8192)) & ~0x1FFF; - - if (!safeSeek(4)) { - lastError = ERROR_INVALID_FORMAT; - return false; - } - - delete root; - root = new NodeStruct(); - root->start = 4; - - int32_t byte; - if (safeSeek(4) && readByte(byte) && byte == NODE_START) { - return parseNode(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: - 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 >= buffer_size) { - delete[] buffer; - - while (node->propsSize >= buffer_size) { - buffer_size *= 2; - } - - buffer = new uint8_t[buffer_size]; - } - - //get buffer - if (!readBytes(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 (buffer[i] == ESCAPE_CHAR) { - //escape char found, skip it and write next - buffer[j] = buffer[++i]; - //is neede a displacement for next bytes - escaped = true; - } else if (escaped) { - //perform that displacement - buffer[j] = buffer[i]; - } - } - - size = j; - return 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 = root->type; - return 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 (cache_index == NO_VALID_CACHE) { - lastError = ERROR_CACHE_ERROR; - return false; - } - - if (cache_offset >= cached_data[cache_index].size) { - int32_t pos = cache_offset + cached_data[cache_index].base; - int32_t tmp = getCacheBlock(pos); - if (tmp < 0) { - return false; - } - - cache_index = tmp; - cache_offset = pos - cached_data[cache_index].base; - if (cache_offset >= cached_data[cache_index].size) { - return false; - } - } - - value = cached_data[cache_index].data[cache_offset++]; - return true; -} - -inline bool FileLoader::readBytes(uint32_t size, int32_t pos) -{ - //seek at pos - uint32_t remain = size; - uint8_t* buf = this->buffer; - do { - //prepare cache - uint32_t i = getCacheBlock(pos); - if (i == NO_VALID_CACHE) { - return false; - } - - cache_index = i; - cache_offset = pos - cached_data[i].base; - - //get maximum read block size and calculate remaining bytes - uint32_t reading = std::min(remain, cached_data[i].size - cache_offset); - remain -= reading; - - //read it - memcpy(buf, cached_data[cache_index].data + cache_offset, reading); - - //update variables - cache_offset += reading; - buf += 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; - } - - cache_index = i; - cache_offset = pos - cached_data[i].base; - return true; -} - -inline bool FileLoader::safeTell(int32_t& pos) -{ - if (cache_index == NO_VALID_CACHE) { - lastError = ERROR_CACHE_ERROR; - return false; - } - - pos = cached_data[cache_index].base + cache_offset - 1; - return true; -} - -inline uint32_t FileLoader::getCacheBlock(uint32_t pos) -{ - bool found = false; - uint32_t i, base_pos = pos & ~(cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (cached_data[i].loaded) { - if (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 & ~(cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (!cached_data[i].loaded) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - for (i = 0; i < CACHE_BLOCKS; i++) { - if (std::abs(static_cast(cached_data[i].base) - base_pos) > static_cast(2 * cache_size)) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - loading_cache = 0; - } - } - - if (cached_data[loading_cache].data == nullptr) { - cached_data[loading_cache].data = new uint8_t[cache_size]; - } - - cached_data[loading_cache].base = base_pos; - - if (fseek(file, cached_data[loading_cache].base, SEEK_SET) != 0) { - lastError = ERROR_SEEK_ERROR; - return -1; - } - - uint32_t size = fread(cached_data[loading_cache].data, 1, cache_size, file); - cached_data[loading_cache].size = size; - - if (size < (pos - cached_data[loading_cache].base)) { - lastError = ERROR_SEEK_ERROR; - return -1; - } - - cached_data[loading_cache].loaded = 1; - return loading_cache; -} diff --git a/path_7_s/src/fileloader.h b/path_7_s/src/fileloader.h deleted file mode 100644 index 54331dcb2..000000000 --- a/path_7_s/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 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(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 cached_data[CACHE_BLOCKS]; - - uint8_t* buffer; - NODE root; - FILE* file; - - FILELOADER_ERRORS lastError; - uint32_t buffer_size; - - uint32_t cache_size; -#define NO_VALID_CACHE 0xFFFFFFFF - uint32_t cache_index; - uint32_t 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_7_s/src/game.cpp b/path_7_s/src/game.cpp deleted file mode 100644 index 197311eeb..000000000 --- a/path_7_s/src/game.cpp +++ /dev/null @@ -1,4644 +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 "actions.h" -#include "iologindata.h" -#include "talkaction.h" -#include "spells.h" -#include "configmanager.h" -#include "server.h" -#include "globalevent.h" -#include "bed.h" -#include "scheduler.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) -{ - 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; -} - -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(); - - 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; - } - - 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->hasFlag(TILESTATE_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->hasFlag(TILESTATE_BLOCKSOLID))) { - tmpTile = map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_BLOCKSOLID)) { - flags |= FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE; - - if (!tmpTile->hasFlag(TILESTATE_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->hasFlag(TILESTATE_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, item->isRune() ? item->getItemCount() : 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*/) -{ - 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()) { - if (item->isRune()) { - m = std::min(item->getItemCount(), maxQueryCount); - } else { - 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->isRune() && 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->isRune() && 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; - } - - 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* subContainer = item->getContainer(); - if (subContainer) { - containers.push_back(subContainer); - } - } - } - 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 { - const uint32_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 { - const uint32_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) { - internalRemoveItem(item); - money -= moneyEntry.first; - } else if (moneyEntry.first > money) { - const uint32_t worth = moneyEntry.first / item->getItemCount(); - const uint32_t removeCount = (money / worth) + 1; - - addMoney(cylinder, (worth * removeCount) - money, flags); - internalRemoveItem(item, removeCount); - break; - } else { - internalRemoveItem(item); - break; - } - } - return true; -} - -void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) -{ - 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); - } - - crystalCoins -= count; - } - - 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 -= platinumCoins * 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; - } - - 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; - } - - player->sendChannel(channel->getId(), channel->getName()); -} - -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::playerReceivePing(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->receivePing(); -} - -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) { - return; - } - - 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::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::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::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::playerChangeOutfit(uint32_t playerId, Outfit_t outfit) -{ - if (!g_config.getBoolean(ConfigManager::ALLOW_CHANGEOUTFIT)) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - 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) { - 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: - case TALKTYPE_PRIVATE_RED: - playerSpeakTo(player, type, receiver, text); - break; - - case TALKTYPE_CHANNEL_O: - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - case TALKTYPE_CHANNEL_R2: - g_chat->talkToChannel(*player, type, text, channelId); - 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 && (player->hasFlag(PlayerFlag_CanTalkRedPrivate) || player->getAccountType() >= ACCOUNT_TYPE_GAMEMASTER)) { - type = TALKTYPE_PRIVATE_RED; - } else { - type = TALKTYPE_PRIVATE; - } - - 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; -} - -//-- -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 (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; - std::ostringstream strHealthChange; - strHealthChange << realHealthChange; - addAnimatedText(strHealthChange.str(), targetPos, 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_STATUS_SMALL; - message.text = "You heal " + target->getNameDescription() + " for " + damageString; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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(); - 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; - 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 += '.'; - - std::ostringstream strManaDamage; - strManaDamage << manaDamage; - addAnimatedText(strManaDamage.str(), targetPos, 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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.primary.color != TEXTCOLOR_NONE) { - std::ostringstream strPrimaryDamage; - strPrimaryDamage << message.primary.value; - addAnimatedText(strPrimaryDamage.str(), targetPos, message.primary.color); - } - } - - if (message.secondary.value) { - combatGetTypeInfo(damage.secondary.type, target, message.secondary.color, hitEffect); - if (hitEffect != CONST_ME_NONE) { - addMagicEffect(list, targetPos, hitEffect); - } - - if (message.secondary.color != TEXTCOLOR_NONE) { - std::ostringstream strSecondaryDamage; - strSecondaryDamage << message.secondary.value; - addAnimatedText(strSecondaryDamage.str(), targetPos, message.secondary.color); - } - } - - 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - // 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 (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(); - 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; - std::ostringstream strManaLoss; - strManaLoss << manaLoss; - addAnimatedText(strManaLoss.str(), targetPos, 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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::addAnimatedText(const std::string& message, const Position& pos, TextColor_t color) -{ - SpectatorVec list; - map.getSpectators(list, pos, true, true); - addAnimatedText(list, message, pos, color); -} - -void Game::addAnimatedText(const SpectatorVec& list, const std::string& message, const Position& pos, TextColor_t color) -{ - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendAnimatedText(message, pos, color); - } - } -} - -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::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::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& bug) -{ - 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& position = player->getPosition(); - fprintf(file, "------------------------------\nName: %s [Position X: %u Y: %u Z: %u]\nBug Report: %s\n", player->getName().c_str(), position.x, position.y, position.z, bug.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::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); - } -} - -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::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::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_7_s/src/game.h b/path_7_s/src/game.h deleted file mode 100644 index 51fb5e847..000000000 --- a/path_7_s/src/game.h +++ /dev/null @@ -1,547 +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& bug); - void playerDebugAssert(uint32_t playerId, const std::string& assertLine, const std::string& date, const std::string& description, const std::string& comment); - - 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 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 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 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 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 parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer); - - 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); - - 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 addAnimatedText(const std::string& message, const Position& pos, TextColor_t color); - static void addAnimatedText(const SpectatorVec& list, const std::string& message, const Position& pos, TextColor_t color); - 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++; } - - const std::unordered_map& getPlayers() const { return players; } - const std::map& getNpcs() const { return npcs; } - - 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 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; - 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 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; - - 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_7_s/src/globalevent.cpp b/path_7_s/src/globalevent.cpp deleted file mode 100644 index 66c610ab3..000000000 --- a/path_7_s/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() : - scriptInterface("GlobalEvent Interface") -{ - 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); - - scriptInterface.reInitState(); -} - -Event* GlobalEvents::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "globalevent") != 0) { - return nullptr; - } - return new GlobalEvent(&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) -{ - eventType = GLOBALEVENT_NONE; - nextExecution = 0; - 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; - } - - name = nameAttribute.as_string(); - 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: " << name << std::endl; - return false; - } - - 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: " << 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: " << 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; - } - - nextExecution = current_time + difference; - eventType = GLOBALEVENT_TIMER; - } else if ((attr = node.attribute("type"))) { - const char* value = attr.value(); - if (strcasecmp(value, "startup") == 0) { - eventType = GLOBALEVENT_STARTUP; - } else if (strcasecmp(value, "shutdown") == 0) { - eventType = GLOBALEVENT_SHUTDOWN; - } else if (strcasecmp(value, "record") == 0) { - eventType = GLOBALEVENT_RECORD; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No valid type \"" << attr.as_string() << "\" for globalevent with name " << name << std::endl; - return false; - } - } else if ((attr = node.attribute("interval"))) { - interval = std::max(SCHEDULER_MINTICKS, pugi::cast(attr.value())); - nextExecution = OTSYS_TIME() + interval; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No interval for globalevent with name " << name << std::endl; - return false; - } - return true; -} - -std::string GlobalEvent::getScriptEventName() const -{ - switch (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeRecord] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - lua_pushnumber(L, current); - lua_pushnumber(L, old); - return scriptInterface->callFunction(2); -} - -bool GlobalEvent::executeEvent() -{ - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeEvent] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - int32_t params = 0; - if (eventType == GLOBALEVENT_NONE || eventType == GLOBALEVENT_TIMER) { - lua_pushnumber(L, interval); - params = 1; - } - - return scriptInterface->callFunction(params); -} diff --git a/path_7_s/src/globalevent.h b/path_7_s/src/globalevent.h deleted file mode 100644 index 0a566b78b..000000000 --- a/path_7_s/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 scriptInterface; - } - LuaScriptInterface 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 eventType; - } - std::string getName() const { - return name; - } - - uint32_t getInterval() const { - return interval; - } - - int64_t getNextExecution() const { - return nextExecution; - } - void setNextExecution(int64_t time) { - nextExecution = time; - } - - protected: - GlobalEvent_t eventType; - - std::string getScriptEventName() const final; - - std::string name; - int64_t nextExecution; - uint32_t interval; -}; - -#endif diff --git a/path_7_s/src/groups.cpp b/path_7_s/src/groups.cpp deleted file mode 100644 index 7eb526276..000000000 --- a/path_7_s/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_7_s/src/groups.h b/path_7_s/src/groups.h deleted file mode 100644 index ff275bf42..000000000 --- a/path_7_s/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_7_s/src/guild.cpp b/path_7_s/src/guild.cpp deleted file mode 100644 index a3b736cfd..000000000 --- a/path_7_s/src/guild.cpp +++ /dev/null @@ -1,65 +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); -} - -void Guild::removeMember(Player* player) -{ - membersOnline.remove(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_7_s/src/guild.h b/path_7_s/src/guild.h deleted file mode 100644 index 6193e42d8..000000000 --- a/path_7_s/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_7_s/src/house.cpp b/path_7_s/src/house.cpp deleted file mode 100644 index 8a0c65f43..000000000 --- a/path_7_s/src/house.cpp +++ /dev/null @@ -1,760 +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_LOCKER) -{ - 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); - } - } - } - } - } - } - - DepotLocker* depotLocker = player->getDepotLocker(townid); - if (depotLocker) { - for (Item* item : moveItemList) { - g_game.internalMoveItem(item->getParent(), depotLocker, 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()); - DepotLocker* depotLocker = player.getDepotLocker(town->getID()); - if (depotLocker) { - g_game.internalAddItem(depotLocker, letter, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - house->setPayRentWarnings(house->getPayRentWarnings() + 1); - } else { - house->setOwner(0, true, &player); - } - } - - IOLoginData::savePlayer(&player); - } -} diff --git a/path_7_s/src/house.h b/path_7_s/src/house.h deleted file mode 100644 index b11abe9b0..000000000 --- a/path_7_s/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_7_s/src/housetile.cpp b/path_7_s/src/housetile.cpp deleted file mode 100644 index 44db6f597..000000000 --- a/path_7_s/src/housetile.cpp +++ /dev/null @@ -1,125 +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; -} - -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_7_s/src/housetile.h b/path_7_s/src/housetile.h deleted file mode 100644 index bc26e04d4..000000000 --- a/path_7_s/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_7_s/src/ioguild.cpp b/path_7_s/src/ioguild.cpp deleted file mode 100644 index 5a700e2a9..000000000 --- a/path_7_s/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_7_s/src/ioguild.h b/path_7_s/src/ioguild.h deleted file mode 100644 index 9b4171ae9..000000000 --- a/path_7_s/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_7_s/src/iologindata.cpp b/path_7_s/src/iologindata.cpp deleted file mode 100644 index 1651cb199..000000000 --- a/path_7_s/src/iologindata.cpp +++ /dev/null @@ -1,986 +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->getNumber("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(uint32_t accountName, 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` = " << accountName; - 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->getNumber("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(uint32_t accountName, const std::string& password, std::string& characterName) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id`, `password` FROM `accounts` WHERE `name` = " << 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; - } - } - } - - 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) { - DepotLocker* depotLocker = player->getDepotLocker(pid); - if (depotLocker) { - depotLocker->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; - } - 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 (const auto& it : player->depotLockerMap) { - DepotLocker* depotLocker = it.second; - for (Item* item : depotLocker->getItemList()) { - if (item->getID() != ITEM_DEPOT) { - itemList.emplace_back(it.first, 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") - ); - } while (result->next()); - } - return entries; -} - -void IOLoginData::addVIPEntry(uint32_t accountId, uint32_t guid) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "INSERT INTO `account_viplist` (`account_id`, `player_id`) VALUES (" << accountId << ',' << 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_7_s/src/iologindata.h b/path_7_s/src/iologindata.h deleted file mode 100644 index 5b26605fb..000000000 --- a/path_7_s/src/iologindata.h +++ /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. - */ - -#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(uint32_t accountName, const std::string& password, Account& account); - static uint32_t gameworldAuthentication(uint32_t 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); - 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_7_s/src/iomap.cpp b/path_7_s/src/iomap.cpp deleted file mode 100644 index bb8a60d79..000000000 --- a/path_7_s/src/iomap.cpp +++ /dev/null @@ -1,472 +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, uint16_t x, uint16_t y, uint8_t z) -{ - if (!ground) { - return new StaticTile(x, y, z); - } - - Tile* tile; - if ((item && item->isBlocking()) || ground->isBlocking()) { - tile = new StaticTile(x, y, z); - } else { - tile = new DynamicTile(x, y, z); - } - - 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 > 3) { - setLastErrorString("Unknown OTBM version detected."); - 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_811) { - 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; - } - - uint16_t base_x = area_coord.x; - uint16_t base_y = area_coord.y; - uint16_t 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 x = base_x + tile_coord.x; - uint16_t y = base_y + tile_coord.y; - - 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:" << x << ", y:" << y << ", z:" << z << "] Could not read house id."; - setLastErrorString(ss.str()); - return false; - } - - house = map->houses.addHouse(houseId); - if (!house) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not create house id: " << houseId; - setLastErrorString(ss.str()); - return false; - } - - tile = new HouseTile(x, y, z, 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:" << x << ", y:" << y << ", z:" << z << "] Failed to read tile flags."; - setLastErrorString(ss.str()); - return false; - } - - if ((flags & OTBM_TILEFLAG_PROTECTIONZONE) != 0) { - tileflags |= TILESTATE_PROTECTIONZONE; - } else if ((flags & OTBM_TILEFLAG_NOPVPZONE) != 0) { - tileflags |= TILESTATE_NOPVPZONE; - } else if ((flags & OTBM_TILEFLAG_PVPZONE) != 0) { - tileflags |= TILESTATE_PVPZONE; - } - - if ((flags & OTBM_TILEFLAG_NOLOGOUT) != 0) { - tileflags |= TILESTATE_NOLOGOUT; - } - break; - } - - case OTBM_ATTR_ITEM: { - Item* item = Item::CreateItem(propStream); - if (!item) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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: " << x << ", y: " << y << ", z: " << z << "]." << 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, x, y, z); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - break; - } - - default: - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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:" << x << ", y:" << y << ", z:" << z << "] 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:" << x << ", y:" << y << ", z:" << z << "] Failed to create item."; - setLastErrorString(ss.str()); - return false; - } - - if (!item->unserializeItemNode(f, nodeItem, stream)) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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: " << x << ", y: " << y << ", z: " << z << "]." << 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, x, y, z); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - - nodeItem = f.getNextNode(nodeItem, type); - } - - if (!tile) { - tile = createTile(ground_item, nullptr, x, y, z); - } - - tile->setFlag(static_cast(tileflags)); - - map->setTile(x, y, z, 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_7_s/src/iomap.h b/path_7_s/src/iomap.h deleted file mode 100644 index 8595d2045..000000000 --- a/path_7_s/src/iomap.h +++ /dev/null @@ -1,154 +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, -}; - -enum OTBM_TileFlag_t : uint32_t { - OTBM_TILEFLAG_PROTECTIONZONE = 1 << 0, - OTBM_TILEFLAG_NOPVPZONE = 1 << 2, - OTBM_TILEFLAG_NOLOGOUT = 1 << 3, - OTBM_TILEFLAG_PVPZONE = 1 << 4 -}; - -#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; -}; - -#pragma pack() - -class IOMap -{ - static Tile* createTile(Item*& ground, Item* item, uint16_t x, uint16_t y, uint8_t z); - - 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_7_s/src/iomapserialize.cpp b/path_7_s/src/iomapserialize.cpp deleted file mode 100644 index dddd4d696..000000000 --- a/path_7_s/src/iomapserialize.cpp +++ /dev/null @@ -1,372 +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 "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_7_s/src/iomapserialize.h b/path_7_s/src/iomapserialize.h deleted file mode 100644 index 8de71d4cb..000000000 --- a/path_7_s/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_7_s/src/item.cpp b/path_7_s/src/item.cpp deleted file mode 100644 index 035d6b59a..000000000 --- a/path_7_s/src/item.cpp +++ /dev/null @@ -1,1665 +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 "bed.h" - -#include "actions.h" -#include "spells.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.runeSpellName.empty()) { - s << " (\"" << it.runeSpellName << "\")"; - } - - if (it.runeLevel > 0 || it.runeMagLevel > 0) { - if (RuneSpell* rune = g_spells->getRuneSpell(it.id)) { - int32_t tmpSubType = subType; - if (item) { - tmpSubType = item->getSubType(); - } - s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used by "; - - 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 { - s << ", "; - } - } - s << asLowerCaseString((*vocLast)->getVocName()) << "s"; - } else { - s << "players"; - } - - 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())) { - uint32_t 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.vocationString.empty()) { - 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; -} - -uint32_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); -} diff --git a/path_7_s/src/item.h b/path_7_s/src/item.h deleted file mode 100644 index 8d61fcc4f..000000000 --- a/path_7_s/src/item.h +++ /dev/null @@ -1,772 +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; - } - 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; - } - - uint32_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 isRune() const { - return items[id].isRune(); - } - 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(); - - void setLoadedFromMap(bool value) { - loadedFromMap = value; - } - bool isCleanable() const { - return !loadedFromMap && canRemove() && isPickupable() && !hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) && !hasAttribute(ITEM_ATTRIBUTE_ACTIONID); - } - - 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_7_s/src/itemloader.h b/path_7_s/src/itemloader.h deleted file mode 100644 index 83bda911d..000000000 --- a/path_7_s/src/itemloader.h +++ /dev/null @@ -1,150 +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, -}; - -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, // unused - FLAG_FLOORCHANGENORTH = 1 << 9, // unused - FLAG_FLOORCHANGEEAST = 1 << 10, // unused - FLAG_FLOORCHANGESOUTH = 1 << 11, // unused - FLAG_FLOORCHANGEWEST = 1 << 12, // unused - FLAG_ALWAYSONTOP = 1 << 13, - FLAG_READABLE = 1 << 14, - FLAG_ROTATABLE = 1 << 15, - FLAG_HANGABLE = 1 << 16, - FLAG_VERTICAL = 1 << 17, - FLAG_HORIZONTAL = 1 << 18, - FLAG_CANNOTDECAY = 1 << 19, // unused - FLAG_ALLOWDISTREAD = 1 << 20, - FLAG_UNUSED = 1 << 21, // unused - FLAG_CLIENTCHARGES = 1 << 22, /* deprecated */ - FLAG_LOOKTHROUGH = 1 << 23, - FLAG_ANIMATION = 1 << 24, - FLAG_FULLTILE = 1 << 25, // unused - 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_7_s/src/items.cpp b/path_7_s/src/items.cpp deleted file mode 100644 index 082b4ee84..000000000 --- a/path_7_s/src/items.cpp +++ /dev/null @@ -1,954 +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() : - group(ITEM_GROUP_NONE), type(ITEM_TYPE_NONE), id(0), clientId(0), - stackable(false), weight(0), levelDoor(0), decayTime(0), - wieldInfo(0), minReqLevel(0), minReqMagicLevel(0), charges(0), maxHitChance(-1), - decayTo(-1), attack(0), defense(0), extraDefense(0), armor(0), rotateTo(0), - runeMagLevel(0), runeLevel(0), combatType(COMBAT_NONE), transformToOnUse(), - transformToFree(0), destroyTo(0), maxTextLen(0), writeOnceItemId(0), - transformEquipTo(0), transformDeEquipTo(0), maxItems(8), slotPosition(SLOTP_HAND), - speed(0), wareId(0), magicEffect(CONST_ME_NONE), bedPartnerDir(DIRECTION_NONE), - weaponType(WEAPON_NONE), ammoType(AMMO_NONE), shootType(CONST_ANI_NONE), - corpseType(RACE_NONE), fluidSource(FLUID_NONE), floorChange(0), - alwaysOnTopOrder(0), lightLevel(0), lightColor(0), shootRange(1), hitChance(0), - forceUse(false), hasHeight(false), walkStack(true), blockSolid(false), - blockPickupable(false), blockProjectile(false), blockPathFind(false), - allowPickupable(false), showDuration(false), showCharges(false), - showAttributes(false), replaceable(true), pickupable(false), rotatable(false), - useable(false), moveable(false), alwaysOnTop(false), canReadText(false), - canWriteText(false), isVertical(false), isHorizontal(false), isHangable(false), - allowDistRead(false), lookThrough(false), stopTime(false), showCount(true) -{ -} - -Items::Items() -{ - items.reserve(20000); -} - -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_811) { - 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 > 20000 && serverId < 20100) { - serverId -= 20000; - } - 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_ROTATABLE, flags); - iType.canReadText = hasBitSet(FLAG_READABLE, flags); - iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, 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 > 20000 && id < 20100) { - id -= 20000; - - 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.floorChange = TILESTATE_FLOORCHANGE_DOWN; - } else if (tmpStrValue == "north") { - it.floorChange = TILESTATE_FLOORCHANGE_NORTH; - } else if (tmpStrValue == "south") { - it.floorChange = TILESTATE_FLOORCHANGE_SOUTH; - } else if (tmpStrValue == "southalt") { - it.floorChange = TILESTATE_FLOORCHANGE_SOUTH_ALT; - } else if (tmpStrValue == "west") { - it.floorChange = TILESTATE_FLOORCHANGE_WEST; - } else if (tmpStrValue == "east") { - it.floorChange = TILESTATE_FLOORCHANGE_EAST; - } else if (tmpStrValue == "eastalt") { - it.floorChange = TILESTATE_FLOORCHANGE_EAST_ALT; - } 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_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 == "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") { - 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_7_s/src/items.h b/path_7_s/src/items.h deleted file mode 100644 index 006acc9a0..000000000 --- a/path_7_s/src/items.h +++ /dev/null @@ -1,321 +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; - - 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 floorChange; - uint8_t alwaysOnTopOrder; - uint8_t lightLevel; - uint8_t lightColor; - uint8_t shootRange; - int8_t hitChance; - - bool forceUse; - 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_7_s/src/lockfree.h b/path_7_s/src/lockfree.h deleted file mode 100644 index 43448f2c8..000000000 --- a/path_7_s/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 - explicit 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_7_s/src/luascript.cpp b/path_7_s/src/luascript.cpp deleted file mode 100644 index a4db933ee..000000000 --- a/path_7_s/src/luascript.cpp +++ /dev/null @@ -1,11961 +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::tempResults; -uint32_t ScriptEnvironment::lastResultId = 0; - -std::multimap ScriptEnvironment::tempItems; - -LuaEnvironment g_luaEnvironment; - -ScriptEnvironment::ScriptEnvironment() -{ - curNpc = nullptr; - resetEnv(); - lastUID = std::numeric_limits::max(); -} - -ScriptEnvironment::~ScriptEnvironment() -{ - resetEnv(); -} - -void ScriptEnvironment::resetEnv() -{ - scriptId = 0; - callbackId = 0; - timerEvent = false; - interface = nullptr; - localMap.clear(); - 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 (this->callbackId != 0) { - //nested callbacks are not allowed - if (interface) { - interface->reportErrorFunc("Nested callbacks!"); - } - return false; - } - - this->callbackId = callbackId; - interface = scriptInterface; - return true; -} - -void ScriptEnvironment::getEventInfo(int32_t& scriptId, LuaScriptInterface*& scriptInterface, int32_t& callbackId, bool& timerEvent) const -{ - scriptId = this->scriptId; - scriptInterface = interface; - callbackId = this->callbackId; - timerEvent = this->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[++lastUID] = item; - return 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) -{ - tempResults[++lastResultId] = res; - return lastResultId; -} - -bool ScriptEnvironment::removeResult(uint32_t id) -{ - auto it = tempResults.find(id); - if (it == tempResults.end()) { - return false; - } - - tempResults.erase(it); - return true; -} - -DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) -{ - auto it = tempResults.find(id); - if (it == 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::scriptEnv[16]; -int32_t LuaScriptInterface::scriptEnvIndex = -1; - -LuaScriptInterface::LuaScriptInterface(std::string interfaceName) - : luaState(nullptr), interfaceName(interfaceName), eventTableRef(-1), 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(luaState, file.c_str()); - if (ret != 0) { - lastLuaError = popString(luaState); - return -1; - } - - //check that it is loaded as a function - if (!isFunction(luaState, -1)) { - return -1; - } - - loadingFile = file; - - if (!reserveScriptEnv()) { - return -1; - } - - ScriptEnvironment* env = getScriptEnv(); - env->setScriptId(EVENT_ID_LOADING, this); - env->setNpc(npc); - - //execute it - ret = protectedCall(luaState, 0, 0); - if (ret != 0) { - reportError(nullptr, popString(luaState)); - resetScriptEnv(); - return -1; - } - - resetScriptEnv(); - return 0; -} - -int32_t LuaScriptInterface::getEvent(const std::string& eventName) -{ - //get our events table - lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(luaState, eventName.c_str()); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 2); - return -1; - } - - //save in our events table - lua_pushvalue(luaState, -1); - lua_rawseti(luaState, -3, runningEventId); - lua_pop(luaState, 2); - - //reset global value of this event - lua_pushnil(luaState); - lua_setglobal(luaState, eventName.c_str()); - - cacheFiles[runningEventId] = loadingFile + ":" + eventName; - return runningEventId++; -} - -int32_t LuaScriptInterface::getMetaEvent(const std::string& globalName, const std::string& eventName) -{ - //get our events table - lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(luaState, globalName.c_str()); - lua_getfield(luaState, -1, eventName.c_str()); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 3); - return -1; - } - - //save in our events table - lua_pushvalue(luaState, -1); - lua_rawseti(luaState, -4, runningEventId); - lua_pop(luaState, 1); - - //reset global value of this event - lua_pushnil(luaState); - lua_setfield(luaState, -2, eventName.c_str()); - lua_pop(luaState, 2); - - cacheFiles[runningEventId] = loadingFile + ":" + globalName + "@" + eventName; - return runningEventId++; -} - -const std::string& LuaScriptInterface::getFileById(int32_t scriptId) -{ - if (scriptId == EVENT_ID_LOADING) { - return loadingFile; - } - - auto it = cacheFiles.find(scriptId); - if (it == 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(luaState, "debug"); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return error_desc; - } - - lua_getfield(luaState, -1, "traceback"); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 2); - return error_desc; - } - - lua_replace(luaState, -2); - pushString(luaState, error_desc); - lua_call(luaState, 1, 1); - return popString(luaState); -} - -void LuaScriptInterface::reportError(const char* function, const std::string& error_desc, bool stack_trace/* = false*/) -{ - int32_t scriptId; - int32_t callbackId; - bool timerEvent; - LuaScriptInterface* scriptInterface; - getScriptEnv()->getEventInfo(scriptId, 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 (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(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - return false; - } - - lua_rawgeti(luaState, -1, functionId); - lua_replace(luaState, -2); - return isFunction(luaState, -1); -} - -bool LuaScriptInterface::initState() -{ - luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return false; - } - - lua_newtable(luaState); - eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX); - runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaScriptInterface::closeState() -{ - if (!g_luaEnvironment.getLuaState() || !luaState) { - return false; - } - - cacheFiles.clear(); - if (eventTableRef != -1) { - luaL_unref(luaState, LUA_REGISTRYINDEX, eventTableRef); - eventTableRef = -1; - } - - 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(luaState); - if (protectedCall(luaState, params, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(luaState, -1)); - } else { - result = LuaScriptInterface::getBoolean(luaState, -1); - } - - lua_pop(luaState, 1); - if ((lua_gettop(luaState) + params + 1) != size) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - resetScriptEnv(); - return result; -} - -void LuaScriptInterface::callVoidFunction(int params) -{ - int size = lua_gettop(luaState); - if (protectedCall(luaState, params, 0) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(luaState)); - } - - if ((lua_gettop(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::pushCylinder(lua_State* L, Cylinder* cylinder) -{ - if (Creature* creature = cylinder->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (Item* parentItem = cylinder->getItem()) { - pushUserdata(L, parentItem); - setItemMetatable(L, -1, parentItem); - } else if (Tile* tile = cylinder->getTile()) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else if (cylinder == VirtualCylinder::virtualCylinder) { - pushBoolean(L, true); - } 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.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, 7); - 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, 7); - 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); -} - -#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(luaState, "getPlayerFlagValue", LuaScriptInterface::luaGetPlayerFlagValue); - - //getPlayerInstantSpellCount(cid) - lua_register(luaState, "getPlayerInstantSpellCount", LuaScriptInterface::luaGetPlayerInstantSpellCount); - - //getPlayerInstantSpellInfo(cid, index) - lua_register(luaState, "getPlayerInstantSpellInfo", LuaScriptInterface::luaGetPlayerInstantSpellInfo); - - //doPlayerAddItem(uid, itemid, count/subtype) - //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) - //Returns uid of the created item - lua_register(luaState, "doPlayerAddItem", LuaScriptInterface::luaDoPlayerAddItem); - - //doCreateItem(itemid, type/count, pos) - //Returns uid of the created item, only works on tiles. - lua_register(luaState, "doCreateItem", LuaScriptInterface::luaDoCreateItem); - - //doCreateItemEx(itemid, count/subtype) - lua_register(luaState, "doCreateItemEx", LuaScriptInterface::luaDoCreateItemEx); - - //doTileAddItemEx(pos, uid) - lua_register(luaState, "doTileAddItemEx", LuaScriptInterface::luaDoTileAddItemEx); - - //doMoveCreature(cid, direction) - lua_register(luaState, "doMoveCreature", LuaScriptInterface::luaDoMoveCreature); - - //doSetCreatureLight(cid, lightLevel, lightColor, time) - lua_register(luaState, "doSetCreatureLight", LuaScriptInterface::luaDoSetCreatureLight); - - //getCreatureCondition(cid, condition[, subId]) - lua_register(luaState, "getCreatureCondition", LuaScriptInterface::luaGetCreatureCondition); - - //isValidUID(uid) - lua_register(luaState, "isValidUID", LuaScriptInterface::luaIsValidUID); - - //isDepot(uid) - lua_register(luaState, "isDepot", LuaScriptInterface::luaIsDepot); - - //isMovable(uid) - lua_register(luaState, "isMovable", LuaScriptInterface::luaIsMoveable); - - //doAddContainerItem(uid, itemid, count/subtype) - lua_register(luaState, "doAddContainerItem", LuaScriptInterface::luaDoAddContainerItem); - - //getDepotId(uid) - lua_register(luaState, "getDepotId", LuaScriptInterface::luaGetDepotId); - - //getWorldTime() - lua_register(luaState, "getWorldTime", LuaScriptInterface::luaGetWorldTime); - - //getWorldLight() - lua_register(luaState, "getWorldLight", LuaScriptInterface::luaGetWorldLight); - - //getWorldUpTime() - lua_register(luaState, "getWorldUpTime", LuaScriptInterface::luaGetWorldUpTime); - - //createCombatArea( {area}, {extArea} ) - lua_register(luaState, "createCombatArea", LuaScriptInterface::luaCreateCombatArea); - - //doAreaCombatHealth(cid, type, pos, area, min, max, effect) - lua_register(luaState, "doAreaCombatHealth", LuaScriptInterface::luaDoAreaCombatHealth); - - //doTargetCombatHealth(cid, target, type, min, max, effect) - lua_register(luaState, "doTargetCombatHealth", LuaScriptInterface::luaDoTargetCombatHealth); - - //doAreaCombatMana(cid, pos, area, min, max, effect) - lua_register(luaState, "doAreaCombatMana", LuaScriptInterface::luaDoAreaCombatMana); - - //doTargetCombatMana(cid, target, min, max, effect) - lua_register(luaState, "doTargetCombatMana", LuaScriptInterface::luaDoTargetCombatMana); - - //doAreaCombatCondition(cid, pos, area, condition, effect) - lua_register(luaState, "doAreaCombatCondition", LuaScriptInterface::luaDoAreaCombatCondition); - - //doTargetCombatCondition(cid, target, condition, effect) - lua_register(luaState, "doTargetCombatCondition", LuaScriptInterface::luaDoTargetCombatCondition); - - //doAreaCombatDispel(cid, pos, area, type, effect) - lua_register(luaState, "doAreaCombatDispel", LuaScriptInterface::luaDoAreaCombatDispel); - - //doTargetCombatDispel(cid, target, type, effect) - lua_register(luaState, "doTargetCombatDispel", LuaScriptInterface::luaDoTargetCombatDispel); - - //doChallengeCreature(cid, target) - lua_register(luaState, "doChallengeCreature", LuaScriptInterface::luaDoChallengeCreature); - - //doSetMonsterOutfit(cid, name, time) - lua_register(luaState, "doSetMonsterOutfit", LuaScriptInterface::luaSetMonsterOutfit); - - //doSetItemOutfit(cid, item, time) - lua_register(luaState, "doSetItemOutfit", LuaScriptInterface::luaSetItemOutfit); - - //doSetCreatureOutfit(cid, outfit, time) - lua_register(luaState, "doSetCreatureOutfit", LuaScriptInterface::luaSetCreatureOutfit); - - //isInArray(array, value) - lua_register(luaState, "isInArray", LuaScriptInterface::luaIsInArray); - - //addEvent(callback, delay, ...) - lua_register(luaState, "addEvent", LuaScriptInterface::luaAddEvent); - - //stopEvent(eventid) - lua_register(luaState, "stopEvent", LuaScriptInterface::luaStopEvent); - - //saveServer() - lua_register(luaState, "saveServer", LuaScriptInterface::luaSaveServer); - - //cleanMap() - lua_register(luaState, "cleanMap", LuaScriptInterface::luaCleanMap); - - //debugPrint(text) - lua_register(luaState, "debugPrint", LuaScriptInterface::luaDebugPrint); - - //isInWar(cid, target) - lua_register(luaState, "isInWar", LuaScriptInterface::luaIsInWar); - - //getWaypointPosition(name) - lua_register(luaState, "getWaypointPositionByName", LuaScriptInterface::luaGetWaypointPositionByName); - - //sendChannelMessage(channelId, type, message) - lua_register(luaState, "sendChannelMessage", LuaScriptInterface::luaSendChannelMessage); - - //sendGuildChannelMessage(guildId, type, message) - lua_register(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(luaState, "bit", LuaScriptInterface::luaBitReg); -#endif - - //configManager table - luaL_register(luaState, "configManager", LuaScriptInterface::luaConfigManagerTable); - - //db table - luaL_register(luaState, "db", LuaScriptInterface::luaDatabaseTable); - - //result table - luaL_register(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(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_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_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_YELLOW) - registerEnum(MESSAGE_STATUS_CONSOLE_LIGHTBLUE) - registerEnum(MESSAGE_STATUS_CONSOLE_ORANGE) - registerEnum(MESSAGE_STATUS_WARNING) - registerEnum(MESSAGE_EVENT_ADVANCE) - registerEnum(MESSAGE_EVENT_DEFAULT) - registerEnum(MESSAGE_STATUS_DEFAULT) - registerEnum(MESSAGE_INFO_DESCR) - registerEnum(MESSAGE_STATUS_SMALL) - registerEnum(MESSAGE_STATUS_CONSOLE_BLUE) - registerEnum(MESSAGE_STATUS_CONSOLE_RED) - - 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(TALKTYPE_SAY) - registerEnum(TALKTYPE_WHISPER) - registerEnum(TALKTYPE_YELL) - registerEnum(TALKTYPE_PRIVATE) - registerEnum(TALKTYPE_CHANNEL_Y) - registerEnum(TALKTYPE_BROADCAST) - registerEnum(TALKTYPE_CHANNEL_R1) - registerEnum(TALKTYPE_PRIVATE_RED) - registerEnum(TALKTYPE_CHANNEL_O) - registerEnum(TALKTYPE_CHANNEL_R2) - registerEnum(TALKTYPE_MONSTER_SAY) - registerEnum(TALKTYPE_MONSTER_YELL) - - 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_NOPVPZONE) - registerEnum(TILESTATE_NOLOGOUT) - registerEnum(TILESTATE_PVPZONE) - 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_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 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::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::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::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::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); - - registerMethod("Game", "sendAnimatedText", LuaScriptInterface::luaGameSendAnimatedText); - - // 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); - - // 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", "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", "isHealthHidden", LuaScriptInterface::luaCreatureIsHealthHidden); - registerMethod("Creature", "setHiddenHealth", LuaScriptInterface::luaCreatureSetHiddenHealth); - - registerMethod("Creature", "isMoveLocked", LuaScriptInterface::luaCreatureIsMoveLocked); - registerMethod("Creature", "setMoveLocked", LuaScriptInterface::luaCreatureSetMoveLocked); - - 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", "hasFlag", LuaScriptInterface::luaPlayerHasFlag); - - registerMethod("Player", "getCapacity", LuaScriptInterface::luaPlayerGetCapacity); - registerMethod("Player", "setCapacity", LuaScriptInterface::luaPlayerSetCapacity); - - registerMethod("Player", "getFreeCapacity", LuaScriptInterface::luaPlayerGetFreeCapacity); - - registerMethod("Player", "getDepotChest", LuaScriptInterface::luaPlayerGetDepotChest); - - 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", "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", "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); - - // 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", "getDecayTime", LuaScriptInterface::luaItemTypeGetDecayTime); - registerMethod("ItemType", "getShowDuration", LuaScriptInterface::luaItemTypeGetShowDuration); - registerMethod("ItemType", "getRequiredLevel", LuaScriptInterface::luaItemTypeGetRequiredLevel); - registerMethod("ItemType", "getSpeed", LuaScriptInterface::luaItemTypeGetSpeed); - registerMethod("ItemType", "getBaseSpeed", LuaScriptInterface::luaItemTypeGetBaseSpeed); - - 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(luaState); - lua_pushvalue(luaState, -1); - lua_setglobal(luaState, className.c_str()); - int methods = lua_gettop(luaState); - - // methodsTable = {} - lua_newtable(luaState); - int methodsTable = lua_gettop(luaState); - - if (newFunction) { - // className.__call = newFunction - lua_pushcfunction(luaState, newFunction); - lua_setfield(luaState, methodsTable, "__call"); - } - - uint32_t parents = 0; - if (!baseClass.empty()) { - lua_getglobal(luaState, baseClass.c_str()); - lua_rawgeti(luaState, -1, 'p'); - parents = getNumber(luaState, -1) + 1; - lua_pop(luaState, 1); - lua_setfield(luaState, methodsTable, "__index"); - } - - // setmetatable(className, methodsTable) - lua_setmetatable(luaState, methods); - - // className.metatable = {} - luaL_newmetatable(luaState, className.c_str()); - int metatable = lua_gettop(luaState); - - // className.metatable.__metatable = className - lua_pushvalue(luaState, methods); - lua_setfield(luaState, metatable, "__metatable"); - - // className.metatable.__index = className - lua_pushvalue(luaState, methods); - lua_setfield(luaState, metatable, "__index"); - - // className.metatable['h'] = hash - lua_pushnumber(luaState, std::hash()(className)); - lua_rawseti(luaState, metatable, 'h'); - - // className.metatable['p'] = parents - lua_pushnumber(luaState, parents); - lua_rawseti(luaState, metatable, 'p'); - - // className.metatable['t'] = type - if (className == "Item") { - lua_pushnumber(luaState, LuaData_Item); - } else if (className == "Container") { - lua_pushnumber(luaState, LuaData_Container); - } else if (className == "Teleport") { - lua_pushnumber(luaState, LuaData_Teleport); - } else if (className == "Player") { - lua_pushnumber(luaState, LuaData_Player); - } else if (className == "Monster") { - lua_pushnumber(luaState, LuaData_Monster); - } else if (className == "Npc") { - lua_pushnumber(luaState, LuaData_Npc); - } else if (className == "Tile") { - lua_pushnumber(luaState, LuaData_Tile); - } else { - lua_pushnumber(luaState, LuaData_Unknown); - } - lua_rawseti(luaState, metatable, 't'); - - // pop className, className.metatable - lua_pop(luaState, 2); -} - -void LuaScriptInterface::registerTable(const std::string& tableName) -{ - // _G[tableName] = {} - lua_newtable(luaState); - lua_setglobal(luaState, tableName.c_str()); -} - -void LuaScriptInterface::registerMethod(const std::string& globalName, const std::string& methodName, lua_CFunction func) -{ - // globalName.methodName = func - lua_getglobal(luaState, globalName.c_str()); - lua_pushcfunction(luaState, func); - lua_setfield(luaState, -2, methodName.c_str()); - - // pop globalName - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerMetaMethod(const std::string& className, const std::string& methodName, lua_CFunction func) -{ - // className.metatable.methodName = func - luaL_getmetatable(luaState, className.c_str()); - lua_pushcfunction(luaState, func); - lua_setfield(luaState, -2, methodName.c_str()); - - // pop className.metatable - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerGlobalMethod(const std::string& functionName, lua_CFunction func) -{ - // _G[functionName] = func - lua_pushcfunction(luaState, func); - lua_setglobal(luaState, functionName.c_str()); -} - -void LuaScriptInterface::registerVariable(const std::string& tableName, const std::string& name, lua_Number value) -{ - // tableName.name = value - lua_getglobal(luaState, tableName.c_str()); - setField(luaState, name.c_str(), value); - - // pop tableName - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerGlobalVariable(const std::string& name, lua_Number value) -{ - // _G[name] = value - lua_pushnumber(luaState, value); - lua_setglobal(luaState, name.c_str()); -} - -void LuaScriptInterface::registerGlobalBoolean(const std::string& name, bool value) -{ - // _G[name] = value - pushBoolean(luaState, value); - lua_setglobal(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.lastEventTimerId; - eventDesc.eventId = g_scheduler.addEvent(createSchedulerTask( - delay, std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment, lastTimerEventId) - )); - - g_luaEnvironment.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.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::luaGameSendAnimatedText(lua_State* L) -{ - // Game.sendAnimatedText(message, position, color) - int parameters = lua_gettop(L); - if (parameters < 3) { - pushBoolean(L, false); - return 1; - } - - TextColor_t color = getNumber(L, 3); - const Position& position = getPosition(L, 2); - const std::string& message = getString(L, 1); - - if (!position.x || !position.y) { - pushBoolean(L, false); - return 1; - } - - g_game.addAnimatedText(message, position, color); - pushBoolean(L, true); - 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; -} - -// 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; - } - - pushCylinder(L, parent); - 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; - } - - pushCylinder(L, topParent); - 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::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; - } - - pushCylinder(L, parent); - 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); - } - 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::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::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::luaCreatureIsMoveLocked(lua_State* L) -{ - // creature:isMoveLocked() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->isMoveLocked()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetMoveLocked(lua_State* L) -{ - // creature:setMoveLocked(moveLocked) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->setMoveLocked(getBoolean(L, 2)); - 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::luaPlayerHasFlag(lua_State* L) -{ - // player:hasFlag(flags) - Player* player = getUserdata(L, 1); - if (player) { - PlayerFlags flag = getNumber(L, 2); - pushBoolean(L, player->hasFlag(flag)); - } 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::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) - TextMessage message(getNumber(L, 2), getString(L, 3)); - 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); - 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::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::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; -} - -// 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::luaItemTypeGetSpeed(lua_State* L) -{ - // itemType:getSpeed() - const ItemType* itemType = getUserdata(L, 1); - if (!itemType) { - lua_pushnil(L); - return 1; - } - - auto& abilities = itemType->abilities; - if (abilities) { - lua_pushnumber(L, abilities->speed); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetBaseSpeed(lua_State* L) -{ - // itemType:getBaseSpeed() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->speed); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDecayTime(lua_State* L) -{ - // itemType:getDecayTime() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->decayTime); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetShowDuration(lua_State* L) -{ - // itemType:getShowDuration() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushboolean(L, itemType->showDuration); - } 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]) - Outfit_t outfit; - if (isTable(L, 2)) { - outfit = getOutfit(L, 2); - } else { - 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"), testInterface(nullptr), - lastEventTimerId(1), lastCombatId(0), lastAreaId(0) -{ - // -} - -LuaEnvironment::~LuaEnvironment() -{ - delete testInterface; - closeState(); -} - -bool LuaEnvironment::initState() -{ - luaState = luaL_newstate(); - if (!luaState) { - return false; - } - - luaL_openlibs(luaState); - registerFunctions(); - - runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaEnvironment::reInitState() -{ - // TODO: get children, reload children - closeState(); - return initState(); -} - -bool LuaEnvironment::closeState() -{ - if (!luaState) { - return false; - } - - for (const auto& combatEntry : combatIdMap) { - clearCombatObjects(combatEntry.first); - } - - for (const auto& areaEntry : areaIdMap) { - clearAreaObjects(areaEntry.first); - } - - for (auto& timerEntry : timerEvents) { - LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second); - for (int32_t parameter : timerEventDesc.parameters) { - luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); - } - luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - } - - combatIdMap.clear(); - areaIdMap.clear(); - timerEvents.clear(); - cacheFiles.clear(); - - lua_close(luaState); - luaState = nullptr; - return true; -} - -LuaScriptInterface* LuaEnvironment::getTestInterface() -{ - if (!testInterface) { - testInterface = new LuaScriptInterface("Test Interface"); - testInterface->initState(); - } - return testInterface; -} - -Combat* LuaEnvironment::getCombatObject(uint32_t id) const -{ - auto it = combatMap.find(id); - if (it == combatMap.end()) { - return nullptr; - } - return it->second; -} - -Combat* LuaEnvironment::createCombatObject(LuaScriptInterface* interface) -{ - Combat* combat = new Combat; - combatMap[++lastCombatId] = combat; - combatIdMap[interface].push_back(lastCombatId); - return combat; -} - -void LuaEnvironment::clearCombatObjects(LuaScriptInterface* interface) -{ - auto it = combatIdMap.find(interface); - if (it == combatIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = combatMap.find(id); - if (itt != combatMap.end()) { - delete itt->second; - combatMap.erase(itt); - } - } - it->second.clear(); -} - -AreaCombat* LuaEnvironment::getAreaObject(uint32_t id) const -{ - auto it = areaMap.find(id); - if (it == areaMap.end()) { - return nullptr; - } - return it->second; -} - -uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface* interface) -{ - areaMap[++lastAreaId] = new AreaCombat; - areaIdMap[interface].push_back(lastAreaId); - return lastAreaId; -} - -void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) -{ - auto it = areaIdMap.find(interface); - if (it == areaIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = areaMap.find(id); - if (itt != areaMap.end()) { - delete itt->second; - areaMap.erase(itt); - } - } - it->second.clear(); -} - -void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) -{ - auto it = timerEvents.find(eventIndex); - if (it == timerEvents.end()) { - return; - } - - LuaTimerEventDesc timerEventDesc = std::move(it->second); - timerEvents.erase(it); - - //push function - lua_rawgeti(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - - //push parameters - for (auto parameter : boost::adaptors::reverse(timerEventDesc.parameters)) { - lua_rawgeti(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(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - for (auto parameter : timerEventDesc.parameters) { - luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); - } -} diff --git a/path_7_s/src/luascript.h b/path_7_s/src/luascript.h deleted file mode 100644 index 6cdaebd43..000000000 --- a/path_7_s/src/luascript.h +++ /dev/null @@ -1,1283 +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 -#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 -#undef lua_equal -#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 Cylinder; -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) { - this->scriptId = scriptId; - interface = scriptInterface; - } - bool setCallbackId(int32_t callbackId, LuaScriptInterface* scriptInterface); - - int32_t getScriptId() const { - return scriptId; - } - LuaScriptInterface* getScriptInterface() { - return interface; - } - - void setTimerEvent() { - timerEvent = true; - } - - void getEventInfo(int32_t& scriptId, 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) { - curNpc = npc; - } - Npc* getNpc() const { - return 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 scriptId; - int32_t callbackId; - bool timerEvent; - LuaScriptInterface* interface; - - //local item map - uint32_t lastUID; - std::unordered_map localMap; - - //temporary item list - static std::multimap tempItems; - - //result map - static uint32_t lastResultId; - static DBResultMap tempResults; - - //for npc scripts - Npc* 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(scriptEnvIndex >= 0 && scriptEnvIndex < 16); - return scriptEnv + scriptEnvIndex; - } - - static bool reserveScriptEnv() { - return ++scriptEnvIndex < 16; - } - - static void resetScriptEnv() { - assert(scriptEnvIndex >= 0); - scriptEnv[scriptEnvIndex--].resetEnv(); - } - - static void reportError(const char* function, const std::string& error_desc, bool stack_trace = false); - - const std::string& getInterfaceName() const { - return interfaceName; - } - const std::string& getLastLuaError() const { - return lastLuaError; - } - - lua_State* getLuaState() const { - return 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 void pushCylinder(lua_State* L, Cylinder* cylinder); - - 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_type(L, arg) == LUA_TNUMBER; - } - 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 luaGameSendAnimatedText(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); - - // 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 luaCreatureIsMoveLocked(lua_State* L); - static int luaCreatureSetMoveLocked(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 luaPlayerHasFlag(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 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 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 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); - - // 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 luaItemTypeGetSpeed(lua_State* L); - static int luaItemTypeGetBaseSpeed(lua_State* L); - static int luaItemTypeGetDecayTime(lua_State* L); - static int luaItemTypeGetShowDuration(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* luaState; - std::string lastLuaError; - - std::string interfaceName; - int32_t eventTableRef; - - static ScriptEnvironment scriptEnv[16]; - static int32_t scriptEnvIndex; - - int32_t runningEventId; - std::string loadingFile; - - //script file cache - std::map 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 timerEvents; - std::unordered_map combatMap; - std::unordered_map areaMap; - - std::unordered_map> combatIdMap; - std::unordered_map> areaIdMap; - - LuaScriptInterface* testInterface; - - uint32_t lastEventTimerId; - uint32_t lastCombatId; - uint32_t lastAreaId; - - // - friend class LuaScriptInterface; - friend class CombatSpell; -}; - -#endif diff --git a/path_7_s/src/mailbox.cpp b/path_7_s/src/mailbox.cpp deleted file mode 100644 index 53f2d725a..000000000 --- a/path_7_s/src/mailbox.cpp +++ /dev/null @@ -1,181 +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; - uint32_t depotId = 0; - if (!getReceiver(item, receiver, depotId)) { - return false; - } - - /**No need to continue if its still empty**/ - if (receiver.empty() || depotId == 0) { - return false; - } - - Player* player = g_game.getPlayerByName(receiver); - if (player) { - DepotLocker* depotLocker = player->getDepotLocker(depotId); - if (depotLocker) { - if (g_game.internalMoveItem(item->getParent(), depotLocker, 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; - } - - DepotLocker* depotLocker = tmpPlayer.getDepotLocker(depotId); - if (depotLocker) { - if (g_game.internalMoveItem(item->getParent(), depotLocker, 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, uint32_t& depotId) const -{ - const Container* container = item->getContainer(); - if (container) { - for (Item* containerItem : container->getItemList()) { - if (containerItem->getID() == ITEM_LABEL && getReceiver(containerItem, name, depotId)) { - return true; - } - } - return false; - } - - const std::string& text = item->getText(); - if (text.empty()) { - return false; - } - - std::string temp; - std::istringstream iss(item->getText(), std::istringstream::in); - std::string strTown = ""; - uint32_t curLine = 1; - - while (getline(iss, temp, '\n')) { - if (curLine == 1) { - name = temp; - } else if (curLine == 2) { - strTown = temp; - } else { - break; - } - - ++curLine; - } - - trimString(strTown); - Town* town = g_game.map.towns.getTown(strTown); - if (town) { - depotId = town->getID(); - return true; - } - - return false; -} - -bool Mailbox::canSend(const Item* item) -{ - return item->getID() == ITEM_PARCEL || item->getID() == ITEM_LETTER; -} diff --git a/path_7_s/src/mailbox.h b/path_7_s/src/mailbox.h deleted file mode 100644 index 80038da21..000000000 --- a/path_7_s/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, uint32_t& depotId) const; - bool sendItem(Item* item) const; - - static bool canSend(const Item* item); -}; - -#endif diff --git a/path_7_s/src/map.cpp b/path_7_s/src/map.cpp deleted file mode 100644 index b07b7bd00..000000000 --- a/path_7_s/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->leafS = leaf; - } - - //update west leaf - QTreeLeafNode* westLeaf = root.getLeaf(x - FLOOR_SIZE, y); - if (westLeaf) { - westLeaf->leafE = leaf; - } - - //update south - QTreeLeafNode* southLeaf = root.getLeaf(x, y + FLOOR_SIZE); - if (southLeaf) { - leaf->leafS = southLeaf; - } - - //update east - QTreeLeafNode* eastLeaf = root.getLeaf(x + FLOOR_SIZE, y); - if (eastLeaf) { - leaf->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->leafE; - } else { - leafE = QTreeNode::getLeafStatic(&root, nx + FLOOR_SIZE, ny); - } - } - - if (leafS) { - leafS = leafS->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() -{ - leaf = false; - child[0] = nullptr; - child[1] = nullptr; - child[2] = nullptr; - child[3] = nullptr; -} - -QTreeNode::~QTreeNode() -{ - delete child[0]; - delete child[1]; - delete child[2]; - delete child[3]; -} - -QTreeLeafNode* QTreeNode::getLeaf(uint32_t x, uint32_t y) -{ - if (leaf) { - return static_cast(this); - } - - QTreeNode* node = 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 (!child[index]) { - if (level != FLOOR_BITS) { - child[index] = new QTreeNode(); - } else { - child[index] = new QTreeLeafNode(); - QTreeLeafNode::newLeaf = true; - } - } - return 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) { - array[i] = nullptr; - } - - leaf = true; - leafS = nullptr; - leafE = nullptr; -} - -QTreeLeafNode::~QTreeLeafNode() -{ - for (uint32_t i = 0; i < MAP_MAX_LAYERS; ++i) { - delete array[i]; - } -} - -Floor* QTreeLeafNode::createFloor(uint32_t z) -{ - if (!array[z]) { - array[z] = new Floor(); - } - return 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->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_7_s/src/map.h b/path_7_s/src/map.h deleted file mode 100644 index f6ce2c325..000000000 --- a/path_7_s/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 leaf; - } - - QTreeLeafNode* getLeaf(uint32_t x, uint32_t y); - - template - inline static Leaf getLeafStatic(Node node, uint32_t x, uint32_t y) - { - do { - node = node->child[((x & 0x8000) >> 15) | ((y & 0x8000) >> 14)]; - if (!node) { - return nullptr; - } - - x <<= 1; - y <<= 1; - } while (!node->leaf); - return static_cast(node); - } - - QTreeLeafNode* createLeaf(uint32_t x, uint32_t y, uint32_t level); - - protected: - QTreeNode* child[4]; - - bool leaf; - - 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 array[z]; - } - - void addCreature(Creature* c); - void removeCreature(Creature* c); - - protected: - static bool newLeaf; - QTreeLeafNode* leafS; - QTreeLeafNode* leafE; - Floor* 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_7_s/src/monster.cpp b/path_7_s/src/monster.cpp deleted file mode 100644 index f70707221..000000000 --- a/path_7_s/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->hasFlag(TILESTATE_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_7_s/src/monster.h b/path_7_s/src/monster.h deleted file mode 100644 index 824573026..000000000 --- a/path_7_s/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_7_s/src/monsters.cpp b/path_7_s/src/monsters.cpp deleted file mode 100644 index e4d393a0f..000000000 --- a/path_7_s/src/monsters.cpp +++ /dev/null @@ -1,1298 +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_INFO_DESCR, 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_INFO_DESCR, 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("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_7_s/src/monsters.h b/path_7_s/src/monsters.h deleted file mode 100644 index 01e81a40b..000000000 --- a/path_7_s/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_7_s/src/movement.cpp b/path_7_s/src/movement.cpp deleted file mode 100644 index fc56ef57f..000000000 --- a/path_7_s/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() : - scriptInterface("MoveEvents Interface") -{ - 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(itemIdMap); - clearMap(actionIdMap); - clearMap(uniqueIdMap); - - for (const auto& it : positionMap) { - const MoveEventList& moveEventList = it.second; - for (int32_t i = 0; i < MOVE_EVENT_LAST; ++i) { - for (MoveEvent* moveEvent : moveEventList.moveEvent[i]) { - delete moveEvent; - } - } - } - positionMap.clear(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& MoveEvents::getScriptInterface() -{ - return 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(&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, 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, 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, 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, itemIdMap); - } - } - } else if ((attr = node.attribute("uniqueid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), 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, uniqueIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, uniqueIdMap); - } - } else if ((attr = node.attribute("actionid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), 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, actionIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, 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, 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 = itemIdMap.find(item->getID()); - if (it != 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 = uniqueIdMap.find(item->getUniqueId()); - if (it != uniqueIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - if (item->hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) { - it = actionIdMap.find(item->getActionId()); - if (it != actionIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - it = itemIdMap.find(item->getID()); - if (it != 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 = positionMap.find(tile->getPosition()); - if (it != 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) -{ - 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) -{ - eventType = copy->eventType; - stepFunction = copy->stepFunction; - moveFunction = copy->moveFunction; - equipFunction = copy->equipFunction; - slot = copy->slot; - - if (copy->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 (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") { - eventType = MOVE_EVENT_STEP_IN; - } else if (tmpStr == "stepout") { - eventType = MOVE_EVENT_STEP_OUT; - } else if (tmpStr == "equip") { - eventType = MOVE_EVENT_EQUIP; - } else if (tmpStr == "deequip") { - eventType = MOVE_EVENT_DEEQUIP; - } else if (tmpStr == "additem") { - eventType = MOVE_EVENT_ADD_ITEM; - } else if (tmpStr == "removeitem") { - eventType = MOVE_EVENT_REMOVE_ITEM; - } else { - std::cout << "Error: [MoveEvent::configureMoveEvent] No valid event name " << eventAttr.as_string() << std::endl; - return false; - } - - if (eventType == MOVE_EVENT_EQUIP || 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; - } - - scripted = false; - return true; -} - -MoveEvent_t MoveEvent::getEventType() const -{ - return eventType; -} - -void MoveEvent::setEventType(MoveEvent_t type) -{ - 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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeStep] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushPosition(L, pos); - LuaScriptInterface::pushPosition(L, fromPos); - - return scriptInterface->callFunction(4); -} - -uint32_t MoveEvent::fireEquip(Player* player, Item* item, slots_t slot, bool boolean) -{ - if (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeEquip] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - LuaScriptInterface::pushThing(L, item); - lua_pushnumber(L, slot); - - return scriptInterface->callFunction(3); -} - -uint32_t MoveEvent::fireAddRemItem(Item* item, Item* tileItem, const Position& pos) -{ - if (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeAddRemItem] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushThing(L, tileItem); - LuaScriptInterface::pushPosition(L, pos); - - return scriptInterface->callFunction(3); -} diff --git a/path_7_s/src/movement.h b/path_7_s/src/movement.h deleted file mode 100644 index bee6732e1..000000000 --- a/path_7_s/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 uniqueIdMap; - MoveListMap actionIdMap; - MoveListMap itemIdMap; - MovePosListMap positionMap; - - LuaScriptInterface 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 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_7_s/src/networkmessage.cpp b/path_7_s/src/networkmessage.cpp deleted file mode 100644 index 531ed872b..000000000 --- a/path_7_s/src/networkmessage.cpp +++ /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. - */ - -#include "otpch.h" - -#include "networkmessage.h" - -#include "container.h" -#include "creature.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); - - if (it.stackable) { - addByte(count); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[count & 7]); - } -} - -void NetworkMessage::addItem(const Item* item) -{ - const ItemType& it = Item::items[item->getID()]; - - add(it.clientId); - - if (it.stackable) { - addByte(std::min(0xFF, item->getItemCount())); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[item->getFluidType() & 7]); - } -} - -void NetworkMessage::addItemId(uint16_t itemId) -{ - add(Item::items[itemId].clientId); -} diff --git a/path_7_s/src/networkmessage.h b/path_7_s/src/networkmessage.h deleted file mode 100644 index b34abe078..000000000 --- a/path_7_s/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 = 4; - 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 + 4) || 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_7_s/src/npc.cpp b/path_7_s/src/npc.cpp deleted file mode 100644 index 9ee968a11..000000000 --- a/path_7_s/src/npc.cpp +++ /dev/null @@ -1,899 +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 "pugicast.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::scriptInterface = nullptr; - -void Npcs::reload() -{ - delete Npc::scriptInterface; - Npc::scriptInterface = nullptr; - - const std::map& npcs = g_game.getNpcs(); - 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(), filename("data/npc/" + _name + ".xml") -{ - loaded = false; - - masterRadius = -1; - - 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 (!scriptInterface) { - scriptInterface = new NpcScriptInterface(); - scriptInterface->loadNpcLib("data/npc/lib/npc.lua"); - } - - loaded = loadFromXml(); - return loaded; -} - -void Npc::reset() -{ - loaded = false; - walkTicks = 1500; - floorChange = false; - attackable = false; - ignoreHeight = true; - focusCreature = 0; - - delete npcEventHandler; - npcEventHandler = nullptr; - - parameters.clear(); -} - -void Npc::reload() -{ - reset(); - load(); - - // Simulate that the creature is placed on the map again. - if (npcEventHandler) { - npcEventHandler->onCreatureAppear(this); - } - - if (walkTicks > 0) { - addEventWalk(); - } -} - -bool Npc::loadFromXml() -{ - 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("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()); - } - - currentOutfit = defaultOutfit; - } - - for (auto parameterNode : npcNode.child("parameters").children()) { - parameters[parameterNode.attribute("key").as_string()] = parameterNode.attribute("value").as_string(); - } - - pugi::xml_attribute scriptFile = npcNode.attribute("script"); - if (scriptFile) { - npcEventHandler = new NpcEventsHandler(scriptFile.as_string(), this); - if (!npcEventHandler->isLoaded()) { - delete npcEventHandler; - 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 (npcEventHandler) { - npcEventHandler->onCreatureAppear(creature); - } - } else if (creature->getPlayer()) { - if (npcEventHandler) { - npcEventHandler->onCreatureAppear(creature); - } - } -} - -void Npc::onRemoveCreature(Creature* creature, bool isLogout) -{ - Creature::onRemoveCreature(creature, isLogout); - - if (creature == this) { - if (npcEventHandler) { - npcEventHandler->onCreatureDisappear(creature); - } - } else if (creature->getPlayer()) { - if (npcEventHandler) { - 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 (npcEventHandler) { - 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 (npcEventHandler) { - npcEventHandler->onCreatureSay(player, type, text); - } - } -} - -void Npc::onThink(uint32_t interval) -{ - Creature::onThink(interval); - - if (npcEventHandler) { - 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_SAY, text); - player->onCreatureSay(this, TALKTYPE_SAY, text); - } -} - -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->hasFlag(TILESTATE_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; - } -} - -NpcScriptInterface* Npc::getScriptInterface() -{ - return scriptInterface; -} - -NpcScriptInterface::NpcScriptInterface() : - LuaScriptInterface("Npc interface") -{ - libLoaded = false; - initState(); -} - -bool NpcScriptInterface::initState() -{ - luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return false; - } - - registerFunctions(); - - lua_newtable(luaState); - eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX); - runningEventId = EVENT_ID_USER; - return true; -} - -bool NpcScriptInterface::closeState() -{ - libLoaded = false; - LuaScriptInterface::closeState(); - return true; -} - -bool NpcScriptInterface::loadNpcLib(const std::string& file) -{ - if (libLoaded) { - return true; - } - - if (loadFile(file) == -1) { - std::cout << "[Warning - NpcScriptInterface::loadNpcLib] Can not load " << file << std::endl; - return false; - } - - libLoaded = true; - return true; -} - -void NpcScriptInterface::registerFunctions() -{ - //npc exclusive functions - lua_register(luaState, "selfSay", NpcScriptInterface::luaActionSay); - lua_register(luaState, "selfMove", NpcScriptInterface::luaActionMove); - lua_register(luaState, "selfMoveTo", NpcScriptInterface::luaActionMoveTo); - lua_register(luaState, "selfTurn", NpcScriptInterface::luaActionTurn); - lua_register(luaState, "selfFollow", NpcScriptInterface::luaActionFollow); - lua_register(luaState, "getDistanceTo", NpcScriptInterface::luagetDistanceTo); - lua_register(luaState, "doNpcSetCreatureFocus", NpcScriptInterface::luaSetNpcFocus); - lua_register(luaState, "getNpcCid", NpcScriptInterface::luaGetNpcCid); - lua_register(luaState, "getNpcParameter", NpcScriptInterface::luaGetNpcParameter); - lua_register(luaState, "doSellItem", NpcScriptInterface::luaDoSellItem); - - // metatable - registerMethod("Npc", "getParameter", NpcScriptInterface::luaNpcGetParameter); - registerMethod("Npc", "setFocus", NpcScriptInterface::luaNpcSetFocus); -} - -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->parameters.find(paramKey); - if (it != npc->parameters.end()) { - LuaScriptInterface::pushString(L, it->second); - } else { - lua_pushnil(L); - } - 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->parameters.find(key); - if (it != npc->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; -} - -NpcEventsHandler::NpcEventsHandler(const std::string& file, Npc* npc) -{ - this->npc = npc; - scriptInterface = npc->getScriptInterface(); - loaded = scriptInterface->loadFile("data/npc/scripts/" + file, npc) == 0; - if (!loaded) { - std::cout << "[Warning - NpcScript::NpcScript] Can not load script: " << file << std::endl; - std::cout << scriptInterface->getLastLuaError() << std::endl; - creatureSayEvent = -1; - creatureDisappearEvent = -1; - creatureAppearEvent = -1; - creatureMoveEvent = -1; - thinkEvent = -1; - } else { - creatureSayEvent = scriptInterface->getEvent("onCreatureSay"); - creatureDisappearEvent = scriptInterface->getEvent("onCreatureDisappear"); - creatureAppearEvent = scriptInterface->getEvent("onCreatureAppear"); - creatureMoveEvent = scriptInterface->getEvent("onCreatureMove"); - thinkEvent = scriptInterface->getEvent("onThink"); - } -} - -bool NpcEventsHandler::isLoaded() const -{ - return loaded; -} - -void NpcEventsHandler::onCreatureAppear(Creature* creature) -{ - if (creatureAppearEvent == -1) { - return; - } - - //onCreatureAppear(creature) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureAppear] Call stack overflow" << std::endl; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureAppearEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureAppearEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureDisappear(Creature* creature) -{ - if (creatureDisappearEvent == -1) { - return; - } - - //onCreatureDisappear(creature) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureDisappear] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureDisappearEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureDisappearEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureMove(Creature* creature, const Position& oldPos, const Position& newPos) -{ - if (creatureMoveEvent == -1) { - return; - } - - //onCreatureMove(creature, oldPos, newPos) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureMove] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureMoveEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureMoveEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushPosition(L, oldPos); - LuaScriptInterface::pushPosition(L, newPos); - scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) -{ - if (creatureSayEvent == -1) { - return; - } - - //onCreatureSay(creature, type, msg) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureSay] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureSayEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureSayEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, type); - LuaScriptInterface::pushString(L, text); - scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onThink() -{ - if (thinkEvent == -1) { - return; - } - - //onThink() - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onThink] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(thinkEvent, scriptInterface); - env->setNpc(npc); - - scriptInterface->pushFunction(thinkEvent); - scriptInterface->callFunction(0); -} diff --git a/path_7_s/src/npc.h b/path_7_s/src/npc.h deleted file mode 100644 index f99fe9634..000000000 --- a/path_7_s/src/npc.h +++ /dev/null @@ -1,219 +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 luaDoSellItem(lua_State* L); - - // metatable - static int luaNpcGetParameter(lua_State* L); - static int luaNpcSetFocus(lua_State* L); - - private: - bool initState() final; - bool closeState() final; - - bool 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 onThink(); - - bool isLoaded() const; - - protected: - Npc* npc; - NpcScriptInterface* scriptInterface; - - int32_t creatureAppearEvent; - int32_t creatureDisappearEvent; - int32_t creatureMoveEvent; - int32_t creatureSayEvent; - int32_t thinkEvent; - bool 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; - } - - 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 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(); - - std::map parameters; - - std::string name; - std::string filename; - - NpcEventsHandler* npcEventHandler; - - Position masterPos; - - uint32_t walkTicks; - int32_t focusCreature; - int32_t masterRadius; - - bool floorChange; - bool attackable; - bool ignoreHeight; - bool loaded; - - static NpcScriptInterface* scriptInterface; - - friend class Npcs; - friend class NpcScriptInterface; -}; - -#endif diff --git a/path_7_s/src/otpch.cpp b/path_7_s/src/otpch.cpp deleted file mode 100644 index b8314c168..000000000 --- a/path_7_s/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_7_s/src/otpch.h b/path_7_s/src/otpch.h deleted file mode 100644 index 62bfb20c6..000000000 --- a/path_7_s/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 diff --git a/path_7_s/src/otserv.cpp b/path_7_s/src/otserv.cpp deleted file mode 100644 index 0956cc1c2..000000000 --- a/path_7_s/src/otserv.cpp +++ /dev/null @@ -1,334 +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" - -#ifndef _WIN32 -#include // for sigemptyset() -#endif - -#include "configmanager.h" -#include "scriptmanager.h" -#include "rsa.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; - -IPList serverIPs; - -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)); - - 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); - - std::cout << ">> Loaded all modules, server starting up..." << std::endl; - - std::pair IpNetMask; - IpNetMask.first = inet_addr("127.0.0.1"); - IpNetMask.second = 0xFFFFFFFF; - serverIPs.push_back(IpNetMask); - - char szHostName[128]; - if (gethostname(szHostName, 128) == 0) { - hostent* he = gethostbyname(szHostName); - if (he) { - unsigned char** addr = (unsigned char**)he->h_addr_list; - while (addr[0] != nullptr) { - IpNetMask.first = *(uint32_t*)(*addr); - IpNetMask.second = 0xFFFFFFFF; - serverIPs.push_back(IpNetMask); - addr++; - } - } - } - - std::string ip = g_config.getString(ConfigManager::IP); - - uint32_t resolvedIp = inet_addr(ip.c_str()); - if (resolvedIp == INADDR_NONE) { - struct hostent* he = gethostbyname(ip.c_str()); - if (!he) { - std::ostringstream ss; - ss << "ERROR: Cannot resolve " << ip << "!" << std::endl; - startupErrorMessage(ss.str()); - return; - } - resolvedIp = *(uint32_t*)he->h_addr; - } - - IpNetMask.first = resolvedIp; - IpNetMask.second = 0; - serverIPs.push_back(IpNetMask); - -#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_7_s/src/outfit.cpp b/path_7_s/src/outfit.cpp deleted file mode 100644 index 2ad61e01b..000000000 --- a/path_7_s/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_7_s/src/outfit.h b/path_7_s/src/outfit.h deleted file mode 100644 index 01385e159..000000000 --- a/path_7_s/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_7_s/src/outputmessage.cpp b/path_7_s/src/outputmessage.cpp deleted file mode 100644 index 81a6d97f6..000000000 --- a/path_7_s/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_7_s/src/outputmessage.h b/path_7_s/src/outputmessage.h deleted file mode 100644 index 1e5bbc994..000000000 --- a/path_7_s/src/outputmessage.h +++ /dev/null @@ -1,105 +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() { - writeMessageLength(); - } - - inline void append(const NetworkMessage& msg) { - auto msgLen = msg.getLength(); - memcpy(buffer + position, msg.getBuffer() + 4, msgLen); - length += msgLen; - position += msgLen; - } - - inline void append(const OutputMessage_ptr& msg) { - auto msgLen = msg->getLength(); - memcpy(buffer + position, msg->getBuffer() + 4, 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_7_s/src/party.cpp b/path_7_s/src/party.cpp deleted file mode 100644 index 556431457..000000000 --- a/path_7_s/src/party.cpp +++ /dev/null @@ -1,485 +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); - 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); - } - 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); - - for (Player* member : memberList) { - member->sendCreatureSkull(player); - player->sendPlayerPartyIcons(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); - - 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(); - } - - 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); - - 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_7_s/src/party.h b/path_7_s/src/party.h deleted file mode 100644 index 849685317..000000000 --- a/path_7_s/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_7_s/src/player.cpp b/path_7_s/src/player.cpp deleted file mode 100644 index e85213214..000000000 --- a/path_7_s/src/player.cpp +++ /dev/null @@ -1,4102 +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 "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(), client(p), varSkills(), varStats(), inventoryAbilities() -{ - isConnecting = false; - - accountNumber = 0; - vocation = nullptr; - 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; - - pzLocked = false; - bloodHitCount = 0; - shieldBlockCount = 0; - lastAttackBlockType = BLOCK_NONE; - addAttackSkillPoint = false; - lastAttack = 0; - - blessings = 0; - - 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; - - sex = PLAYERSEX_FEMALE; - - town = nullptr; - - accountType = ACCOUNT_TYPE_NORMAL; - premiumDays = 0; - - idleTime = 0; - - skullTicks = 0; - party = nullptr; - - bankBalance = 0; - - offlineTrainingSkill = -1; - offlineTrainingTime = 0; - lastStatsTrainingTime = 0; - - ghostMode = false; - - staminaMinutes = 3240; - - lastQuestlogUpdate = 0; - - inventoryWeight = 0; - operatingSystem = CLIENTOS_NONE; - secureMode = false; - guid = 0; -} - -Player::~Player() -{ - for (Item* item : inventory) { - if (item) { - item->setParent(nullptr); - item->decrementReferenceCounter(); - } - } - - for (const auto& it : depotLockerMap) { - it.second->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 || 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_SWORDS; - } - - if (_tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - // 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; - } - - auto it = openContainers.find(cid); - if (it != openContainers.end()) { - OpenContainer& openContainer = it->second; - 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; - } - - openContainers.erase(it); -} - -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 { - 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; -} - -void Player::onReceiveMail() const -{ - 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()) { - return it->second; - } - - DepotLocker* depotLocker = new DepotLocker(ITEM_LOCKER); - depotLocker->setDepotId(depotId); - 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; - } - - if (openContainer.index >= container->capacity()) { - item = container->getItemByIndex(openContainer.index - 1); - } - client->sendAddContainerItem(it.first, 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)); - } -} - -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); - } - } - - 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); - } - - 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::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); - } - } - - 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); - } - } - } -} - -//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_STATUS_SMALL, "You gained " + expString); - sendTextMessage(message); - - std::ostringstream strExp; - strExp << exp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_WHITE_EXP); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL, "You lost " + expString); - sendTextMessage(message); - - std::ostringstream strExp; - strExp << lostExp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_RED); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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) { - - //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(); - - 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(); - - 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::addCombatExhaust(uint32_t ticks) -{ - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST_COMBAT, ticks, 0); - addCondition(condition); -} - -void Player::addHealExhaust(uint32_t ticks) -{ - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST_HEAL, ticks, 0); - addCondition(condition); -} - -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); -} - -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); - if (client) { - client->sendVIP(vipGuid, vipName, 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; -} - -//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->isRune() || 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->isRune() && 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*, 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); - } - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - updateInventoryWeight(); - updateItemsLight(); - sendStats(); - } - - if (const Item* item = thing->getItem()) { - if (const Container* container = item->getContainer()) { - onSendContainer(container); - } - } 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*, int32_t index, cylinderlink_t link /*= LINK_OWNER*/) -{ - if (link == LINK_OWNER) { - //calling movement scripts - g_moveEvents->onPlayerDeEquip(this, thing->getItem(), static_cast(index)); - } - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - 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); - } - } - } -} - -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); - sendIcons(); -} - -void Player::onAddCombatCondition(ConditionType_t type) -{ - switch (type) { - case CONDITION_POISON: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are poisoned."); - break; - - case CONDITION_DROWN: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are drowning."); - break; - - case CONDITION_PARALYZE: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are paralyzed."); - break; - - case CONDITION_DRUNK: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are drunk."); - break; - - case CONDITION_CURSED: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are cursed."); - break; - - case CONDITION_FREEZING: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are freezing."); - break; - - case CONDITION_DAZZLED: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are dazzled."); - break; - - case CONDITION_BLEEDING: - sendTextMessage(MESSAGE_STATUS_SMALL, "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) { - 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); - - 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_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 && 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; - } - - lossPercent *= vocation->getLessLoss(); - - 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; -} - -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; - } - - 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(); -} - -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; -} - -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_7_s/src/player.h b/path_7_s/src/player.h deleted file mode 100644 index aa607126d..000000000 --- a/path_7_s/src/player.h +++ /dev/null @@ -1,1167 +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 "depotchest.h" -#include "depotlocker.h" -#include "guild.h" -#include "groups.h" -#include "town.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 secureMode_t : uint8_t { - SECUREMODE_OFF = 0, - SECUREMODE_ON = 1, -}; - -enum tradestate_t : uint8_t { - TRADE_NONE, - TRADE_INITIATED, - TRADE_ACCEPT, - TRADE_ACKNOWLEDGE, - TRADE_TRANSFER, -}; - -struct VIPEntry { - VIPEntry(uint32_t guid, const std::string& name) - : guid(guid), name(name) {} - - uint32_t guid; - std::string name; -}; - -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; - } - - 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; - - uint16_t getClientIcons() const; - - const GuildWarList& getGuildWarList() const { - return 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(); - - 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 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); - - 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; - } - - 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() const; - bool isNearDepotBox() const; - - bool canSee(const Position& pos) const final; - bool canSeeCreature(const Creature* creature) const final; - - 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; - } - - //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); - - //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 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 addCombatExhaust(uint32_t ticks); - void addHealExhaust(uint32_t ticks); - 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 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 sendCreatureShield(const Creature* creature) { - if (client) { - client->sendCreatureShield(creature); - } - } - void sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color) { - if (client) { - client->sendAnimatedText(message, pos, color); - } - } - - //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 sendStats(); - 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() const { - if (client) { - client->sendReLoginWindow(); - } - } - 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 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) { - if (client) { - client->sendChannel(channelId, channelName); - } - } - 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 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::forward_list invitePartyList; - 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; - - 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 lastPing; - int64_t lastPong; - int64_t nextAction; - - BedItem* bedItem; - Guild* guild; - Group* group; - 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 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_7_s/src/position.cpp b/path_7_s/src/position.cpp deleted file mode 100644 index 5b943b6a6..000000000 --- a/path_7_s/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_7_s/src/position.h b/path_7_s/src/position.h deleted file mode 100644 index 6fb0bc744..000000000 --- a/path_7_s/src/position.h +++ /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. - */ - -#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_NONE = 8, -}; - -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_7_s/src/protocol.cpp b/path_7_s/src/protocol.cpp deleted file mode 100644 index 3936bcba9..000000000 --- a/path_7_s/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 (!rawMessages) { - msg->writeMessageLength(); - - if (encryptionEnabled) { - XTEA_encrypt(*msg); - msg->addCryptoHeader(); - } - } -} - -void Protocol::onRecvMessage(NetworkMessage& msg) -{ - if (encryptionEnabled && !XTEA_decrypt(msg)) { - return; - } - - parsePacket(msg); -} - -OutputMessage_ptr Protocol::getOutputBuffer(int32_t size) -{ - //dispatcher thread - if (outputBuffer && NetworkMessage::MAX_BODY_LENGTH >= outputBuffer->getLength() + size) { - return outputBuffer; - } else { - outputBuffer = OutputMessagePool::getOutputMessage(); - return 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[] = {key[0], key[1], key[2], 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() - 2) & 7) != 0) { - return false; - } - - const uint32_t delta = 0x61C88647; - - uint8_t* buffer = msg.getBuffer() + msg.getBufferPosition(); - const size_t messageLength = (msg.getLength() - 2); - size_t readPos = 0; - const uint32_t k[] = {key[0], key[1], key[2], 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() - 4) { - 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_7_s/src/protocol.h b/path_7_s/src/protocol.h deleted file mode 100644 index fd51df7f7..000000000 --- a/path_7_s/src/protocol.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_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) : connection(connection), key(), encryptionEnabled(false), 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 connection.expired(); - } - - Connection_ptr getConnection() const { - return connection.lock(); - } - - uint32_t getIP() const; - - //Use this function for autosend messages only - OutputMessage_ptr getOutputBuffer(int32_t size); - - OutputMessage_ptr& getCurrentBuffer() { - return 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() { - encryptionEnabled = true; - } - void setXTEAKey(const uint32_t* key) { - memcpy(this->key, key, sizeof(*key) * 4); - } - - void XTEA_encrypt(OutputMessage& msg) const; - bool XTEA_decrypt(NetworkMessage& msg) const; - static bool RSA_decrypt(NetworkMessage& msg); - - void setRawMessages(bool value) { - rawMessages = value; - } - - virtual void release() {} - friend class Connection; - - OutputMessage_ptr outputBuffer; - private: - const ConnectionWeak_ptr connection; - uint32_t key[4]; - bool encryptionEnabled; - bool rawMessages; -}; - -#endif diff --git a/path_7_s/src/protocolgame.cpp b/path_7_s/src/protocolgame.cpp deleted file mode 100644 index 8ac2043da..000000000 --- a/path_7_s/src/protocolgame.cpp +++ /dev/null @@ -1,2073 +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 "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), - version(CLIENT_VERSION_MIN), - debugAssertSent(false), - 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); - 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->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); - 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(); - - 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 - - uint32_t accountName = msg.get(); - std::string characterName = msg.getString(); - std::string password = msg.getString(); - if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); - return; - } - - if (accountName == 0) { - disconnectClient("You must enter your account name."); - 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() -{ - // -} - -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 (!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 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 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 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 0xD2: addGameTask(&Game::playerRequestOutfit, player->getID()); break; - case 0xD3: parseSetOutfit(msg); break; - case 0xDC: parseAddVip(msg); break; - case 0xDD: parseRemoveVip(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; - - 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) -{ - 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() > 150) { - // 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() + 4)) { - 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(); - addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit); -} - -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: - case TALKTYPE_PRIVATE_RED: - receiver = msg.getString(); - channelId = 0; - break; - - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - case TALKTYPE_CHANNEL_R2: - 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 - - 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::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::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) -{ - std::string bug = msg.getString(); - addGameTask(&Game::playerReportBug, player->getID(), bug); -} - -void ProtocolGame::parseDebugAssert(NetworkMessage& msg) -{ - if (debugAssertSent) { - return; - } - - 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); -} - -// Send methods -void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver) -{ - NetworkMessage msg; - msg.addByte(0xAD); - msg.addString(receiver); - 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::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::sendCreatureSquare(const Creature* creature, SquareColor_t color) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x86); - msg.add(creature->getID()); - msg.addByte(color); - 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() -{ - NetworkMessage msg; - msg.addByte(0x28); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendStats() -{ - NetworkMessage msg; - AddPlayerStats(msg); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextMessage(MessageClasses mclass, const std::string& message) -{ - NetworkMessage msg; - msg.addByte(0xB4); - msg.addByte(mclass); - msg.addString(message); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextMessage(const TextMessage& message) -{ - NetworkMessage msg; - msg.addByte(0xB4); - msg.addByte(message.type); - 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); - 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) -{ - NetworkMessage msg; - msg.addByte(0xAC); - msg.add(channelId); - msg.addString(channelName); - 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); - - msg.addItem(container); - msg.addString(container->getName()); - - msg.addByte(container->capacity()); - - msg.addByte(hasParent ? 0x01 : 0x00); - - msg.addByte(std::min(0xFF, container->size())); - - uint32_t i = 0; - const ItemDeque& itemList = container->getItemList(); - for (ItemDeque::const_iterator it = itemList.begin() + firstIndex, end = itemList.end(); i < 0xFF && it != end; ++it, ++i) { - msg.addItem(*it); - } - 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()); - 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); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed) -{ - NetworkMessage msg; - msg.addByte(0x8F); - msg.add(creature->getID()); - msg.add(speed); - 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(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, const Item* item) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x6A); - msg.addPosition(pos); - 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::sendFightModes() -{ - NetworkMessage msg; - msg.addByte(0xA7); - msg.addByte(player->fightMode); - msg.addByte(player->chaseMode); - msg.addByte(player->secureMode); - 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); - - 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(0x0A); - - msg.add(player->getID()); - msg.addByte(0x32); // beat duration (50) - msg.addByte(0x00); - - // can report bugs? - if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) { - msg.addByte(0x01); - } else { - msg.addByte(0x00); - } - - if (player->hasFlag(PlayerFlag_CanAnswerRuleViolations)) { - msg.addByte(0x0B); - - for (uint8_t i = 0; i < 32; i++) { - msg.addByte(0xFF); - } - } - - writeToOutputBuffer(msg); - - 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, 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, vipStatus); - } - } - - 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, const Item* item) -{ - NetworkMessage msg; - msg.addByte(0x70); - msg.addByte(cid); - 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.addByte(slot); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot) -{ - NetworkMessage msg; - msg.addByte(0x72); - msg.addByte(cid); - msg.addByte(slot); - 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(); - 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() == 50) { // Game client doesn't allow more than 50 outfits - break; - } - } - - msg.addByte(protocolOutfits.size()); - for (const ProtocolOutfit& outfit : protocolOutfits) { - msg.add(outfit.lookType); - msg.addString(*outfit.name); - msg.addByte(outfit.addons); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdatedVIPStatus(uint32_t guid, VipStatus_t newStatus) -{ - NetworkMessage msg; - msg.addByte(newStatus ? 0xD3 : 0xD4); - msg.add(guid); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, VipStatus_t status) -{ - NetworkMessage msg; - msg.addByte(0xD2); - msg.add(guid); - msg.addString(name); - msg.addByte(status); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x84); - msg.addPosition(pos); - msg.addByte(color); - msg.addString(message); - writeToOutputBuffer(msg); -} - -////////////// Add common messages -void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bool known, uint32_t remove) -{ - 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.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()); - - msg.addByte(player->getSkullClient(otherPlayer)); - msg.addByte(player->getPartyShield(otherPlayer)); -} - -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(std::min(player->getExperience(), 0x7FFFFFFF)); - - msg.add(player->getLevel()); - msg.addByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT)); - - 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(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT)); - - msg.addByte(player->getSoul()); - - msg.add(player->getStaminaMinutes()); -} - -void ProtocolGame::AddPlayerSkills(NetworkMessage& msg) -{ - msg.addByte(0xA1); - - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - msg.addByte(std::min(player->getSkillLevel(i), std::numeric_limits::max())); - 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); - } -} - -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::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_7_s/src/protocolgame.h b/path_7_s/src/protocolgame.h deleted file mode 100644 index ffb467e5d..000000000 --- a/path_7_s/src/protocolgame.h +++ /dev/null @@ -1,292 +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 - 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 parseQuestLine(NetworkMessage& msg); - - void parseInviteToParty(NetworkMessage& msg); - void parseJoinParty(NetworkMessage& msg); - void parseRevokePartyInvite(NetworkMessage& msg); - void parsePassPartyLeadership(NetworkMessage& msg); - void parseEnableSharedPartyExperience(NetworkMessage& msg); - - //trade methods - void parseRequestTrade(NetworkMessage& msg); - void parseLookInTrade(NetworkMessage& msg); - - //VIP methods - void parseAddVip(NetworkMessage& msg); - void parseRemoveVip(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 sendClosePrivate(uint16_t channelId); - void sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName); - void sendChannelsDialog(); - void sendChannel(uint16_t channelId, const std::string& channelName); - 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 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 sendTextMessage(MessageClasses mclass, const std::string& message); - void sendTextMessage(const TextMessage& message); - void sendReLoginWindow(); - - void sendAddMarker(const Position& pos, uint8_t markType, const std::string& desc); - - void sendCreatureShield(const Creature* creature); - void sendCreatureSkull(const Creature* creature); - - 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, VipStatus_t status); - - void sendFightModes(); - - void sendCreatureLight(const Creature* creature); - void sendWorldLight(const LightInfo& lightInfo); - - void sendCreatureSquare(const Creature* creature, SquareColor_t color); - - //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, const Item* item); - void sendUpdateContainerItem(uint8_t cid, uint16_t slot, const Item* item); - void sendRemoveContainerItem(uint8_t cid, uint16_t slot); - - 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 sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color); - - //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); - - //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; - uint16_t version; - - bool debugAssertSent; - bool acceptPackets; -}; - -#endif diff --git a/path_7_s/src/protocollogin.cpp b/path_7_s/src/protocollogin.cpp deleted file mode 100644 index 5b2895b8c..000000000 --- a/path_7_s/src/protocollogin.cpp +++ /dev/null @@ -1,181 +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 "tasks.h" - -#include "configmanager.h" -#include "iologindata.h" -#include "ban.h" -#include -#include "game.h" - -extern ConfigManager g_config; -extern IPList serverIPs; -extern Game g_game; - -void ProtocolLogin::disconnectClient(const std::string& message) -{ - auto output = OutputMessagePool::getOutputMessage(); - - output->addByte(0x0A); - output->addString(message); - send(output); - - disconnect(); -} - -void ProtocolLogin::getCharacterList(uint32_t accountName, const std::string& password) -{ - uint32_t serverIp = serverIPs[0].first; - for (uint32_t i = 0; i < serverIPs.size(); i++) { - if ((serverIPs[i].first & serverIPs[i].second) == (getConnection()->getIP() & serverIPs[i].second)) { - serverIp = serverIPs[i].first; - break; - } - } - - Account account; - if (!IOLoginData::loginserverAuthentication(accountName, password, account)) { - disconnectClient("Account name or password is not correct."); - 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 char list - output->addByte(0x64); - - uint8_t size = std::min(std::numeric_limits::max(), account.characters.size()); - output->addByte(size); - for (uint8_t i = 0; i < size; i++) { - output->addString(account.characters[i]); - output->addString(g_config.getString(ConfigManager::SERVER_NAME)); - output->add(serverIp); - output->add(g_config.getNumber(ConfigManager::GAME_PORT)); - } - - //Add premium days - if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { - output->add(0xFFFF); //client displays free premium - } else { - output->add(account.premiumDays); - } - - send(output); - - disconnect(); -} - -void ProtocolLogin::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); - /* - * 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!"); - 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); - - uint32_t accountName = msg.get(); - std::string password = msg.getString(); - - 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.\nPlease re-connect in a while."); - 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()); - return; - } - - if (accountName == 0) { - disconnectClient("Invalid account name."); - return; - } - - auto thisPtr = std::dynamic_pointer_cast(shared_from_this()); - g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountName, password))); -} diff --git a/path_7_s/src/protocollogin.h b/path_7_s/src/protocollogin.h deleted file mode 100644 index 01469157c..000000000 --- a/path_7_s/src/protocollogin.h +++ /dev/null @@ -1,48 +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}; - 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); - - void getCharacterList(uint32_t accountName, const std::string& password); -}; - -#endif diff --git a/path_7_s/src/protocolstatus.cpp b/path_7_s/src/protocolstatus.cpp deleted file mode 100644 index afb1a722b..000000000 --- a/path_7_s/src/protocolstatus.cpp +++ /dev/null @@ -1,228 +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 "outputmessage.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_7_s/src/protocolstatus.h b/path_7_s/src/protocolstatus.h deleted file mode 100644 index a29febfef..000000000 --- a/path_7_s/src/protocolstatus.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_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}; - 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_7_s/src/pugicast.h b/path_7_s/src/pugicast.h deleted file mode 100644 index e8b7fd515..000000000 --- a/path_7_s/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_7_s/src/quests.cpp b/path_7_s/src/quests.cpp deleted file mode 100644 index a105bde4b..000000000 --- a/path_7_s/src/quests.cpp +++ /dev/null @@ -1,228 +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 (!mainDescription.empty()) { - std::string desc = mainDescription; - replaceString(desc, "|STATE|", std::to_string(value)); - replaceString(desc, "\\n", "\n"); - return desc; - } - - if (ignoreEndValue) { - for (int32_t current = endValue; current >= startValue; current--) { - if (value >= current) { - auto sit = descriptions.find(current); - if (sit != descriptions.end()) { - return sit->second; - } - } - } - } else { - for (int32_t current = endValue; current >= startValue; current--) { - if (value == current) { - auto sit = descriptions.find(current); - if (sit != descriptions.end()) { - return sit->second; - } - } - } - } - 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 mainDescription = 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 (mainDescription.empty()) { - for (auto missionStateNode : missionNode.children()) { - int32_t missionId = pugi::cast(missionStateNode.attribute("id").value()); - mission.descriptions.emplace(missionId, missionStateNode.attribute("description").as_string()); - } - } else { - mission.mainDescription = mainDescription; - } - } - } - 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.getStorageId() == key && value >= mission.getStartStorageValue() && value <= mission.getEndStorageValue()) { - return mission.mainDescription.empty() || oldValue < mission.getStartStorageValue() || oldValue > mission.getEndStorageValue(); - } - } - } - return false; -} diff --git a/path_7_s/src/quests.h b/path_7_s/src/quests.h deleted file mode 100644 index b4787f86b..000000000 --- a/path_7_s/src/quests.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_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 -#define FS_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 - -#include "player.h" -#include "networkmessage.h" - -class Mission; -class Quest; - -typedef std::list MissionsList; -typedef std::list QuestsList; - -class Mission -{ - public: - Mission(std::string name, int32_t storageID, int32_t startValue, int32_t endValue, bool ignoreEndValue) - : 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 descriptions; - std::string mainDescription; - - 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_7_s/src/raids.cpp b/path_7_s/src/raids.cpp deleted file mode 100644 index 6de28ad0d..000000000 --- a/path_7_s/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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ScriptEvent::onRaid] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - scriptInterface->pushFunction(scriptId); - - return scriptInterface->callFunction(0); -} diff --git a/path_7_s/src/raids.h b/path_7_s/src/raids.h deleted file mode 100644 index 2773fd7b8..000000000 --- a/path_7_s/src/raids.h +++ /dev/null @@ -1,233 +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; - } - - 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_7_s/src/rsa.cpp b/path_7_s/src/rsa.cpp deleted file mode 100644 index dadb42d88..000000000 --- a/path_7_s/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_7_s/src/rsa.h b/path_7_s/src/rsa.h deleted file mode 100644 index c356a9d64..000000000 --- a/path_7_s/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_7_s/src/scheduler.cpp b/path_7_s/src/scheduler.cpp deleted file mode 100644 index 5a275b215..000000000 --- a/path_7_s/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_7_s/src/scheduler.h b/path_7_s/src/scheduler.h deleted file mode 100644 index 0a0f9a9f5..000000000 --- a/path_7_s/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_7_s/src/scriptmanager.cpp b/path_7_s/src/scriptmanager.cpp deleted file mode 100644 index 0f44b04c1..000000000 --- a/path_7_s/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_7_s/src/scriptmanager.h b/path_7_s/src/scriptmanager.h deleted file mode 100644 index 5a3f26fb2..000000000 --- a/path_7_s/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_7_s/src/server.cpp b/path_7_s/src/server.cpp deleted file mode 100644 index 820ffe722..000000000 --- a/path_7_s/src/server.cpp +++ /dev/null @@ -1,219 +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(NetworkMessage& msg, const Connection_ptr& connection) const -{ - uint8_t protocolID = msg.getByte(); - for (auto& service : services) { - if (protocolID != service->get_protocol_identifier()) { - continue; - } - - 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_7_s/src/server.h b/path_7_s/src/server.h deleted file mode 100644 index 86ee1b83d..000000000 --- a/path_7_s/src/server.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_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 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; - } - 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(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_7_s/src/spawn.cpp b/path_7_s/src/spawn.cpp deleted file mode 100644 index 56fab6664..000000000 --- a/path_7_s/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_7_s/src/spawn.h b/path_7_s/src/spawn.h deleted file mode 100644 index c04aa1187..000000000 --- a/path_7_s/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_7_s/src/spells.cpp b/path_7_s/src/spells.cpp deleted file mode 100644 index a168d28a8..000000000 --- a/path_7_s/src/spells.cpp +++ /dev/null @@ -1,1985 +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(): - scriptInterface("Spell Interface") -{ - 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(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Spells::getScriptInterface() -{ - return 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(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "instant") == 0) { - return new InstantSpell(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "conjure") == 0) { - return new ConjureSpell(&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 (!scripted) { - delete combat; - } -} - -bool CombatSpell::loadScriptCombat() -{ - combat = g_luaEnvironment.getCombatObject(g_luaEnvironment.lastCombatId); - return combat != nullptr; -} - -bool CombatSpell::castSpell(Creature* creature) -{ - if (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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CombatSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return scriptInterface->callFunction(2); -} - -Spell::Spell() -{ - spellId = 0; - level = 0; - magLevel = 0; - mana = 0; - manaPercent = 0; - soul = 0; - range = -1; - cooldown = 1000; - fist = 0; - club = 0; - sword = 0; - axe = 0; - distance = 0; - shield = 0; - fish = 0; - needTarget = false; - needWeapon = false; - selfTarget = false; - blockingSolid = false; - blockingCreature = false; - premium = false; - enabled = true; - aggressive = true; - learnable = false; -} - -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("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("exhaustion")) || (attr = node.attribute("cooldown"))) { - cooldown = 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("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()); - } - - 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->hasFlag(PlayerFlag_HasNoExhaustion)) { - bool exhaust = false; - if (aggressive) { - if (player->hasCondition(CONDITION_EXHAUST_COMBAT)) { - exhaust = true; - } - } else { - if (player->hasCondition(CONDITION_EXHAUST_HEAL)) { - exhaust = true; - } - } - - if (exhaust) { - 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->hasFlag(TILESTATE_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->hasFlag(TILESTATE_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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - if (!player->hasFlag(PlayerFlag_NotGainInFight)) { - 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; - } - - 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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - 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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - 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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - InstantSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return 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->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID | TILESTATE_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->hasFlag(TILESTATE_BLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.z + 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID | TILESTATE_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&) -{ - 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 (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; - } - - 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.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 (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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - RuneSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - LuaScriptInterface::pushBoolean(L, isHotkey); - - return scriptInterface->callFunction(3); -} diff --git a/path_7_s/src/spells.h b/path_7_s/src/spells.h deleted file mode 100644 index 3d67debc1..000000000 --- a/path_7_s/src/spells.h +++ /dev/null @@ -1,329 +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 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; - - 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_7_s/src/talkaction.cpp b/path_7_s/src/talkaction.cpp deleted file mode 100644 index 28a65ea45..000000000 --- a/path_7_s/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() - : scriptInterface("TalkAction Interface") -{ - scriptInterface.initState(); -} - -TalkActions::~TalkActions() -{ - clear(); -} - -void TalkActions::clear() -{ - for (TalkAction* talkAction : talkActions) { - delete talkAction; - } - talkActions.clear(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& TalkActions::getScriptInterface() -{ - return 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(&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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TalkAction::executeSay] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushString(L, words); - LuaScriptInterface::pushString(L, param); - lua_pushnumber(L, type); - - return scriptInterface->callFunction(4); -} diff --git a/path_7_s/src/talkaction.h b/path_7_s/src/talkaction.h deleted file mode 100644 index 5cc50af59..000000000 --- a/path_7_s/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 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_7_s/src/tasks.cpp b/path_7_s/src/tasks.cpp deleted file mode 100644 index e1b9e014b..000000000 --- a/path_7_s/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_7_s/src/tasks.h b/path_7_s/src/tasks.h deleted file mode 100644 index 33b68d00f..000000000 --- a/path_7_s/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_7_s/src/teleport.cpp b/path_7_s/src/teleport.cpp deleted file mode 100644 index ba0a8a2f0..000000000 --- a/path_7_s/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_7_s/src/teleport.h b/path_7_s/src/teleport.h deleted file mode 100644 index 41aad9260..000000000 --- a/path_7_s/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_7_s/src/thing.cpp b/path_7_s/src/thing.cpp deleted file mode 100644 index 24e8c95c5..000000000 --- a/path_7_s/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_7_s/src/thing.h b/path_7_s/src/thing.h deleted file mode 100644 index 47c04a686..000000000 --- a/path_7_s/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_7_s/src/thread_holder_base.h b/path_7_s/src/thread_holder_base.h deleted file mode 100644 index 79ce284d5..000000000 --- a/path_7_s/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_7_s/src/tile.cpp b/path_7_s/src/tile.cpp deleted file mode 100644 index 80e042ec7..000000000 --- a/path_7_s/src/tile.cpp +++ /dev/null @@ -1,1583 +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 "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) -{ - 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) -{ - 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) -{ - 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) && hasFlag(TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (creature->isMoveLocked() || ground == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (const Monster* monster = creature->getMonster()) { - if (hasFlag(TILESTATE_PROTECTIONZONE | TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) { - 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()) { - 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 (hasFlag(TILESTATE_FLOORCHANGE_DOWN)) { - 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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { - ++dy; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) { - --dy; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) { - dy -= 2; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST)) { - --dx; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST_ALT)) { - dx -= 2; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_WEST)) { - ++dx; - } - - destTile = g_game.map.getTile(dx, dy, dz); - } - } - } - } else if (hasFlag(TILESTATE_FLOORCHANGE)) { - uint16_t dx = tilePos.x; - uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z - 1; - - if (hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { - --dy; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) { - ++dy; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_EAST)) { - ++dx; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_WEST)) { - --dx; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) { - dy += 2; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_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->end(), 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.floorChange != 0) { - setFlag(it.floorChange); - } - } - - 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.floorChange != 0) { - resetFlag(TILESTATE_FLOORCHANGE); - } - - 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_7_s/src/tile.h b/path_7_s/src/tile.h deleted file mode 100644 index 8978d3d56..000000000 --- a/path_7_s/src/tile.h +++ /dev/null @@ -1,419 +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 = 0, - - TILESTATE_FLOORCHANGE_DOWN = 1 << 0, - TILESTATE_FLOORCHANGE_NORTH = 1 << 1, - TILESTATE_FLOORCHANGE_SOUTH = 1 << 2, - TILESTATE_FLOORCHANGE_EAST = 1 << 3, - TILESTATE_FLOORCHANGE_WEST = 1 << 4, - TILESTATE_FLOORCHANGE_SOUTH_ALT = 1 << 5, - TILESTATE_FLOORCHANGE_EAST_ALT = 1 << 6, - TILESTATE_PROTECTIONZONE = 1 << 7, - TILESTATE_NOPVPZONE = 1 << 8, - TILESTATE_NOLOGOUT = 1 << 9, - TILESTATE_PVPZONE = 1 << 10, - TILESTATE_TELEPORT = 1 << 11, - TILESTATE_MAGICFIELD = 1 << 12, - TILESTATE_MAILBOX = 1 << 13, - TILESTATE_TRASHHOLDER = 1 << 14, - TILESTATE_BED = 1 << 15, - TILESTATE_DEPOT = 1 << 16, - TILESTATE_BLOCKSOLID = 1 << 17, - TILESTATE_BLOCKPATH = 1 << 18, - TILESTATE_IMMOVABLEBLOCKSOLID = 1 << 19, - TILESTATE_IMMOVABLEBLOCKPATH = 1 << 20, - TILESTATE_IMMOVABLENOFIELDBLOCKPATH = 1 << 21, - TILESTATE_NOFIELDBLOCKPATH = 1 << 22, - TILESTATE_SUPPORTS_HANGABLE = 1 << 23, - - TILESTATE_FLOORCHANGE = TILESTATE_FLOORCHANGE_DOWN | TILESTATE_FLOORCHANGE_NORTH | TILESTATE_FLOORCHANGE_SOUTH | TILESTATE_FLOORCHANGE_EAST | TILESTATE_FLOORCHANGE_WEST | TILESTATE_FLOORCHANGE_SOUTH_ALT | TILESTATE_FLOORCHANGE_EAST_ALT, -}; - -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; - - inline bool hasFlag(uint32_t flag) const { - return hasBitSet(flag, this->flags); - } - inline void setFlag(uint32_t flag) { - this->flags |= flag; - } - inline void resetFlag(uint32_t flag) { - this->flags &= ~flag; - } - - 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 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), - 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) -{ -} - -inline DynamicTile::~DynamicTile() -{ - for (Item* item : items) { - item->decrementReferenceCounter(); - } -} - -#endif diff --git a/path_7_s/src/tools.cpp b/path_7_s/src/tools.cpp deleted file mode 100644 index feee45974..000000000 --- a/path_7_s/src/tools.cpp +++ /dev/null @@ -1,1128 +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; -} - -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); - } - - int32_t increment; - const int32_t diff = maxNumber - minNumber; - const float v = normalRand(getRandomGenerator()); - if (v < 0.0) { - increment = diff / 2; - } else if (v > 1.0) { - increment = (diff + 1) / 2; - } else { - increment = round(v * diff); - } - return minNumber + increment; -} - -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}, -}; - -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}, -}; - -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}, -}; - -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"; - } -} - -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_7_s/src/tools.h b/path_7_s/src/tools.h deleted file mode 100644 index c28afd2db..000000000 --- a/path_7_s/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); -inline bool hasBitSet(uint32_t flag, uint32_t flags) { - return (flags & flag) != 0; -} - -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); - -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_7_s/src/town.h b/path_7_s/src/town.h deleted file mode 100644 index 3d9b34acd..000000000 --- a/path_7_s/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_7_s/src/trashholder.cpp b/path_7_s/src/trashholder.cpp deleted file mode 100644 index 7b688c102..000000000 --- a/path_7_s/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_7_s/src/trashholder.h b/path_7_s/src/trashholder.h deleted file mode 100644 index 45a7cbc96..000000000 --- a/path_7_s/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_7_s/src/vocation.cpp b/path_7_s/src/vocation.cpp deleted file mode 100644 index ca575c8c7..000000000 --- a/path_7_s/src/vocation.cpp +++ /dev/null @@ -1,252 +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()); - } - - if ((attr = vocationNode.attribute("lessloss"))) { - voc.lessLoss = 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_7_s/src/vocation.h b/path_7_s/src/vocation.h deleted file mode 100644 index b7fd7407b..000000000 --- a/path_7_s/src/vocation.h +++ /dev/null @@ -1,141 +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; - } - - uint32_t getLessLoss() const { - return lessLoss; - } - - 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; - float lessLoss; - - 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_7_s/src/waitlist.cpp b/path_7_s/src/waitlist.cpp deleted file mode 100644 index 48cb94f8e..000000000 --- a/path_7_s/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_7_s/src/waitlist.h b/path_7_s/src/waitlist.h deleted file mode 100644 index 9b7fe02e6..000000000 --- a/path_7_s/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_7_s/src/weapons.cpp b/path_7_s/src/weapons.cpp deleted file mode 100644 index a3e25f149..000000000 --- a/path_7_s/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(): - scriptInterface("Weapon Interface") -{ - 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(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Weapons::getScriptInterface() -{ - return 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(&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(&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(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "distance") == 0) { - return new WeaponDistance(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "wand") == 0) { - return new WeaponWand(&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) -{ - 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 (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 (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) { - Weapon::decrementItemCount(item); - return; - } - - switch (action) { - case WEAPONACTION_REMOVECOUNT: - Weapon::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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Weapon::executeUseWeapon] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - scriptInterface->pushVariant(L, var); - - return scriptInterface->callFunction(2); -} - -void Weapon::decrementItemCount(Item* item) -{ - 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->hasFlag(TILESTATE_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_7_s/src/weapons.h b/path_7_s/src/weapons.h deleted file mode 100644 index 67172f05c..000000000 --- a/path_7_s/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 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: - static void decrementItemCount(Item* item); - - 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_7_s/src/wildcardtree.cpp b/path_7_s/src/wildcardtree.cpp deleted file mode 100644 index 542da0669..000000000 --- a/path_7_s/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_7_s/src/wildcardtree.h b/path_7_s/src/wildcardtree.h deleted file mode 100644 index ed8eaddce..000000000 --- a/path_7_s/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_7_s/vc14/TheForgottenServer.rc b/path_7_s/vc14/TheForgottenServer.rc deleted file mode 100644 index 5147602ee..000000000 --- a/path_7_s/vc14/TheForgottenServer.rc +++ /dev/null @@ -1 +0,0 @@ -MAINICON ICON "TheForgottenServer.ico" \ No newline at end of file diff --git a/path_7_s/vc14/arch32.props b/path_7_s/vc14/arch32.props deleted file mode 100644 index d2adc41ef..000000000 --- a/path_7_s/vc14/arch32.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - $(TFS_LIBS) - true - - - - \ No newline at end of file diff --git a/path_7_s/vc14/arch64.props b/path_7_s/vc14/arch64.props deleted file mode 100644 index 6c086a54a..000000000 --- a/path_7_s/vc14/arch64.props +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - $(TFS_LIBS64) - - - - \ No newline at end of file diff --git a/path_7_s/vc14/debug.props b/path_7_s/vc14/debug.props deleted file mode 100644 index ab4fb7de3..000000000 --- a/path_7_s/vc14/debug.props +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - true - - - - false - false - EnableFastChecks - MultiThreadedDebugDLL - $(IntDir)\obj_d\ - - - $(TFS_LIBDEPS_D) - - - - - diff --git a/path_7_s/vc14/release.props b/path_7_s/vc14/release.props deleted file mode 100644 index 1a6520d97..000000000 --- a/path_7_s/vc14/release.props +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - false - - - - Full - $(IntDir)\obj_r\ - - - UseLinkTimeCodeGeneration - - - - - diff --git a/path_7_s/vc14/settings.props b/path_7_s/vc14/settings.props deleted file mode 100644 index b7fc74a9a..000000000 --- a/path_7_s/vc14/settings.props +++ /dev/null @@ -1,74 +0,0 @@ - - - - - $(TFSSDKDir)\LuaJIT\ - $(TFSSDKDir)\mpir\ - $(TFSSDKDir)\mysql-connector-c\ - $(TFSSDKDir)\pugixml\ - _CRT_SECURE_NO_WARNINGS; - $(BOOST_ROOT);$(LUA_DIR)\include;$(GMP_DIR)\include;$(MYSQLC_DIR)\include;$(PUGIXML_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_7_s/vc14/theforgottenserver.ico b/path_7_s/vc14/theforgottenserver.ico deleted file mode 100644 index 78af5e576..000000000 Binary files a/path_7_s/vc14/theforgottenserver.ico and /dev/null differ diff --git a/path_7_s/vc14/theforgottenserver.sln b/path_7_s/vc14/theforgottenserver.sln deleted file mode 100644 index 4c37956c6..000000000 --- a/path_7_s/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_7_s/vc14/theforgottenserver.vcxproj b/path_7_s/vc14/theforgottenserver.vcxproj deleted file mode 100644 index b84cefa8b..000000000 --- a/path_7_s/vc14/theforgottenserver.vcxproj +++ /dev/null @@ -1,294 +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_8_0/.editorconfig b/path_8_0/.editorconfig deleted file mode 100644 index 26b3599ca..000000000 --- a/path_8_0/.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_8_0/.gitattributes b/path_8_0/.gitattributes deleted file mode 100644 index 109adf08d..000000000 --- a/path_8_0/.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_8_0/.gitignore b/path_8_0/.gitignore deleted file mode 100644 index 5400463dd..000000000 --- a/path_8_0/.gitignore +++ /dev/null @@ -1,172 +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 -*.opendb -*.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_8_0/.travis.yml b/path_8_0/.travis.yml deleted file mode 100644 index f0741bfa5..000000000 --- a/path_8_0/.travis.yml +++ /dev/null @@ -1,23 +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 - - libpugixml-dev -before_script: - - mkdir build && cd build - - cmake -DCMAKE_BUILD_TYPE=Release -DUSE_LUAJIT=${LUAJIT} .. -script: make -j2 diff --git a/path_8_0/CMakeLists.txt b/path_8_0/CMakeLists.txt deleted file mode 100644 index ae6fdcaba..000000000 --- a/path_8_0/CMakeLists.txt +++ /dev/null @@ -1,53 +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(PugiXML 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} ${PUGIXML_INCLUDE_DIR} ${GMP_INCLUDE_DIR}) -target_link_libraries(tfs ${MYSQL_CLIENT_LIBS} ${LUA_LIBRARIES} ${Boost_LIBRARIES} ${PUGIXML_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_8_0/cmake/FindCXX11.cmake b/path_8_0/cmake/FindCXX11.cmake deleted file mode 100644 index 1702e8dfb..000000000 --- a/path_8_0/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_8_0/cmake/FindGMP.cmake b/path_8_0/cmake/FindGMP.cmake deleted file mode 100644 index 80805443f..000000000 --- a/path_8_0/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_8_0/cmake/FindLua.cmake b/path_8_0/cmake/FindLua.cmake deleted file mode 100644 index 57a48ebca..000000000 --- a/path_8_0/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_8_0/cmake/FindLuaJIT.cmake b/path_8_0/cmake/FindLuaJIT.cmake deleted file mode 100644 index e626a5a1d..000000000 --- a/path_8_0/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_8_0/cmake/FindMySQL.cmake b/path_8_0/cmake/FindMySQL.cmake deleted file mode 100644 index 5e378d5b4..000000000 --- a/path_8_0/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_8_0/cmake/FindPugiXML.cmake b/path_8_0/cmake/FindPugiXML.cmake deleted file mode 100644 index 4f09e0b55..000000000 --- a/path_8_0/cmake/FindPugiXML.cmake +++ /dev/null @@ -1,7 +0,0 @@ -find_path(PUGIXML_INCLUDE_DIR NAMES pugixml.hpp) -find_library(PUGIXML_LIBRARIES NAMES pugixml) - -include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(PugiXML REQUIRED_VARS PUGIXML_INCLUDE_DIR PUGIXML_LIBRARIES) - -mark_as_advanced(PUGIXML_INCLUDE_DIR PUGIXML_LIBRARIES) diff --git a/path_8_0/cmake/cotire.cmake b/path_8_0/cmake/cotire.cmake deleted file mode 100644 index a4fb533c6..000000000 --- a/path_8_0/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_8_0/config.lua b/path_8_0/config.lua deleted file mode 100644 index 28ab78597..000000000 --- a/path_8_0/config.lua +++ /dev/null @@ -1,102 +0,0 @@ --- Combat settings --- NOTE: valid values for worldType are: "pvp", "no-pvp" and "pvp-enforced" -worldType = "pvp" -hotkeyAimbotEnabled = true -protectionLevel = 1 -killsToRedSkull = 3 -pzLocked = 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 Forgotten Server!" -onePlayerOnlinePerAccount = true -allowClones = false -serverName = "Forgotten" -statusTimeout = 5 * 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 = "weekly" - --- Item Usage -timeBetweenActions = 200 -timeBetweenExActions = 1000 - --- Map --- NOTE: set mapName WITHOUT .otbm at the end -mapName = "forgotten" -mapAuthor = "Komic" - --- MySQL -mysqlHost = "127.0.0.1" -mysqlUser = "forgottenserver" -mysqlPass = "" -mysqlDatabase = "forgottenserver" -mysqlPort = 3306 -mysqlSock = "" - --- Misc. -allowChangeOutfit = true -freePremium = false -kickIdlePlayerAfterMinutes = 15 -maxMessageBuffer = 4 -emoteSpells = true -classicEquipmentSlots = false - --- 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 - --- Rates --- NOTE: rateExp is not used if you have enabled stages in data/XML/stages.xml -rateExp = 5 -rateSkill = 3 -rateLoot = 2 -rateMagic = 3 -rateSpawn = 1 - --- 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 = "http://darkkonia.sytes.net/" -location = "Mexico" diff --git a/path_8_0/data/XML/commands.xml b/path_8_0/data/XML/commands.xml deleted file mode 100644 index 9b1630aaa..000000000 --- a/path_8_0/data/XML/commands.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/path_8_0/data/XML/groups.xml b/path_8_0/data/XML/groups.xml deleted file mode 100644 index cd5ed0486..000000000 --- a/path_8_0/data/XML/groups.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_8_0/data/XML/outfits.xml b/path_8_0/data/XML/outfits.xml deleted file mode 100644 index 4f82f5a2c..000000000 --- a/path_8_0/data/XML/outfits.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/XML/quests.xml b/path_8_0/data/XML/quests.xml deleted file mode 100644 index 4633d44f7..000000000 --- a/path_8_0/data/XML/quests.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/path_8_0/data/XML/stages.xml b/path_8_0/data/XML/stages.xml deleted file mode 100644 index 06b639c0e..000000000 --- a/path_8_0/data/XML/stages.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_8_0/data/XML/vocations.xml b/path_8_0/data/XML/vocations.xml deleted file mode 100644 index 6ddebd0c9..000000000 --- a/path_8_0/data/XML/vocations.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/actions/actions.xml b/path_8_0/data/actions/actions.xml deleted file mode 100644 index 4aa067b12..000000000 --- a/path_8_0/data/actions/actions.xml +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/actions/lib/actions.lua b/path_8_0/data/actions/lib/actions.lua deleted file mode 100644 index e6092fd66..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/blueberrybush.lua b/path_8_0/data/actions/scripts/other/blueberrybush.lua deleted file mode 100644 index a471e0c2f..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/changegold.lua b/path_8_0/data/actions/scripts/other/changegold.lua deleted file mode 100644 index 6af63855a..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/constructionkits.lua b/path_8_0/data/actions/scripts/other/constructionkits.lua deleted file mode 100644 index e65a42302..000000000 --- a/path_8_0/data/actions/scripts/other/constructionkits.lua +++ /dev/null @@ -1,28 +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, -} - -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_8_0/data/actions/scripts/other/createbread.lua b/path_8_0/data/actions/scripts/other/createbread.lua deleted file mode 100644 index f58eb1a0b..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/decayto.lua b/path_8_0/data/actions/scripts/other/decayto.lua deleted file mode 100644 index ee8543e86..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/destroy.lua b/path_8_0/data/actions/scripts/other/destroy.lua deleted file mode 100644 index 0499f62cc..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/dice.lua b/path_8_0/data/actions/scripts/other/dice.lua deleted file mode 100644 index 86505a5dc..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/doors.lua b/path_8_0/data/actions/scripts/other/doors.lua deleted file mode 100644 index 0374d46a9..000000000 --- a/path_8_0/data/actions/scripts/other/doors.lua +++ /dev/null @@ -1,68 +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(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 - 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_8_0/data/actions/scripts/other/fireworksrocket.lua b/path_8_0/data/actions/scripts/other/fireworksrocket.lua deleted file mode 100644 index 57ce7989d..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/fluids.lua b/path_8_0/data/actions/scripts/other/fluids.lua deleted file mode 100644 index c01f40334..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/food.lua b/path_8_0/data/actions/scripts/other/food.lua deleted file mode 100644 index 005fa5545..000000000 --- a/path_8_0/data/actions/scripts/other/food.lua +++ /dev/null @@ -1,80 +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) -} - -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_8_0/data/actions/scripts/other/music.lua b/path_8_0/data/actions/scripts/other/music.lua deleted file mode 100644 index a6bdb61ab..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/partyhat.lua b/path_8_0/data/actions/scripts/other/partyhat.lua deleted file mode 100644 index 6e41b5871..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/partytrumpet.lua b/path_8_0/data/actions/scripts/other/partytrumpet.lua deleted file mode 100644 index 8e178c67a..000000000 --- a/path_8_0/data/actions/scripts/other/partytrumpet.lua +++ /dev/null @@ -1,7 +0,0 @@ -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - item:transform(6573) - item:decay() - player:say("TOOOOOOT!", TALKTYPE_MONSTER_SAY) - fromPosition:sendMagicEffect(CONST_ME_SOUND_BLUE) - return true -end diff --git a/path_8_0/data/actions/scripts/other/piggybank.lua b/path_8_0/data/actions/scripts/other/piggybank.lua deleted file mode 100644 index 07f5d93ad..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/potions.lua b/path_8_0/data/actions/scripts/other/potions.lua deleted file mode 100644 index 9a59245b7..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/skilltrainer.lua b/path_8_0/data/actions/scripts/other/skilltrainer.lua deleted file mode 100644 index 8e995faff..000000000 --- a/path_8_0/data/actions/scripts/other/skilltrainer.lua +++ /dev/null @@ -1,27 +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:getActionId()] - if not skill then - return false - end - - 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_8_0/data/actions/scripts/other/spellbook.lua b/path_8_0/data/actions/scripts/other/spellbook.lua deleted file mode 100644 index 5c7da6c00..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/surprisebag.lua b/path_8_0/data/actions/scripts/other/surprisebag.lua deleted file mode 100644 index 4727e0537..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/teleport.lua b/path_8_0/data/actions/scripts/other/teleport.lua deleted file mode 100644 index 8cb599463..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/trap.lua b/path_8_0/data/actions/scripts/other/trap.lua deleted file mode 100644 index 9d4554707..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/watch.lua b/path_8_0/data/actions/scripts/other/watch.lua deleted file mode 100644 index 88b7df4ea..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/other/windows.lua b/path_8_0/data/actions/scripts/other/windows.lua deleted file mode 100644 index 3a701b46e..000000000 --- a/path_8_0/data/actions/scripts/other/windows.lua +++ /dev/null @@ -1,43 +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, -} - -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_8_0/data/actions/scripts/quests/annihilator.lua b/path_8_0/data/actions/scripts/quests/annihilator.lua deleted file mode 100644 index 70066e1dd..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/quests/quests.lua b/path_8_0/data/actions/scripts/quests/quests.lua deleted file mode 100644 index 0463324a8..000000000 --- a/path_8_0/data/actions/scripts/quests/quests.lua +++ /dev/null @@ -1,42 +0,0 @@ -local annihilatorReward = {1990, 2400, 2431, 2494} -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - if item.uid <= 1250 or item.uid >= 12660 then - return false - end - - local itemType = ItemType(item.uid) - if itemType:getId() == 0 then - return false - end - - 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_8_0/data/actions/scripts/quests/system.lua b/path_8_0/data/actions/scripts/quests/system.lua deleted file mode 100644 index 9f37e462e..000000000 --- a/path_8_0/data/actions/scripts/quests/system.lua +++ /dev/null @@ -1,87 +0,0 @@ -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_8_0/data/actions/scripts/tools/fishing.lua b/path_8_0/data/actions/scripts/tools/fishing.lua deleted file mode 100644 index d50d11631..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/tools/machete.lua b/path_8_0/data/actions/scripts/tools/machete.lua deleted file mode 100644 index daf0ed3da..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/tools/pick.lua b/path_8_0/data/actions/scripts/tools/pick.lua deleted file mode 100644 index 7ef688b5f..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/tools/rope.lua b/path_8_0/data/actions/scripts/tools/rope.lua deleted file mode 100644 index 5b0b80d4c..000000000 --- a/path_8_0/data/actions/scripts/tools/rope.lua +++ /dev/null @@ -1,24 +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 -} - -function onUse(player, item, fromPosition, target, toPosition, isHotkey) - local tile = Tile(toPosition) - if isInArray(ropeSpots, tile:getGround():getId()) 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_8_0/data/actions/scripts/tools/scythe.lua b/path_8_0/data/actions/scripts/tools/scythe.lua deleted file mode 100644 index 3d2f7c18f..000000000 --- a/path_8_0/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_8_0/data/actions/scripts/tools/shovel.lua b/path_8_0/data/actions/scripts/tools/shovel.lua deleted file mode 100644 index 3bacc66d8..000000000 --- a/path_8_0/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_8_0/data/chatchannels/chatchannels.xml b/path_8_0/data/chatchannels/chatchannels.xml deleted file mode 100644 index dc7922473..000000000 --- a/path_8_0/data/chatchannels/chatchannels.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_8_0/data/chatchannels/scripts/advertising-rook.lua b/path_8_0/data/chatchannels/scripts/advertising-rook.lua deleted file mode 100644 index 6c92b4ef8..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/advertising.lua b/path_8_0/data/chatchannels/scripts/advertising.lua deleted file mode 100644 index 0f90e3340..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/englishchat.lua b/path_8_0/data/chatchannels/scripts/englishchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/gamemaster.lua b/path_8_0/data/chatchannels/scripts/gamemaster.lua deleted file mode 100644 index b3050cc53..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/help.lua b/path_8_0/data/chatchannels/scripts/help.lua deleted file mode 100644 index 54e7de61e..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/tutor.lua b/path_8_0/data/chatchannels/scripts/tutor.lua deleted file mode 100644 index 8db26a8ba..000000000 --- a/path_8_0/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_8_0/data/chatchannels/scripts/worldchat.lua b/path_8_0/data/chatchannels/scripts/worldchat.lua deleted file mode 100644 index 04cf10ce0..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/creaturescripts.xml b/path_8_0/data/creaturescripts/creaturescripts.xml deleted file mode 100644 index 18f666513..000000000 --- a/path_8_0/data/creaturescripts/creaturescripts.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/path_8_0/data/creaturescripts/lib/creaturescripts.lua b/path_8_0/data/creaturescripts/lib/creaturescripts.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_8_0/data/creaturescripts/lib/creaturescripts.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_8_0/data/creaturescripts/scripts/advance_save.lua b/path_8_0/data/creaturescripts/scripts/advance_save.lua deleted file mode 100644 index b4095a9d0..000000000 --- a/path_8_0/data/creaturescripts/scripts/advance_save.lua +++ /dev/null @@ -1,25 +0,0 @@ -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_8_0/data/creaturescripts/scripts/droploot.lua b/path_8_0/data/creaturescripts/scripts/droploot.lua deleted file mode 100644 index 371c48a59..000000000 --- a/path_8_0/data/creaturescripts/scripts/droploot.lua +++ /dev/null @@ -1,43 +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) - local hasSkull = isInArray({SKULL_RED, SKULL_BLACK}, player:getSkull()) - if amulet and amulet.itemid == ITEM_AMULETOFLOSS and not hasSkull 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 - local lossPercent = player:getLossPercent() - for i = CONST_SLOT_HEAD, CONST_SLOT_AMMO do - local item = player:getSlotItem(i) - if item then - if hasSkull or math.random(item:isContainer() and 100 or 1000) <= lossPercent 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_8_0/data/creaturescripts/scripts/extendedopcode.lua b/path_8_0/data/creaturescripts/scripts/extendedopcode.lua deleted file mode 100644 index 7fa2d42e6..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/scripts/firstitems.lua b/path_8_0/data/creaturescripts/scripts/firstitems.lua deleted file mode 100644 index f778c7878..000000000 --- a/path_8_0/data/creaturescripts/scripts/firstitems.lua +++ /dev/null @@ -1,52 +0,0 @@ --- Without Rookgaard -local config = { - [1] = { - --equipment spellbook, wand of vortex, studded legs, leather boots, scarf - items = {{2175, 1}, {2190, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - --container rope, shovel - container = {{2120, 1}, {2554, 1}} - }, - [2] = { - --equipment spellbook, snakebite rod, studded legs, leather boots scarf - items = {{2175, 1}, {2182, 1}, {2468, 1}, {2643, 1}, {2661, 1}}, - --container rope, shovel - container = {{2120, 1}, {2554, 1}} - }, - [3] = { - --equipment dwrven shield, 5 spear, ranger's cloak, scarf, legion helmet - items = {{2525, 1}, {2389, 5}, {2660, 1}, {2643, 1}, {2661, 1}, {2480, 1}}, - --container rope, shovel, bow, 50 arrow - container = {{2120, 1}, {2554, 1}, {2456, 1}, {2544, 50}} - }, - [4] = { - --equipment dwarven shield, orcish axe, brass armor, brass helmet, brass legs scarf - items = {{2525, 1}, {2428, 1}, {2465, 1}, {2460, 1}, {2478, 1}, {2643, 1}, {2661, 1}}, - --container spike sword, daramian mace, rope, shovel, health potion - container = {{2383, 1}, {2439, 1}, {2120, 1}, {2554, 1}} - } -} - -function onLogin(player) - 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_8_0/data/creaturescripts/scripts/login.lua b/path_8_0/data/creaturescripts/scripts/login.lua deleted file mode 100644 index 6c414c1bb..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/scripts/logout.lua b/path_8_0/data/creaturescripts/scripts/logout.lua deleted file mode 100644 index 5a5bfe4eb..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/scripts/offlinetraining.lua b/path_8_0/data/creaturescripts/scripts/offlinetraining.lua deleted file mode 100644 index 98e37aeae..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/scripts/playerdeath.lua b/path_8_0/data/creaturescripts/scripts/playerdeath.lua deleted file mode 100644 index 159dbc720..000000000 --- a/path_8_0/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_8_0/data/creaturescripts/scripts/regeneratestamina.lua b/path_8_0/data/creaturescripts/scripts/regeneratestamina.lua deleted file mode 100644 index 04409058b..000000000 --- a/path_8_0/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_8_0/data/events/events.xml b/path_8_0/data/events/events.xml deleted file mode 100644 index 7b6bdc7f5..000000000 --- a/path_8_0/data/events/events.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/events/scripts/creature.lua b/path_8_0/data/events/scripts/creature.lua deleted file mode 100644 index 17116ec37..000000000 --- a/path_8_0/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_8_0/data/events/scripts/monster.lua b/path_8_0/data/events/scripts/monster.lua deleted file mode 100644 index 5afd8d131..000000000 --- a/path_8_0/data/events/scripts/monster.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Monster:onSpawn(position, isStartup) - return true -end diff --git a/path_8_0/data/events/scripts/party.lua b/path_8_0/data/events/scripts/party.lua deleted file mode 100644 index bbb4cfa29..000000000 --- a/path_8_0/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_8_0/data/events/scripts/player.lua b/path_8_0/data/events/scripts/player.lua deleted file mode 100644 index 4e6072ca7..000000000 --- a/path_8_0/data/events/scripts/player.lua +++ /dev/null @@ -1,215 +0,0 @@ -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) - 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 - -function Player:onMoveCreature(creature, fromPosition, toPosition) - return true -end - -function Player:onTurn(direction) - if self:getGroup():getAccess() and self:getDirection() == direction then - local nextPosition = self:getPosition() - nextPosition:getNextPosition(direction) - - self:teleportTo(nextPosition, true) - end - - 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_8_0/data/global.lua b/path_8_0/data/global.lua deleted file mode 100644 index d5f0a5300..000000000 --- a/path_8_0/data/global.lua +++ /dev/null @@ -1,70 +0,0 @@ -dofile('data/lib/lib.lua') - -ddos = {}; -ddos.enabled = false; -ddos.broadcasted = false - -STORAGEVALUE_PROMOTION = 30018 - -ropeSpots = {384, 418} - -doors = { - [1209] = 1211, [1210] = 1211, [1212] = 1214, [1213] = 1214, [1214] = 1212, [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, -} - -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} -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} -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} -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} -levelDoors = {1227, 1229, 1245, 1247, 1259, 1261, 3540, 3549, 5103, 5112, 5121, 5130, 5292, 5294, 6206, 6208, 6263, 6265, 6896, 6905, 7038, 7047} -keys = {2086, 2087, 2088, 2089, 2090, 2091, 2092} - -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_8_0/data/globalevents/globalevents.xml b/path_8_0/data/globalevents/globalevents.xml deleted file mode 100644 index 8012f11aa..000000000 --- a/path_8_0/data/globalevents/globalevents.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_8_0/data/globalevents/lib/globalevents.lua b/path_8_0/data/globalevents/lib/globalevents.lua deleted file mode 100644 index 6116bcc01..000000000 --- a/path_8_0/data/globalevents/lib/globalevents.lua +++ /dev/null @@ -1 +0,0 @@ --- empty file -- diff --git a/path_8_0/data/globalevents/scripts/cleanmap.lua b/path_8_0/data/globalevents/scripts/cleanmap.lua deleted file mode 100644 index bc69435f4..000000000 --- a/path_8_0/data/globalevents/scripts/cleanmap.lua +++ /dev/null @@ -1,10 +0,0 @@ -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_8_0/data/globalevents/scripts/ddos.lua b/path_8_0/data/globalevents/scripts/ddos.lua deleted file mode 100644 index c629eaffd..000000000 --- a/path_8_0/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_8_0/data/globalevents/scripts/record.lua b/path_8_0/data/globalevents/scripts/record.lua deleted file mode 100644 index 47d6b79ef..000000000 --- a/path_8_0/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_8_0/data/globalevents/scripts/serversave.lua b/path_8_0/data/globalevents/scripts/serversave.lua deleted file mode 100644 index e943e74d5..000000000 --- a/path_8_0/data/globalevents/scripts/serversave.lua +++ /dev/null @@ -1,4 +0,0 @@ -function onThink(interval) - saveServer() - return true -end diff --git a/path_8_0/data/globalevents/scripts/startup.lua b/path_8_0/data/globalevents/scripts/startup.lua deleted file mode 100644 index bb2542118..000000000 --- a/path_8_0/data/globalevents/scripts/startup.lua +++ /dev/null @@ -1,38 +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()) - - -- 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_8_0/data/items/items.otb b/path_8_0/data/items/items.otb deleted file mode 100644 index fe4446714..000000000 Binary files a/path_8_0/data/items/items.otb and /dev/null differ diff --git a/path_8_0/data/items/items.xml b/path_8_0/data/items/items.xml deleted file mode 100644 index 38396a37d..000000000 --- a/path_8_0/data/items/items.xml +++ /dev/null @@ -1,15278 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/lib/compat/compat.lua b/path_8_0/data/lib/compat/compat.lua deleted file mode 100644 index 16dddf5dc..000000000 --- a/path_8_0/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(message, position, color) return Game.sendAnimatedText(message, position, color) 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:getHouse() ~= nil - 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_8_0/data/lib/core/constants.lua b/path_8_0/data/lib/core/constants.lua deleted file mode 100644 index 9d1f90bc1..000000000 --- a/path_8_0/data/lib/core/constants.lua +++ /dev/null @@ -1 +0,0 @@ -CONTAINER_POSITION = 0xFFFF diff --git a/path_8_0/data/lib/core/container.lua b/path_8_0/data/lib/core/container.lua deleted file mode 100644 index 65343eb7f..000000000 --- a/path_8_0/data/lib/core/container.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Container.isContainer(self) - return true -end diff --git a/path_8_0/data/lib/core/core.lua b/path_8_0/data/lib/core/core.lua deleted file mode 100644 index 1b78513f1..000000000 --- a/path_8_0/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_8_0/data/lib/core/creature.lua b/path_8_0/data/lib/core/creature.lua deleted file mode 100644 index e0fd78578..000000000 --- a/path_8_0/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_8_0/data/lib/core/game.lua b/path_8_0/data/lib/core/game.lua deleted file mode 100644 index 4e0c5d8aa..000000000 --- a/path_8_0/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_8_0/data/lib/core/item.lua b/path_8_0/data/lib/core/item.lua deleted file mode 100644 index 7980d5ae1..000000000 --- a/path_8_0/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_8_0/data/lib/core/itemtype.lua b/path_8_0/data/lib/core/itemtype.lua deleted file mode 100644 index c94ba7f1b..000000000 --- a/path_8_0/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_8_0/data/lib/core/player.lua b/path_8_0/data/lib/core/player.lua deleted file mode 100644 index db09d6816..000000000 --- a/path_8_0/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 - -local lossPercent = { - [0] = 100, - [1] = 70, - [2] = 45, - [3] = 25, - [4] = 10, - [5] = 0 -} - -function Player.getLossPercent(self) - local blessings = 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_8_0/data/lib/core/position.lua b/path_8_0/data/lib/core/position.lua deleted file mode 100644 index 572c6a29f..000000000 --- a/path_8_0/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_8_0/data/lib/core/teleport.lua b/path_8_0/data/lib/core/teleport.lua deleted file mode 100644 index 89302688e..000000000 --- a/path_8_0/data/lib/core/teleport.lua +++ /dev/null @@ -1,3 +0,0 @@ -function Teleport.isTeleport(self) - return true -end diff --git a/path_8_0/data/lib/core/tile.lua b/path_8_0/data/lib/core/tile.lua deleted file mode 100644 index e2e26c4ba..000000000 --- a/path_8_0/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_8_0/data/lib/custom/custom.lua b/path_8_0/data/lib/custom/custom.lua deleted file mode 100644 index 3a1167657..000000000 --- a/path_8_0/data/lib/custom/custom.lua +++ /dev/null @@ -1,85 +0,0 @@ -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_8_0/data/lib/custom/storages.lua b/path_8_0/data/lib/custom/storages.lua deleted file mode 100644 index 0cbf79c31..000000000 --- a/path_8_0/data/lib/custom/storages.lua +++ /dev/null @@ -1,5 +0,0 @@ --- STORAGES -- --- (HIGHLY RECOMMENDED -> ONE mission per STORAGE) -- --- Sort it in Values - - -Storage = {} diff --git a/path_8_0/data/lib/lib.lua b/path_8_0/data/lib/lib.lua deleted file mode 100644 index 2ffc31da5..000000000 --- a/path_8_0/data/lib/lib.lua +++ /dev/null @@ -1,9 +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') - --- Custom -dofile('data/lib/custom/custom.lua') -dofile('data/lib/custom/storages.lua') diff --git a/path_8_0/data/logs/.gitignore b/path_8_0/data/logs/.gitignore deleted file mode 100644 index 5e7d2734c..000000000 --- a/path_8_0/data/logs/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore diff --git a/path_8_0/data/migrations/0.lua b/path_8_0/data/migrations/0.lua deleted file mode 100644 index 0fb3ff971..000000000 --- a/path_8_0/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_8_0/data/migrations/1.lua b/path_8_0/data/migrations/1.lua deleted file mode 100644 index c3e6f22fb..000000000 --- a/path_8_0/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_8_0/data/migrations/10.lua b/path_8_0/data/migrations/10.lua deleted file mode 100644 index 9e1357e73..000000000 --- a/path_8_0/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_8_0/data/migrations/11.lua b/path_8_0/data/migrations/11.lua deleted file mode 100644 index 69b1691cb..000000000 --- a/path_8_0/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_8_0/data/migrations/12.lua b/path_8_0/data/migrations/12.lua deleted file mode 100644 index 6e168586b..000000000 --- a/path_8_0/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_8_0/data/migrations/13.lua b/path_8_0/data/migrations/13.lua deleted file mode 100644 index 7b123b40f..000000000 --- a/path_8_0/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_8_0/data/migrations/14.lua b/path_8_0/data/migrations/14.lua deleted file mode 100644 index 632bbaf09..000000000 --- a/path_8_0/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_8_0/data/migrations/15.lua b/path_8_0/data/migrations/15.lua deleted file mode 100644 index f04796b66..000000000 --- a/path_8_0/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_8_0/data/migrations/16.lua b/path_8_0/data/migrations/16.lua deleted file mode 100644 index 45e742227..000000000 --- a/path_8_0/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_8_0/data/migrations/17.lua b/path_8_0/data/migrations/17.lua deleted file mode 100644 index e26bdd430..000000000 --- a/path_8_0/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_8_0/data/migrations/18.lua b/path_8_0/data/migrations/18.lua deleted file mode 100644 index d0ffd9c0c..000000000 --- a/path_8_0/data/migrations/18.lua +++ /dev/null @@ -1,3 +0,0 @@ -function onUpdateDatabase() - return false -end diff --git a/path_8_0/data/migrations/2.lua b/path_8_0/data/migrations/2.lua deleted file mode 100644 index 942a1cd76..000000000 --- a/path_8_0/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_8_0/data/migrations/3.lua b/path_8_0/data/migrations/3.lua deleted file mode 100644 index c93e34d54..000000000 --- a/path_8_0/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_8_0/data/migrations/4.lua b/path_8_0/data/migrations/4.lua deleted file mode 100644 index 069a6432d..000000000 --- a/path_8_0/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_8_0/data/migrations/5.lua b/path_8_0/data/migrations/5.lua deleted file mode 100644 index 82ba621a6..000000000 --- a/path_8_0/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_8_0/data/migrations/6.lua b/path_8_0/data/migrations/6.lua deleted file mode 100644 index f98946764..000000000 --- a/path_8_0/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_8_0/data/migrations/7.lua b/path_8_0/data/migrations/7.lua deleted file mode 100644 index 1fd4a1196..000000000 --- a/path_8_0/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_8_0/data/migrations/8.lua b/path_8_0/data/migrations/8.lua deleted file mode 100644 index d2d9f1750..000000000 --- a/path_8_0/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_8_0/data/migrations/9.lua b/path_8_0/data/migrations/9.lua deleted file mode 100644 index 33022ee08..000000000 --- a/path_8_0/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_8_0/data/monster/Amazons/amazon.xml b/path_8_0/data/monster/Amazons/amazon.xml deleted file mode 100644 index 9bc831a04..000000000 --- a/path_8_0/data/monster/Amazons/amazon.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Amazons/valkyrie.xml b/path_8_0/data/monster/Amazons/valkyrie.xml deleted file mode 100644 index b36103999..000000000 --- a/path_8_0/data/monster/Amazons/valkyrie.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Annelids/carrion worm.xml b/path_8_0/data/monster/Annelids/carrion worm.xml deleted file mode 100644 index 19b2bce4a..000000000 --- a/path_8_0/data/monster/Annelids/carrion worm.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Annelids/rotworm.xml b/path_8_0/data/monster/Annelids/rotworm.xml deleted file mode 100644 index 0506dd91b..000000000 --- a/path_8_0/data/monster/Annelids/rotworm.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Apes/kongra.xml b/path_8_0/data/monster/Apes/kongra.xml deleted file mode 100644 index 4fde32524..000000000 --- a/path_8_0/data/monster/Apes/kongra.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Apes/merlkin.xml b/path_8_0/data/monster/Apes/merlkin.xml deleted file mode 100644 index 3b2794a3f..000000000 --- a/path_8_0/data/monster/Apes/merlkin.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Apes/sibang.xml b/path_8_0/data/monster/Apes/sibang.xml deleted file mode 100644 index 1f62e4dfb..000000000 --- a/path_8_0/data/monster/Apes/sibang.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Apes/yeti.xml b/path_8_0/data/monster/Apes/yeti.xml deleted file mode 100644 index 5faa737f6..000000000 --- a/path_8_0/data/monster/Apes/yeti.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/crystal spider.xml b/path_8_0/data/monster/Arachnids/crystal spider.xml deleted file mode 100644 index 80575371b..000000000 --- a/path_8_0/data/monster/Arachnids/crystal spider.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/giant spider.xml b/path_8_0/data/monster/Arachnids/giant spider.xml deleted file mode 100644 index 0e235e35a..000000000 --- a/path_8_0/data/monster/Arachnids/giant spider.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/poison spider.xml b/path_8_0/data/monster/Arachnids/poison spider.xml deleted file mode 100644 index 07e543df9..000000000 --- a/path_8_0/data/monster/Arachnids/poison spider.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/scorpion.xml b/path_8_0/data/monster/Arachnids/scorpion.xml deleted file mode 100644 index 8f74aae3f..000000000 --- a/path_8_0/data/monster/Arachnids/scorpion.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/spider.xml b/path_8_0/data/monster/Arachnids/spider.xml deleted file mode 100644 index 3bd0faf05..000000000 --- a/path_8_0/data/monster/Arachnids/spider.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arachnids/tarantula.xml b/path_8_0/data/monster/Arachnids/tarantula.xml deleted file mode 100644 index 5f5a3c10c..000000000 --- a/path_8_0/data/monster/Arachnids/tarantula.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/achad.xml b/path_8_0/data/monster/Arena/greenhorn/achad.xml deleted file mode 100644 index e4e722b1e..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/achad.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/axeitus headbanger.xml b/path_8_0/data/monster/Arena/greenhorn/axeitus headbanger.xml deleted file mode 100644 index d77f18405..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/axeitus headbanger.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/bloodpaw.xml b/path_8_0/data/monster/Arena/greenhorn/bloodpaw.xml deleted file mode 100644 index b8b9fe98a..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/bloodpaw.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/bovinus.xml b/path_8_0/data/monster/Arena/greenhorn/bovinus.xml deleted file mode 100644 index 84f832d78..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/bovinus.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/colerian the barbarian.xml b/path_8_0/data/monster/Arena/greenhorn/colerian the barbarian.xml deleted file mode 100644 index 35e9462db..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/colerian the barbarian.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/cursed gladiator.xml b/path_8_0/data/monster/Arena/greenhorn/cursed gladiator.xml deleted file mode 100644 index a3230bae8..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/cursed gladiator.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/frostfur.xml b/path_8_0/data/monster/Arena/greenhorn/frostfur.xml deleted file mode 100644 index 570d82689..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/frostfur.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/orcus the cruel.xml b/path_8_0/data/monster/Arena/greenhorn/orcus the cruel.xml deleted file mode 100644 index 5ae4f278d..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/orcus the cruel.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/rocky.xml b/path_8_0/data/monster/Arena/greenhorn/rocky.xml deleted file mode 100644 index d0f33ebe0..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/rocky.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/greenhorn/the hairy one.xml b/path_8_0/data/monster/Arena/greenhorn/the hairy one.xml deleted file mode 100644 index b2b227f87..000000000 --- a/path_8_0/data/monster/Arena/greenhorn/the hairy one.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/avalanche.xml b/path_8_0/data/monster/Arena/scrapper/avalanche.xml deleted file mode 100644 index 632efc88e..000000000 --- a/path_8_0/data/monster/Arena/scrapper/avalanche.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/drasilla.xml b/path_8_0/data/monster/Arena/scrapper/drasilla.xml deleted file mode 100644 index 0597feec6..000000000 --- a/path_8_0/data/monster/Arena/scrapper/drasilla.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/grimgor guteater.xml b/path_8_0/data/monster/Arena/scrapper/grimgor guteater.xml deleted file mode 100644 index 44ab725ef..000000000 --- a/path_8_0/data/monster/Arena/scrapper/grimgor guteater.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/kreebosh the exile.xml b/path_8_0/data/monster/Arena/scrapper/kreebosh the exile.xml deleted file mode 100644 index 354033c29..000000000 --- a/path_8_0/data/monster/Arena/scrapper/kreebosh the exile.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/slim.xml b/path_8_0/data/monster/Arena/scrapper/slim.xml deleted file mode 100644 index 757e45d4a..000000000 --- a/path_8_0/data/monster/Arena/scrapper/slim.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/spirit of earth.xml b/path_8_0/data/monster/Arena/scrapper/spirit of earth.xml deleted file mode 100644 index 0e3b90359..000000000 --- a/path_8_0/data/monster/Arena/scrapper/spirit of earth.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/spirit of fire.xml b/path_8_0/data/monster/Arena/scrapper/spirit of fire.xml deleted file mode 100644 index 2fa56ed7a..000000000 --- a/path_8_0/data/monster/Arena/scrapper/spirit of fire.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/spirit of water.xml b/path_8_0/data/monster/Arena/scrapper/spirit of water.xml deleted file mode 100644 index ea45271cb..000000000 --- a/path_8_0/data/monster/Arena/scrapper/spirit of water.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/the dark dancer.xml b/path_8_0/data/monster/Arena/scrapper/the dark dancer.xml deleted file mode 100644 index 56f55b449..000000000 --- a/path_8_0/data/monster/Arena/scrapper/the dark dancer.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/scrapper/the hag.xml b/path_8_0/data/monster/Arena/scrapper/the hag.xml deleted file mode 100644 index 0893946bd..000000000 --- a/path_8_0/data/monster/Arena/scrapper/the hag.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/darakan the executioner.xml b/path_8_0/data/monster/Arena/warlord/darakan the executioner.xml deleted file mode 100644 index 289db40e4..000000000 --- a/path_8_0/data/monster/Arena/warlord/darakan the executioner.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/deathbringer.xml b/path_8_0/data/monster/Arena/warlord/deathbringer.xml deleted file mode 100644 index 843622990..000000000 --- a/path_8_0/data/monster/Arena/warlord/deathbringer.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml b/path_8_0/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml deleted file mode 100644 index e22f6f3ec..000000000 --- a/path_8_0/data/monster/Arena/warlord/fallen mooh'tah master ghar.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/gnorre chyllson.xml b/path_8_0/data/monster/Arena/warlord/gnorre chyllson.xml deleted file mode 100644 index 0f48e5165..000000000 --- a/path_8_0/data/monster/Arena/warlord/gnorre chyllson.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/norgle glacierbeard.xml b/path_8_0/data/monster/Arena/warlord/norgle glacierbeard.xml deleted file mode 100644 index a3fbd82bd..000000000 --- a/path_8_0/data/monster/Arena/warlord/norgle glacierbeard.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/svoren the mad.xml b/path_8_0/data/monster/Arena/warlord/svoren the mad.xml deleted file mode 100644 index 7dc8b7b3b..000000000 --- a/path_8_0/data/monster/Arena/warlord/svoren the mad.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/the masked marauder.xml b/path_8_0/data/monster/Arena/warlord/the masked marauder.xml deleted file mode 100644 index dfbe0f8a0..000000000 --- a/path_8_0/data/monster/Arena/warlord/the masked marauder.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/the obliverator.xml b/path_8_0/data/monster/Arena/warlord/the obliverator.xml deleted file mode 100644 index d41561c45..000000000 --- a/path_8_0/data/monster/Arena/warlord/the obliverator.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/the pit lord.xml b/path_8_0/data/monster/Arena/warlord/the pit lord.xml deleted file mode 100644 index 0ecb6d5d5..000000000 --- a/path_8_0/data/monster/Arena/warlord/the pit lord.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Arena/warlord/webster.xml b/path_8_0/data/monster/Arena/warlord/webster.xml deleted file mode 100644 index 7b5c07443..000000000 --- a/path_8_0/data/monster/Arena/warlord/webster.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Barbarians/barbarian bloodwalker.xml b/path_8_0/data/monster/Barbarians/barbarian bloodwalker.xml deleted file mode 100644 index 38fe831de..000000000 --- a/path_8_0/data/monster/Barbarians/barbarian bloodwalker.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Barbarians/barbarian brutetamer.xml b/path_8_0/data/monster/Barbarians/barbarian brutetamer.xml deleted file mode 100644 index 6d556cc40..000000000 --- a/path_8_0/data/monster/Barbarians/barbarian brutetamer.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Barbarians/barbarian headsplitter.xml b/path_8_0/data/monster/Barbarians/barbarian headsplitter.xml deleted file mode 100644 index 176abc9d6..000000000 --- a/path_8_0/data/monster/Barbarians/barbarian headsplitter.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Barbarians/barbarian skullhunter.xml b/path_8_0/data/monster/Barbarians/barbarian skullhunter.xml deleted file mode 100644 index efa9e6f6e..000000000 --- a/path_8_0/data/monster/Barbarians/barbarian skullhunter.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bears/bear.xml b/path_8_0/data/monster/Bears/bear.xml deleted file mode 100644 index e07bfaa17..000000000 --- a/path_8_0/data/monster/Bears/bear.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bears/panda.xml b/path_8_0/data/monster/Bears/panda.xml deleted file mode 100644 index d7a9f0637..000000000 --- a/path_8_0/data/monster/Bears/panda.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bears/polar bear.xml b/path_8_0/data/monster/Bears/polar bear.xml deleted file mode 100644 index aaa41711f..000000000 --- a/path_8_0/data/monster/Bears/polar bear.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bio-Elementals/carniphila.xml b/path_8_0/data/monster/Bio-Elementals/carniphila.xml deleted file mode 100644 index 726db41b6..000000000 --- a/path_8_0/data/monster/Bio-Elementals/carniphila.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bio-Elementals/defiler.xml b/path_8_0/data/monster/Bio-Elementals/defiler.xml deleted file mode 100644 index f79b2f940..000000000 --- a/path_8_0/data/monster/Bio-Elementals/defiler.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bio-Elementals/slime.xml b/path_8_0/data/monster/Bio-Elementals/slime.xml deleted file mode 100644 index 4267d221c..000000000 --- a/path_8_0/data/monster/Bio-Elementals/slime.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bio-Elementals/son of verminor.xml b/path_8_0/data/monster/Bio-Elementals/son of verminor.xml deleted file mode 100644 index 4f03ba841..000000000 --- a/path_8_0/data/monster/Bio-Elementals/son of verminor.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bio-Elementals/spit nettle.xml b/path_8_0/data/monster/Bio-Elementals/spit nettle.xml deleted file mode 100644 index e55d0584a..000000000 --- a/path_8_0/data/monster/Bio-Elementals/spit nettle.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/chicken.xml b/path_8_0/data/monster/Birds/chicken.xml deleted file mode 100644 index 527c7e1b2..000000000 --- a/path_8_0/data/monster/Birds/chicken.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/flamingo.xml b/path_8_0/data/monster/Birds/flamingo.xml deleted file mode 100644 index 27e1ba97c..000000000 --- a/path_8_0/data/monster/Birds/flamingo.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/parrot.xml b/path_8_0/data/monster/Birds/parrot.xml deleted file mode 100644 index 446d6b47d..000000000 --- a/path_8_0/data/monster/Birds/parrot.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/penguin.xml b/path_8_0/data/monster/Birds/penguin.xml deleted file mode 100644 index 82e7d4b48..000000000 --- a/path_8_0/data/monster/Birds/penguin.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/seagull.xml b/path_8_0/data/monster/Birds/seagull.xml deleted file mode 100644 index 6ac3624f8..000000000 --- a/path_8_0/data/monster/Birds/seagull.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Birds/terror bird.xml b/path_8_0/data/monster/Birds/terror bird.xml deleted file mode 100644 index 28353a3a7..000000000 --- a/path_8_0/data/monster/Birds/terror bird.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/annihilon.xml b/path_8_0/data/monster/Bosses/annihilon.xml deleted file mode 100644 index 1aa9ed4ca..000000000 --- a/path_8_0/data/monster/Bosses/annihilon.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/apprentice sheng.xml b/path_8_0/data/monster/Bosses/apprentice sheng.xml deleted file mode 100644 index 06db7e042..000000000 --- a/path_8_0/data/monster/Bosses/apprentice sheng.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/barbaria.xml b/path_8_0/data/monster/Bosses/barbaria.xml deleted file mode 100644 index 1505de6c1..000000000 --- a/path_8_0/data/monster/Bosses/barbaria.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/bones.xml b/path_8_0/data/monster/Bosses/bones.xml deleted file mode 100644 index f7401c9c5..000000000 --- a/path_8_0/data/monster/Bosses/bones.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/brutus bloodbeard.xml b/path_8_0/data/monster/Bosses/brutus bloodbeard.xml deleted file mode 100644 index 387ff18ac..000000000 --- a/path_8_0/data/monster/Bosses/brutus bloodbeard.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/countess sorrow.xml b/path_8_0/data/monster/Bosses/countess sorrow.xml deleted file mode 100644 index 3e67e1513..000000000 --- a/path_8_0/data/monster/Bosses/countess sorrow.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/deadeye devious.xml b/path_8_0/data/monster/Bosses/deadeye devious.xml deleted file mode 100644 index a550a0f85..000000000 --- a/path_8_0/data/monster/Bosses/deadeye devious.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/demodras.xml b/path_8_0/data/monster/Bosses/demodras.xml deleted file mode 100644 index 839d64565..000000000 --- a/path_8_0/data/monster/Bosses/demodras.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/dharalion.xml b/path_8_0/data/monster/Bosses/dharalion.xml deleted file mode 100644 index 83850d8a0..000000000 --- a/path_8_0/data/monster/Bosses/dharalion.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/dire penguin.xml b/path_8_0/data/monster/Bosses/dire penguin.xml deleted file mode 100644 index 42887ee23..000000000 --- a/path_8_0/data/monster/Bosses/dire penguin.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/dracola.xml b/path_8_0/data/monster/Bosses/dracola.xml deleted file mode 100644 index b7bddf66d..000000000 --- a/path_8_0/data/monster/Bosses/dracola.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/fernfang.xml b/path_8_0/data/monster/Bosses/fernfang.xml deleted file mode 100644 index 0f9f9d904..000000000 --- a/path_8_0/data/monster/Bosses/fernfang.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/ferumbras.xml b/path_8_0/data/monster/Bosses/ferumbras.xml deleted file mode 100644 index 402b0cf18..000000000 --- a/path_8_0/data/monster/Bosses/ferumbras.xml +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/fluffy.xml b/path_8_0/data/monster/Bosses/fluffy.xml deleted file mode 100644 index ef1c3d23a..000000000 --- a/path_8_0/data/monster/Bosses/fluffy.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/foreman kneebiter.xml b/path_8_0/data/monster/Bosses/foreman kneebiter.xml deleted file mode 100644 index 4f74bdd40..000000000 --- a/path_8_0/data/monster/Bosses/foreman kneebiter.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/general murius.xml b/path_8_0/data/monster/Bosses/general murius.xml deleted file mode 100644 index b3fd507b8..000000000 --- a/path_8_0/data/monster/Bosses/general murius.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/ghazbaran.xml b/path_8_0/data/monster/Bosses/ghazbaran.xml deleted file mode 100644 index 81a367e8d..000000000 --- a/path_8_0/data/monster/Bosses/ghazbaran.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/golgordan.xml b/path_8_0/data/monster/Bosses/golgordan.xml deleted file mode 100644 index 6c485946d..000000000 --- a/path_8_0/data/monster/Bosses/golgordan.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/grorlam.xml b/path_8_0/data/monster/Bosses/grorlam.xml deleted file mode 100644 index 0c53f7c7f..000000000 --- a/path_8_0/data/monster/Bosses/grorlam.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/hairman the huge.xml b/path_8_0/data/monster/Bosses/hairman the huge.xml deleted file mode 100644 index bd25ebc64..000000000 --- a/path_8_0/data/monster/Bosses/hairman the huge.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/handmaiden.xml b/path_8_0/data/monster/Bosses/handmaiden.xml deleted file mode 100644 index 5ebd42598..000000000 --- a/path_8_0/data/monster/Bosses/handmaiden.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/hellgorak.xml b/path_8_0/data/monster/Bosses/hellgorak.xml deleted file mode 100644 index eabafede5..000000000 --- a/path_8_0/data/monster/Bosses/hellgorak.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/koshei the deathless.xml b/path_8_0/data/monster/Bosses/koshei the deathless.xml deleted file mode 100644 index bed77fdf9..000000000 --- a/path_8_0/data/monster/Bosses/koshei the deathless.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/latrivan.xml b/path_8_0/data/monster/Bosses/latrivan.xml deleted file mode 100644 index 953eaa744..000000000 --- a/path_8_0/data/monster/Bosses/latrivan.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/lethal lissy.xml b/path_8_0/data/monster/Bosses/lethal lissy.xml deleted file mode 100644 index c176579b8..000000000 --- a/path_8_0/data/monster/Bosses/lethal lissy.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/mad technomancer.xml b/path_8_0/data/monster/Bosses/mad technomancer.xml deleted file mode 100644 index f97163ec8..000000000 --- a/path_8_0/data/monster/Bosses/mad technomancer.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/madareth.xml b/path_8_0/data/monster/Bosses/madareth.xml deleted file mode 100644 index 8296fee60..000000000 --- a/path_8_0/data/monster/Bosses/madareth.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/man in the cave.xml b/path_8_0/data/monster/Bosses/man in the cave.xml deleted file mode 100644 index bb59b88fe..000000000 --- a/path_8_0/data/monster/Bosses/man in the cave.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/massacre.xml b/path_8_0/data/monster/Bosses/massacre.xml deleted file mode 100644 index eee4188b8..000000000 --- a/path_8_0/data/monster/Bosses/massacre.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/minishabaal.xml b/path_8_0/data/monster/Bosses/minishabaal.xml deleted file mode 100644 index fa6917683..000000000 --- a/path_8_0/data/monster/Bosses/minishabaal.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/morgaroth.xml b/path_8_0/data/monster/Bosses/morgaroth.xml deleted file mode 100644 index 759b6c2cb..000000000 --- a/path_8_0/data/monster/Bosses/morgaroth.xml +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/mr. punish.xml b/path_8_0/data/monster/Bosses/mr. punish.xml deleted file mode 100644 index 3dc5c5e8e..000000000 --- a/path_8_0/data/monster/Bosses/mr. punish.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/munster.xml b/path_8_0/data/monster/Bosses/munster.xml deleted file mode 100644 index 0f2755869..000000000 --- a/path_8_0/data/monster/Bosses/munster.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/necropharus.xml b/path_8_0/data/monster/Bosses/necropharus.xml deleted file mode 100644 index 97fce3af6..000000000 --- a/path_8_0/data/monster/Bosses/necropharus.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/orshabaal.xml b/path_8_0/data/monster/Bosses/orshabaal.xml deleted file mode 100644 index 93255a541..000000000 --- a/path_8_0/data/monster/Bosses/orshabaal.xml +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/ron the ripper.xml b/path_8_0/data/monster/Bosses/ron the ripper.xml deleted file mode 100644 index 4a3a50d35..000000000 --- a/path_8_0/data/monster/Bosses/ron the ripper.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the abomination.xml b/path_8_0/data/monster/Bosses/the abomination.xml deleted file mode 100644 index f6a99b018..000000000 --- a/path_8_0/data/monster/Bosses/the abomination.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the evil eye.xml b/path_8_0/data/monster/Bosses/the evil eye.xml deleted file mode 100644 index b2305017c..000000000 --- a/path_8_0/data/monster/Bosses/the evil eye.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the handmaiden.xml b/path_8_0/data/monster/Bosses/the handmaiden.xml deleted file mode 100644 index 1cd2e7118..000000000 --- a/path_8_0/data/monster/Bosses/the handmaiden.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the horned fox.xml b/path_8_0/data/monster/Bosses/the horned fox.xml deleted file mode 100644 index f5ad9f314..000000000 --- a/path_8_0/data/monster/Bosses/the horned fox.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the imperor.xml b/path_8_0/data/monster/Bosses/the imperor.xml deleted file mode 100644 index 0af978dfd..000000000 --- a/path_8_0/data/monster/Bosses/the imperor.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the old widow.xml b/path_8_0/data/monster/Bosses/the old widow.xml deleted file mode 100644 index 5900fd4a0..000000000 --- a/path_8_0/data/monster/Bosses/the old widow.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/the plasmother.xml b/path_8_0/data/monster/Bosses/the plasmother.xml deleted file mode 100644 index 39da9d0d9..000000000 --- a/path_8_0/data/monster/Bosses/the plasmother.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/thul.xml b/path_8_0/data/monster/Bosses/thul.xml deleted file mode 100644 index acc7ff2b9..000000000 --- a/path_8_0/data/monster/Bosses/thul.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/tibia bug.xml b/path_8_0/data/monster/Bosses/tibia bug.xml deleted file mode 100644 index e9f178905..000000000 --- a/path_8_0/data/monster/Bosses/tibia bug.xml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/tiquandas revenge.xml b/path_8_0/data/monster/Bosses/tiquandas revenge.xml deleted file mode 100644 index cd5402461..000000000 --- a/path_8_0/data/monster/Bosses/tiquandas revenge.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/undead minion.xml b/path_8_0/data/monster/Bosses/undead minion.xml deleted file mode 100644 index 910cc10d8..000000000 --- a/path_8_0/data/monster/Bosses/undead minion.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/ungreez.xml b/path_8_0/data/monster/Bosses/ungreez.xml deleted file mode 100644 index cd8959c2a..000000000 --- a/path_8_0/data/monster/Bosses/ungreez.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/ushuriel.xml b/path_8_0/data/monster/Bosses/ushuriel.xml deleted file mode 100644 index bf5c87d81..000000000 --- a/path_8_0/data/monster/Bosses/ushuriel.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/xenia.xml b/path_8_0/data/monster/Bosses/xenia.xml deleted file mode 100644 index 184a4a11c..000000000 --- a/path_8_0/data/monster/Bosses/xenia.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Bosses/zugurosh.xml b/path_8_0/data/monster/Bosses/zugurosh.xml deleted file mode 100644 index 1605a313e..000000000 --- a/path_8_0/data/monster/Bosses/zugurosh.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/dog.xml b/path_8_0/data/monster/Canines/dog.xml deleted file mode 100644 index 01aeee631..000000000 --- a/path_8_0/data/monster/Canines/dog.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/hellhound.xml b/path_8_0/data/monster/Canines/hellhound.xml deleted file mode 100644 index e37291b29..000000000 --- a/path_8_0/data/monster/Canines/hellhound.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/husky.xml b/path_8_0/data/monster/Canines/husky.xml deleted file mode 100644 index 04d71532e..000000000 --- a/path_8_0/data/monster/Canines/husky.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/war wolf.xml b/path_8_0/data/monster/Canines/war wolf.xml deleted file mode 100644 index c6f944fab..000000000 --- a/path_8_0/data/monster/Canines/war wolf.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/winter wolf.xml b/path_8_0/data/monster/Canines/winter wolf.xml deleted file mode 100644 index 115d77ad1..000000000 --- a/path_8_0/data/monster/Canines/winter wolf.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Canines/wolf.xml b/path_8_0/data/monster/Canines/wolf.xml deleted file mode 100644 index 757de4588..000000000 --- a/path_8_0/data/monster/Canines/wolf.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Chakoyas/chakoya toolshaper.xml b/path_8_0/data/monster/Chakoyas/chakoya toolshaper.xml deleted file mode 100644 index 9f7e1b42c..000000000 --- a/path_8_0/data/monster/Chakoyas/chakoya toolshaper.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Chakoyas/chakoya tribewarden.xml b/path_8_0/data/monster/Chakoyas/chakoya tribewarden.xml deleted file mode 100644 index 5f9321947..000000000 --- a/path_8_0/data/monster/Chakoyas/chakoya tribewarden.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Chakoyas/chakoya windcaller.xml b/path_8_0/data/monster/Chakoyas/chakoya windcaller.xml deleted file mode 100644 index cc51c8928..000000000 --- a/path_8_0/data/monster/Chakoyas/chakoya windcaller.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Crustaceans/blood crab.xml b/path_8_0/data/monster/Crustaceans/blood crab.xml deleted file mode 100644 index 10d162785..000000000 --- a/path_8_0/data/monster/Crustaceans/blood crab.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Crustaceans/crab.xml b/path_8_0/data/monster/Crustaceans/crab.xml deleted file mode 100644 index 5403d1636..000000000 --- a/path_8_0/data/monster/Crustaceans/crab.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Cryo-Elementals/ice golem.xml b/path_8_0/data/monster/Cryo-Elementals/ice golem.xml deleted file mode 100644 index 0962c095c..000000000 --- a/path_8_0/data/monster/Cryo-Elementals/ice golem.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/dark torturer.xml b/path_8_0/data/monster/Demons/dark torturer.xml deleted file mode 100644 index 0f582c466..000000000 --- a/path_8_0/data/monster/Demons/dark torturer.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/demon (dcq).xml b/path_8_0/data/monster/Demons/demon (dcq).xml deleted file mode 100644 index bbd092cd0..000000000 --- a/path_8_0/data/monster/Demons/demon (dcq).xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/demon.xml b/path_8_0/data/monster/Demons/demon.xml deleted file mode 100644 index af718370c..000000000 --- a/path_8_0/data/monster/Demons/demon.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/destroyer.xml b/path_8_0/data/monster/Demons/destroyer.xml deleted file mode 100644 index 0b5bf1083..000000000 --- a/path_8_0/data/monster/Demons/destroyer.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/diabolic imp.xml b/path_8_0/data/monster/Demons/diabolic imp.xml deleted file mode 100644 index 1a96ea904..000000000 --- a/path_8_0/data/monster/Demons/diabolic imp.xml +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/fire devil.xml b/path_8_0/data/monster/Demons/fire devil.xml deleted file mode 100644 index d100e1f91..000000000 --- a/path_8_0/data/monster/Demons/fire devil.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/fury.xml b/path_8_0/data/monster/Demons/fury.xml deleted file mode 100644 index d31ee4413..000000000 --- a/path_8_0/data/monster/Demons/fury.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/hand of cursed fate.xml b/path_8_0/data/monster/Demons/hand of cursed fate.xml deleted file mode 100644 index 4714dad9d..000000000 --- a/path_8_0/data/monster/Demons/hand of cursed fate.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/juggernaut.xml b/path_8_0/data/monster/Demons/juggernaut.xml deleted file mode 100644 index 2a7869622..000000000 --- a/path_8_0/data/monster/Demons/juggernaut.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/nightmare.xml b/path_8_0/data/monster/Demons/nightmare.xml deleted file mode 100644 index 80388860a..000000000 --- a/path_8_0/data/monster/Demons/nightmare.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Demons/plaguesmith.xml b/path_8_0/data/monster/Demons/plaguesmith.xml deleted file mode 100644 index e645c6e66..000000000 --- a/path_8_0/data/monster/Demons/plaguesmith.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Djinns/blue djinn.xml b/path_8_0/data/monster/Djinns/blue djinn.xml deleted file mode 100644 index a9cbbb51d..000000000 --- a/path_8_0/data/monster/Djinns/blue djinn.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Djinns/efreet.xml b/path_8_0/data/monster/Djinns/efreet.xml deleted file mode 100644 index 5238a43b2..000000000 --- a/path_8_0/data/monster/Djinns/efreet.xml +++ /dev/null @@ -1,73 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Djinns/green djinn.xml b/path_8_0/data/monster/Djinns/green djinn.xml deleted file mode 100644 index 20e7b6cff..000000000 --- a/path_8_0/data/monster/Djinns/green djinn.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Djinns/marid.xml b/path_8_0/data/monster/Djinns/marid.xml deleted file mode 100644 index b3efa30cf..000000000 --- a/path_8_0/data/monster/Djinns/marid.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dragons/dragon lord.xml b/path_8_0/data/monster/Dragons/dragon lord.xml deleted file mode 100644 index c2ee427a1..000000000 --- a/path_8_0/data/monster/Dragons/dragon lord.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dragons/dragon.xml b/path_8_0/data/monster/Dragons/dragon.xml deleted file mode 100644 index a1e28f685..000000000 --- a/path_8_0/data/monster/Dragons/dragon.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dragons/frost dragon.xml b/path_8_0/data/monster/Dragons/frost dragon.xml deleted file mode 100644 index d100c2420..000000000 --- a/path_8_0/data/monster/Dragons/frost dragon.xml +++ /dev/null @@ -1,81 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dragons/undead dragon.xml b/path_8_0/data/monster/Dragons/undead dragon.xml deleted file mode 100644 index 1bc920ca1..000000000 --- a/path_8_0/data/monster/Dragons/undead dragon.xml +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dwarves/dwarf geomancer.xml b/path_8_0/data/monster/Dwarves/dwarf geomancer.xml deleted file mode 100644 index 0b75f1778..000000000 --- a/path_8_0/data/monster/Dwarves/dwarf geomancer.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dwarves/dwarf guard.xml b/path_8_0/data/monster/Dwarves/dwarf guard.xml deleted file mode 100644 index 09a64a240..000000000 --- a/path_8_0/data/monster/Dwarves/dwarf guard.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dwarves/dwarf soldier.xml b/path_8_0/data/monster/Dwarves/dwarf soldier.xml deleted file mode 100644 index 99cc9a6ee..000000000 --- a/path_8_0/data/monster/Dwarves/dwarf soldier.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dwarves/dwarf.xml b/path_8_0/data/monster/Dwarves/dwarf.xml deleted file mode 100644 index 877fbafec..000000000 --- a/path_8_0/data/monster/Dwarves/dwarf.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dworcs/dworc fleshhunter.xml b/path_8_0/data/monster/Dworcs/dworc fleshhunter.xml deleted file mode 100644 index f0ba931c1..000000000 --- a/path_8_0/data/monster/Dworcs/dworc fleshhunter.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dworcs/dworc venomsniper.xml b/path_8_0/data/monster/Dworcs/dworc venomsniper.xml deleted file mode 100644 index 3c746df7a..000000000 --- a/path_8_0/data/monster/Dworcs/dworc venomsniper.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Dworcs/dworc voodoomaster.xml b/path_8_0/data/monster/Dworcs/dworc voodoomaster.xml deleted file mode 100644 index 32f8145d9..000000000 --- a/path_8_0/data/monster/Dworcs/dworc voodoomaster.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Elves/elf arcanist.xml b/path_8_0/data/monster/Elves/elf arcanist.xml deleted file mode 100644 index 5952a8efe..000000000 --- a/path_8_0/data/monster/Elves/elf arcanist.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Elves/elf scout.xml b/path_8_0/data/monster/Elves/elf scout.xml deleted file mode 100644 index f5f86962c..000000000 --- a/path_8_0/data/monster/Elves/elf scout.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Elves/elf.xml b/path_8_0/data/monster/Elves/elf.xml deleted file mode 100644 index bf6774cba..000000000 --- a/path_8_0/data/monster/Elves/elf.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Felines/lion.xml b/path_8_0/data/monster/Felines/lion.xml deleted file mode 100644 index c0071f15d..000000000 --- a/path_8_0/data/monster/Felines/lion.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Felines/tiger.xml b/path_8_0/data/monster/Felines/tiger.xml deleted file mode 100644 index c9ff06a63..000000000 --- a/path_8_0/data/monster/Felines/tiger.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/azure frog.xml b/path_8_0/data/monster/Frogs/azure frog.xml deleted file mode 100644 index 1649336bd..000000000 --- a/path_8_0/data/monster/Frogs/azure frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/coral frog.xml b/path_8_0/data/monster/Frogs/coral frog.xml deleted file mode 100644 index eb8e8715d..000000000 --- a/path_8_0/data/monster/Frogs/coral frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/crimson frog.xml b/path_8_0/data/monster/Frogs/crimson frog.xml deleted file mode 100644 index f57f2bf45..000000000 --- a/path_8_0/data/monster/Frogs/crimson frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/green frog.xml b/path_8_0/data/monster/Frogs/green frog.xml deleted file mode 100644 index d73285982..000000000 --- a/path_8_0/data/monster/Frogs/green frog.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/orchid frog.xml b/path_8_0/data/monster/Frogs/orchid frog.xml deleted file mode 100644 index d4cbde37f..000000000 --- a/path_8_0/data/monster/Frogs/orchid frog.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Frogs/toad.xml b/path_8_0/data/monster/Frogs/toad.xml deleted file mode 100644 index a636024c9..000000000 --- a/path_8_0/data/monster/Frogs/toad.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Geo-Elementals/gargoyle.xml b/path_8_0/data/monster/Geo-Elementals/gargoyle.xml deleted file mode 100644 index 84ce7dc92..000000000 --- a/path_8_0/data/monster/Geo-Elementals/gargoyle.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Geo-Elementals/stone golem.xml b/path_8_0/data/monster/Geo-Elementals/stone golem.xml deleted file mode 100644 index 3d6d9093e..000000000 --- a/path_8_0/data/monster/Geo-Elementals/stone golem.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Ghosts/ghost.xml b/path_8_0/data/monster/Ghosts/ghost.xml deleted file mode 100644 index 9ab423dc4..000000000 --- a/path_8_0/data/monster/Ghosts/ghost.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Ghosts/phantasm summon.xml b/path_8_0/data/monster/Ghosts/phantasm summon.xml deleted file mode 100644 index e471f7de1..000000000 --- a/path_8_0/data/monster/Ghosts/phantasm summon.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Ghosts/phantasm.xml b/path_8_0/data/monster/Ghosts/phantasm.xml deleted file mode 100644 index a2c293b0b..000000000 --- a/path_8_0/data/monster/Ghosts/phantasm.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Ghosts/spectre.xml b/path_8_0/data/monster/Ghosts/spectre.xml deleted file mode 100644 index 75bfa1631..000000000 --- a/path_8_0/data/monster/Ghosts/spectre.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Giants/behemoth.xml b/path_8_0/data/monster/Giants/behemoth.xml deleted file mode 100644 index 039ff41b0..000000000 --- a/path_8_0/data/monster/Giants/behemoth.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Giants/cyclops.xml b/path_8_0/data/monster/Giants/cyclops.xml deleted file mode 100644 index dabfb5266..000000000 --- a/path_8_0/data/monster/Giants/cyclops.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Giants/frost giant.xml b/path_8_0/data/monster/Giants/frost giant.xml deleted file mode 100644 index 9f95dbe2e..000000000 --- a/path_8_0/data/monster/Giants/frost giant.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Giants/frost giantess.xml b/path_8_0/data/monster/Giants/frost giantess.xml deleted file mode 100644 index dec2fc7ab..000000000 --- a/path_8_0/data/monster/Giants/frost giantess.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Goblins/demon (goblin).xml b/path_8_0/data/monster/Goblins/demon (goblin).xml deleted file mode 100644 index 10205c559..000000000 --- a/path_8_0/data/monster/Goblins/demon (goblin).xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Goblins/goblin.xml b/path_8_0/data/monster/Goblins/goblin.xml deleted file mode 100644 index 2f0f7c45d..000000000 --- a/path_8_0/data/monster/Goblins/goblin.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/ancient scarab.xml b/path_8_0/data/monster/Insects/ancient scarab.xml deleted file mode 100644 index 797c8dacd..000000000 --- a/path_8_0/data/monster/Insects/ancient scarab.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/blue butterfly.xml b/path_8_0/data/monster/Insects/blue butterfly.xml deleted file mode 100644 index 5c4e0205d..000000000 --- a/path_8_0/data/monster/Insects/blue butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/bug.xml b/path_8_0/data/monster/Insects/bug.xml deleted file mode 100644 index 2cde49f13..000000000 --- a/path_8_0/data/monster/Insects/bug.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/butterfly.xml b/path_8_0/data/monster/Insects/butterfly.xml deleted file mode 100644 index 26582b97b..000000000 --- a/path_8_0/data/monster/Insects/butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/larva.xml b/path_8_0/data/monster/Insects/larva.xml deleted file mode 100644 index 521d0ceb4..000000000 --- a/path_8_0/data/monster/Insects/larva.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/pink butterfly.xml b/path_8_0/data/monster/Insects/pink butterfly.xml deleted file mode 100644 index 4dc00c20a..000000000 --- a/path_8_0/data/monster/Insects/pink butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/purple butterfly.xml b/path_8_0/data/monster/Insects/purple butterfly.xml deleted file mode 100644 index e3c81b3bf..000000000 --- a/path_8_0/data/monster/Insects/purple butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/red butterfly.xml b/path_8_0/data/monster/Insects/red butterfly.xml deleted file mode 100644 index 0ff74de94..000000000 --- a/path_8_0/data/monster/Insects/red butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/scarab.xml b/path_8_0/data/monster/Insects/scarab.xml deleted file mode 100644 index cd2d3db34..000000000 --- a/path_8_0/data/monster/Insects/scarab.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/wasp.xml b/path_8_0/data/monster/Insects/wasp.xml deleted file mode 100644 index 967d2755a..000000000 --- a/path_8_0/data/monster/Insects/wasp.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Insects/yellow butterfly.xml b/path_8_0/data/monster/Insects/yellow butterfly.xml deleted file mode 100644 index 1b38da032..000000000 --- a/path_8_0/data/monster/Insects/yellow butterfly.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Lizards/lizard noble.xml b/path_8_0/data/monster/Lizards/lizard noble.xml deleted file mode 100644 index 22fd37a77..000000000 --- a/path_8_0/data/monster/Lizards/lizard noble.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Lizards/lizard sentinel.xml b/path_8_0/data/monster/Lizards/lizard sentinel.xml deleted file mode 100644 index 2be80bb33..000000000 --- a/path_8_0/data/monster/Lizards/lizard sentinel.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Lizards/lizard snakecharmer.xml b/path_8_0/data/monster/Lizards/lizard snakecharmer.xml deleted file mode 100644 index 583efa593..000000000 --- a/path_8_0/data/monster/Lizards/lizard snakecharmer.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Lizards/lizard templar.xml b/path_8_0/data/monster/Lizards/lizard templar.xml deleted file mode 100644 index 93a1075db..000000000 --- a/path_8_0/data/monster/Lizards/lizard templar.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Lizards/wyvern.xml b/path_8_0/data/monster/Lizards/wyvern.xml deleted file mode 100644 index b74579f39..000000000 --- a/path_8_0/data/monster/Lizards/wyvern.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Minotaurs/minotaur archer.xml b/path_8_0/data/monster/Minotaurs/minotaur archer.xml deleted file mode 100644 index 5080e2987..000000000 --- a/path_8_0/data/monster/Minotaurs/minotaur archer.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Minotaurs/minotaur guard.xml b/path_8_0/data/monster/Minotaurs/minotaur guard.xml deleted file mode 100644 index d0b283bf7..000000000 --- a/path_8_0/data/monster/Minotaurs/minotaur guard.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Minotaurs/minotaur mage.xml b/path_8_0/data/monster/Minotaurs/minotaur mage.xml deleted file mode 100644 index 46fbeef15..000000000 --- a/path_8_0/data/monster/Minotaurs/minotaur mage.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Minotaurs/minotaur.xml b/path_8_0/data/monster/Minotaurs/minotaur.xml deleted file mode 100644 index a7e8d34f7..000000000 --- a/path_8_0/data/monster/Minotaurs/minotaur.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc mammals/badger.xml b/path_8_0/data/monster/Misc/misc mammals/badger.xml deleted file mode 100644 index 2ad3a8f67..000000000 --- a/path_8_0/data/monster/Misc/misc mammals/badger.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc mammals/bat.xml b/path_8_0/data/monster/Misc/misc mammals/bat.xml deleted file mode 100644 index 855d0c09c..000000000 --- a/path_8_0/data/monster/Misc/misc mammals/bat.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc mammals/hyaena.xml b/path_8_0/data/monster/Misc/misc mammals/hyaena.xml deleted file mode 100644 index e5131f099..000000000 --- a/path_8_0/data/monster/Misc/misc mammals/hyaena.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc mammals/skunk.xml b/path_8_0/data/monster/Misc/misc mammals/skunk.xml deleted file mode 100644 index 19125c596..000000000 --- a/path_8_0/data/monster/Misc/misc mammals/skunk.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc reptiles/crocodile.xml b/path_8_0/data/monster/Misc/misc reptiles/crocodile.xml deleted file mode 100644 index 3c84a4a4c..000000000 --- a/path_8_0/data/monster/Misc/misc reptiles/crocodile.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc reptiles/hydra.xml b/path_8_0/data/monster/Misc/misc reptiles/hydra.xml deleted file mode 100644 index fde9a0f54..000000000 --- a/path_8_0/data/monster/Misc/misc reptiles/hydra.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc reptiles/thornback tortoise.xml b/path_8_0/data/monster/Misc/misc reptiles/thornback tortoise.xml deleted file mode 100644 index 0a9ec4f2a..000000000 --- a/path_8_0/data/monster/Misc/misc reptiles/thornback tortoise.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Misc/misc reptiles/tortoise.xml b/path_8_0/data/monster/Misc/misc reptiles/tortoise.xml deleted file mode 100644 index 269dd63d0..000000000 --- a/path_8_0/data/monster/Misc/misc reptiles/tortoise.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Monks/dark monk.xml b/path_8_0/data/monster/Monks/dark monk.xml deleted file mode 100644 index ea9c9e051..000000000 --- a/path_8_0/data/monster/Monks/dark monk.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Monks/monk.xml b/path_8_0/data/monster/Monks/monk.xml deleted file mode 100644 index cdd846e2e..000000000 --- a/path_8_0/data/monster/Monks/monk.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Necromancers/necromancer.xml b/path_8_0/data/monster/Necromancers/necromancer.xml deleted file mode 100644 index 2ad8e284d..000000000 --- a/path_8_0/data/monster/Necromancers/necromancer.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Necromancers/priestess.xml b/path_8_0/data/monster/Necromancers/priestess.xml deleted file mode 100644 index 4f46d4406..000000000 --- a/path_8_0/data/monster/Necromancers/priestess.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc berserker.xml b/path_8_0/data/monster/Orcs/orc berserker.xml deleted file mode 100644 index 132d5a177..000000000 --- a/path_8_0/data/monster/Orcs/orc berserker.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc leader.xml b/path_8_0/data/monster/Orcs/orc leader.xml deleted file mode 100644 index 509c569d3..000000000 --- a/path_8_0/data/monster/Orcs/orc leader.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc rider.xml b/path_8_0/data/monster/Orcs/orc rider.xml deleted file mode 100644 index 610edd475..000000000 --- a/path_8_0/data/monster/Orcs/orc rider.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc shaman.xml b/path_8_0/data/monster/Orcs/orc shaman.xml deleted file mode 100644 index 6fe3a973e..000000000 --- a/path_8_0/data/monster/Orcs/orc shaman.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc spearman.xml b/path_8_0/data/monster/Orcs/orc spearman.xml deleted file mode 100644 index df38336ad..000000000 --- a/path_8_0/data/monster/Orcs/orc spearman.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc warlord.xml b/path_8_0/data/monster/Orcs/orc warlord.xml deleted file mode 100644 index 05dcc386a..000000000 --- a/path_8_0/data/monster/Orcs/orc warlord.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc warrior.xml b/path_8_0/data/monster/Orcs/orc warrior.xml deleted file mode 100644 index 3fa512fba..000000000 --- a/path_8_0/data/monster/Orcs/orc warrior.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Orcs/orc.xml b/path_8_0/data/monster/Orcs/orc.xml deleted file mode 100644 index 8ccd47fac..000000000 --- a/path_8_0/data/monster/Orcs/orc.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/assassin.xml b/path_8_0/data/monster/Outlaws/assassin.xml deleted file mode 100644 index 3fd101219..000000000 --- a/path_8_0/data/monster/Outlaws/assassin.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/bandit.xml b/path_8_0/data/monster/Outlaws/bandit.xml deleted file mode 100644 index 509ce5b79..000000000 --- a/path_8_0/data/monster/Outlaws/bandit.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/black knight.xml b/path_8_0/data/monster/Outlaws/black knight.xml deleted file mode 100644 index eb9cec97f..000000000 --- a/path_8_0/data/monster/Outlaws/black knight.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/hero.xml b/path_8_0/data/monster/Outlaws/hero.xml deleted file mode 100644 index 9ab624a1a..000000000 --- a/path_8_0/data/monster/Outlaws/hero.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/hunter.xml b/path_8_0/data/monster/Outlaws/hunter.xml deleted file mode 100644 index 4439004b1..000000000 --- a/path_8_0/data/monster/Outlaws/hunter.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/nomad.xml b/path_8_0/data/monster/Outlaws/nomad.xml deleted file mode 100644 index 5e473d030..000000000 --- a/path_8_0/data/monster/Outlaws/nomad.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/smuggler.xml b/path_8_0/data/monster/Outlaws/smuggler.xml deleted file mode 100644 index 53114186c..000000000 --- a/path_8_0/data/monster/Outlaws/smuggler.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/stalker.xml b/path_8_0/data/monster/Outlaws/stalker.xml deleted file mode 100644 index b9d6987e4..000000000 --- a/path_8_0/data/monster/Outlaws/stalker.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Outlaws/wild warrior.xml b/path_8_0/data/monster/Outlaws/wild warrior.xml deleted file mode 100644 index 9ab80a3d5..000000000 --- a/path_8_0/data/monster/Outlaws/wild warrior.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/ashmunrah.xml b/path_8_0/data/monster/Pharaohs/ashmunrah.xml deleted file mode 100644 index 409147e3f..000000000 --- a/path_8_0/data/monster/Pharaohs/ashmunrah.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/dipthrah.xml b/path_8_0/data/monster/Pharaohs/dipthrah.xml deleted file mode 100644 index ba8a9ecf4..000000000 --- a/path_8_0/data/monster/Pharaohs/dipthrah.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/mahrdis.xml b/path_8_0/data/monster/Pharaohs/mahrdis.xml deleted file mode 100644 index 1325b0ee1..000000000 --- a/path_8_0/data/monster/Pharaohs/mahrdis.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/morguthis.xml b/path_8_0/data/monster/Pharaohs/morguthis.xml deleted file mode 100644 index 1dba1a91c..000000000 --- a/path_8_0/data/monster/Pharaohs/morguthis.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/omruc.xml b/path_8_0/data/monster/Pharaohs/omruc.xml deleted file mode 100644 index 31b24e6b9..000000000 --- a/path_8_0/data/monster/Pharaohs/omruc.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/rahemos.xml b/path_8_0/data/monster/Pharaohs/rahemos.xml deleted file mode 100644 index 02ee5128a..000000000 --- a/path_8_0/data/monster/Pharaohs/rahemos.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/superior death minion.xml b/path_8_0/data/monster/Pharaohs/superior death minion.xml deleted file mode 100644 index 868b7aa43..000000000 --- a/path_8_0/data/monster/Pharaohs/superior death minion.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/thalas.xml b/path_8_0/data/monster/Pharaohs/thalas.xml deleted file mode 100644 index 38e7843c0..000000000 --- a/path_8_0/data/monster/Pharaohs/thalas.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pharaohs/vashresamun.xml b/path_8_0/data/monster/Pharaohs/vashresamun.xml deleted file mode 100644 index 06bfd40e5..000000000 --- a/path_8_0/data/monster/Pharaohs/vashresamun.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate buccaneer.xml b/path_8_0/data/monster/Pirates/pirate buccaneer.xml deleted file mode 100644 index e465d94d4..000000000 --- a/path_8_0/data/monster/Pirates/pirate buccaneer.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate corsair.xml b/path_8_0/data/monster/Pirates/pirate corsair.xml deleted file mode 100644 index d70c73a03..000000000 --- a/path_8_0/data/monster/Pirates/pirate corsair.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate cutthroat.xml b/path_8_0/data/monster/Pirates/pirate cutthroat.xml deleted file mode 100644 index 5468ea8ad..000000000 --- a/path_8_0/data/monster/Pirates/pirate cutthroat.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate ghost.xml b/path_8_0/data/monster/Pirates/pirate ghost.xml deleted file mode 100644 index 6e44799a3..000000000 --- a/path_8_0/data/monster/Pirates/pirate ghost.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate marauder.xml b/path_8_0/data/monster/Pirates/pirate marauder.xml deleted file mode 100644 index c03d63f4e..000000000 --- a/path_8_0/data/monster/Pirates/pirate marauder.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pirates/pirate skeleton.xml b/path_8_0/data/monster/Pirates/pirate skeleton.xml deleted file mode 100644 index 68a1b3431..000000000 --- a/path_8_0/data/monster/Pirates/pirate skeleton.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pyro-Elementals/fire elemental.xml b/path_8_0/data/monster/Pyro-Elementals/fire elemental.xml deleted file mode 100644 index bdaa4960e..000000000 --- a/path_8_0/data/monster/Pyro-Elementals/fire elemental.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Pyro-Elementals/hellfire fighter.xml b/path_8_0/data/monster/Pyro-Elementals/hellfire fighter.xml deleted file mode 100644 index 26000938f..000000000 --- a/path_8_0/data/monster/Pyro-Elementals/hellfire fighter.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara constrictor scout.xml b/path_8_0/data/monster/Quaras/quara constrictor scout.xml deleted file mode 100644 index 7f800452b..000000000 --- a/path_8_0/data/monster/Quaras/quara constrictor scout.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara constrictor.xml b/path_8_0/data/monster/Quaras/quara constrictor.xml deleted file mode 100644 index 2b8273a9a..000000000 --- a/path_8_0/data/monster/Quaras/quara constrictor.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara hydromancer scout.xml b/path_8_0/data/monster/Quaras/quara hydromancer scout.xml deleted file mode 100644 index 748ac5f59..000000000 --- a/path_8_0/data/monster/Quaras/quara hydromancer scout.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara hydromancer.xml b/path_8_0/data/monster/Quaras/quara hydromancer.xml deleted file mode 100644 index a9f9e79ed..000000000 --- a/path_8_0/data/monster/Quaras/quara hydromancer.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara mantassin scout.xml b/path_8_0/data/monster/Quaras/quara mantassin scout.xml deleted file mode 100644 index 5b487938f..000000000 --- a/path_8_0/data/monster/Quaras/quara mantassin scout.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara mantassin.xml b/path_8_0/data/monster/Quaras/quara mantassin.xml deleted file mode 100644 index a2e2350a1..000000000 --- a/path_8_0/data/monster/Quaras/quara mantassin.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara pincher scout.xml b/path_8_0/data/monster/Quaras/quara pincher scout.xml deleted file mode 100644 index 3ab6a824f..000000000 --- a/path_8_0/data/monster/Quaras/quara pincher scout.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara pincher.xml b/path_8_0/data/monster/Quaras/quara pincher.xml deleted file mode 100644 index 1764e261e..000000000 --- a/path_8_0/data/monster/Quaras/quara pincher.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara predator scout.xml b/path_8_0/data/monster/Quaras/quara predator scout.xml deleted file mode 100644 index af6a7b06a..000000000 --- a/path_8_0/data/monster/Quaras/quara predator scout.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Quaras/quara predator.xml b/path_8_0/data/monster/Quaras/quara predator.xml deleted file mode 100644 index 5116d2ef5..000000000 --- a/path_8_0/data/monster/Quaras/quara predator.xml +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Serpents/cobra.xml b/path_8_0/data/monster/Serpents/cobra.xml deleted file mode 100644 index 97595d636..000000000 --- a/path_8_0/data/monster/Serpents/cobra.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Serpents/serpent spawn.xml b/path_8_0/data/monster/Serpents/serpent spawn.xml deleted file mode 100644 index 144ff66df..000000000 --- a/path_8_0/data/monster/Serpents/serpent spawn.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Serpents/snake.xml b/path_8_0/data/monster/Serpents/snake.xml deleted file mode 100644 index e2ee57d95..000000000 --- a/path_8_0/data/monster/Serpents/snake.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Skeletons/betrayed wraith.xml b/path_8_0/data/monster/Skeletons/betrayed wraith.xml deleted file mode 100644 index 2b66cfba7..000000000 --- a/path_8_0/data/monster/Skeletons/betrayed wraith.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Skeletons/bonebeast.xml b/path_8_0/data/monster/Skeletons/bonebeast.xml deleted file mode 100644 index ac0a16340..000000000 --- a/path_8_0/data/monster/Skeletons/bonebeast.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Skeletons/demon skeleton.xml b/path_8_0/data/monster/Skeletons/demon skeleton.xml deleted file mode 100644 index 0430dcf12..000000000 --- a/path_8_0/data/monster/Skeletons/demon skeleton.xml +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Skeletons/lost soul.xml b/path_8_0/data/monster/Skeletons/lost soul.xml deleted file mode 100644 index e9994c0ca..000000000 --- a/path_8_0/data/monster/Skeletons/lost soul.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Skeletons/skeleton.xml b/path_8_0/data/monster/Skeletons/skeleton.xml deleted file mode 100644 index 3a3af0e21..000000000 --- a/path_8_0/data/monster/Skeletons/skeleton.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Sorcerers/dark magician.xml b/path_8_0/data/monster/Sorcerers/dark magician.xml deleted file mode 100644 index 2962964c7..000000000 --- a/path_8_0/data/monster/Sorcerers/dark magician.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Sorcerers/ice witch.xml b/path_8_0/data/monster/Sorcerers/ice witch.xml deleted file mode 100644 index 61dab10ba..000000000 --- a/path_8_0/data/monster/Sorcerers/ice witch.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Sorcerers/warlock.xml b/path_8_0/data/monster/Sorcerers/warlock.xml deleted file mode 100644 index 1d5e6ffb8..000000000 --- a/path_8_0/data/monster/Sorcerers/warlock.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Sorcerers/witch.xml b/path_8_0/data/monster/Sorcerers/witch.xml deleted file mode 100644 index 0b806166b..000000000 --- a/path_8_0/data/monster/Sorcerers/witch.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/a carved stone tile.xml b/path_8_0/data/monster/Traps/a carved stone tile.xml deleted file mode 100644 index 690f38569..000000000 --- a/path_8_0/data/monster/Traps/a carved stone tile.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/deathslicer.xml b/path_8_0/data/monster/Traps/deathslicer.xml deleted file mode 100644 index aea09d36b..000000000 --- a/path_8_0/data/monster/Traps/deathslicer.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/flamethrower.xml b/path_8_0/data/monster/Traps/flamethrower.xml deleted file mode 100644 index 835522c57..000000000 --- a/path_8_0/data/monster/Traps/flamethrower.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/hell hole.xml b/path_8_0/data/monster/Traps/hell hole.xml deleted file mode 100644 index a5880b72e..000000000 --- a/path_8_0/data/monster/Traps/hell hole.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/lavahole.xml b/path_8_0/data/monster/Traps/lavahole.xml deleted file mode 100644 index 2f9f24bc6..000000000 --- a/path_8_0/data/monster/Traps/lavahole.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/magic pillar.xml b/path_8_0/data/monster/Traps/magic pillar.xml deleted file mode 100644 index 8c19b2915..000000000 --- a/path_8_0/data/monster/Traps/magic pillar.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/magicthrower.xml b/path_8_0/data/monster/Traps/magicthrower.xml deleted file mode 100644 index 50304607b..000000000 --- a/path_8_0/data/monster/Traps/magicthrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/pillar.xml b/path_8_0/data/monster/Traps/pillar.xml deleted file mode 100644 index d1560821f..000000000 --- a/path_8_0/data/monster/Traps/pillar.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/plaguethrower.xml b/path_8_0/data/monster/Traps/plaguethrower.xml deleted file mode 100644 index b661e3baf..000000000 --- a/path_8_0/data/monster/Traps/plaguethrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Traps/shredderthrower.xml b/path_8_0/data/monster/Traps/shredderthrower.xml deleted file mode 100644 index 1a3128caf..000000000 --- a/path_8_0/data/monster/Traps/shredderthrower.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Trolls/frost troll.xml b/path_8_0/data/monster/Trolls/frost troll.xml deleted file mode 100644 index 41d695482..000000000 --- a/path_8_0/data/monster/Trolls/frost troll.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Trolls/swamp troll.xml b/path_8_0/data/monster/Trolls/swamp troll.xml deleted file mode 100644 index b1204ba36..000000000 --- a/path_8_0/data/monster/Trolls/swamp troll.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Trolls/troll.xml b/path_8_0/data/monster/Trolls/troll.xml deleted file mode 100644 index bc4011b35..000000000 --- a/path_8_0/data/monster/Trolls/troll.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/banshee.xml b/path_8_0/data/monster/Undead Humanoids/banshee.xml deleted file mode 100644 index ce6685ac3..000000000 --- a/path_8_0/data/monster/Undead Humanoids/banshee.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/blightwalker.xml b/path_8_0/data/monster/Undead Humanoids/blightwalker.xml deleted file mode 100644 index 771d6d8c7..000000000 --- a/path_8_0/data/monster/Undead Humanoids/blightwalker.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/crypt shambler.xml b/path_8_0/data/monster/Undead Humanoids/crypt shambler.xml deleted file mode 100644 index ffacd4c72..000000000 --- a/path_8_0/data/monster/Undead Humanoids/crypt shambler.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/ghoul.xml b/path_8_0/data/monster/Undead Humanoids/ghoul.xml deleted file mode 100644 index 798290bd2..000000000 --- a/path_8_0/data/monster/Undead Humanoids/ghoul.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/lich.xml b/path_8_0/data/monster/Undead Humanoids/lich.xml deleted file mode 100644 index b546cec8c..000000000 --- a/path_8_0/data/monster/Undead Humanoids/lich.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/Undead Humanoids/mummy.xml b/path_8_0/data/monster/Undead Humanoids/mummy.xml deleted file mode 100644 index f8f709cdf..000000000 --- a/path_8_0/data/monster/Undead Humanoids/mummy.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bats/bat.xml b/path_8_0/data/monster/bats/bat.xml deleted file mode 100644 index 855d0c09c..000000000 --- a/path_8_0/data/monster/bats/bat.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bonelords/beholder.xml b/path_8_0/data/monster/bonelords/beholder.xml deleted file mode 100644 index 24e6deee9..000000000 --- a/path_8_0/data/monster/bonelords/beholder.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bonelords/braindeath.xml b/path_8_0/data/monster/bonelords/braindeath.xml deleted file mode 100644 index a2f8bd9ad..000000000 --- a/path_8_0/data/monster/bonelords/braindeath.xml +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bonelords/elder beholder.xml b/path_8_0/data/monster/bonelords/elder beholder.xml deleted file mode 100644 index 53768ce4f..000000000 --- a/path_8_0/data/monster/bonelords/elder beholder.xml +++ /dev/null @@ -1,66 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bonelords/eye of the seven.xml b/path_8_0/data/monster/bonelords/eye of the seven.xml deleted file mode 100644 index 44e24ca79..000000000 --- a/path_8_0/data/monster/bonelords/eye of the seven.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/bonelords/gazer.xml b/path_8_0/data/monster/bonelords/gazer.xml deleted file mode 100644 index 430e26091..000000000 --- a/path_8_0/data/monster/bonelords/gazer.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/glires/cave rat.xml b/path_8_0/data/monster/glires/cave rat.xml deleted file mode 100644 index c0963db4f..000000000 --- a/path_8_0/data/monster/glires/cave rat.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/glires/rabbit.xml b/path_8_0/data/monster/glires/rabbit.xml deleted file mode 100644 index af8ad673f..000000000 --- a/path_8_0/data/monster/glires/rabbit.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/glires/rat.xml b/path_8_0/data/monster/glires/rat.xml deleted file mode 100644 index 174750406..000000000 --- a/path_8_0/data/monster/glires/rat.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/glires/silver rabbit.xml b/path_8_0/data/monster/glires/silver rabbit.xml deleted file mode 100644 index 75f99a821..000000000 --- a/path_8_0/data/monster/glires/silver rabbit.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/monsters.xml b/path_8_0/data/monster/monsters.xml deleted file mode 100644 index 2ea948950..000000000 --- a/path_8_0/data/monster/monsters.xml +++ /dev/null @@ -1,410 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/myriapods/centipede.xml b/path_8_0/data/monster/myriapods/centipede.xml deleted file mode 100644 index 726ab1b5b..000000000 --- a/path_8_0/data/monster/myriapods/centipede.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/black sheep.xml b/path_8_0/data/monster/ungulates/black sheep.xml deleted file mode 100644 index 86524152e..000000000 --- a/path_8_0/data/monster/ungulates/black sheep.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/deer.xml b/path_8_0/data/monster/ungulates/deer.xml deleted file mode 100644 index 20976abbc..000000000 --- a/path_8_0/data/monster/ungulates/deer.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/elephant.xml b/path_8_0/data/monster/ungulates/elephant.xml deleted file mode 100644 index 6d0a77419..000000000 --- a/path_8_0/data/monster/ungulates/elephant.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/mammoth.xml b/path_8_0/data/monster/ungulates/mammoth.xml deleted file mode 100644 index 5d1a02e3b..000000000 --- a/path_8_0/data/monster/ungulates/mammoth.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/pig.xml b/path_8_0/data/monster/ungulates/pig.xml deleted file mode 100644 index 92f963145..000000000 --- a/path_8_0/data/monster/ungulates/pig.xml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/ungulates/sheep.xml b/path_8_0/data/monster/ungulates/sheep.xml deleted file mode 100644 index 3acfa1c9d..000000000 --- a/path_8_0/data/monster/ungulates/sheep.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/vampires/vampire.xml b/path_8_0/data/monster/vampires/vampire.xml deleted file mode 100644 index d1ff32418..000000000 --- a/path_8_0/data/monster/vampires/vampire.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/voodoo cultists/acolyte of the cult.xml b/path_8_0/data/monster/voodoo cultists/acolyte of the cult.xml deleted file mode 100644 index de9cc37b7..000000000 --- a/path_8_0/data/monster/voodoo cultists/acolyte of the cult.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/voodoo cultists/adept of the cult.xml b/path_8_0/data/monster/voodoo cultists/adept of the cult.xml deleted file mode 100644 index 4c69f4f58..000000000 --- a/path_8_0/data/monster/voodoo cultists/adept of the cult.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/voodoo cultists/enlightened of the cult.xml b/path_8_0/data/monster/voodoo cultists/enlightened of the cult.xml deleted file mode 100644 index e46e9ac8b..000000000 --- a/path_8_0/data/monster/voodoo cultists/enlightened of the cult.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/monster/voodoo cultists/novice of the cult.xml b/path_8_0/data/monster/voodoo cultists/novice of the cult.xml deleted file mode 100644 index 1a613993f..000000000 --- a/path_8_0/data/monster/voodoo cultists/novice of the cult.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/movements/lib/movements.lua b/path_8_0/data/movements/lib/movements.lua deleted file mode 100644 index b081a0ffe..000000000 --- a/path_8_0/data/movements/lib/movements.lua +++ /dev/null @@ -1,2 +0,0 @@ --- Nothing -- - diff --git a/path_8_0/data/movements/movements.xml b/path_8_0/data/movements/movements.xml deleted file mode 100644 index 4e86ef5c4..000000000 --- a/path_8_0/data/movements/movements.xml +++ /dev/null @@ -1,438 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/movements/scripts/citizen.lua b/path_8_0/data/movements/scripts/citizen.lua deleted file mode 100644 index 541cfa3a6..000000000 --- a/path_8_0/data/movements/scripts/citizen.lua +++ /dev/null @@ -1,13 +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) - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are the newest resident of " .. town:getName(town) .. ".") - end - return true -end diff --git a/path_8_0/data/movements/scripts/closingdoor.lua b/path_8_0/data/movements/scripts/closingdoor.lua deleted file mode 100644 index 83904ae06..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/decay.lua b/path_8_0/data/movements/scripts/decay.lua deleted file mode 100644 index 9a48822b2..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/dough.lua b/path_8_0/data/movements/scripts/dough.lua deleted file mode 100644 index a0b371fa4..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/drowning.lua b/path_8_0/data/movements/scripts/drowning.lua deleted file mode 100644 index ee5a6979d..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/snow.lua b/path_8_0/data/movements/scripts/snow.lua deleted file mode 100644 index 8a07bbfa3..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/swimming.lua b/path_8_0/data/movements/scripts/swimming.lua deleted file mode 100644 index f11af1a6c..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/tiles.lua b/path_8_0/data/movements/scripts/tiles.lua deleted file mode 100644 index cdb765677..000000000 --- a/path_8_0/data/movements/scripts/tiles.lua +++ /dev/null @@ -1,56 +0,0 @@ -local increasing = {[416] = 417, [426] = 425, [446] = 447, [3216] = 3217, [3202] = 3215} -local decreasing = {[417] = 416, [425] = 426, [447] = 446, [3217] = 3216, [3215] = 3202} - -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_8_0/data/movements/scripts/trap.lua b/path_8_0/data/movements/scripts/trap.lua deleted file mode 100644 index e8a49f7a5..000000000 --- a/path_8_0/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_8_0/data/movements/scripts/walkback.lua b/path_8_0/data/movements/scripts/walkback.lua deleted file mode 100644 index 30b00f21f..000000000 --- a/path_8_0/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_8_0/data/npc/Alice.xml b/path_8_0/data/npc/Alice.xml deleted file mode 100644 index 5f02ca5ea..000000000 --- a/path_8_0/data/npc/Alice.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_8_0/data/npc/Deruno.xml b/path_8_0/data/npc/Deruno.xml deleted file mode 100644 index 3015d5fff..000000000 --- a/path_8_0/data/npc/Deruno.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_8_0/data/npc/Dimral.xml b/path_8_0/data/npc/Dimral.xml deleted file mode 100644 index 287660d3f..000000000 --- a/path_8_0/data/npc/Dimral.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_8_0/data/npc/Donald.xml b/path_8_0/data/npc/Donald.xml deleted file mode 100644 index 91e5bd147..000000000 --- a/path_8_0/data/npc/Donald.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_8_0/data/npc/Eryn.xml b/path_8_0/data/npc/Eryn.xml deleted file mode 100644 index 93622cdbf..000000000 --- a/path_8_0/data/npc/Eryn.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_8_0/data/npc/Naji.xml b/path_8_0/data/npc/Naji.xml deleted file mode 100644 index 7aa02a4f0..000000000 --- a/path_8_0/data/npc/Naji.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_8_0/data/npc/Riona.xml b/path_8_0/data/npc/Riona.xml deleted file mode 100644 index 13a1df43f..000000000 --- a/path_8_0/data/npc/Riona.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/path_8_0/data/npc/Soya.xml b/path_8_0/data/npc/Soya.xml deleted file mode 100644 index 3f9ad1381..000000000 --- a/path_8_0/data/npc/Soya.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/path_8_0/data/npc/The Forgotten King.xml b/path_8_0/data/npc/The Forgotten King.xml deleted file mode 100644 index 5f34703f6..000000000 --- a/path_8_0/data/npc/The Forgotten King.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/path_8_0/data/npc/The Oracle.xml b/path_8_0/data/npc/The Oracle.xml deleted file mode 100644 index 8aec9e74f..000000000 --- a/path_8_0/data/npc/The Oracle.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/path_8_0/data/npc/Tyoric.xml b/path_8_0/data/npc/Tyoric.xml deleted file mode 100644 index 38f6114b1..000000000 --- a/path_8_0/data/npc/Tyoric.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/path_8_0/data/npc/lib/npc.lua b/path_8_0/data/npc/lib/npc.lua deleted file mode 100644 index c6d3e2cf6..000000000 --- a/path_8_0/data/npc/lib/npc.lua +++ /dev/null @@ -1,131 +0,0 @@ --- 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() - 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_8_0/data/npc/lib/npcsystem/customModules.lua b/path_8_0/data/npc/lib/npcsystem/customModules.lua deleted file mode 100644 index f44c8a8b0..000000000 --- a/path_8_0/data/npc/lib/npcsystem/customModules.lua +++ /dev/null @@ -1,192 +0,0 @@ --- 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_8_0/data/npc/lib/npcsystem/keywordhandler.lua b/path_8_0/data/npc/lib/npcsystem/keywordhandler.lua deleted file mode 100644 index ea4f5d3ad..000000000 --- a/path_8_0/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_8_0/data/npc/lib/npcsystem/modules.lua b/path_8_0/data/npc/lib/npcsystem/modules.lua deleted file mode 100644 index a127d198a..000000000 --- a/path_8_0/data/npc/lib/npcsystem/modules.lua +++ /dev/null @@ -1,1193 +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) - 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_8_0/data/npc/lib/npcsystem/npchandler.lua b/path_8_0/data/npc/lib/npcsystem/npchandler.lua deleted file mode 100644 index d867ca5c1..000000000 --- a/path_8_0/data/npc/lib/npcsystem/npchandler.lua +++ /dev/null @@ -1,595 +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 - 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() - 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) 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 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_SAY, ((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:gsub("|PLAYERNAME|", player:getName()), TALKTYPE_SAY) - end - end, self.talkDelayTime * 1000, Npc():getId(), message, focus) - end -end diff --git a/path_8_0/data/npc/lib/npcsystem/npcsystem.lua b/path_8_0/data/npc/lib/npcsystem/npcsystem.lua deleted file mode 100644 index 15d7f5fa4..000000000 --- a/path_8_0/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_8_0/data/npc/scripts/The Oracle.lua b/path_8_0/data/npc/scripts/The Oracle.lua deleted file mode 100644 index 6619adda1..000000000 --- a/path_8_0/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_8_0/data/npc/scripts/bank.lua b/path_8_0/data/npc/scripts/bank.lua deleted file mode 100644 index e20f20a92..000000000 --- a/path_8_0/data/npc/scripts/bank.lua +++ /dev/null @@ -1,323 +0,0 @@ -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_8_0/data/npc/scripts/bless.lua b/path_8_0/data/npc/scripts/bless.lua deleted file mode 100644 index eb3fc5ac3..000000000 --- a/path_8_0/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_8_0/data/npc/scripts/default.lua b/path_8_0/data/npc/scripts/default.lua deleted file mode 100644 index 36d042db2..000000000 --- a/path_8_0/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_8_0/data/npc/scripts/promotion.lua b/path_8_0/data/npc/scripts/promotion.lua deleted file mode 100644 index e565d5703..000000000 --- a/path_8_0/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_8_0/data/npc/scripts/runes.lua b/path_8_0/data/npc/scripts/runes.lua deleted file mode 100644 index 84915f2d8..000000000 --- a/path_8_0/data/npc/scripts/runes.lua +++ /dev/null @@ -1,123 +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: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 cosmic energy', 'cosmic energy'}, 2189, 10000, 'wand of cosmic energy') -shopModule:addBuyableItem({'wand of inferno', 'inferno'}, 2187, 15000, 'wand of inferno') - -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({'terra rod', 'terra'}, 2181, 10000, 'terra rod') -shopModule:addBuyableItem({'hailstorm rod', 'hailstorm'}, 2183, 15000, 'hailstorm rod') - -shopModule:addSellableItem({'wand of vortex', 'vortex'}, 2190, 250, 'wand of vortex') -shopModule:addSellableItem({'wand of dragonbreath', 'dragonbreath'}, 2191, 500, 'wand of dragonbreath') -shopModule:addSellableItem({'wand of decay', 'decay'}, 2188, 2500, 'wand of decay') -shopModule:addSellableItem({'wand of cosmic energy', 'cosmic energy'}, 2189, 5000, 'wand of cosmic energy') -shopModule:addSellableItem({'wand of inferno', 'inferno'},2187, 7500, 'wand of inferno') - -shopModule:addSellableItem({'snakebite rod', 'snakebite'}, 2182, 250,'snakebite rod') -shopModule:addSellableItem({'moonlight rod', 'moonlight'}, 2186, 500, 'moonlight rod') -shopModule:addSellableItem({'necrotic rod', 'necrotic'}, 2185, 2500, 'necrotic rod') -shopModule:addSellableItem({'terra rod', 'terra'}, 2181, 5000, 'terra rod') -shopModule:addSellableItem({'hailstorm rod', 'hailstorm'}, 2183, 7500, 'hailstorm 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_8_0/data/raids/raids.xml b/path_8_0/data/raids/raids.xml deleted file mode 100644 index e61a5a6e4..000000000 --- a/path_8_0/data/raids/raids.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/path_8_0/data/raids/testraid.xml b/path_8_0/data/raids/testraid.xml deleted file mode 100644 index ebfe9d0c9..000000000 --- a/path_8_0/data/raids/testraid.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/reports/.gitignore b/path_8_0/data/reports/.gitignore deleted file mode 100644 index eb67fe0af..000000000 --- a/path_8_0/data/reports/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Ignore user generated reports -* -!.gitignore diff --git a/path_8_0/data/spells/lib/spells.lua b/path_8_0/data/spells/lib/spells.lua deleted file mode 100644 index bf1c9e98d..000000000 --- a/path_8_0/data/spells/lib/spells.lua +++ /dev/null @@ -1,250 +0,0 @@ ---Pre-made areas - ---Waves -AREA_WAVE3 = { -{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_8_0/data/spells/scripts/attack/berserk.lua b/path_8_0/data/spells/scripts/attack/berserk.lua deleted file mode 100644 index 9afe6025f..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/energy beam.lua b/path_8_0/data/spells/scripts/attack/energy beam.lua deleted file mode 100644 index 47b8c177d..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/energy bomb.lua b/path_8_0/data/spells/scripts/attack/energy bomb.lua deleted file mode 100644 index 78726107d..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/energy field.lua b/path_8_0/data/spells/scripts/attack/energy field.lua deleted file mode 100644 index f026a05ed..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/energy strike.lua b/path_8_0/data/spells/scripts/attack/energy strike.lua deleted file mode 100644 index 73b623338..000000000 --- a/path_8_0/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_ENERGYHIT) -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_8_0/data/spells/scripts/attack/energy wall.lua b/path_8_0/data/spells/scripts/attack/energy wall.lua deleted file mode 100644 index 9888b87d8..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/energy wave.lua b/path_8_0/data/spells/scripts/attack/energy wave.lua deleted file mode 100644 index 714d38025..000000000 --- a/path_8_0/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_TELEPORT) -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_8_0/data/spells/scripts/attack/envenom.lua b/path_8_0/data/spells/scripts/attack/envenom.lua deleted file mode 100644 index e2901383f..000000000 --- a/path_8_0/data/spells/scripts/attack/envenom.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_8_0/data/spells/scripts/attack/ethereal spear.lua b/path_8_0/data/spells/scripts/attack/ethereal spear.lua deleted file mode 100644 index d97832f5a..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/explosion.lua b/path_8_0/data/spells/scripts/attack/explosion.lua deleted file mode 100644 index ddb1dc5a3..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fierce berserk.lua b/path_8_0/data/spells/scripts/attack/fierce berserk.lua deleted file mode 100644 index 1f051ba06..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fire bomb.lua b/path_8_0/data/spells/scripts/attack/fire bomb.lua deleted file mode 100644 index eba9401f8..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fire field.lua b/path_8_0/data/spells/scripts/attack/fire field.lua deleted file mode 100644 index 59b2aa7e4..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fire wall.lua b/path_8_0/data/spells/scripts/attack/fire wall.lua deleted file mode 100644 index 8935419a6..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fire wave.lua b/path_8_0/data/spells/scripts/attack/fire wave.lua deleted file mode 100644 index 98b7f4bc0..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/fireball.lua b/path_8_0/data/spells/scripts/attack/fireball.lua deleted file mode 100644 index 1a29dd5c5..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/flame strike.lua b/path_8_0/data/spells/scripts/attack/flame strike.lua deleted file mode 100644 index 924eb1580..000000000 --- a/path_8_0/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_FIREAREA) -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_8_0/data/spells/scripts/attack/force strike.lua b/path_8_0/data/spells/scripts/attack/force strike.lua deleted file mode 100644 index 7b5c0e9bb..000000000 --- a/path_8_0/data/spells/scripts/attack/force strike.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -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_8_0/data/spells/scripts/attack/great energy beam.lua b/path_8_0/data/spells/scripts/attack/great energy beam.lua deleted file mode 100644 index 5a40cd6fe..000000000 --- a/path_8_0/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_BEAM8)) - -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_8_0/data/spells/scripts/attack/great fireball.lua b/path_8_0/data/spells/scripts/attack/great fireball.lua deleted file mode 100644 index 2c9291ae3..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/groundshaker.lua b/path_8_0/data/spells/scripts/attack/groundshaker.lua deleted file mode 100644 index bb9995407..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/heavy magic missile.lua b/path_8_0/data/spells/scripts/attack/heavy magic missile.lua deleted file mode 100644 index 6e6f6dea9..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/light magic missile.lua b/path_8_0/data/spells/scripts/attack/light magic missile.lua deleted file mode 100644 index 977d302cd..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/poison bomb.lua b/path_8_0/data/spells/scripts/attack/poison bomb.lua deleted file mode 100644 index ec5522574..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/poison field.lua b/path_8_0/data/spells/scripts/attack/poison field.lua deleted file mode 100644 index f4e9e6224..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/poison storm.lua b/path_8_0/data/spells/scripts/attack/poison storm.lua deleted file mode 100644 index c243d508c..000000000 --- a/path_8_0/data/spells/scripts/attack/poison storm.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_EARTHDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_GREEN_RINGS) -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_8_0/data/spells/scripts/attack/poison wall.lua b/path_8_0/data/spells/scripts/attack/poison wall.lua deleted file mode 100644 index a9b8460ae..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/soul fire.lua b/path_8_0/data/spells/scripts/attack/soul fire.lua deleted file mode 100644 index 74ee7015c..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/attack/sudden death.lua b/path_8_0/data/spells/scripts/attack/sudden death.lua deleted file mode 100644 index a2dd09f3f..000000000 --- a/path_8_0/data/spells/scripts/attack/sudden death.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -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 * 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_8_0/data/spells/scripts/attack/ultimate explosion.lua b/path_8_0/data/spells/scripts/attack/ultimate explosion.lua deleted file mode 100644 index efd08b292..000000000 --- a/path_8_0/data/spells/scripts/attack/ultimate explosion.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_TYPE, COMBAT_PHYSICALDAMAGE) -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_EXPLOSIONAREA) -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_8_0/data/spells/scripts/attack/whirlwind throw.lua b/path_8_0/data/spells/scripts/attack/whirlwind throw.lua deleted file mode 100644 index 508062132..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/custom/apocalypse.lua b/path_8_0/data/spells/scripts/custom/apocalypse.lua deleted file mode 100644 index 70dead24b..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/custom/combustion.lua b/path_8_0/data/spells/scripts/custom/combustion.lua deleted file mode 100644 index ca9cb5aa7..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/custom/drunk.lua b/path_8_0/data/spells/scripts/custom/drunk.lua deleted file mode 100644 index 3c19aea0c..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/custom/magic prison.lua b/path_8_0/data/spells/scripts/custom/magic prison.lua deleted file mode 100644 index ee5bfba68..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/custom/polymorph.lua b/path_8_0/data/spells/scripts/custom/polymorph.lua deleted file mode 100644 index 27efef382..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/cure poison rune.lua b/path_8_0/data/spells/scripts/healing/cure poison rune.lua deleted file mode 100644 index f272fb983..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/cure poison.lua b/path_8_0/data/spells/scripts/healing/cure poison.lua deleted file mode 100644 index b50548e72..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/heal friend.lua b/path_8_0/data/spells/scripts/healing/heal friend.lua deleted file mode 100644 index 621628afc..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/intense healing rune.lua b/path_8_0/data/spells/scripts/healing/intense healing rune.lua deleted file mode 100644 index 53fa135aa..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/intense healing.lua b/path_8_0/data/spells/scripts/healing/intense healing.lua deleted file mode 100644 index 2a61b871c..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/light healing.lua b/path_8_0/data/spells/scripts/healing/light healing.lua deleted file mode 100644 index bd3a0908d..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/mass healing.lua b/path_8_0/data/spells/scripts/healing/mass healing.lua deleted file mode 100644 index 0b984503e..000000000 --- a/path_8_0/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 - - if not healMonsters then - local master = target:getMaster() - 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_8_0/data/spells/scripts/healing/ultimate healing rune.lua b/path_8_0/data/spells/scripts/healing/ultimate healing rune.lua deleted file mode 100644 index 5aac4c00f..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/healing/ultimate healing.lua b/path_8_0/data/spells/scripts/healing/ultimate healing.lua deleted file mode 100644 index ec18d9ed9..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua b/path_8_0/data/spells/scripts/monster/barbarian brutetamer skill reducer.lua deleted file mode 100644 index 8d7ff3758..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/betrayed wraith skill reducer.lua b/path_8_0/data/spells/scripts/monster/betrayed wraith skill reducer.lua deleted file mode 100644 index a6d972a52..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/choking fear drown.lua b/path_8_0/data/spells/scripts/monster/choking fear drown.lua deleted file mode 100644 index 42b7ad8eb..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/cliff strider electrify.lua b/path_8_0/data/spells/scripts/monster/cliff strider electrify.lua deleted file mode 100644 index 7231acef3..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/cliff strider skill reducer.lua b/path_8_0/data/spells/scripts/monster/cliff strider skill reducer.lua deleted file mode 100644 index e60f3b996..000000000 --- a/path_8_0/data/spells/scripts/monster/cliff strider 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, 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) - return combat:execute(creature, variant) -end diff --git a/path_8_0/data/spells/scripts/monster/dark torturer skill reducer.lua b/path_8_0/data/spells/scripts/monster/dark torturer skill reducer.lua deleted file mode 100644 index 559cec088..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/deepling spellsinger skill reducer.lua b/path_8_0/data/spells/scripts/monster/deepling spellsinger skill reducer.lua deleted file mode 100644 index cb0d443d2..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/demon outcast skill reducer.lua b/path_8_0/data/spells/scripts/monster/demon outcast skill reducer.lua deleted file mode 100644 index e36bbc78a..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/diabolic imp skill reducer.lua b/path_8_0/data/spells/scripts/monster/diabolic imp skill reducer.lua deleted file mode 100644 index 00b3193c4..000000000 --- a/path_8_0/data/spells/scripts/monster/diabolic imp skill reducer.lua +++ /dev/null @@ -1,16 +0,0 @@ -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_DISTANCEEFFECT, CONST_ANI_ENERGY) - combat[i]:setArea(createCombatArea(AREA_BEAM1)) - combat[i]:setCondition(condition) -end - -function onCastSpell(creature, variant) - return combat[math.random(70, 80)]:execute(creature, variant) -end diff --git a/path_8_0/data/spells/scripts/monster/dipthrah skill reducer.lua b/path_8_0/data/spells/scripts/monster/dipthrah skill reducer.lua deleted file mode 100644 index feb2df27a..000000000 --- a/path_8_0/data/spells/scripts/monster/dipthrah skill reducer.lua +++ /dev/null @@ -1,16 +0,0 @@ -local combat = Combat() -combat:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE) - -local area = createCombatArea(AREA_CIRCLE3X3) -combat:setArea(area) - -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 6000) -condition:setParameter(CONDITION_PARAM_SKILL_MELEEPERCENT, 50) -condition:setParameter(CONDITION_PARAM_SKILL_DISTANCEPERCENT, 50) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) -combat:setCondition(condition) - -function onCastSpell(creature, var) - return combat:execute(creature, var) -end diff --git a/path_8_0/data/spells/scripts/monster/djinn cancel invisibility.lua b/path_8_0/data/spells/scripts/monster/djinn cancel invisibility.lua deleted file mode 100644 index 61128bc97..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/djinn electrify.lua b/path_8_0/data/spells/scripts/monster/djinn electrify.lua deleted file mode 100644 index 83eb0c4eb..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/energy elemental electrify.lua b/path_8_0/data/spells/scripts/monster/energy elemental electrify.lua deleted file mode 100644 index 0d479c47a..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua b/path_8_0/data/spells/scripts/monster/enslaved dwarf skill reducer 1.lua deleted file mode 100644 index 3790028db..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua b/path_8_0/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua deleted file mode 100644 index e8e2b0be8..000000000 --- a/path_8_0/data/spells/scripts/monster/enslaved dwarf skill reducer 2.lua +++ /dev/null @@ -1,12 +0,0 @@ -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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_8_0/data/spells/scripts/monster/feversleep skill reducer.lua b/path_8_0/data/spells/scripts/monster/feversleep skill reducer.lua deleted file mode 100644 index f4b62f910..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/forest fury skill reducer.lua b/path_8_0/data/spells/scripts/monster/forest fury skill reducer.lua deleted file mode 100644 index 422fde6a9..000000000 --- a/path_8_0/data/spells/scripts/monster/forest fury skill reducer.lua +++ /dev/null @@ -1,14 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 4000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_8_0/data/spells/scripts/monster/fury skill reducer.lua b/path_8_0/data/spells/scripts/monster/fury skill reducer.lua deleted file mode 100644 index 2f0534660..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/hellfire fighter soulfire.lua b/path_8_0/data/spells/scripts/monster/hellfire fighter soulfire.lua deleted file mode 100644 index 8ae590fdd..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/hellspawn soulfire.lua b/path_8_0/data/spells/scripts/monster/hellspawn soulfire.lua deleted file mode 100644 index 1c7f144e2..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/ice golem skill reducer.lua b/path_8_0/data/spells/scripts/monster/ice golem skill reducer.lua deleted file mode 100644 index d7bc670f0..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/lava golem soulfire.lua b/path_8_0/data/spells/scripts/monster/lava golem soulfire.lua deleted file mode 100644 index 69aacb1e3..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/magma crawler soulfire.lua b/path_8_0/data/spells/scripts/monster/magma crawler soulfire.lua deleted file mode 100644 index 68135f908..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/massive energy elemental electrify.lua b/path_8_0/data/spells/scripts/monster/massive energy elemental electrify.lua deleted file mode 100644 index 1bbd62614..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/massive fire elemental soulfire.lua b/path_8_0/data/spells/scripts/monster/massive fire elemental soulfire.lua deleted file mode 100644 index 1c759518a..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/phantasm drown.lua b/path_8_0/data/spells/scripts/monster/phantasm drown.lua deleted file mode 100644 index bc13da129..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/pirate corsair skill reducer.lua b/path_8_0/data/spells/scripts/monster/pirate corsair skill reducer.lua deleted file mode 100644 index 7435ff606..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/quara constrictor electrify.lua b/path_8_0/data/spells/scripts/monster/quara constrictor electrify.lua deleted file mode 100644 index 83eb0c4eb..000000000 --- a/path_8_0/data/spells/scripts/monster/quara constrictor 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_8_0/data/spells/scripts/monster/sea serpent drown.lua b/path_8_0/data/spells/scripts/monster/sea serpent drown.lua deleted file mode 100644 index c0af07d2a..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/shock head skill reducer 1.lua b/path_8_0/data/spells/scripts/monster/shock head skill reducer 1.lua deleted file mode 100644 index a7733c502..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/shock head skill reducer 2.lua b/path_8_0/data/spells/scripts/monster/shock head skill reducer 2.lua deleted file mode 100644 index f70279d7f..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/silencer skill reducer.lua b/path_8_0/data/spells/scripts/monster/silencer skill reducer.lua deleted file mode 100644 index 5e2cc3d9d..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/souleater drown.lua b/path_8_0/data/spells/scripts/monster/souleater drown.lua deleted file mode 100644 index aa1c8c820..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/spectre drown.lua b/path_8_0/data/spells/scripts/monster/spectre drown.lua deleted file mode 100644 index d1eda5fa3..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/stampor skill reducer.lua b/path_8_0/data/spells/scripts/monster/stampor skill reducer.lua deleted file mode 100644 index 5e2594633..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/vulcongra soulfire.lua b/path_8_0/data/spells/scripts/monster/vulcongra soulfire.lua deleted file mode 100644 index d56c65ec5..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/war golem electrify.lua b/path_8_0/data/spells/scripts/monster/war golem electrify.lua deleted file mode 100644 index 630922952..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/war golem skill reducer.lua b/path_8_0/data/spells/scripts/monster/war golem skill reducer.lua deleted file mode 100644 index af28828b6..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/warlock skill reducer.lua b/path_8_0/data/spells/scripts/monster/warlock skill reducer.lua deleted file mode 100644 index 49dbbad2c..000000000 --- a/path_8_0/data/spells/scripts/monster/warlock skill reducer.lua +++ /dev/null @@ -1,14 +0,0 @@ -local condition = Condition(CONDITION_ATTRIBUTES) -condition:setParameter(CONDITION_PARAM_TICKS, 5000) -condition:setParameter(CONDITION_PARAM_SKILL_SHIELDPERCENT, 50) -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)) -combat:setCondition(condition) - -function onCastSpell(creature, variant) - return combat:execute(creature, variant) -end diff --git a/path_8_0/data/spells/scripts/monster/werewolf skill reducer.lua b/path_8_0/data/spells/scripts/monster/werewolf skill reducer.lua deleted file mode 100644 index ceaa58e67..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/monster/young sea serpent drown.lua b/path_8_0/data/spells/scripts/monster/young sea serpent drown.lua deleted file mode 100644 index 93d9fb5b5..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/animate dead rune.lua b/path_8_0/data/spells/scripts/support/animate dead rune.lua deleted file mode 100644 index daa1dca62..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/cancel invisibility.lua b/path_8_0/data/spells/scripts/support/cancel invisibility.lua deleted file mode 100644 index 1137dce45..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/challenge.lua b/path_8_0/data/spells/scripts/support/challenge.lua deleted file mode 100644 index 348a3a7ad..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/destroy field rune.lua b/path_8_0/data/spells/scripts/support/destroy field rune.lua deleted file mode 100644 index d6ccc1162..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/disintegrate rune.lua b/path_8_0/data/spells/scripts/support/disintegrate rune.lua deleted file mode 100644 index e1f510c8d..000000000 --- a/path_8_0/data/spells/scripts/support/disintegrate rune.lua +++ /dev/null @@ -1,24 +0,0 @@ -local corpseIds = {3058, 3059, 3060, 3061, 3064, 3065, 3066} -local removalLimit = 500 - -function onCastSpell(creature, variant, isHotkey) - local position = variant:getPosition() - local tile = Tile(position) - if tile then - local items = tile:getItems() - if items then - for i, item in ipairs(items) do - if item:getType():isMovable() and item:getUniqueId() > 65535 and item:getActionId() == 0 and not isInArray(corpseIds, item:getId()) then - item:remove() - end - - if i == removalLimit then - break - end - end - end - end - - position:sendMagicEffect(CONST_ME_POFF) - return true -end diff --git a/path_8_0/data/spells/scripts/support/food.lua b/path_8_0/data/spells/scripts/support/food.lua deleted file mode 100644 index 4b7a37081..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/great light.lua b/path_8_0/data/spells/scripts/support/great light.lua deleted file mode 100644 index 8eea28af1..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/haste.lua b/path_8_0/data/spells/scripts/support/haste.lua deleted file mode 100644 index 51aca5baa..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/invisible.lua b/path_8_0/data/spells/scripts/support/invisible.lua deleted file mode 100644 index c5d1eec86..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/light.lua b/path_8_0/data/spells/scripts/support/light.lua deleted file mode 100644 index 591bf912b..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/magic rope.lua b/path_8_0/data/spells/scripts/support/magic rope.lua deleted file mode 100644 index 012311df6..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/magic shield.lua b/path_8_0/data/spells/scripts/support/magic shield.lua deleted file mode 100644 index adf714704..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/magic wall rune.lua b/path_8_0/data/spells/scripts/support/magic wall rune.lua deleted file mode 100644 index 79c26ee0c..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/paralyze rune.lua b/path_8_0/data/spells/scripts/support/paralyze rune.lua deleted file mode 100644 index 4e76c6b35..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/strong haste.lua b/path_8_0/data/spells/scripts/support/strong haste.lua deleted file mode 100644 index 3a02eadc6..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/ultimate light.lua b/path_8_0/data/spells/scripts/support/ultimate light.lua deleted file mode 100644 index cea27680f..000000000 --- a/path_8_0/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_8_0/data/spells/scripts/support/wild growth rune.lua b/path_8_0/data/spells/scripts/support/wild growth rune.lua deleted file mode 100644 index 1ab7d6004..000000000 --- a/path_8_0/data/spells/scripts/support/wild growth 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_WILDGROWTH) - -function onCastSpell(creature, variant, isHotkey) - return combat:execute(creature, variant) -end diff --git a/path_8_0/data/spells/spells.xml b/path_8_0/data/spells/spells.xml deleted file mode 100644 index ea71ad595..000000000 --- a/path_8_0/data/spells/spells.xml +++ /dev/null @@ -1,486 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/talkactions/lib/talkactions.lua b/path_8_0/data/talkactions/lib/talkactions.lua deleted file mode 100644 index 585eb19d6..000000000 --- a/path_8_0/data/talkactions/lib/talkactions.lua +++ /dev/null @@ -1 +0,0 @@ --- Nothing -- diff --git a/path_8_0/data/talkactions/scripts/add_skill.lua b/path_8_0/data/talkactions/scripts/add_skill.lua deleted file mode 100644 index 613ed0e5d..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/add_tutor.lua b/path_8_0/data/talkactions/scripts/add_tutor.lua deleted file mode 100644 index 621b6e8df..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/addon.lua b/path_8_0/data/talkactions/scripts/addon.lua deleted file mode 100644 index 50681a10a..000000000 --- a/path_8_0/data/talkactions/scripts/addon.lua +++ /dev/null @@ -1,181 +0,0 @@ -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_8_0/data/talkactions/scripts/alladdons.lua b/path_8_0/data/talkactions/scripts/alladdons.lua deleted file mode 100644 index 255da61da..000000000 --- a/path_8_0/data/talkactions/scripts/alladdons.lua +++ /dev/null @@ -1,41 +0,0 @@ -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 -} - -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_8_0/data/talkactions/scripts/allmounts.lua b/path_8_0/data/talkactions/scripts/allmounts.lua deleted file mode 100644 index 5e27a9dce..000000000 --- a/path_8_0/data/talkactions/scripts/allmounts.lua +++ /dev/null @@ -1,34 +0,0 @@ -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, 12 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_8_0/data/talkactions/scripts/animationeffect.lua b/path_8_0/data/talkactions/scripts/animationeffect.lua deleted file mode 100644 index ba55558ce..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/ban.lua b/path_8_0/data/talkactions/scripts/ban.lua deleted file mode 100644 index fc46763f0..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/broadcast.lua b/path_8_0/data/talkactions/scripts/broadcast.lua deleted file mode 100644 index 1b7a1420b..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/buyhouse.lua b/path_8_0/data/talkactions/scripts/buyhouse.lua deleted file mode 100644 index 58e0c4545..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/buyprem.lua b/path_8_0/data/talkactions/scripts/buyprem.lua deleted file mode 100644 index 1aa4f5f0e..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/chameleon.lua b/path_8_0/data/talkactions/scripts/chameleon.lua deleted file mode 100644 index d3fcbe2f7..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/changesex.lua b/path_8_0/data/talkactions/scripts/changesex.lua deleted file mode 100644 index 3b71fe0cc..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/clean.lua b/path_8_0/data/talkactions/scripts/clean.lua deleted file mode 100644 index 0d5f7aa95..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/closeserver.lua b/path_8_0/data/talkactions/scripts/closeserver.lua deleted file mode 100644 index 2f7c95ec3..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/create_item.lua b/path_8_0/data/talkactions/scripts/create_item.lua deleted file mode 100644 index 1a7bf4148..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/deathlist.lua b/path_8_0/data/talkactions/scripts/deathlist.lua deleted file mode 100644 index c1066a960..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/down.lua b/path_8_0/data/talkactions/scripts/down.lua deleted file mode 100644 index 460e0c490..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/ghost.lua b/path_8_0/data/talkactions/scripts/ghost.lua deleted file mode 100644 index 2ba455bd9..000000000 --- a/path_8_0/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_POFF) - else - player:sendTextMessage(MESSAGE_INFO_DESCR, "You are visible again.") - position.x = position.x + 1 - position:sendMagicEffect(CONST_ME_POFF) - end - return false -end diff --git a/path_8_0/data/talkactions/scripts/hide.lua b/path_8_0/data/talkactions/scripts/hide.lua deleted file mode 100644 index 1e84352f2..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/info.lua b/path_8_0/data/talkactions/scripts/info.lua deleted file mode 100644 index 8969b1cae..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/ipban.lua b/path_8_0/data/talkactions/scripts/ipban.lua deleted file mode 100644 index 1a393e2a9..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/kick.lua b/path_8_0/data/talkactions/scripts/kick.lua deleted file mode 100644 index 67f8ec4aa..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/kills.lua b/path_8_0/data/talkactions/scripts/kills.lua deleted file mode 100644 index 98dd37cc9..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/leavehouse.lua b/path_8_0/data/talkactions/scripts/leavehouse.lua deleted file mode 100644 index 18938cc7c..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/looktype.lua b/path_8_0/data/talkactions/scripts/looktype.lua deleted file mode 100644 index 1a1b11dc9..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/magiceffect.lua b/path_8_0/data/talkactions/scripts/magiceffect.lua deleted file mode 100644 index ebc26b3ec..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/mccheck.lua b/path_8_0/data/talkactions/scripts/mccheck.lua deleted file mode 100644 index 13ffbc970..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/online.lua b/path_8_0/data/talkactions/scripts/online.lua deleted file mode 100644 index da1c1a4bd..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/openserver.lua b/path_8_0/data/talkactions/scripts/openserver.lua deleted file mode 100644 index c3896e728..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/owner.lua b/path_8_0/data/talkactions/scripts/owner.lua deleted file mode 100644 index d56f4897b..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/place_monster.lua b/path_8_0/data/talkactions/scripts/place_monster.lua deleted file mode 100644 index 8446c0b01..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/place_npc.lua b/path_8_0/data/talkactions/scripts/place_npc.lua deleted file mode 100644 index aaf6ef6e5..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/place_summon.lua b/path_8_0/data/talkactions/scripts/place_summon.lua deleted file mode 100644 index f511d2083..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/position.lua b/path_8_0/data/talkactions/scripts/position.lua deleted file mode 100644 index 299ce6e56..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/remove_tutor.lua b/path_8_0/data/talkactions/scripts/remove_tutor.lua deleted file mode 100644 index 27b0bdb1b..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/removething.lua b/path_8_0/data/talkactions/scripts/removething.lua deleted file mode 100644 index 8216e03ba..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/save.lua b/path_8_0/data/talkactions/scripts/save.lua deleted file mode 100644 index f1949517a..000000000 --- a/path_8_0/data/talkactions/scripts/save.lua +++ /dev/null @@ -1,19 +0,0 @@ -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_8_0/data/talkactions/scripts/serverinfo.lua b/path_8_0/data/talkactions/scripts/serverinfo.lua deleted file mode 100644 index 6b26b9814..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/teleport_creature_here.lua b/path_8_0/data/talkactions/scripts/teleport_creature_here.lua deleted file mode 100644 index ea3691991..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/teleport_home.lua b/path_8_0/data/talkactions/scripts/teleport_home.lua deleted file mode 100644 index 64852301d..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/teleport_ntiles.lua b/path_8_0/data/talkactions/scripts/teleport_ntiles.lua deleted file mode 100644 index 28cbccb0f..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/teleport_to_creature.lua b/path_8_0/data/talkactions/scripts/teleport_to_creature.lua deleted file mode 100644 index 17a7da995..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/teleport_to_pos.lua b/path_8_0/data/talkactions/scripts/teleport_to_pos.lua deleted file mode 100644 index 2b0f31a20..000000000 --- a/path_8_0/data/talkactions/scripts/teleport_to_pos.lua +++ /dev/null @@ -1,27 +0,0 @@ -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_8_0/data/talkactions/scripts/teleport_to_town.lua b/path_8_0/data/talkactions/scripts/teleport_to_town.lua deleted file mode 100644 index 87cdfae39..000000000 --- a/path_8_0/data/talkactions/scripts/teleport_to_town.lua +++ /dev/null @@ -1,18 +0,0 @@ -function onSay(player, words, param) - if not player:getGroup():getAccess() then - return true - end - - local town = Town(param) - if town == nil then - town = Town(tonumber(param)) - end - - if town == nil then - player:sendCancelMessage("Town not found.") - return false - end - - player:teleportTo(town:getTemplePosition()) - return false -end diff --git a/path_8_0/data/talkactions/scripts/unban.lua b/path_8_0/data/talkactions/scripts/unban.lua deleted file mode 100644 index b65c4c705..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/up.lua b/path_8_0/data/talkactions/scripts/up.lua deleted file mode 100644 index c48bfd726..000000000 --- a/path_8_0/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_8_0/data/talkactions/scripts/uptime.lua b/path_8_0/data/talkactions/scripts/uptime.lua deleted file mode 100644 index 7c0e291ed..000000000 --- a/path_8_0/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_8_0/data/talkactions/talkactions.xml b/path_8_0/data/talkactions/talkactions.xml deleted file mode 100644 index ae85082af..000000000 --- a/path_8_0/data/talkactions/talkactions.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/weapons/lib/weapons.lua b/path_8_0/data/weapons/lib/weapons.lua deleted file mode 100644 index e69de29bb..000000000 diff --git a/path_8_0/data/weapons/scripts/burst_arrow.lua b/path_8_0/data/weapons/scripts/burst_arrow.lua deleted file mode 100644 index eb8290173..000000000 --- a/path_8_0/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_8_0/data/weapons/scripts/poison_arrow.lua b/path_8_0/data/weapons/scripts/poison_arrow.lua deleted file mode 100644 index 2e0f64a62..000000000 --- a/path_8_0/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_8_0/data/weapons/scripts/viper_star.lua b/path_8_0/data/weapons/scripts/viper_star.lua deleted file mode 100644 index 023325818..000000000 --- a/path_8_0/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_8_0/data/weapons/weapons.xml b/path_8_0/data/weapons/weapons.xml deleted file mode 100644 index f47b10cb1..000000000 --- a/path_8_0/data/weapons/weapons.xml +++ /dev/null @@ -1,426 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/world/forgotten-house.xml b/path_8_0/data/world/forgotten-house.xml deleted file mode 100644 index 4279d5650..000000000 --- a/path_8_0/data/world/forgotten-house.xml +++ /dev/null @@ -1,113 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/world/forgotten-spawn.xml b/path_8_0/data/world/forgotten-spawn.xml deleted file mode 100644 index d97e97c92..000000000 --- a/path_8_0/data/world/forgotten-spawn.xml +++ /dev/null @@ -1,1544 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/path_8_0/data/world/forgotten.otbm b/path_8_0/data/world/forgotten.otbm deleted file mode 100644 index 517c3c0a7..000000000 Binary files a/path_8_0/data/world/forgotten.otbm and /dev/null differ diff --git a/path_8_0/schema.sql b/path_8_0/schema.sql deleted file mode 100644 index 804f1c746..000000000 --- a/path_8_0/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_8_0/src/CMakeLists.txt b/path_8_0/src/CMakeLists.txt deleted file mode 100644 index da0aa5ed3..000000000 --- a/path_8_0/src/CMakeLists.txt +++ /dev/null @@ -1,75 +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}/definitions.h - ${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}/ioguild.cpp - ${CMAKE_CURRENT_LIST_DIR}/iologindata.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomap.cpp - ${CMAKE_CURRENT_LIST_DIR}/iomapserialize.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}/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}/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_8_0/src/account.h b/path_8_0/src/account.h deleted file mode 100644 index 870e65018..000000000 --- a/path_8_0/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; - uint32_t 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_8_0/src/actions.cpp b/path_8_0/src/actions.cpp deleted file mode 100644 index bbe3183c3..000000000 --- a/path_8_0/src/actions.cpp +++ /dev/null @@ -1,523 +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() : - scriptInterface("Action Interface") -{ - 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); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Actions::getScriptInterface() -{ - return 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(&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 - return g_spells->getRuneSpell(item->getID()); -} - -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; - } - - bed->sleep(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()); - 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 { - std::cout << "[Warning - Action::loadFunction] Function \"" << functionName << "\" does not exist." << std::endl; - return false; - } - - 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; -} - -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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Action::executeUse] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(6); -} diff --git a/path_8_0/src/actions.h b/path_8_0/src/actions.h deleted file mode 100644 index dd6ca3c29..000000000 --- a/path_8_0/src/actions.h +++ /dev/null @@ -1,125 +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; - - 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 scriptInterface; -}; - -#endif diff --git a/path_8_0/src/ban.cpp b/path_8_0/src/ban.cpp deleted file mode 100644 index ebe974fd4..000000000 --- a/path_8_0/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_8_0/src/ban.h b/path_8_0/src/ban.h deleted file mode 100644 index 994507dd6..000000000 --- a/path_8_0/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_8_0/src/baseevents.cpp b/path_8_0/src/baseevents.cpp deleted file mode 100644 index db3f645c3..000000000 --- a/path_8_0/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() -{ - loaded = false; -} - -bool BaseEvents::loadFromXml() -{ - if (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; - } - - 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() -{ - loaded = false; - clear(); - return loadFromXml(); -} - -Event::Event(LuaScriptInterface* _interface) -{ - scriptInterface = _interface; - scriptId = 0; - scripted = false; -} - -Event::Event(const Event* copy) -{ - scriptInterface = copy->scriptInterface; - scriptId = copy->scriptId; - scripted = copy->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 (scriptId != 0) { - std::cout << "[Failure - Event::checkScript] scriptid = " << 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 (!scriptInterface || scriptId != 0) { - std::cout << "Failure: [Event::loadScript] scriptInterface == nullptr. scriptid = " << scriptId << std::endl; - return false; - } - - if (scriptInterface->loadFile(scriptFile) == -1) { - std::cout << "[Warning - Event::loadScript] Can not load script. " << scriptFile << std::endl; - std::cout << scriptInterface->getLastLuaError() << std::endl; - return false; - } - - int32_t id = scriptInterface->getEvent(getScriptEventName()); - if (id == -1) { - std::cout << "[Warning - Event::loadScript] Event " << getScriptEventName() << " not found. " << scriptFile << std::endl; - return false; - } - - scripted = true; - scriptId = id; - return true; -} - -CallBack::CallBack() -{ - scriptId = 0; - scriptInterface = nullptr; - loaded = false; -} - -bool CallBack::loadCallBack(LuaScriptInterface* _interface, const std::string& name) -{ - if (!_interface) { - std::cout << "Failure: [CallBack::loadCallBack] scriptInterface == nullptr" << std::endl; - return false; - } - - scriptInterface = _interface; - - int32_t id = scriptInterface->getEvent(name.c_str()); - if (id == -1) { - std::cout << "[Warning - CallBack::loadCallBack] Event " << name << " not found." << std::endl; - return false; - } - - callbackName = name; - scriptId = id; - loaded = true; - return true; -} diff --git a/path_8_0/src/baseevents.h b/path_8_0/src/baseevents.h deleted file mode 100644 index ccffcfbaf..000000000 --- a/path_8_0/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 scripted; - } - - protected: - virtual std::string getScriptEventName() const = 0; - - bool scripted; - int32_t scriptId; - LuaScriptInterface* scriptInterface; -}; - -class BaseEvents -{ - public: - BaseEvents(); - virtual ~BaseEvents() = default; - - bool loadFromXml(); - bool reload(); - bool isLoaded() const { - return 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 loaded; -}; - -class CallBack -{ - public: - CallBack(); - - bool loadCallBack(LuaScriptInterface* _interface, const std::string& name); - - protected: - int32_t scriptId; - LuaScriptInterface* scriptInterface; - - bool loaded; - - std::string callbackName; -}; - -#endif diff --git a/path_8_0/src/bed.cpp b/path_8_0/src/bed.cpp deleted file mode 100644 index 196421450..000000000 --- a/path_8_0/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_8_0/src/bed.h b/path_8_0/src/bed.h deleted file mode 100644 index e65dd72aa..000000000 --- a/path_8_0/src/bed.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_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; - } - - 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_8_0/src/chat.cpp b/path_8_0/src/chat.cpp deleted file mode 100644 index 9f3365d29..000000000 --- a/path_8_0/src/chat.cpp +++ /dev/null @@ -1,605 +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 "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()); -} - -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); -} - -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()))); - } - } - - 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); - - 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* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CanJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(canJoinEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(canJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnJoinEvent(const Player& player) -{ - if (onJoinEvent == -1) { - return true; - } - - //onJoin(player) - LuaScriptInterface* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnJoinChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onJoinEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(onJoinEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return scriptInterface->callFunction(1); -} - -bool ChatChannel::executeOnLeaveEvent(const Player& player) -{ - if (onLeaveEvent == -1) { - return true; - } - - //onLeave(player) - LuaScriptInterface* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnLeaveChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onLeaveEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(onLeaveEvent); - LuaScriptInterface::pushUserdata(L, &player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - return 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* scriptInterface = g_chat->getScriptInterface(); - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - OnSpeakChannelEvent::execute] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(onSpeakEvent, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - 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 = 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!"); - } - 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_8_0/src/chat.h b/path_8_0/src/chat.h deleted file mode 100644 index 8b03ffb44..000000000 --- a/path_8_0/src/chat.h +++ /dev/null @@ -1,167 +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* getInvitedUsers() 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 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_8_0/src/combat.cpp b/path_8_0/src/combat.cpp deleted file mode 100644 index d2423e478..000000000 --- a/path_8_0/src/combat.cpp +++ /dev/null @@ -1,1408 +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->hasFlag(TILESTATE_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; - } - - 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 | 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()) { - 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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ValueCallback::getMinMaxValues] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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; - 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!"); - } - - scriptInterface->resetScriptEnv(); -} - -//**********************************************************// - -void TileCallback::onTileCombat(Creature* creature, Tile* tile) const -{ - //onTileCombat(creature, pos) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TileCallback::onTileCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - if (creature) { - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - } else { - lua_pushnil(L); - } - LuaScriptInterface::pushPosition(L, tile->getPosition()); - - scriptInterface->callFunction(2); -} - -//**********************************************************// - -void TargetCallback::onTargetCombat(Creature* creature, Creature* target) const -{ - //onTargetCombat(creature, target) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TargetCallback::onTargetCombat] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - if (!env->setCallbackId(scriptId, scriptInterface)) { - scriptInterface->resetScriptEnv(); - return; - } - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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!"); - } - - 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_8_0/src/combat.h b/path_8_0/src/combat.h deleted file mode 100644 index 0e38330e7..000000000 --- a/path_8_0/src/combat.h +++ /dev/null @@ -1,383 +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_8_0/src/commands.cpp b/path_8_0/src/commands.cpp deleted file mode 100644 index eb922ccb9..000000000 --- a/path_8_0/src/commands.cpp +++ /dev/null @@ -1,344 +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() -{ - // set up command map - for (uint32_t i = 0; i < sizeof(defined_commands) / sizeof(defined_commands[0]); i++) { - commandMap[defined_commands[i].name] = new Command(defined_commands[i].f, 1, ACCOUNT_TYPE_GOD, true); - } -} - -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; - } - - 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) { - command->groupId = pugi::cast(groupAttribute.value()); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing group for command " << it->first << std::endl; - } - - pugi::xml_attribute acctypeAttribute = commandNode.attribute("acctype"); - if (acctypeAttribute) { - command->accountType = static_cast(pugi::cast(acctypeAttribute.value())); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing acctype for command " << it->first << std::endl; - } - - pugi::xml_attribute logAttribute = commandNode.attribute("log"); - if (logAttribute) { - command->log = booleanString(logAttribute.as_string()); - } else { - std::cout << "[Warning - Commands::loadFromXml] Missing log for command " << it->first << std::endl; - } - g_game.addCommandTag(it->first.front()); - } - return true; -} - -bool Commands::reload() -{ - for (const auto& it : commandMap) { - Command* command = it.second; - command->groupId = 1; - command->accountType = ACCOUNT_TYPE_GOD; - command->log = true; - } - - 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->log) { - 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) -{ - // Always reload the global libraries - g_luaEnvironment.loadFile("data/global.lua"); - - 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 == "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") { - player.sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Reloaded globals."); - } 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_8_0/src/commands.h b/path_8_0/src/commands.h deleted file mode 100644 index 7da91eb79..000000000 --- a/path_8_0/src/commands.h +++ /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. - */ - -#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; -}; - -typedef void (Commands::*CommandFunc)(Player&, const std::string&); - -struct Command { - Command(CommandFunc f, uint32_t groupId, AccountType_t accountType, bool log) - : f(f), groupId(groupId), accountType(accountType), log(log) {} - - CommandFunc f; - uint32_t groupId; - AccountType_t accountType; - bool log; -}; - -struct s_defcommands { - const char* name; - CommandFunc f; -}; - -#endif diff --git a/path_8_0/src/condition.cpp b/path_8_0/src/condition.cpp deleted file mode 100644 index 547afaabd..000000000 --- a/path_8_0/src/condition.cpp +++ /dev/null @@ -1,1632 +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_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_STATUS_SMALL, "You were healed for " + healString); - player->sendTextMessage(message); - - std::ostringstream strHealthGain; - strHealthGain << realHealthGain; - g_game.addAnimatedText(strHealthGain.str(), player->getPosition(), TEXTCOLOR_MAYABLUE); - - SpectatorVec list; - g_game.map.getSpectators(list, player->getPosition(), false, true); - list.erase(player); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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; - - 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); -} diff --git a/path_8_0/src/condition.h b/path_8_0/src/condition.h deleted file mode 100644 index c3eb5e4b5..000000000 --- a/path_8_0/src/condition.h +++ /dev/null @@ -1,379 +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; -}; - -#endif diff --git a/path_8_0/src/configmanager.cpp b/path_8_0/src/configmanager.cpp deleted file mode 100644 index 11d11b7d0..000000000 --- a/path_8_0/src/configmanager.cpp +++ /dev/null @@ -1,207 +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 -#undef lua_strlen -#define lua_strlen lua_rawlen -#endif - -extern Game g_game; - -ConfigManager::ConfigManager() - : integer(), boolean() -{ - 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); - - } - - 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[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); - - 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[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[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_8_0/src/configmanager.h b/path_8_0/src/configmanager.h deleted file mode 100644 index 27677e8aa..000000000 --- a/path_8_0/src/configmanager.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_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, - EMOTE_SPELLS, - STAMINA_SYSTEM, - WARN_UNSAFE_SCRIPTS, - CONVERT_UNSAFE_SCRIPTS, - CLASSIC_EQUIPMENT_SLOTS, - - 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, - 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, - 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_8_0/src/connection.cpp b/path_8_0/src/connection.cpp deleted file mode 100644 index 3890c97a2..000000000 --- a/path_8_0/src/connection.cpp +++ /dev/null @@ -1,295 +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; - } - - if (!receivedFirst) { - // First message received - receivedFirst = true; - - if (!protocol) { - // Game protocol has already been created at this point - protocol = service_port->make_protocol(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_8_0/src/connection.h b/path_8_0/src/connection.h deleted file mode 100644 index b2c242cb6..000000000 --- a/path_8_0/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_8_0/src/const.h b/path_8_0/src/const.h deleted file mode 100644 index 5a3898228..000000000 --- a/path_8_0/src/const.h +++ /dev/null @@ -1,468 +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_LAST = CONST_ME_PLANTATTACK, -}; - -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_LAST = CONST_ANI_CAKE, - - // 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 = 4, - TALKTYPE_CHANNEL_Y = 5, - TALKTYPE_RVR_CHANNEL = 6, - TALKTYPE_RVR_ANSWER = 7, - TALKTYPE_RVR_CONTINUE = 8, - TALKTYPE_BROADCAST = 9, - TALKTYPE_CHANNEL_R1 = 10, //red - #c text - TALKTYPE_PRIVATE_RED = 11, //@name@text - TALKTYPE_CHANNEL_O = 12, //@name@text - TALKTYPE_CHANNEL_R2 = 14, //#d - TALKTYPE_MONSTER_SAY = 16, - TALKTYPE_MONSTER_YELL = 17, -}; - -enum MessageClasses : uint8_t { - MESSAGE_STATUS_CONSOLE_YELLOW = 1, /*Yellow message in the console*/ - MESSAGE_STATUS_CONSOLE_LIGHTBLUE = 4, /*Light blue message in the console*/ - MESSAGE_STATUS_CONSOLE_ORANGE = 17, /*Orange message 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_EVENT_DEFAULT = 20, /*White message at the bottom of the game window and in the console*/ - MESSAGE_STATUS_DEFAULT = 21, /*White message at the bottom of the game window and in the console*/ - MESSAGE_INFO_DESCR = 22, /*Green message in game window and in the console*/ - MESSAGE_STATUS_SMALL = 23, /*White message at the bottom of the game window"*/ - MESSAGE_STATUS_CONSOLE_BLUE = 24, /*Blue message in the console*/ - MESSAGE_STATUS_CONSOLE_RED = 25, /*Red 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 = 155, - 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, -}; - -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, -}; - -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, -}; - -enum item_t : uint16_t { - 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 = ITEM_MAGICWALL, - - ITEM_WILDGROWTH = 1499, - ITEM_WILDGROWTH_PERSISTENT = 2721, - ITEM_WILDGROWTH_SAFE = ITEM_WILDGROWTH, - - ITEM_BAG = 1987, - - ITEM_GOLD_COIN = 2148, - ITEM_PLATINUM_COIN = 2152, - ITEM_CRYSTAL_COIN = 2160, - - ITEM_DEPOT = 2594, - ITEM_LOCKER = 2589, - - 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, - PlayerFlag_CanAnswerRuleViolations = static_cast(1) << 38, -}; - -#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 - -#define IS_IN_KEYRANGE(key, range) (key >= PSTRG_##range##_START && ((key - PSTRG_##range##_START) <= PSTRG_##range##_SIZE)) - -#endif diff --git a/path_8_0/src/container.cpp b/path_8_0/src/container.cpp deleted file mode 100644 index 0ef3e0c10..000000000 --- a/path_8_0/src/container.cpp +++ /dev/null @@ -1,705 +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; -} - -Container::Container(uint16_t _type, uint16_t _size) : Item(_type) -{ - maxSize = _size; - totalWeight = 0; - serializationCount = 0; - unlocked = true; -} - -Container::~Container() -{ - 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 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; - } - - 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_8_0/src/container.h b/path_8_0/src/container.h deleted file mode 100644 index 783bc1ca8..000000000 --- a/path_8_0/src/container.h +++ /dev/null @@ -1,170 +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; - } - - //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; - - friend class ContainerIterator; - friend class IOMapSerialize; -}; - -#endif diff --git a/path_8_0/src/creature.cpp b/path_8_0/src/creature.cpp deleted file mode 100644 index ce9ed0620..000000000 --- a/path_8_0/src/creature.cpp +++ /dev/null @@ -1,1639 +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; - moveLocked = 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); - - std::ostringstream strExp; - strExp << gainExp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_WHITE_EXP); -} - -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_8_0/src/creature.h b/path_8_0/src/creature.h deleted file mode 100644 index 5ecb83973..000000000 --- a/path_8_0/src/creature.h +++ /dev/null @@ -1,582 +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; - } - - bool isMoveLocked() const { - return moveLocked; - } - void setMoveLocked(bool locked) { - moveLocked = locked; - } - - 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; - } - - 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; - bool moveLocked; - - //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_8_0/src/creatureevent.cpp b/path_8_0/src/creatureevent.cpp deleted file mode 100644 index 161aafe78..000000000 --- a/path_8_0/src/creatureevent.cpp +++ /dev/null @@ -1,559 +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() : - scriptInterface("CreatureScript Interface") -{ - scriptInterface.initState(); -} - -CreatureEvents::~CreatureEvents() -{ - for (const auto& it : creatureEvents) { - delete it.second; - } -} - -void CreatureEvents::clear() -{ - //clear creature events - for (const auto& it : creatureEvents) { - it.second->clearEvent(); - } - - //clear lua state - scriptInterface.reInitState(); -} - -LuaScriptInterface& CreatureEvents::getScriptInterface() -{ - return 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(&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 - creatureEvents[creatureEvent->getName()] = creatureEvent; - return true; - } -} - -CreatureEvent* CreatureEvents::getEventByName(const std::string& name, bool forceLoaded /*= true*/) -{ - CreatureEventList::iterator it = creatureEvents.find(name); - if (it != 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 : 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 : 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 : 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) -{ - type = CREATURE_EVENT_NONE; - loaded = 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; - } - - eventName = nameAttribute.as_string(); - - pugi::xml_attribute typeAttribute = node.attribute("type"); - if (!typeAttribute) { - std::cout << "[Error - CreatureEvent::configureEvent] Missing type for creature event: " << eventName << std::endl; - return false; - } - - std::string tmpStr = asLowerCaseString(typeAttribute.as_string()); - if (tmpStr == "login") { - type = CREATURE_EVENT_LOGIN; - } else if (tmpStr == "logout") { - type = CREATURE_EVENT_LOGOUT; - } else if (tmpStr == "think") { - type = CREATURE_EVENT_THINK; - } else if (tmpStr == "preparedeath") { - type = CREATURE_EVENT_PREPAREDEATH; - } else if (tmpStr == "death") { - type = CREATURE_EVENT_DEATH; - } else if (tmpStr == "kill") { - type = CREATURE_EVENT_KILL; - } else if (tmpStr == "advance") { - type = CREATURE_EVENT_ADVANCE; - } else if (tmpStr == "textedit") { - type = CREATURE_EVENT_TEXTEDIT; - } else if (tmpStr == "healthchange") { - type = CREATURE_EVENT_HEALTHCHANGE; - } else if (tmpStr == "manachange") { - type = CREATURE_EVENT_MANACHANGE; - } else if (tmpStr == "extendedopcode") { - type = CREATURE_EVENT_EXTENDED_OPCODE; - } else { - std::cout << "[Error - CreatureEvent::configureEvent] Invalid type for creature event: " << eventName << std::endl; - return false; - } - - loaded = true; - return true; -} - -std::string CreatureEvent::getScriptEventName() const -{ - //Depending on the type script event name is different - switch (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_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) -{ - scriptId = creatureEvent->scriptId; - scriptInterface = creatureEvent->scriptInterface; - scripted = creatureEvent->scripted; - loaded = creatureEvent->loaded; -} - -void CreatureEvent::clearEvent() -{ - scriptId = 0; - scriptInterface = nullptr; - scripted = false; - loaded = false; -} - -bool CreatureEvent::executeOnLogin(Player* player) -{ - //onLogin(player) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogin] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnLogout(Player* player) -{ - //onLogout(player) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnLogout] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - return scriptInterface->callFunction(1); -} - -bool CreatureEvent::executeOnThink(Creature* creature, uint32_t interval) -{ - //onThink(creature, interval) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnThink] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, interval); - - return scriptInterface->callFunction(2); -} - -bool CreatureEvent::executeOnPrepareDeath(Creature* creature, Creature* killer) -{ - //onPrepareDeath(creature, killer) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnPrepareDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnDeath] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(6); -} - -bool CreatureEvent::executeAdvance(Player* player, skills_t skill, uint32_t oldLevel, - uint32_t newLevel) -{ - //onAdvance(player, skill, oldLevel, newLevel) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeAdvance] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(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 scriptInterface->callFunction(4); -} - -void CreatureEvent::executeOnKill(Creature* creature, Creature* target) -{ - //onKill(creature, target) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeOnKill] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushUserdata(L, target); - LuaScriptInterface::setCreatureMetatable(L, -1, target); - scriptInterface->callVoidFunction(2); -} - -bool CreatureEvent::executeTextEdit(Player* player, Item* item, const std::string& text) -{ - //onTextEdit(player, item, text) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeTextEdit] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushString(L, text); - - return scriptInterface->callFunction(3); -} - -void CreatureEvent::executeHealthChange(Creature* creature, Creature* attacker, CombatDamage& damage) -{ - //onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeHealthChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(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 (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; - } - } - - scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeManaChange(Creature* creature, Creature* attacker, int32_t& manaChange, CombatOrigin origin) -{ - //onManaChange(creature, attacker, manaChange, origin) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeManaChange] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(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 (scriptInterface->protectedCall(L, 4, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(L, -1)); - } else { - manaChange = LuaScriptInterface::getNumber(L, -1); - } - lua_pop(L, 1); - - scriptInterface->resetScriptEnv(); -} - -void CreatureEvent::executeExtendedOpcode(Player* player, uint8_t opcode, const std::string& buffer) -{ - //onExtendedOpcode(player, opcode, buffer) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CreatureEvent::executeExtendedOpcode] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - lua_pushnumber(L, opcode); - LuaScriptInterface::pushString(L, buffer); - - scriptInterface->callVoidFunction(3); -} diff --git a/path_8_0/src/creatureevent.h b/path_8_0/src/creatureevent.h deleted file mode 100644 index a96ce8edd..000000000 --- a/path_8_0/src/creatureevent.h +++ /dev/null @@ -1,117 +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_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 creatureEvents; - - LuaScriptInterface scriptInterface; -}; - -class CreatureEvent final : public Event -{ - public: - explicit CreatureEvent(LuaScriptInterface* _interface); - - bool configureEvent(const pugi::xml_node& node) final; - - CreatureEventType_t getEventType() const { - return type; - } - const std::string& getName() const { - return eventName; - } - bool isLoaded() const { - return loaded; - } - - 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); - 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 eventName; - CreatureEventType_t type; - bool loaded; -}; - -#endif diff --git a/path_8_0/src/cylinder.cpp b/path_8_0/src/cylinder.cpp deleted file mode 100644 index 4d4a22ede..000000000 --- a/path_8_0/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_8_0/src/cylinder.h b/path_8_0/src/cylinder.h deleted file mode 100644 index 2c61889ea..000000000 --- a/path_8_0/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_8_0/src/database.cpp b/path_8_0/src/database.cpp deleted file mode 100644 index a10524ff3..000000000 --- a/path_8_0/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_8_0/src/database.h b/path_8_0/src/database.h deleted file mode 100644 index d3f2c8b8e..000000000 --- a/path_8_0/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_8_0/src/databasemanager.cpp b/path_8_0/src/databasemanager.cpp deleted file mode 100644 index 2940f201e..000000000 --- a/path_8_0/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_8_0/src/databasemanager.h b/path_8_0/src/databasemanager.h deleted file mode 100644 index 128827578..000000000 --- a/path_8_0/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_8_0/src/databasetasks.cpp b/path_8_0/src/databasetasks.cpp deleted file mode 100644 index f479500dc..000000000 --- a/path_8_0/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_8_0/src/databasetasks.h b/path_8_0/src/databasetasks.h deleted file mode 100644 index 1d8738f40..000000000 --- a/path_8_0/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_8_0/src/definitions.h b/path_8_0/src/definitions.h deleted file mode 100644 index 44c6deea0..000000000 --- a/path_8_0/src/definitions.h +++ /dev/null @@ -1,84 +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 "3" -#define REVISION_VERSION "-" -#define SOFTWARE_CODENAME "-" -#define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" -#define GIT_REPO "https://github.com/mattyx14/otxserver/" - -#define CLIENT_VERSION_MIN 811 -#define CLIENT_VERSION_MAX 811 -#define CLIENT_VERSION_STR "8.11" - -#ifndef __FUNCTION__ -#define __FUNCTION__ __func__ -#endif - -#ifndef _USE_MATH_DEFINES -#define _USE_MATH_DEFINES -#endif - -#include -#include -#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 -#pragma warning(disable:4996) -#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 - -typedef std::vector> IPList; - -#endif diff --git a/path_8_0/src/depotchest.cpp b/path_8_0/src/depotchest.cpp deleted file mode 100644 index 64e8c4710..000000000 --- a/path_8_0/src/depotchest.cpp +++ /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. - */ - -#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) -{ - if (parent != nullptr) { - parent->postAddNotification(thing, oldParent, index, LINK_PARENT); - } -} - -void DepotChest::postRemoveNotification(Thing* thing, const Cylinder* newParent, int32_t index, cylinderlink_t) -{ - if (parent != nullptr) { - parent->postRemoveNotification(thing, newParent, index, LINK_PARENT); - } -} diff --git a/path_8_0/src/depotchest.h b/path_8_0/src/depotchest.h deleted file mode 100644 index 1e1b267eb..000000000 --- a/path_8_0/src/depotchest.h +++ /dev/null @@ -1,56 +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* getRealParent() const { - return parent; - } - - private: - uint32_t maxDepotItems; -}; - -#endif - diff --git a/path_8_0/src/depotlocker.cpp b/path_8_0/src/depotlocker.cpp deleted file mode 100644 index 64b58f795..000000000 --- a/path_8_0/src/depotlocker.cpp +++ /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. - */ - -#include "otpch.h" - -#include "depotlocker.h" - -DepotLocker::DepotLocker(uint16_t _type) : - Container(_type) -{ - depotId = 0; - maxSize = 30; -} - -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 index, const Thing& thing, uint32_t count, - uint32_t flags, Creature* actor/* = nullptr*/) const -{ - return Container::queryAdd(index, thing, count, flags, actor); -} - -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); - } -} diff --git a/path_8_0/src/depotlocker.h b/path_8_0/src/depotlocker.h deleted file mode 100644 index 5ed614196..000000000 --- a/path_8_0/src/depotlocker.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_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 -#define FS_DEPOTLOCKER_H_53AD8E0606A34070B87F792611F4F3F8 - -#include "container.h" - -class DepotLocker final : public Container -{ - public: - explicit DepotLocker(uint16_t _type); - - DepotLocker* getDepotLocker() final { - return this; - } - const DepotLocker* getDepotLocker() const final { - return this; - } - - //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_8_0/src/enums.h b/path_8_0/src/enums.h deleted file mode 100644 index b512e65e5..000000000 --- a/path_8_0/src/enums.h +++ /dev/null @@ -1,444 +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 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 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_NONE = 0, - - CLIENTOS_LINUX = 1, - CLIENTOS_WINDOWS = 2, - CLIENTOS_FLASH = 3, - - CLIENTOS_OTCLIENT_LINUX = 10, - CLIENTOS_OTCLIENT_WINDOWS = 11, - CLIENTOS_OTCLIENT_MAC = 12, -}; - -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 = 0, - - 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, -}; - -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 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; - lookHead = 0; - lookBody = 0; - lookLegs = 0; - lookFeet = 0; - lookAddons = 0; - } - - uint16_t lookType; - uint16_t lookTypeEx; - 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; - } -}; - -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; - } -}; - -#endif diff --git a/path_8_0/src/events.cpp b/path_8_0/src/events.cpp deleted file mode 100644 index 8830581c0..000000000 --- a/path_8_0/src/events.cpp +++ /dev/null @@ -1,758 +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 - playerOnLook = -1; - playerOnLookInBattleList = -1; - playerOnLookInTrade = -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 == "onLook") { - playerOnLook = event; - } else if (methodName == "onLookInBattleList") { - playerOnLookInBattleList = event; - } else if (methodName == "onLookInTrade") { - playerOnLookInTrade = 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 -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::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_8_0/src/events.h b/path_8_0/src/events.h deleted file mode 100644 index 0c5288b22..000000000 --- a/path_8_0/src/events.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_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 - 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 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 playerOnLook; - int32_t playerOnLookInBattleList; - int32_t playerOnLookInTrade; - 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_8_0/src/fileloader.cpp b/path_8_0/src/fileloader.cpp deleted file mode 100644 index 1fa6fea2f..000000000 --- a/path_8_0/src/fileloader.cpp +++ /dev/null @@ -1,419 +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() : cached_data() -{ - file = nullptr; - root = nullptr; - buffer = new uint8_t[1024]; - buffer_size = 1024; - lastError = ERROR_NONE; - - //cache - cache_size = 0; - cache_index = NO_VALID_CACHE; - cache_offset = NO_VALID_CACHE; -} - -FileLoader::~FileLoader() -{ - if (file) { - fclose(file); - file = nullptr; - } - - NodeStruct::clearNet(root); - delete[] buffer; - - for (int32_t i = 0; i < CACHE_BLOCKS; i++) { - delete[] cached_data[i].data; - } -} - -bool FileLoader::openFile(const char* filename, const char* accept_identifier) -{ - file = fopen(filename, "rb"); - if (!file) { - lastError = ERROR_CAN_NOT_OPEN; - return false; - } - - char identifier[4]; - if (fread(identifier, 1, 4, file) < 4) { - fclose(file); - file = nullptr; - 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(file); - file = nullptr; - lastError = ERROR_INVALID_FILE_VERSION; - return false; - } - - fseek(file, 0, SEEK_END); - int32_t file_size = ftell(file); - cache_size = std::min(32768, std::max(file_size / 20, 8192)) & ~0x1FFF; - - if (!safeSeek(4)) { - lastError = ERROR_INVALID_FORMAT; - return false; - } - - delete root; - root = new NodeStruct(); - root->start = 4; - - int32_t byte; - if (safeSeek(4) && readByte(byte) && byte == NODE_START) { - return parseNode(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: - 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 >= buffer_size) { - delete[] buffer; - - while (node->propsSize >= buffer_size) { - buffer_size *= 2; - } - - buffer = new uint8_t[buffer_size]; - } - - //get buffer - if (!readBytes(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 (buffer[i] == ESCAPE_CHAR) { - //escape char found, skip it and write next - buffer[j] = buffer[++i]; - //is neede a displacement for next bytes - escaped = true; - } else if (escaped) { - //perform that displacement - buffer[j] = buffer[i]; - } - } - - size = j; - return 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 = root->type; - return 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 (cache_index == NO_VALID_CACHE) { - lastError = ERROR_CACHE_ERROR; - return false; - } - - if (cache_offset >= cached_data[cache_index].size) { - int32_t pos = cache_offset + cached_data[cache_index].base; - int32_t tmp = getCacheBlock(pos); - if (tmp < 0) { - return false; - } - - cache_index = tmp; - cache_offset = pos - cached_data[cache_index].base; - if (cache_offset >= cached_data[cache_index].size) { - return false; - } - } - - value = cached_data[cache_index].data[cache_offset++]; - return true; -} - -inline bool FileLoader::readBytes(uint32_t size, int32_t pos) -{ - //seek at pos - uint32_t remain = size; - uint8_t* buf = this->buffer; - do { - //prepare cache - uint32_t i = getCacheBlock(pos); - if (i == NO_VALID_CACHE) { - return false; - } - - cache_index = i; - cache_offset = pos - cached_data[i].base; - - //get maximum read block size and calculate remaining bytes - uint32_t reading = std::min(remain, cached_data[i].size - cache_offset); - remain -= reading; - - //read it - memcpy(buf, cached_data[cache_index].data + cache_offset, reading); - - //update variables - cache_offset += reading; - buf += 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; - } - - cache_index = i; - cache_offset = pos - cached_data[i].base; - return true; -} - -inline bool FileLoader::safeTell(int32_t& pos) -{ - if (cache_index == NO_VALID_CACHE) { - lastError = ERROR_CACHE_ERROR; - return false; - } - - pos = cached_data[cache_index].base + cache_offset - 1; - return true; -} - -inline uint32_t FileLoader::getCacheBlock(uint32_t pos) -{ - bool found = false; - uint32_t i, base_pos = pos & ~(cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (cached_data[i].loaded) { - if (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 & ~(cache_size - 1); - - for (i = 0; i < CACHE_BLOCKS; i++) { - if (!cached_data[i].loaded) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - for (i = 0; i < CACHE_BLOCKS; i++) { - if (std::abs(static_cast(cached_data[i].base) - base_pos) > static_cast(2 * cache_size)) { - loading_cache = i; - break; - } - } - - if (loading_cache == -1) { - loading_cache = 0; - } - } - - if (cached_data[loading_cache].data == nullptr) { - cached_data[loading_cache].data = new uint8_t[cache_size]; - } - - cached_data[loading_cache].base = base_pos; - - if (fseek(file, cached_data[loading_cache].base, SEEK_SET) != 0) { - lastError = ERROR_SEEK_ERROR; - return -1; - } - - uint32_t size = fread(cached_data[loading_cache].data, 1, cache_size, file); - cached_data[loading_cache].size = size; - - if (size < (pos - cached_data[loading_cache].base)) { - lastError = ERROR_SEEK_ERROR; - return -1; - } - - cached_data[loading_cache].loaded = 1; - return loading_cache; -} diff --git a/path_8_0/src/fileloader.h b/path_8_0/src/fileloader.h deleted file mode 100644 index 54331dcb2..000000000 --- a/path_8_0/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 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(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 cached_data[CACHE_BLOCKS]; - - uint8_t* buffer; - NODE root; - FILE* file; - - FILELOADER_ERRORS lastError; - uint32_t buffer_size; - - uint32_t cache_size; -#define NO_VALID_CACHE 0xFFFFFFFF - uint32_t cache_index; - uint32_t 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_8_0/src/game.cpp b/path_8_0/src/game.cpp deleted file mode 100644 index 197311eeb..000000000 --- a/path_8_0/src/game.cpp +++ /dev/null @@ -1,4644 +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 "actions.h" -#include "iologindata.h" -#include "talkaction.h" -#include "spells.h" -#include "configmanager.h" -#include "server.h" -#include "globalevent.h" -#include "bed.h" -#include "scheduler.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) -{ - 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; -} - -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(); - - 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; - } - - 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->hasFlag(TILESTATE_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->hasFlag(TILESTATE_BLOCKSOLID))) { - tmpTile = map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_BLOCKSOLID)) { - flags |= FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE; - - if (!tmpTile->hasFlag(TILESTATE_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->hasFlag(TILESTATE_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, item->isRune() ? item->getItemCount() : 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*/) -{ - 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()) { - if (item->isRune()) { - m = std::min(item->getItemCount(), maxQueryCount); - } else { - 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->isRune() && 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->isRune() && 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; - } - - 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* subContainer = item->getContainer(); - if (subContainer) { - containers.push_back(subContainer); - } - } - } - 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 { - const uint32_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 { - const uint32_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) { - internalRemoveItem(item); - money -= moneyEntry.first; - } else if (moneyEntry.first > money) { - const uint32_t worth = moneyEntry.first / item->getItemCount(); - const uint32_t removeCount = (money / worth) + 1; - - addMoney(cylinder, (worth * removeCount) - money, flags); - internalRemoveItem(item, removeCount); - break; - } else { - internalRemoveItem(item); - break; - } - } - return true; -} - -void Game::addMoney(Cylinder* cylinder, uint64_t money, uint32_t flags /*= 0*/) -{ - 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); - } - - crystalCoins -= count; - } - - 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 -= platinumCoins * 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; - } - - 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; - } - - player->sendChannel(channel->getId(), channel->getName()); -} - -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::playerReceivePing(uint32_t playerId) -{ - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - player->receivePing(); -} - -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) { - return; - } - - 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::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::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::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::playerChangeOutfit(uint32_t playerId, Outfit_t outfit) -{ - if (!g_config.getBoolean(ConfigManager::ALLOW_CHANGEOUTFIT)) { - return; - } - - Player* player = getPlayerByID(playerId); - if (!player) { - return; - } - - 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) { - 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: - case TALKTYPE_PRIVATE_RED: - playerSpeakTo(player, type, receiver, text); - break; - - case TALKTYPE_CHANNEL_O: - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - case TALKTYPE_CHANNEL_R2: - g_chat->talkToChannel(*player, type, text, channelId); - 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 && (player->hasFlag(PlayerFlag_CanTalkRedPrivate) || player->getAccountType() >= ACCOUNT_TYPE_GAMEMASTER)) { - type = TALKTYPE_PRIVATE_RED; - } else { - type = TALKTYPE_PRIVATE; - } - - 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; -} - -//-- -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 (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; - std::ostringstream strHealthChange; - strHealthChange << realHealthChange; - addAnimatedText(strHealthChange.str(), targetPos, 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_STATUS_SMALL; - message.text = "You heal " + target->getNameDescription() + " for " + damageString; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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(); - 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; - 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 += '.'; - - std::ostringstream strManaDamage; - strManaDamage << manaDamage; - addAnimatedText(strManaDamage.str(), targetPos, 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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.primary.color != TEXTCOLOR_NONE) { - std::ostringstream strPrimaryDamage; - strPrimaryDamage << message.primary.value; - addAnimatedText(strPrimaryDamage.str(), targetPos, message.primary.color); - } - } - - if (message.secondary.value) { - combatGetTypeInfo(damage.secondary.type, target, message.secondary.color, hitEffect); - if (hitEffect != CONST_ME_NONE) { - addMagicEffect(list, targetPos, hitEffect); - } - - if (message.secondary.color != TEXTCOLOR_NONE) { - std::ostringstream strSecondaryDamage; - strSecondaryDamage << message.secondary.value; - addAnimatedText(strSecondaryDamage.str(), targetPos, message.secondary.color); - } - } - - 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - // 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 (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(); - 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; - std::ostringstream strManaLoss; - strManaLoss << manaLoss; - addAnimatedText(strManaLoss.str(), targetPos, 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_STATUS_SMALL; - message.text = ucfirst(target->getNameDescription()) + " loses " + damageString + " mana due to your attack."; - } else if (tmpPlayer == targetPlayer) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL; - 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::addAnimatedText(const std::string& message, const Position& pos, TextColor_t color) -{ - SpectatorVec list; - map.getSpectators(list, pos, true, true); - addAnimatedText(list, message, pos, color); -} - -void Game::addAnimatedText(const SpectatorVec& list, const std::string& message, const Position& pos, TextColor_t color) -{ - for (Creature* spectator : list) { - if (Player* tmpPlayer = spectator->getPlayer()) { - tmpPlayer->sendAnimatedText(message, pos, color); - } - } -} - -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::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::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& bug) -{ - 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& position = player->getPosition(); - fprintf(file, "------------------------------\nName: %s [Position X: %u Y: %u Z: %u]\nBug Report: %s\n", player->getName().c_str(), position.x, position.y, position.z, bug.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::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); - } -} - -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::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::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_8_0/src/game.h b/path_8_0/src/game.h deleted file mode 100644 index 51fb5e847..000000000 --- a/path_8_0/src/game.h +++ /dev/null @@ -1,547 +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& bug); - void playerDebugAssert(uint32_t playerId, const std::string& assertLine, const std::string& date, const std::string& description, const std::string& comment); - - 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 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 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 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 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 parsePlayerExtendedOpcode(uint32_t playerId, uint8_t opcode, const std::string& buffer); - - 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); - - 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 addAnimatedText(const std::string& message, const Position& pos, TextColor_t color); - static void addAnimatedText(const SpectatorVec& list, const std::string& message, const Position& pos, TextColor_t color); - 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++; } - - const std::unordered_map& getPlayers() const { return players; } - const std::map& getNpcs() const { return npcs; } - - 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 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; - 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 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; - - 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_8_0/src/globalevent.cpp b/path_8_0/src/globalevent.cpp deleted file mode 100644 index 66c610ab3..000000000 --- a/path_8_0/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() : - scriptInterface("GlobalEvent Interface") -{ - 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); - - scriptInterface.reInitState(); -} - -Event* GlobalEvents::getEvent(const std::string& nodeName) -{ - if (strcasecmp(nodeName.c_str(), "globalevent") != 0) { - return nullptr; - } - return new GlobalEvent(&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) -{ - eventType = GLOBALEVENT_NONE; - nextExecution = 0; - 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; - } - - name = nameAttribute.as_string(); - 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: " << name << std::endl; - return false; - } - - 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: " << 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: " << 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; - } - - nextExecution = current_time + difference; - eventType = GLOBALEVENT_TIMER; - } else if ((attr = node.attribute("type"))) { - const char* value = attr.value(); - if (strcasecmp(value, "startup") == 0) { - eventType = GLOBALEVENT_STARTUP; - } else if (strcasecmp(value, "shutdown") == 0) { - eventType = GLOBALEVENT_SHUTDOWN; - } else if (strcasecmp(value, "record") == 0) { - eventType = GLOBALEVENT_RECORD; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No valid type \"" << attr.as_string() << "\" for globalevent with name " << name << std::endl; - return false; - } - } else if ((attr = node.attribute("interval"))) { - interval = std::max(SCHEDULER_MINTICKS, pugi::cast(attr.value())); - nextExecution = OTSYS_TIME() + interval; - } else { - std::cout << "[Error - GlobalEvent::configureEvent] No interval for globalevent with name " << name << std::endl; - return false; - } - return true; -} - -std::string GlobalEvent::getScriptEventName() const -{ - switch (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeRecord] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - lua_pushnumber(L, current); - lua_pushnumber(L, old); - return scriptInterface->callFunction(2); -} - -bool GlobalEvent::executeEvent() -{ - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - GlobalEvent::executeEvent] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(scriptId); - - int32_t params = 0; - if (eventType == GLOBALEVENT_NONE || eventType == GLOBALEVENT_TIMER) { - lua_pushnumber(L, interval); - params = 1; - } - - return scriptInterface->callFunction(params); -} diff --git a/path_8_0/src/globalevent.h b/path_8_0/src/globalevent.h deleted file mode 100644 index 0a566b78b..000000000 --- a/path_8_0/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 scriptInterface; - } - LuaScriptInterface 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 eventType; - } - std::string getName() const { - return name; - } - - uint32_t getInterval() const { - return interval; - } - - int64_t getNextExecution() const { - return nextExecution; - } - void setNextExecution(int64_t time) { - nextExecution = time; - } - - protected: - GlobalEvent_t eventType; - - std::string getScriptEventName() const final; - - std::string name; - int64_t nextExecution; - uint32_t interval; -}; - -#endif diff --git a/path_8_0/src/groups.cpp b/path_8_0/src/groups.cpp deleted file mode 100644 index 7eb526276..000000000 --- a/path_8_0/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_8_0/src/groups.h b/path_8_0/src/groups.h deleted file mode 100644 index ff275bf42..000000000 --- a/path_8_0/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_8_0/src/guild.cpp b/path_8_0/src/guild.cpp deleted file mode 100644 index a3b736cfd..000000000 --- a/path_8_0/src/guild.cpp +++ /dev/null @@ -1,65 +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); -} - -void Guild::removeMember(Player* player) -{ - membersOnline.remove(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_8_0/src/guild.h b/path_8_0/src/guild.h deleted file mode 100644 index 6193e42d8..000000000 --- a/path_8_0/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_8_0/src/house.cpp b/path_8_0/src/house.cpp deleted file mode 100644 index 8a0c65f43..000000000 --- a/path_8_0/src/house.cpp +++ /dev/null @@ -1,760 +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_LOCKER) -{ - 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); - } - } - } - } - } - } - - DepotLocker* depotLocker = player->getDepotLocker(townid); - if (depotLocker) { - for (Item* item : moveItemList) { - g_game.internalMoveItem(item->getParent(), depotLocker, 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()); - DepotLocker* depotLocker = player.getDepotLocker(town->getID()); - if (depotLocker) { - g_game.internalAddItem(depotLocker, letter, INDEX_WHEREEVER, FLAG_NOLIMIT); - } - house->setPayRentWarnings(house->getPayRentWarnings() + 1); - } else { - house->setOwner(0, true, &player); - } - } - - IOLoginData::savePlayer(&player); - } -} diff --git a/path_8_0/src/house.h b/path_8_0/src/house.h deleted file mode 100644 index b11abe9b0..000000000 --- a/path_8_0/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_8_0/src/housetile.cpp b/path_8_0/src/housetile.cpp deleted file mode 100644 index 44db6f597..000000000 --- a/path_8_0/src/housetile.cpp +++ /dev/null @@ -1,125 +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; -} - -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_8_0/src/housetile.h b/path_8_0/src/housetile.h deleted file mode 100644 index bc26e04d4..000000000 --- a/path_8_0/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_8_0/src/ioguild.cpp b/path_8_0/src/ioguild.cpp deleted file mode 100644 index 5a700e2a9..000000000 --- a/path_8_0/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_8_0/src/ioguild.h b/path_8_0/src/ioguild.h deleted file mode 100644 index 9b4171ae9..000000000 --- a/path_8_0/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_8_0/src/iologindata.cpp b/path_8_0/src/iologindata.cpp deleted file mode 100644 index 1651cb199..000000000 --- a/path_8_0/src/iologindata.cpp +++ /dev/null @@ -1,986 +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->getNumber("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(uint32_t accountName, 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` = " << accountName; - 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->getNumber("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(uint32_t accountName, const std::string& password, std::string& characterName) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "SELECT `id`, `password` FROM `accounts` WHERE `name` = " << 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; - } - } - } - - 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) { - DepotLocker* depotLocker = player->getDepotLocker(pid); - if (depotLocker) { - depotLocker->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; - } - 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 (const auto& it : player->depotLockerMap) { - DepotLocker* depotLocker = it.second; - for (Item* item : depotLocker->getItemList()) { - if (item->getID() != ITEM_DEPOT) { - itemList.emplace_back(it.first, 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") - ); - } while (result->next()); - } - return entries; -} - -void IOLoginData::addVIPEntry(uint32_t accountId, uint32_t guid) -{ - Database* db = Database::getInstance(); - - std::ostringstream query; - query << "INSERT INTO `account_viplist` (`account_id`, `player_id`) VALUES (" << accountId << ',' << 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_8_0/src/iologindata.h b/path_8_0/src/iologindata.h deleted file mode 100644 index 5b26605fb..000000000 --- a/path_8_0/src/iologindata.h +++ /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. - */ - -#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(uint32_t accountName, const std::string& password, Account& account); - static uint32_t gameworldAuthentication(uint32_t 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); - 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_8_0/src/iomap.cpp b/path_8_0/src/iomap.cpp deleted file mode 100644 index bb8a60d79..000000000 --- a/path_8_0/src/iomap.cpp +++ /dev/null @@ -1,472 +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, uint16_t x, uint16_t y, uint8_t z) -{ - if (!ground) { - return new StaticTile(x, y, z); - } - - Tile* tile; - if ((item && item->isBlocking()) || ground->isBlocking()) { - tile = new StaticTile(x, y, z); - } else { - tile = new DynamicTile(x, y, z); - } - - 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 > 3) { - setLastErrorString("Unknown OTBM version detected."); - 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_811) { - 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; - } - - uint16_t base_x = area_coord.x; - uint16_t base_y = area_coord.y; - uint16_t 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 x = base_x + tile_coord.x; - uint16_t y = base_y + tile_coord.y; - - 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:" << x << ", y:" << y << ", z:" << z << "] Could not read house id."; - setLastErrorString(ss.str()); - return false; - } - - house = map->houses.addHouse(houseId); - if (!house) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] Could not create house id: " << houseId; - setLastErrorString(ss.str()); - return false; - } - - tile = new HouseTile(x, y, z, 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:" << x << ", y:" << y << ", z:" << z << "] Failed to read tile flags."; - setLastErrorString(ss.str()); - return false; - } - - if ((flags & OTBM_TILEFLAG_PROTECTIONZONE) != 0) { - tileflags |= TILESTATE_PROTECTIONZONE; - } else if ((flags & OTBM_TILEFLAG_NOPVPZONE) != 0) { - tileflags |= TILESTATE_NOPVPZONE; - } else if ((flags & OTBM_TILEFLAG_PVPZONE) != 0) { - tileflags |= TILESTATE_PVPZONE; - } - - if ((flags & OTBM_TILEFLAG_NOLOGOUT) != 0) { - tileflags |= TILESTATE_NOLOGOUT; - } - break; - } - - case OTBM_ATTR_ITEM: { - Item* item = Item::CreateItem(propStream); - if (!item) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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: " << x << ", y: " << y << ", z: " << z << "]." << 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, x, y, z); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - break; - } - - default: - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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:" << x << ", y:" << y << ", z:" << z << "] 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:" << x << ", y:" << y << ", z:" << z << "] Failed to create item."; - setLastErrorString(ss.str()); - return false; - } - - if (!item->unserializeItemNode(f, nodeItem, stream)) { - std::ostringstream ss; - ss << "[x:" << x << ", y:" << y << ", z:" << z << "] 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: " << x << ", y: " << y << ", z: " << z << "]." << 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, x, y, z); - tile->internalAddThing(item); - item->startDecaying(); - item->setLoadedFromMap(true); - } - } - - nodeItem = f.getNextNode(nodeItem, type); - } - - if (!tile) { - tile = createTile(ground_item, nullptr, x, y, z); - } - - tile->setFlag(static_cast(tileflags)); - - map->setTile(x, y, z, 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_8_0/src/iomap.h b/path_8_0/src/iomap.h deleted file mode 100644 index 8595d2045..000000000 --- a/path_8_0/src/iomap.h +++ /dev/null @@ -1,154 +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, -}; - -enum OTBM_TileFlag_t : uint32_t { - OTBM_TILEFLAG_PROTECTIONZONE = 1 << 0, - OTBM_TILEFLAG_NOPVPZONE = 1 << 2, - OTBM_TILEFLAG_NOLOGOUT = 1 << 3, - OTBM_TILEFLAG_PVPZONE = 1 << 4 -}; - -#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; -}; - -#pragma pack() - -class IOMap -{ - static Tile* createTile(Item*& ground, Item* item, uint16_t x, uint16_t y, uint8_t z); - - 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_8_0/src/iomapserialize.cpp b/path_8_0/src/iomapserialize.cpp deleted file mode 100644 index dddd4d696..000000000 --- a/path_8_0/src/iomapserialize.cpp +++ /dev/null @@ -1,372 +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 "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_8_0/src/iomapserialize.h b/path_8_0/src/iomapserialize.h deleted file mode 100644 index 8de71d4cb..000000000 --- a/path_8_0/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_8_0/src/item.cpp b/path_8_0/src/item.cpp deleted file mode 100644 index 035d6b59a..000000000 --- a/path_8_0/src/item.cpp +++ /dev/null @@ -1,1665 +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 "bed.h" - -#include "actions.h" -#include "spells.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.runeSpellName.empty()) { - s << " (\"" << it.runeSpellName << "\")"; - } - - if (it.runeLevel > 0 || it.runeMagLevel > 0) { - if (RuneSpell* rune = g_spells->getRuneSpell(it.id)) { - int32_t tmpSubType = subType; - if (item) { - tmpSubType = item->getSubType(); - } - s << ". " << (it.stackable && tmpSubType > 1 ? "They" : "It") << " can only be used by "; - - 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 { - s << ", "; - } - } - s << asLowerCaseString((*vocLast)->getVocName()) << "s"; - } else { - s << "players"; - } - - 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())) { - uint32_t 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.vocationString.empty()) { - 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; -} - -uint32_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); -} diff --git a/path_8_0/src/item.h b/path_8_0/src/item.h deleted file mode 100644 index 8d61fcc4f..000000000 --- a/path_8_0/src/item.h +++ /dev/null @@ -1,772 +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; - } - 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; - } - - uint32_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 isRune() const { - return items[id].isRune(); - } - 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(); - - void setLoadedFromMap(bool value) { - loadedFromMap = value; - } - bool isCleanable() const { - return !loadedFromMap && canRemove() && isPickupable() && !hasAttribute(ITEM_ATTRIBUTE_UNIQUEID) && !hasAttribute(ITEM_ATTRIBUTE_ACTIONID); - } - - 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_8_0/src/itemloader.h b/path_8_0/src/itemloader.h deleted file mode 100644 index 83bda911d..000000000 --- a/path_8_0/src/itemloader.h +++ /dev/null @@ -1,150 +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, -}; - -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, // unused - FLAG_FLOORCHANGENORTH = 1 << 9, // unused - FLAG_FLOORCHANGEEAST = 1 << 10, // unused - FLAG_FLOORCHANGESOUTH = 1 << 11, // unused - FLAG_FLOORCHANGEWEST = 1 << 12, // unused - FLAG_ALWAYSONTOP = 1 << 13, - FLAG_READABLE = 1 << 14, - FLAG_ROTATABLE = 1 << 15, - FLAG_HANGABLE = 1 << 16, - FLAG_VERTICAL = 1 << 17, - FLAG_HORIZONTAL = 1 << 18, - FLAG_CANNOTDECAY = 1 << 19, // unused - FLAG_ALLOWDISTREAD = 1 << 20, - FLAG_UNUSED = 1 << 21, // unused - FLAG_CLIENTCHARGES = 1 << 22, /* deprecated */ - FLAG_LOOKTHROUGH = 1 << 23, - FLAG_ANIMATION = 1 << 24, - FLAG_FULLTILE = 1 << 25, // unused - 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_8_0/src/items.cpp b/path_8_0/src/items.cpp deleted file mode 100644 index 082b4ee84..000000000 --- a/path_8_0/src/items.cpp +++ /dev/null @@ -1,954 +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() : - group(ITEM_GROUP_NONE), type(ITEM_TYPE_NONE), id(0), clientId(0), - stackable(false), weight(0), levelDoor(0), decayTime(0), - wieldInfo(0), minReqLevel(0), minReqMagicLevel(0), charges(0), maxHitChance(-1), - decayTo(-1), attack(0), defense(0), extraDefense(0), armor(0), rotateTo(0), - runeMagLevel(0), runeLevel(0), combatType(COMBAT_NONE), transformToOnUse(), - transformToFree(0), destroyTo(0), maxTextLen(0), writeOnceItemId(0), - transformEquipTo(0), transformDeEquipTo(0), maxItems(8), slotPosition(SLOTP_HAND), - speed(0), wareId(0), magicEffect(CONST_ME_NONE), bedPartnerDir(DIRECTION_NONE), - weaponType(WEAPON_NONE), ammoType(AMMO_NONE), shootType(CONST_ANI_NONE), - corpseType(RACE_NONE), fluidSource(FLUID_NONE), floorChange(0), - alwaysOnTopOrder(0), lightLevel(0), lightColor(0), shootRange(1), hitChance(0), - forceUse(false), hasHeight(false), walkStack(true), blockSolid(false), - blockPickupable(false), blockProjectile(false), blockPathFind(false), - allowPickupable(false), showDuration(false), showCharges(false), - showAttributes(false), replaceable(true), pickupable(false), rotatable(false), - useable(false), moveable(false), alwaysOnTop(false), canReadText(false), - canWriteText(false), isVertical(false), isHorizontal(false), isHangable(false), - allowDistRead(false), lookThrough(false), stopTime(false), showCount(true) -{ -} - -Items::Items() -{ - items.reserve(20000); -} - -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_811) { - 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 > 20000 && serverId < 20100) { - serverId -= 20000; - } - 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_ROTATABLE, flags); - iType.canReadText = hasBitSet(FLAG_READABLE, flags); - iType.lookThrough = hasBitSet(FLAG_LOOKTHROUGH, 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 > 20000 && id < 20100) { - id -= 20000; - - 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.floorChange = TILESTATE_FLOORCHANGE_DOWN; - } else if (tmpStrValue == "north") { - it.floorChange = TILESTATE_FLOORCHANGE_NORTH; - } else if (tmpStrValue == "south") { - it.floorChange = TILESTATE_FLOORCHANGE_SOUTH; - } else if (tmpStrValue == "southalt") { - it.floorChange = TILESTATE_FLOORCHANGE_SOUTH_ALT; - } else if (tmpStrValue == "west") { - it.floorChange = TILESTATE_FLOORCHANGE_WEST; - } else if (tmpStrValue == "east") { - it.floorChange = TILESTATE_FLOORCHANGE_EAST; - } else if (tmpStrValue == "eastalt") { - it.floorChange = TILESTATE_FLOORCHANGE_EAST_ALT; - } 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_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 == "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") { - 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_8_0/src/items.h b/path_8_0/src/items.h deleted file mode 100644 index 006acc9a0..000000000 --- a/path_8_0/src/items.h +++ /dev/null @@ -1,321 +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; - - 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 floorChange; - uint8_t alwaysOnTopOrder; - uint8_t lightLevel; - uint8_t lightColor; - uint8_t shootRange; - int8_t hitChance; - - bool forceUse; - 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_8_0/src/lockfree.h b/path_8_0/src/lockfree.h deleted file mode 100644 index 43448f2c8..000000000 --- a/path_8_0/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 - explicit 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_8_0/src/luascript.cpp b/path_8_0/src/luascript.cpp deleted file mode 100644 index a4db933ee..000000000 --- a/path_8_0/src/luascript.cpp +++ /dev/null @@ -1,11961 +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::tempResults; -uint32_t ScriptEnvironment::lastResultId = 0; - -std::multimap ScriptEnvironment::tempItems; - -LuaEnvironment g_luaEnvironment; - -ScriptEnvironment::ScriptEnvironment() -{ - curNpc = nullptr; - resetEnv(); - lastUID = std::numeric_limits::max(); -} - -ScriptEnvironment::~ScriptEnvironment() -{ - resetEnv(); -} - -void ScriptEnvironment::resetEnv() -{ - scriptId = 0; - callbackId = 0; - timerEvent = false; - interface = nullptr; - localMap.clear(); - 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 (this->callbackId != 0) { - //nested callbacks are not allowed - if (interface) { - interface->reportErrorFunc("Nested callbacks!"); - } - return false; - } - - this->callbackId = callbackId; - interface = scriptInterface; - return true; -} - -void ScriptEnvironment::getEventInfo(int32_t& scriptId, LuaScriptInterface*& scriptInterface, int32_t& callbackId, bool& timerEvent) const -{ - scriptId = this->scriptId; - scriptInterface = interface; - callbackId = this->callbackId; - timerEvent = this->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[++lastUID] = item; - return 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) -{ - tempResults[++lastResultId] = res; - return lastResultId; -} - -bool ScriptEnvironment::removeResult(uint32_t id) -{ - auto it = tempResults.find(id); - if (it == tempResults.end()) { - return false; - } - - tempResults.erase(it); - return true; -} - -DBResult_ptr ScriptEnvironment::getResultByID(uint32_t id) -{ - auto it = tempResults.find(id); - if (it == 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::scriptEnv[16]; -int32_t LuaScriptInterface::scriptEnvIndex = -1; - -LuaScriptInterface::LuaScriptInterface(std::string interfaceName) - : luaState(nullptr), interfaceName(interfaceName), eventTableRef(-1), 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(luaState, file.c_str()); - if (ret != 0) { - lastLuaError = popString(luaState); - return -1; - } - - //check that it is loaded as a function - if (!isFunction(luaState, -1)) { - return -1; - } - - loadingFile = file; - - if (!reserveScriptEnv()) { - return -1; - } - - ScriptEnvironment* env = getScriptEnv(); - env->setScriptId(EVENT_ID_LOADING, this); - env->setNpc(npc); - - //execute it - ret = protectedCall(luaState, 0, 0); - if (ret != 0) { - reportError(nullptr, popString(luaState)); - resetScriptEnv(); - return -1; - } - - resetScriptEnv(); - return 0; -} - -int32_t LuaScriptInterface::getEvent(const std::string& eventName) -{ - //get our events table - lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(luaState, eventName.c_str()); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 2); - return -1; - } - - //save in our events table - lua_pushvalue(luaState, -1); - lua_rawseti(luaState, -3, runningEventId); - lua_pop(luaState, 2); - - //reset global value of this event - lua_pushnil(luaState); - lua_setglobal(luaState, eventName.c_str()); - - cacheFiles[runningEventId] = loadingFile + ":" + eventName; - return runningEventId++; -} - -int32_t LuaScriptInterface::getMetaEvent(const std::string& globalName, const std::string& eventName) -{ - //get our events table - lua_rawgeti(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return -1; - } - - //get current event function pointer - lua_getglobal(luaState, globalName.c_str()); - lua_getfield(luaState, -1, eventName.c_str()); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 3); - return -1; - } - - //save in our events table - lua_pushvalue(luaState, -1); - lua_rawseti(luaState, -4, runningEventId); - lua_pop(luaState, 1); - - //reset global value of this event - lua_pushnil(luaState); - lua_setfield(luaState, -2, eventName.c_str()); - lua_pop(luaState, 2); - - cacheFiles[runningEventId] = loadingFile + ":" + globalName + "@" + eventName; - return runningEventId++; -} - -const std::string& LuaScriptInterface::getFileById(int32_t scriptId) -{ - if (scriptId == EVENT_ID_LOADING) { - return loadingFile; - } - - auto it = cacheFiles.find(scriptId); - if (it == 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(luaState, "debug"); - if (!isTable(luaState, -1)) { - lua_pop(luaState, 1); - return error_desc; - } - - lua_getfield(luaState, -1, "traceback"); - if (!isFunction(luaState, -1)) { - lua_pop(luaState, 2); - return error_desc; - } - - lua_replace(luaState, -2); - pushString(luaState, error_desc); - lua_call(luaState, 1, 1); - return popString(luaState); -} - -void LuaScriptInterface::reportError(const char* function, const std::string& error_desc, bool stack_trace/* = false*/) -{ - int32_t scriptId; - int32_t callbackId; - bool timerEvent; - LuaScriptInterface* scriptInterface; - getScriptEnv()->getEventInfo(scriptId, 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 (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(luaState, LUA_REGISTRYINDEX, eventTableRef); - if (!isTable(luaState, -1)) { - return false; - } - - lua_rawgeti(luaState, -1, functionId); - lua_replace(luaState, -2); - return isFunction(luaState, -1); -} - -bool LuaScriptInterface::initState() -{ - luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return false; - } - - lua_newtable(luaState); - eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX); - runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaScriptInterface::closeState() -{ - if (!g_luaEnvironment.getLuaState() || !luaState) { - return false; - } - - cacheFiles.clear(); - if (eventTableRef != -1) { - luaL_unref(luaState, LUA_REGISTRYINDEX, eventTableRef); - eventTableRef = -1; - } - - 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(luaState); - if (protectedCall(luaState, params, 1) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::getString(luaState, -1)); - } else { - result = LuaScriptInterface::getBoolean(luaState, -1); - } - - lua_pop(luaState, 1); - if ((lua_gettop(luaState) + params + 1) != size) { - LuaScriptInterface::reportError(nullptr, "Stack size changed!"); - } - - resetScriptEnv(); - return result; -} - -void LuaScriptInterface::callVoidFunction(int params) -{ - int size = lua_gettop(luaState); - if (protectedCall(luaState, params, 0) != 0) { - LuaScriptInterface::reportError(nullptr, LuaScriptInterface::popString(luaState)); - } - - if ((lua_gettop(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::pushCylinder(lua_State* L, Cylinder* cylinder) -{ - if (Creature* creature = cylinder->getCreature()) { - pushUserdata(L, creature); - setCreatureMetatable(L, -1, creature); - } else if (Item* parentItem = cylinder->getItem()) { - pushUserdata(L, parentItem); - setItemMetatable(L, -1, parentItem); - } else if (Tile* tile = cylinder->getTile()) { - pushUserdata(L, tile); - setMetatable(L, -1, "Tile"); - } else if (cylinder == VirtualCylinder::virtualCylinder) { - pushBoolean(L, true); - } 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.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, 7); - 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, 7); - 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); -} - -#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(luaState, "getPlayerFlagValue", LuaScriptInterface::luaGetPlayerFlagValue); - - //getPlayerInstantSpellCount(cid) - lua_register(luaState, "getPlayerInstantSpellCount", LuaScriptInterface::luaGetPlayerInstantSpellCount); - - //getPlayerInstantSpellInfo(cid, index) - lua_register(luaState, "getPlayerInstantSpellInfo", LuaScriptInterface::luaGetPlayerInstantSpellInfo); - - //doPlayerAddItem(uid, itemid, count/subtype) - //doPlayerAddItem(cid, itemid, count, canDropOnMap, subtype) - //Returns uid of the created item - lua_register(luaState, "doPlayerAddItem", LuaScriptInterface::luaDoPlayerAddItem); - - //doCreateItem(itemid, type/count, pos) - //Returns uid of the created item, only works on tiles. - lua_register(luaState, "doCreateItem", LuaScriptInterface::luaDoCreateItem); - - //doCreateItemEx(itemid, count/subtype) - lua_register(luaState, "doCreateItemEx", LuaScriptInterface::luaDoCreateItemEx); - - //doTileAddItemEx(pos, uid) - lua_register(luaState, "doTileAddItemEx", LuaScriptInterface::luaDoTileAddItemEx); - - //doMoveCreature(cid, direction) - lua_register(luaState, "doMoveCreature", LuaScriptInterface::luaDoMoveCreature); - - //doSetCreatureLight(cid, lightLevel, lightColor, time) - lua_register(luaState, "doSetCreatureLight", LuaScriptInterface::luaDoSetCreatureLight); - - //getCreatureCondition(cid, condition[, subId]) - lua_register(luaState, "getCreatureCondition", LuaScriptInterface::luaGetCreatureCondition); - - //isValidUID(uid) - lua_register(luaState, "isValidUID", LuaScriptInterface::luaIsValidUID); - - //isDepot(uid) - lua_register(luaState, "isDepot", LuaScriptInterface::luaIsDepot); - - //isMovable(uid) - lua_register(luaState, "isMovable", LuaScriptInterface::luaIsMoveable); - - //doAddContainerItem(uid, itemid, count/subtype) - lua_register(luaState, "doAddContainerItem", LuaScriptInterface::luaDoAddContainerItem); - - //getDepotId(uid) - lua_register(luaState, "getDepotId", LuaScriptInterface::luaGetDepotId); - - //getWorldTime() - lua_register(luaState, "getWorldTime", LuaScriptInterface::luaGetWorldTime); - - //getWorldLight() - lua_register(luaState, "getWorldLight", LuaScriptInterface::luaGetWorldLight); - - //getWorldUpTime() - lua_register(luaState, "getWorldUpTime", LuaScriptInterface::luaGetWorldUpTime); - - //createCombatArea( {area}, {extArea} ) - lua_register(luaState, "createCombatArea", LuaScriptInterface::luaCreateCombatArea); - - //doAreaCombatHealth(cid, type, pos, area, min, max, effect) - lua_register(luaState, "doAreaCombatHealth", LuaScriptInterface::luaDoAreaCombatHealth); - - //doTargetCombatHealth(cid, target, type, min, max, effect) - lua_register(luaState, "doTargetCombatHealth", LuaScriptInterface::luaDoTargetCombatHealth); - - //doAreaCombatMana(cid, pos, area, min, max, effect) - lua_register(luaState, "doAreaCombatMana", LuaScriptInterface::luaDoAreaCombatMana); - - //doTargetCombatMana(cid, target, min, max, effect) - lua_register(luaState, "doTargetCombatMana", LuaScriptInterface::luaDoTargetCombatMana); - - //doAreaCombatCondition(cid, pos, area, condition, effect) - lua_register(luaState, "doAreaCombatCondition", LuaScriptInterface::luaDoAreaCombatCondition); - - //doTargetCombatCondition(cid, target, condition, effect) - lua_register(luaState, "doTargetCombatCondition", LuaScriptInterface::luaDoTargetCombatCondition); - - //doAreaCombatDispel(cid, pos, area, type, effect) - lua_register(luaState, "doAreaCombatDispel", LuaScriptInterface::luaDoAreaCombatDispel); - - //doTargetCombatDispel(cid, target, type, effect) - lua_register(luaState, "doTargetCombatDispel", LuaScriptInterface::luaDoTargetCombatDispel); - - //doChallengeCreature(cid, target) - lua_register(luaState, "doChallengeCreature", LuaScriptInterface::luaDoChallengeCreature); - - //doSetMonsterOutfit(cid, name, time) - lua_register(luaState, "doSetMonsterOutfit", LuaScriptInterface::luaSetMonsterOutfit); - - //doSetItemOutfit(cid, item, time) - lua_register(luaState, "doSetItemOutfit", LuaScriptInterface::luaSetItemOutfit); - - //doSetCreatureOutfit(cid, outfit, time) - lua_register(luaState, "doSetCreatureOutfit", LuaScriptInterface::luaSetCreatureOutfit); - - //isInArray(array, value) - lua_register(luaState, "isInArray", LuaScriptInterface::luaIsInArray); - - //addEvent(callback, delay, ...) - lua_register(luaState, "addEvent", LuaScriptInterface::luaAddEvent); - - //stopEvent(eventid) - lua_register(luaState, "stopEvent", LuaScriptInterface::luaStopEvent); - - //saveServer() - lua_register(luaState, "saveServer", LuaScriptInterface::luaSaveServer); - - //cleanMap() - lua_register(luaState, "cleanMap", LuaScriptInterface::luaCleanMap); - - //debugPrint(text) - lua_register(luaState, "debugPrint", LuaScriptInterface::luaDebugPrint); - - //isInWar(cid, target) - lua_register(luaState, "isInWar", LuaScriptInterface::luaIsInWar); - - //getWaypointPosition(name) - lua_register(luaState, "getWaypointPositionByName", LuaScriptInterface::luaGetWaypointPositionByName); - - //sendChannelMessage(channelId, type, message) - lua_register(luaState, "sendChannelMessage", LuaScriptInterface::luaSendChannelMessage); - - //sendGuildChannelMessage(guildId, type, message) - lua_register(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(luaState, "bit", LuaScriptInterface::luaBitReg); -#endif - - //configManager table - luaL_register(luaState, "configManager", LuaScriptInterface::luaConfigManagerTable); - - //db table - luaL_register(luaState, "db", LuaScriptInterface::luaDatabaseTable); - - //result table - luaL_register(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(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_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_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_YELLOW) - registerEnum(MESSAGE_STATUS_CONSOLE_LIGHTBLUE) - registerEnum(MESSAGE_STATUS_CONSOLE_ORANGE) - registerEnum(MESSAGE_STATUS_WARNING) - registerEnum(MESSAGE_EVENT_ADVANCE) - registerEnum(MESSAGE_EVENT_DEFAULT) - registerEnum(MESSAGE_STATUS_DEFAULT) - registerEnum(MESSAGE_INFO_DESCR) - registerEnum(MESSAGE_STATUS_SMALL) - registerEnum(MESSAGE_STATUS_CONSOLE_BLUE) - registerEnum(MESSAGE_STATUS_CONSOLE_RED) - - 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(TALKTYPE_SAY) - registerEnum(TALKTYPE_WHISPER) - registerEnum(TALKTYPE_YELL) - registerEnum(TALKTYPE_PRIVATE) - registerEnum(TALKTYPE_CHANNEL_Y) - registerEnum(TALKTYPE_BROADCAST) - registerEnum(TALKTYPE_CHANNEL_R1) - registerEnum(TALKTYPE_PRIVATE_RED) - registerEnum(TALKTYPE_CHANNEL_O) - registerEnum(TALKTYPE_CHANNEL_R2) - registerEnum(TALKTYPE_MONSTER_SAY) - registerEnum(TALKTYPE_MONSTER_YELL) - - 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_NOPVPZONE) - registerEnum(TILESTATE_NOLOGOUT) - registerEnum(TILESTATE_PVPZONE) - 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_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 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::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::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::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::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); - - registerMethod("Game", "sendAnimatedText", LuaScriptInterface::luaGameSendAnimatedText); - - // 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); - - // 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", "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", "isHealthHidden", LuaScriptInterface::luaCreatureIsHealthHidden); - registerMethod("Creature", "setHiddenHealth", LuaScriptInterface::luaCreatureSetHiddenHealth); - - registerMethod("Creature", "isMoveLocked", LuaScriptInterface::luaCreatureIsMoveLocked); - registerMethod("Creature", "setMoveLocked", LuaScriptInterface::luaCreatureSetMoveLocked); - - 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", "hasFlag", LuaScriptInterface::luaPlayerHasFlag); - - registerMethod("Player", "getCapacity", LuaScriptInterface::luaPlayerGetCapacity); - registerMethod("Player", "setCapacity", LuaScriptInterface::luaPlayerSetCapacity); - - registerMethod("Player", "getFreeCapacity", LuaScriptInterface::luaPlayerGetFreeCapacity); - - registerMethod("Player", "getDepotChest", LuaScriptInterface::luaPlayerGetDepotChest); - - 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", "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", "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); - - // 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", "getDecayTime", LuaScriptInterface::luaItemTypeGetDecayTime); - registerMethod("ItemType", "getShowDuration", LuaScriptInterface::luaItemTypeGetShowDuration); - registerMethod("ItemType", "getRequiredLevel", LuaScriptInterface::luaItemTypeGetRequiredLevel); - registerMethod("ItemType", "getSpeed", LuaScriptInterface::luaItemTypeGetSpeed); - registerMethod("ItemType", "getBaseSpeed", LuaScriptInterface::luaItemTypeGetBaseSpeed); - - 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(luaState); - lua_pushvalue(luaState, -1); - lua_setglobal(luaState, className.c_str()); - int methods = lua_gettop(luaState); - - // methodsTable = {} - lua_newtable(luaState); - int methodsTable = lua_gettop(luaState); - - if (newFunction) { - // className.__call = newFunction - lua_pushcfunction(luaState, newFunction); - lua_setfield(luaState, methodsTable, "__call"); - } - - uint32_t parents = 0; - if (!baseClass.empty()) { - lua_getglobal(luaState, baseClass.c_str()); - lua_rawgeti(luaState, -1, 'p'); - parents = getNumber(luaState, -1) + 1; - lua_pop(luaState, 1); - lua_setfield(luaState, methodsTable, "__index"); - } - - // setmetatable(className, methodsTable) - lua_setmetatable(luaState, methods); - - // className.metatable = {} - luaL_newmetatable(luaState, className.c_str()); - int metatable = lua_gettop(luaState); - - // className.metatable.__metatable = className - lua_pushvalue(luaState, methods); - lua_setfield(luaState, metatable, "__metatable"); - - // className.metatable.__index = className - lua_pushvalue(luaState, methods); - lua_setfield(luaState, metatable, "__index"); - - // className.metatable['h'] = hash - lua_pushnumber(luaState, std::hash()(className)); - lua_rawseti(luaState, metatable, 'h'); - - // className.metatable['p'] = parents - lua_pushnumber(luaState, parents); - lua_rawseti(luaState, metatable, 'p'); - - // className.metatable['t'] = type - if (className == "Item") { - lua_pushnumber(luaState, LuaData_Item); - } else if (className == "Container") { - lua_pushnumber(luaState, LuaData_Container); - } else if (className == "Teleport") { - lua_pushnumber(luaState, LuaData_Teleport); - } else if (className == "Player") { - lua_pushnumber(luaState, LuaData_Player); - } else if (className == "Monster") { - lua_pushnumber(luaState, LuaData_Monster); - } else if (className == "Npc") { - lua_pushnumber(luaState, LuaData_Npc); - } else if (className == "Tile") { - lua_pushnumber(luaState, LuaData_Tile); - } else { - lua_pushnumber(luaState, LuaData_Unknown); - } - lua_rawseti(luaState, metatable, 't'); - - // pop className, className.metatable - lua_pop(luaState, 2); -} - -void LuaScriptInterface::registerTable(const std::string& tableName) -{ - // _G[tableName] = {} - lua_newtable(luaState); - lua_setglobal(luaState, tableName.c_str()); -} - -void LuaScriptInterface::registerMethod(const std::string& globalName, const std::string& methodName, lua_CFunction func) -{ - // globalName.methodName = func - lua_getglobal(luaState, globalName.c_str()); - lua_pushcfunction(luaState, func); - lua_setfield(luaState, -2, methodName.c_str()); - - // pop globalName - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerMetaMethod(const std::string& className, const std::string& methodName, lua_CFunction func) -{ - // className.metatable.methodName = func - luaL_getmetatable(luaState, className.c_str()); - lua_pushcfunction(luaState, func); - lua_setfield(luaState, -2, methodName.c_str()); - - // pop className.metatable - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerGlobalMethod(const std::string& functionName, lua_CFunction func) -{ - // _G[functionName] = func - lua_pushcfunction(luaState, func); - lua_setglobal(luaState, functionName.c_str()); -} - -void LuaScriptInterface::registerVariable(const std::string& tableName, const std::string& name, lua_Number value) -{ - // tableName.name = value - lua_getglobal(luaState, tableName.c_str()); - setField(luaState, name.c_str(), value); - - // pop tableName - lua_pop(luaState, 1); -} - -void LuaScriptInterface::registerGlobalVariable(const std::string& name, lua_Number value) -{ - // _G[name] = value - lua_pushnumber(luaState, value); - lua_setglobal(luaState, name.c_str()); -} - -void LuaScriptInterface::registerGlobalBoolean(const std::string& name, bool value) -{ - // _G[name] = value - pushBoolean(luaState, value); - lua_setglobal(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.lastEventTimerId; - eventDesc.eventId = g_scheduler.addEvent(createSchedulerTask( - delay, std::bind(&LuaEnvironment::executeTimerEvent, &g_luaEnvironment, lastTimerEventId) - )); - - g_luaEnvironment.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.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::luaGameSendAnimatedText(lua_State* L) -{ - // Game.sendAnimatedText(message, position, color) - int parameters = lua_gettop(L); - if (parameters < 3) { - pushBoolean(L, false); - return 1; - } - - TextColor_t color = getNumber(L, 3); - const Position& position = getPosition(L, 2); - const std::string& message = getString(L, 1); - - if (!position.x || !position.y) { - pushBoolean(L, false); - return 1; - } - - g_game.addAnimatedText(message, position, color); - pushBoolean(L, true); - 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; -} - -// 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; - } - - pushCylinder(L, parent); - 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; - } - - pushCylinder(L, topParent); - 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::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; - } - - pushCylinder(L, parent); - 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); - } - 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::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::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::luaCreatureIsMoveLocked(lua_State* L) -{ - // creature:isMoveLocked() - const Creature* creature = getUserdata(L, 1); - if (creature) { - pushBoolean(L, creature->isMoveLocked()); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaCreatureSetMoveLocked(lua_State* L) -{ - // creature:setMoveLocked(moveLocked) - Creature* creature = getUserdata(L, 1); - if (creature) { - creature->setMoveLocked(getBoolean(L, 2)); - 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::luaPlayerHasFlag(lua_State* L) -{ - // player:hasFlag(flags) - Player* player = getUserdata(L, 1); - if (player) { - PlayerFlags flag = getNumber(L, 2); - pushBoolean(L, player->hasFlag(flag)); - } 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::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) - TextMessage message(getNumber(L, 2), getString(L, 3)); - 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); - 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::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::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; -} - -// 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::luaItemTypeGetSpeed(lua_State* L) -{ - // itemType:getSpeed() - const ItemType* itemType = getUserdata(L, 1); - if (!itemType) { - lua_pushnil(L); - return 1; - } - - auto& abilities = itemType->abilities; - if (abilities) { - lua_pushnumber(L, abilities->speed); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetBaseSpeed(lua_State* L) -{ - // itemType:getBaseSpeed() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->speed); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetDecayTime(lua_State* L) -{ - // itemType:getDecayTime() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushnumber(L, itemType->decayTime); - } else { - lua_pushnil(L); - } - return 1; -} - -int LuaScriptInterface::luaItemTypeGetShowDuration(lua_State* L) -{ - // itemType:getShowDuration() - const ItemType* itemType = getUserdata(L, 1); - if (itemType) { - lua_pushboolean(L, itemType->showDuration); - } 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]) - Outfit_t outfit; - if (isTable(L, 2)) { - outfit = getOutfit(L, 2); - } else { - 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"), testInterface(nullptr), - lastEventTimerId(1), lastCombatId(0), lastAreaId(0) -{ - // -} - -LuaEnvironment::~LuaEnvironment() -{ - delete testInterface; - closeState(); -} - -bool LuaEnvironment::initState() -{ - luaState = luaL_newstate(); - if (!luaState) { - return false; - } - - luaL_openlibs(luaState); - registerFunctions(); - - runningEventId = EVENT_ID_USER; - return true; -} - -bool LuaEnvironment::reInitState() -{ - // TODO: get children, reload children - closeState(); - return initState(); -} - -bool LuaEnvironment::closeState() -{ - if (!luaState) { - return false; - } - - for (const auto& combatEntry : combatIdMap) { - clearCombatObjects(combatEntry.first); - } - - for (const auto& areaEntry : areaIdMap) { - clearAreaObjects(areaEntry.first); - } - - for (auto& timerEntry : timerEvents) { - LuaTimerEventDesc timerEventDesc = std::move(timerEntry.second); - for (int32_t parameter : timerEventDesc.parameters) { - luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); - } - luaL_unref(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - } - - combatIdMap.clear(); - areaIdMap.clear(); - timerEvents.clear(); - cacheFiles.clear(); - - lua_close(luaState); - luaState = nullptr; - return true; -} - -LuaScriptInterface* LuaEnvironment::getTestInterface() -{ - if (!testInterface) { - testInterface = new LuaScriptInterface("Test Interface"); - testInterface->initState(); - } - return testInterface; -} - -Combat* LuaEnvironment::getCombatObject(uint32_t id) const -{ - auto it = combatMap.find(id); - if (it == combatMap.end()) { - return nullptr; - } - return it->second; -} - -Combat* LuaEnvironment::createCombatObject(LuaScriptInterface* interface) -{ - Combat* combat = new Combat; - combatMap[++lastCombatId] = combat; - combatIdMap[interface].push_back(lastCombatId); - return combat; -} - -void LuaEnvironment::clearCombatObjects(LuaScriptInterface* interface) -{ - auto it = combatIdMap.find(interface); - if (it == combatIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = combatMap.find(id); - if (itt != combatMap.end()) { - delete itt->second; - combatMap.erase(itt); - } - } - it->second.clear(); -} - -AreaCombat* LuaEnvironment::getAreaObject(uint32_t id) const -{ - auto it = areaMap.find(id); - if (it == areaMap.end()) { - return nullptr; - } - return it->second; -} - -uint32_t LuaEnvironment::createAreaObject(LuaScriptInterface* interface) -{ - areaMap[++lastAreaId] = new AreaCombat; - areaIdMap[interface].push_back(lastAreaId); - return lastAreaId; -} - -void LuaEnvironment::clearAreaObjects(LuaScriptInterface* interface) -{ - auto it = areaIdMap.find(interface); - if (it == areaIdMap.end()) { - return; - } - - for (uint32_t id : it->second) { - auto itt = areaMap.find(id); - if (itt != areaMap.end()) { - delete itt->second; - areaMap.erase(itt); - } - } - it->second.clear(); -} - -void LuaEnvironment::executeTimerEvent(uint32_t eventIndex) -{ - auto it = timerEvents.find(eventIndex); - if (it == timerEvents.end()) { - return; - } - - LuaTimerEventDesc timerEventDesc = std::move(it->second); - timerEvents.erase(it); - - //push function - lua_rawgeti(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - - //push parameters - for (auto parameter : boost::adaptors::reverse(timerEventDesc.parameters)) { - lua_rawgeti(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(luaState, LUA_REGISTRYINDEX, timerEventDesc.function); - for (auto parameter : timerEventDesc.parameters) { - luaL_unref(luaState, LUA_REGISTRYINDEX, parameter); - } -} diff --git a/path_8_0/src/luascript.h b/path_8_0/src/luascript.h deleted file mode 100644 index 6cdaebd43..000000000 --- a/path_8_0/src/luascript.h +++ /dev/null @@ -1,1283 +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 -#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 -#undef lua_equal -#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 Cylinder; -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) { - this->scriptId = scriptId; - interface = scriptInterface; - } - bool setCallbackId(int32_t callbackId, LuaScriptInterface* scriptInterface); - - int32_t getScriptId() const { - return scriptId; - } - LuaScriptInterface* getScriptInterface() { - return interface; - } - - void setTimerEvent() { - timerEvent = true; - } - - void getEventInfo(int32_t& scriptId, 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) { - curNpc = npc; - } - Npc* getNpc() const { - return 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 scriptId; - int32_t callbackId; - bool timerEvent; - LuaScriptInterface* interface; - - //local item map - uint32_t lastUID; - std::unordered_map localMap; - - //temporary item list - static std::multimap tempItems; - - //result map - static uint32_t lastResultId; - static DBResultMap tempResults; - - //for npc scripts - Npc* 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(scriptEnvIndex >= 0 && scriptEnvIndex < 16); - return scriptEnv + scriptEnvIndex; - } - - static bool reserveScriptEnv() { - return ++scriptEnvIndex < 16; - } - - static void resetScriptEnv() { - assert(scriptEnvIndex >= 0); - scriptEnv[scriptEnvIndex--].resetEnv(); - } - - static void reportError(const char* function, const std::string& error_desc, bool stack_trace = false); - - const std::string& getInterfaceName() const { - return interfaceName; - } - const std::string& getLastLuaError() const { - return lastLuaError; - } - - lua_State* getLuaState() const { - return 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 void pushCylinder(lua_State* L, Cylinder* cylinder); - - 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_type(L, arg) == LUA_TNUMBER; - } - 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 luaGameSendAnimatedText(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); - - // 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 luaCreatureIsMoveLocked(lua_State* L); - static int luaCreatureSetMoveLocked(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 luaPlayerHasFlag(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 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 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 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); - - // 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 luaItemTypeGetSpeed(lua_State* L); - static int luaItemTypeGetBaseSpeed(lua_State* L); - static int luaItemTypeGetDecayTime(lua_State* L); - static int luaItemTypeGetShowDuration(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* luaState; - std::string lastLuaError; - - std::string interfaceName; - int32_t eventTableRef; - - static ScriptEnvironment scriptEnv[16]; - static int32_t scriptEnvIndex; - - int32_t runningEventId; - std::string loadingFile; - - //script file cache - std::map 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 timerEvents; - std::unordered_map combatMap; - std::unordered_map areaMap; - - std::unordered_map> combatIdMap; - std::unordered_map> areaIdMap; - - LuaScriptInterface* testInterface; - - uint32_t lastEventTimerId; - uint32_t lastCombatId; - uint32_t lastAreaId; - - // - friend class LuaScriptInterface; - friend class CombatSpell; -}; - -#endif diff --git a/path_8_0/src/mailbox.cpp b/path_8_0/src/mailbox.cpp deleted file mode 100644 index 53f2d725a..000000000 --- a/path_8_0/src/mailbox.cpp +++ /dev/null @@ -1,181 +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; - uint32_t depotId = 0; - if (!getReceiver(item, receiver, depotId)) { - return false; - } - - /**No need to continue if its still empty**/ - if (receiver.empty() || depotId == 0) { - return false; - } - - Player* player = g_game.getPlayerByName(receiver); - if (player) { - DepotLocker* depotLocker = player->getDepotLocker(depotId); - if (depotLocker) { - if (g_game.internalMoveItem(item->getParent(), depotLocker, 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; - } - - DepotLocker* depotLocker = tmpPlayer.getDepotLocker(depotId); - if (depotLocker) { - if (g_game.internalMoveItem(item->getParent(), depotLocker, 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, uint32_t& depotId) const -{ - const Container* container = item->getContainer(); - if (container) { - for (Item* containerItem : container->getItemList()) { - if (containerItem->getID() == ITEM_LABEL && getReceiver(containerItem, name, depotId)) { - return true; - } - } - return false; - } - - const std::string& text = item->getText(); - if (text.empty()) { - return false; - } - - std::string temp; - std::istringstream iss(item->getText(), std::istringstream::in); - std::string strTown = ""; - uint32_t curLine = 1; - - while (getline(iss, temp, '\n')) { - if (curLine == 1) { - name = temp; - } else if (curLine == 2) { - strTown = temp; - } else { - break; - } - - ++curLine; - } - - trimString(strTown); - Town* town = g_game.map.towns.getTown(strTown); - if (town) { - depotId = town->getID(); - return true; - } - - return false; -} - -bool Mailbox::canSend(const Item* item) -{ - return item->getID() == ITEM_PARCEL || item->getID() == ITEM_LETTER; -} diff --git a/path_8_0/src/mailbox.h b/path_8_0/src/mailbox.h deleted file mode 100644 index 80038da21..000000000 --- a/path_8_0/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, uint32_t& depotId) const; - bool sendItem(Item* item) const; - - static bool canSend(const Item* item); -}; - -#endif diff --git a/path_8_0/src/map.cpp b/path_8_0/src/map.cpp deleted file mode 100644 index b07b7bd00..000000000 --- a/path_8_0/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->leafS = leaf; - } - - //update west leaf - QTreeLeafNode* westLeaf = root.getLeaf(x - FLOOR_SIZE, y); - if (westLeaf) { - westLeaf->leafE = leaf; - } - - //update south - QTreeLeafNode* southLeaf = root.getLeaf(x, y + FLOOR_SIZE); - if (southLeaf) { - leaf->leafS = southLeaf; - } - - //update east - QTreeLeafNode* eastLeaf = root.getLeaf(x + FLOOR_SIZE, y); - if (eastLeaf) { - leaf->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->leafE; - } else { - leafE = QTreeNode::getLeafStatic(&root, nx + FLOOR_SIZE, ny); - } - } - - if (leafS) { - leafS = leafS->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() -{ - leaf = false; - child[0] = nullptr; - child[1] = nullptr; - child[2] = nullptr; - child[3] = nullptr; -} - -QTreeNode::~QTreeNode() -{ - delete child[0]; - delete child[1]; - delete child[2]; - delete child[3]; -} - -QTreeLeafNode* QTreeNode::getLeaf(uint32_t x, uint32_t y) -{ - if (leaf) { - return static_cast(this); - } - - QTreeNode* node = 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 (!child[index]) { - if (level != FLOOR_BITS) { - child[index] = new QTreeNode(); - } else { - child[index] = new QTreeLeafNode(); - QTreeLeafNode::newLeaf = true; - } - } - return 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) { - array[i] = nullptr; - } - - leaf = true; - leafS = nullptr; - leafE = nullptr; -} - -QTreeLeafNode::~QTreeLeafNode() -{ - for (uint32_t i = 0; i < MAP_MAX_LAYERS; ++i) { - delete array[i]; - } -} - -Floor* QTreeLeafNode::createFloor(uint32_t z) -{ - if (!array[z]) { - array[z] = new Floor(); - } - return 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->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_8_0/src/map.h b/path_8_0/src/map.h deleted file mode 100644 index f6ce2c325..000000000 --- a/path_8_0/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 leaf; - } - - QTreeLeafNode* getLeaf(uint32_t x, uint32_t y); - - template - inline static Leaf getLeafStatic(Node node, uint32_t x, uint32_t y) - { - do { - node = node->child[((x & 0x8000) >> 15) | ((y & 0x8000) >> 14)]; - if (!node) { - return nullptr; - } - - x <<= 1; - y <<= 1; - } while (!node->leaf); - return static_cast(node); - } - - QTreeLeafNode* createLeaf(uint32_t x, uint32_t y, uint32_t level); - - protected: - QTreeNode* child[4]; - - bool leaf; - - 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 array[z]; - } - - void addCreature(Creature* c); - void removeCreature(Creature* c); - - protected: - static bool newLeaf; - QTreeLeafNode* leafS; - QTreeLeafNode* leafE; - Floor* 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_8_0/src/monster.cpp b/path_8_0/src/monster.cpp deleted file mode 100644 index f70707221..000000000 --- a/path_8_0/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->hasFlag(TILESTATE_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_8_0/src/monster.h b/path_8_0/src/monster.h deleted file mode 100644 index 824573026..000000000 --- a/path_8_0/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_8_0/src/monsters.cpp b/path_8_0/src/monsters.cpp deleted file mode 100644 index e4d393a0f..000000000 --- a/path_8_0/src/monsters.cpp +++ /dev/null @@ -1,1298 +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_INFO_DESCR, 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_INFO_DESCR, 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("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_8_0/src/monsters.h b/path_8_0/src/monsters.h deleted file mode 100644 index 01e81a40b..000000000 --- a/path_8_0/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_8_0/src/movement.cpp b/path_8_0/src/movement.cpp deleted file mode 100644 index fc56ef57f..000000000 --- a/path_8_0/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() : - scriptInterface("MoveEvents Interface") -{ - 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(itemIdMap); - clearMap(actionIdMap); - clearMap(uniqueIdMap); - - for (const auto& it : positionMap) { - const MoveEventList& moveEventList = it.second; - for (int32_t i = 0; i < MOVE_EVENT_LAST; ++i) { - for (MoveEvent* moveEvent : moveEventList.moveEvent[i]) { - delete moveEvent; - } - } - } - positionMap.clear(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& MoveEvents::getScriptInterface() -{ - return 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(&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, 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, 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, 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, itemIdMap); - } - } - } else if ((attr = node.attribute("uniqueid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), 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, uniqueIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, uniqueIdMap); - } - } else if ((attr = node.attribute("actionid"))) { - addEvent(moveEvent, pugi::cast(attr.value()), 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, actionIdMap); - while (++id <= endId) { - addEvent(moveEvent, id, 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, 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 = itemIdMap.find(item->getID()); - if (it != 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 = uniqueIdMap.find(item->getUniqueId()); - if (it != uniqueIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - if (item->hasAttribute(ITEM_ATTRIBUTE_ACTIONID)) { - it = actionIdMap.find(item->getActionId()); - if (it != actionIdMap.end()) { - std::list& moveEventList = it->second.moveEvent[eventType]; - if (!moveEventList.empty()) { - return *moveEventList.begin(); - } - } - } - - it = itemIdMap.find(item->getID()); - if (it != 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 = positionMap.find(tile->getPosition()); - if (it != 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) -{ - 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) -{ - eventType = copy->eventType; - stepFunction = copy->stepFunction; - moveFunction = copy->moveFunction; - equipFunction = copy->equipFunction; - slot = copy->slot; - - if (copy->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 (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") { - eventType = MOVE_EVENT_STEP_IN; - } else if (tmpStr == "stepout") { - eventType = MOVE_EVENT_STEP_OUT; - } else if (tmpStr == "equip") { - eventType = MOVE_EVENT_EQUIP; - } else if (tmpStr == "deequip") { - eventType = MOVE_EVENT_DEEQUIP; - } else if (tmpStr == "additem") { - eventType = MOVE_EVENT_ADD_ITEM; - } else if (tmpStr == "removeitem") { - eventType = MOVE_EVENT_REMOVE_ITEM; - } else { - std::cout << "Error: [MoveEvent::configureMoveEvent] No valid event name " << eventAttr.as_string() << std::endl; - return false; - } - - if (eventType == MOVE_EVENT_EQUIP || 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; - } - - scripted = false; - return true; -} - -MoveEvent_t MoveEvent::getEventType() const -{ - return eventType; -} - -void MoveEvent::setEventType(MoveEvent_t type) -{ - 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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeStep] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushPosition(L, pos); - LuaScriptInterface::pushPosition(L, fromPos); - - return scriptInterface->callFunction(4); -} - -uint32_t MoveEvent::fireEquip(Player* player, Item* item, slots_t slot, bool boolean) -{ - if (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeEquip] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - LuaScriptInterface::pushThing(L, item); - lua_pushnumber(L, slot); - - return scriptInterface->callFunction(3); -} - -uint32_t MoveEvent::fireAddRemItem(Item* item, Item* tileItem, const Position& pos) -{ - if (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - MoveEvent::executeAddRemItem] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushThing(L, item); - LuaScriptInterface::pushThing(L, tileItem); - LuaScriptInterface::pushPosition(L, pos); - - return scriptInterface->callFunction(3); -} diff --git a/path_8_0/src/movement.h b/path_8_0/src/movement.h deleted file mode 100644 index bee6732e1..000000000 --- a/path_8_0/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 uniqueIdMap; - MoveListMap actionIdMap; - MoveListMap itemIdMap; - MovePosListMap positionMap; - - LuaScriptInterface 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 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_8_0/src/networkmessage.cpp b/path_8_0/src/networkmessage.cpp deleted file mode 100644 index 531ed872b..000000000 --- a/path_8_0/src/networkmessage.cpp +++ /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. - */ - -#include "otpch.h" - -#include "networkmessage.h" - -#include "container.h" -#include "creature.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); - - if (it.stackable) { - addByte(count); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[count & 7]); - } -} - -void NetworkMessage::addItem(const Item* item) -{ - const ItemType& it = Item::items[item->getID()]; - - add(it.clientId); - - if (it.stackable) { - addByte(std::min(0xFF, item->getItemCount())); - } else if (it.isSplash() || it.isFluidContainer()) { - addByte(fluidMap[item->getFluidType() & 7]); - } -} - -void NetworkMessage::addItemId(uint16_t itemId) -{ - add(Item::items[itemId].clientId); -} diff --git a/path_8_0/src/networkmessage.h b/path_8_0/src/networkmessage.h deleted file mode 100644 index b34abe078..000000000 --- a/path_8_0/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 = 4; - 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 + 4) || 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_8_0/src/npc.cpp b/path_8_0/src/npc.cpp deleted file mode 100644 index 9ee968a11..000000000 --- a/path_8_0/src/npc.cpp +++ /dev/null @@ -1,899 +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 "pugicast.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::scriptInterface = nullptr; - -void Npcs::reload() -{ - delete Npc::scriptInterface; - Npc::scriptInterface = nullptr; - - const std::map& npcs = g_game.getNpcs(); - 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(), filename("data/npc/" + _name + ".xml") -{ - loaded = false; - - masterRadius = -1; - - 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 (!scriptInterface) { - scriptInterface = new NpcScriptInterface(); - scriptInterface->loadNpcLib("data/npc/lib/npc.lua"); - } - - loaded = loadFromXml(); - return loaded; -} - -void Npc::reset() -{ - loaded = false; - walkTicks = 1500; - floorChange = false; - attackable = false; - ignoreHeight = true; - focusCreature = 0; - - delete npcEventHandler; - npcEventHandler = nullptr; - - parameters.clear(); -} - -void Npc::reload() -{ - reset(); - load(); - - // Simulate that the creature is placed on the map again. - if (npcEventHandler) { - npcEventHandler->onCreatureAppear(this); - } - - if (walkTicks > 0) { - addEventWalk(); - } -} - -bool Npc::loadFromXml() -{ - 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("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()); - } - - currentOutfit = defaultOutfit; - } - - for (auto parameterNode : npcNode.child("parameters").children()) { - parameters[parameterNode.attribute("key").as_string()] = parameterNode.attribute("value").as_string(); - } - - pugi::xml_attribute scriptFile = npcNode.attribute("script"); - if (scriptFile) { - npcEventHandler = new NpcEventsHandler(scriptFile.as_string(), this); - if (!npcEventHandler->isLoaded()) { - delete npcEventHandler; - 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 (npcEventHandler) { - npcEventHandler->onCreatureAppear(creature); - } - } else if (creature->getPlayer()) { - if (npcEventHandler) { - npcEventHandler->onCreatureAppear(creature); - } - } -} - -void Npc::onRemoveCreature(Creature* creature, bool isLogout) -{ - Creature::onRemoveCreature(creature, isLogout); - - if (creature == this) { - if (npcEventHandler) { - npcEventHandler->onCreatureDisappear(creature); - } - } else if (creature->getPlayer()) { - if (npcEventHandler) { - 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 (npcEventHandler) { - 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 (npcEventHandler) { - npcEventHandler->onCreatureSay(player, type, text); - } - } -} - -void Npc::onThink(uint32_t interval) -{ - Creature::onThink(interval); - - if (npcEventHandler) { - 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_SAY, text); - player->onCreatureSay(this, TALKTYPE_SAY, text); - } -} - -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->hasFlag(TILESTATE_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; - } -} - -NpcScriptInterface* Npc::getScriptInterface() -{ - return scriptInterface; -} - -NpcScriptInterface::NpcScriptInterface() : - LuaScriptInterface("Npc interface") -{ - libLoaded = false; - initState(); -} - -bool NpcScriptInterface::initState() -{ - luaState = g_luaEnvironment.getLuaState(); - if (!luaState) { - return false; - } - - registerFunctions(); - - lua_newtable(luaState); - eventTableRef = luaL_ref(luaState, LUA_REGISTRYINDEX); - runningEventId = EVENT_ID_USER; - return true; -} - -bool NpcScriptInterface::closeState() -{ - libLoaded = false; - LuaScriptInterface::closeState(); - return true; -} - -bool NpcScriptInterface::loadNpcLib(const std::string& file) -{ - if (libLoaded) { - return true; - } - - if (loadFile(file) == -1) { - std::cout << "[Warning - NpcScriptInterface::loadNpcLib] Can not load " << file << std::endl; - return false; - } - - libLoaded = true; - return true; -} - -void NpcScriptInterface::registerFunctions() -{ - //npc exclusive functions - lua_register(luaState, "selfSay", NpcScriptInterface::luaActionSay); - lua_register(luaState, "selfMove", NpcScriptInterface::luaActionMove); - lua_register(luaState, "selfMoveTo", NpcScriptInterface::luaActionMoveTo); - lua_register(luaState, "selfTurn", NpcScriptInterface::luaActionTurn); - lua_register(luaState, "selfFollow", NpcScriptInterface::luaActionFollow); - lua_register(luaState, "getDistanceTo", NpcScriptInterface::luagetDistanceTo); - lua_register(luaState, "doNpcSetCreatureFocus", NpcScriptInterface::luaSetNpcFocus); - lua_register(luaState, "getNpcCid", NpcScriptInterface::luaGetNpcCid); - lua_register(luaState, "getNpcParameter", NpcScriptInterface::luaGetNpcParameter); - lua_register(luaState, "doSellItem", NpcScriptInterface::luaDoSellItem); - - // metatable - registerMethod("Npc", "getParameter", NpcScriptInterface::luaNpcGetParameter); - registerMethod("Npc", "setFocus", NpcScriptInterface::luaNpcSetFocus); -} - -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->parameters.find(paramKey); - if (it != npc->parameters.end()) { - LuaScriptInterface::pushString(L, it->second); - } else { - lua_pushnil(L); - } - 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->parameters.find(key); - if (it != npc->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; -} - -NpcEventsHandler::NpcEventsHandler(const std::string& file, Npc* npc) -{ - this->npc = npc; - scriptInterface = npc->getScriptInterface(); - loaded = scriptInterface->loadFile("data/npc/scripts/" + file, npc) == 0; - if (!loaded) { - std::cout << "[Warning - NpcScript::NpcScript] Can not load script: " << file << std::endl; - std::cout << scriptInterface->getLastLuaError() << std::endl; - creatureSayEvent = -1; - creatureDisappearEvent = -1; - creatureAppearEvent = -1; - creatureMoveEvent = -1; - thinkEvent = -1; - } else { - creatureSayEvent = scriptInterface->getEvent("onCreatureSay"); - creatureDisappearEvent = scriptInterface->getEvent("onCreatureDisappear"); - creatureAppearEvent = scriptInterface->getEvent("onCreatureAppear"); - creatureMoveEvent = scriptInterface->getEvent("onCreatureMove"); - thinkEvent = scriptInterface->getEvent("onThink"); - } -} - -bool NpcEventsHandler::isLoaded() const -{ - return loaded; -} - -void NpcEventsHandler::onCreatureAppear(Creature* creature) -{ - if (creatureAppearEvent == -1) { - return; - } - - //onCreatureAppear(creature) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureAppear] Call stack overflow" << std::endl; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureAppearEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureAppearEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureDisappear(Creature* creature) -{ - if (creatureDisappearEvent == -1) { - return; - } - - //onCreatureDisappear(creature) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureDisappear] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureDisappearEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureDisappearEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - scriptInterface->callFunction(1); -} - -void NpcEventsHandler::onCreatureMove(Creature* creature, const Position& oldPos, const Position& newPos) -{ - if (creatureMoveEvent == -1) { - return; - } - - //onCreatureMove(creature, oldPos, newPos) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureMove] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureMoveEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureMoveEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - LuaScriptInterface::pushPosition(L, oldPos); - LuaScriptInterface::pushPosition(L, newPos); - scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onCreatureSay(Creature* creature, SpeakClasses type, const std::string& text) -{ - if (creatureSayEvent == -1) { - return; - } - - //onCreatureSay(creature, type, msg) - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onCreatureSay] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(creatureSayEvent, scriptInterface); - env->setNpc(npc); - - lua_State* L = scriptInterface->getLuaState(); - scriptInterface->pushFunction(creatureSayEvent); - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - lua_pushnumber(L, type); - LuaScriptInterface::pushString(L, text); - scriptInterface->callFunction(3); -} - -void NpcEventsHandler::onThink() -{ - if (thinkEvent == -1) { - return; - } - - //onThink() - if (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - NpcScript::onThink] Call stack overflow" << std::endl; - return; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(thinkEvent, scriptInterface); - env->setNpc(npc); - - scriptInterface->pushFunction(thinkEvent); - scriptInterface->callFunction(0); -} diff --git a/path_8_0/src/npc.h b/path_8_0/src/npc.h deleted file mode 100644 index f99fe9634..000000000 --- a/path_8_0/src/npc.h +++ /dev/null @@ -1,219 +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 luaDoSellItem(lua_State* L); - - // metatable - static int luaNpcGetParameter(lua_State* L); - static int luaNpcSetFocus(lua_State* L); - - private: - bool initState() final; - bool closeState() final; - - bool 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 onThink(); - - bool isLoaded() const; - - protected: - Npc* npc; - NpcScriptInterface* scriptInterface; - - int32_t creatureAppearEvent; - int32_t creatureDisappearEvent; - int32_t creatureMoveEvent; - int32_t creatureSayEvent; - int32_t thinkEvent; - bool 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; - } - - 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 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(); - - std::map parameters; - - std::string name; - std::string filename; - - NpcEventsHandler* npcEventHandler; - - Position masterPos; - - uint32_t walkTicks; - int32_t focusCreature; - int32_t masterRadius; - - bool floorChange; - bool attackable; - bool ignoreHeight; - bool loaded; - - static NpcScriptInterface* scriptInterface; - - friend class Npcs; - friend class NpcScriptInterface; -}; - -#endif diff --git a/path_8_0/src/otpch.cpp b/path_8_0/src/otpch.cpp deleted file mode 100644 index b8314c168..000000000 --- a/path_8_0/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_8_0/src/otpch.h b/path_8_0/src/otpch.h deleted file mode 100644 index 62bfb20c6..000000000 --- a/path_8_0/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 diff --git a/path_8_0/src/otserv.cpp b/path_8_0/src/otserv.cpp deleted file mode 100644 index 0956cc1c2..000000000 --- a/path_8_0/src/otserv.cpp +++ /dev/null @@ -1,334 +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" - -#ifndef _WIN32 -#include // for sigemptyset() -#endif - -#include "configmanager.h" -#include "scriptmanager.h" -#include "rsa.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; - -IPList serverIPs; - -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)); - - 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); - - std::cout << ">> Loaded all modules, server starting up..." << std::endl; - - std::pair IpNetMask; - IpNetMask.first = inet_addr("127.0.0.1"); - IpNetMask.second = 0xFFFFFFFF; - serverIPs.push_back(IpNetMask); - - char szHostName[128]; - if (gethostname(szHostName, 128) == 0) { - hostent* he = gethostbyname(szHostName); - if (he) { - unsigned char** addr = (unsigned char**)he->h_addr_list; - while (addr[0] != nullptr) { - IpNetMask.first = *(uint32_t*)(*addr); - IpNetMask.second = 0xFFFFFFFF; - serverIPs.push_back(IpNetMask); - addr++; - } - } - } - - std::string ip = g_config.getString(ConfigManager::IP); - - uint32_t resolvedIp = inet_addr(ip.c_str()); - if (resolvedIp == INADDR_NONE) { - struct hostent* he = gethostbyname(ip.c_str()); - if (!he) { - std::ostringstream ss; - ss << "ERROR: Cannot resolve " << ip << "!" << std::endl; - startupErrorMessage(ss.str()); - return; - } - resolvedIp = *(uint32_t*)he->h_addr; - } - - IpNetMask.first = resolvedIp; - IpNetMask.second = 0; - serverIPs.push_back(IpNetMask); - -#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_8_0/src/outfit.cpp b/path_8_0/src/outfit.cpp deleted file mode 100644 index 2ad61e01b..000000000 --- a/path_8_0/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_8_0/src/outfit.h b/path_8_0/src/outfit.h deleted file mode 100644 index 01385e159..000000000 --- a/path_8_0/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_8_0/src/outputmessage.cpp b/path_8_0/src/outputmessage.cpp deleted file mode 100644 index 81a6d97f6..000000000 --- a/path_8_0/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_8_0/src/outputmessage.h b/path_8_0/src/outputmessage.h deleted file mode 100644 index 1e5bbc994..000000000 --- a/path_8_0/src/outputmessage.h +++ /dev/null @@ -1,105 +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() { - writeMessageLength(); - } - - inline void append(const NetworkMessage& msg) { - auto msgLen = msg.getLength(); - memcpy(buffer + position, msg.getBuffer() + 4, msgLen); - length += msgLen; - position += msgLen; - } - - inline void append(const OutputMessage_ptr& msg) { - auto msgLen = msg->getLength(); - memcpy(buffer + position, msg->getBuffer() + 4, 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_8_0/src/party.cpp b/path_8_0/src/party.cpp deleted file mode 100644 index 556431457..000000000 --- a/path_8_0/src/party.cpp +++ /dev/null @@ -1,485 +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); - 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); - } - 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); - - for (Player* member : memberList) { - member->sendCreatureSkull(player); - player->sendPlayerPartyIcons(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); - - 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(); - } - - 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); - - 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_8_0/src/party.h b/path_8_0/src/party.h deleted file mode 100644 index 849685317..000000000 --- a/path_8_0/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_8_0/src/player.cpp b/path_8_0/src/player.cpp deleted file mode 100644 index e85213214..000000000 --- a/path_8_0/src/player.cpp +++ /dev/null @@ -1,4102 +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 "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(), client(p), varSkills(), varStats(), inventoryAbilities() -{ - isConnecting = false; - - accountNumber = 0; - vocation = nullptr; - 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; - - pzLocked = false; - bloodHitCount = 0; - shieldBlockCount = 0; - lastAttackBlockType = BLOCK_NONE; - addAttackSkillPoint = false; - lastAttack = 0; - - blessings = 0; - - 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; - - sex = PLAYERSEX_FEMALE; - - town = nullptr; - - accountType = ACCOUNT_TYPE_NORMAL; - premiumDays = 0; - - idleTime = 0; - - skullTicks = 0; - party = nullptr; - - bankBalance = 0; - - offlineTrainingSkill = -1; - offlineTrainingTime = 0; - lastStatsTrainingTime = 0; - - ghostMode = false; - - staminaMinutes = 3240; - - lastQuestlogUpdate = 0; - - inventoryWeight = 0; - operatingSystem = CLIENTOS_NONE; - secureMode = false; - guid = 0; -} - -Player::~Player() -{ - for (Item* item : inventory) { - if (item) { - item->setParent(nullptr); - item->decrementReferenceCounter(); - } - } - - for (const auto& it : depotLockerMap) { - it.second->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 || 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_SWORDS; - } - - if (_tile->hasFlag(TILESTATE_PROTECTIONZONE)) { - // 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; - } - - auto it = openContainers.find(cid); - if (it != openContainers.end()) { - OpenContainer& openContainer = it->second; - 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; - } - - openContainers.erase(it); -} - -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 { - 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; -} - -void Player::onReceiveMail() const -{ - 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()) { - return it->second; - } - - DepotLocker* depotLocker = new DepotLocker(ITEM_LOCKER); - depotLocker->setDepotId(depotId); - 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; - } - - if (openContainer.index >= container->capacity()) { - item = container->getItemByIndex(openContainer.index - 1); - } - client->sendAddContainerItem(it.first, 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)); - } -} - -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); - } - } - - 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); - } - - 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::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); - } - } - - 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); - } - } - } -} - -//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_STATUS_SMALL, "You gained " + expString); - sendTextMessage(message); - - std::ostringstream strExp; - strExp << exp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_WHITE_EXP); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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_STATUS_SMALL, "You lost " + expString); - sendTextMessage(message); - - std::ostringstream strExp; - strExp << lostExp; - g_game.addAnimatedText(strExp.str(), _position, TEXTCOLOR_RED); - - SpectatorVec list; - g_game.map.getSpectators(list, _position, false, true); - list.erase(this); - if (!list.empty()) { - message.type = MESSAGE_STATUS_SMALL; - 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) { - - //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(); - - 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(); - - 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::addCombatExhaust(uint32_t ticks) -{ - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST_COMBAT, ticks, 0); - addCondition(condition); -} - -void Player::addHealExhaust(uint32_t ticks) -{ - Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST_HEAL, ticks, 0); - addCondition(condition); -} - -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); -} - -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); - if (client) { - client->sendVIP(vipGuid, vipName, 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; -} - -//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->isRune() || 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->isRune() && 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*, 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); - } - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - updateInventoryWeight(); - updateItemsLight(); - sendStats(); - } - - if (const Item* item = thing->getItem()) { - if (const Container* container = item->getContainer()) { - onSendContainer(container); - } - } 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*, int32_t index, cylinderlink_t link /*= LINK_OWNER*/) -{ - if (link == LINK_OWNER) { - //calling movement scripts - g_moveEvents->onPlayerDeEquip(this, thing->getItem(), static_cast(index)); - } - - if (link == LINK_OWNER || link == LINK_TOPPARENT) { - 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); - } - } - } -} - -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); - sendIcons(); -} - -void Player::onAddCombatCondition(ConditionType_t type) -{ - switch (type) { - case CONDITION_POISON: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are poisoned."); - break; - - case CONDITION_DROWN: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are drowning."); - break; - - case CONDITION_PARALYZE: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are paralyzed."); - break; - - case CONDITION_DRUNK: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are drunk."); - break; - - case CONDITION_CURSED: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are cursed."); - break; - - case CONDITION_FREEZING: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are freezing."); - break; - - case CONDITION_DAZZLED: - sendTextMessage(MESSAGE_STATUS_SMALL, "You are dazzled."); - break; - - case CONDITION_BLEEDING: - sendTextMessage(MESSAGE_STATUS_SMALL, "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) { - 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); - - 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_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 && 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; - } - - lossPercent *= vocation->getLessLoss(); - - 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; -} - -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; - } - - 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(); -} - -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; -} - -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_8_0/src/player.h b/path_8_0/src/player.h deleted file mode 100644 index aa607126d..000000000 --- a/path_8_0/src/player.h +++ /dev/null @@ -1,1167 +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 "depotchest.h" -#include "depotlocker.h" -#include "guild.h" -#include "groups.h" -#include "town.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 secureMode_t : uint8_t { - SECUREMODE_OFF = 0, - SECUREMODE_ON = 1, -}; - -enum tradestate_t : uint8_t { - TRADE_NONE, - TRADE_INITIATED, - TRADE_ACCEPT, - TRADE_ACKNOWLEDGE, - TRADE_TRANSFER, -}; - -struct VIPEntry { - VIPEntry(uint32_t guid, const std::string& name) - : guid(guid), name(name) {} - - uint32_t guid; - std::string name; -}; - -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; - } - - 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; - - uint16_t getClientIcons() const; - - const GuildWarList& getGuildWarList() const { - return 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(); - - 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 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); - - 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; - } - - 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() const; - bool isNearDepotBox() const; - - bool canSee(const Position& pos) const final; - bool canSeeCreature(const Creature* creature) const final; - - 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; - } - - //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); - - //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 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 addCombatExhaust(uint32_t ticks); - void addHealExhaust(uint32_t ticks); - 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 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 sendCreatureShield(const Creature* creature) { - if (client) { - client->sendCreatureShield(creature); - } - } - void sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color) { - if (client) { - client->sendAnimatedText(message, pos, color); - } - } - - //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 sendStats(); - 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() const { - if (client) { - client->sendReLoginWindow(); - } - } - 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 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) { - if (client) { - client->sendChannel(channelId, channelName); - } - } - 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 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::forward_list invitePartyList; - 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; - - 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 lastPing; - int64_t lastPong; - int64_t nextAction; - - BedItem* bedItem; - Guild* guild; - Group* group; - 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 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_8_0/src/position.cpp b/path_8_0/src/position.cpp deleted file mode 100644 index 5b943b6a6..000000000 --- a/path_8_0/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_8_0/src/position.h b/path_8_0/src/position.h deleted file mode 100644 index 6fb0bc744..000000000 --- a/path_8_0/src/position.h +++ /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. - */ - -#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_NONE = 8, -}; - -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_8_0/src/protocol.cpp b/path_8_0/src/protocol.cpp deleted file mode 100644 index 3936bcba9..000000000 --- a/path_8_0/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 (!rawMessages) { - msg->writeMessageLength(); - - if (encryptionEnabled) { - XTEA_encrypt(*msg); - msg->addCryptoHeader(); - } - } -} - -void Protocol::onRecvMessage(NetworkMessage& msg) -{ - if (encryptionEnabled && !XTEA_decrypt(msg)) { - return; - } - - parsePacket(msg); -} - -OutputMessage_ptr Protocol::getOutputBuffer(int32_t size) -{ - //dispatcher thread - if (outputBuffer && NetworkMessage::MAX_BODY_LENGTH >= outputBuffer->getLength() + size) { - return outputBuffer; - } else { - outputBuffer = OutputMessagePool::getOutputMessage(); - return 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[] = {key[0], key[1], key[2], 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() - 2) & 7) != 0) { - return false; - } - - const uint32_t delta = 0x61C88647; - - uint8_t* buffer = msg.getBuffer() + msg.getBufferPosition(); - const size_t messageLength = (msg.getLength() - 2); - size_t readPos = 0; - const uint32_t k[] = {key[0], key[1], key[2], 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() - 4) { - 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_8_0/src/protocol.h b/path_8_0/src/protocol.h deleted file mode 100644 index fd51df7f7..000000000 --- a/path_8_0/src/protocol.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_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) : connection(connection), key(), encryptionEnabled(false), 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 connection.expired(); - } - - Connection_ptr getConnection() const { - return connection.lock(); - } - - uint32_t getIP() const; - - //Use this function for autosend messages only - OutputMessage_ptr getOutputBuffer(int32_t size); - - OutputMessage_ptr& getCurrentBuffer() { - return 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() { - encryptionEnabled = true; - } - void setXTEAKey(const uint32_t* key) { - memcpy(this->key, key, sizeof(*key) * 4); - } - - void XTEA_encrypt(OutputMessage& msg) const; - bool XTEA_decrypt(NetworkMessage& msg) const; - static bool RSA_decrypt(NetworkMessage& msg); - - void setRawMessages(bool value) { - rawMessages = value; - } - - virtual void release() {} - friend class Connection; - - OutputMessage_ptr outputBuffer; - private: - const ConnectionWeak_ptr connection; - uint32_t key[4]; - bool encryptionEnabled; - bool rawMessages; -}; - -#endif diff --git a/path_8_0/src/protocolgame.cpp b/path_8_0/src/protocolgame.cpp deleted file mode 100644 index 8ac2043da..000000000 --- a/path_8_0/src/protocolgame.cpp +++ /dev/null @@ -1,2073 +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 "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), - version(CLIENT_VERSION_MIN), - debugAssertSent(false), - 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); - 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->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); - 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(); - - 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 - - uint32_t accountName = msg.get(); - std::string characterName = msg.getString(); - std::string password = msg.getString(); - if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) { - disconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!"); - return; - } - - if (accountName == 0) { - disconnectClient("You must enter your account name."); - 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() -{ - // -} - -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 (!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 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 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 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 0xD2: addGameTask(&Game::playerRequestOutfit, player->getID()); break; - case 0xD3: parseSetOutfit(msg); break; - case 0xDC: parseAddVip(msg); break; - case 0xDD: parseRemoveVip(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; - - 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) -{ - 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() > 150) { - // 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() + 4)) { - 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(); - addGameTask(&Game::playerChangeOutfit, player->getID(), newOutfit); -} - -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: - case TALKTYPE_PRIVATE_RED: - receiver = msg.getString(); - channelId = 0; - break; - - case TALKTYPE_CHANNEL_Y: - case TALKTYPE_CHANNEL_R1: - case TALKTYPE_CHANNEL_R2: - 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 - - 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::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::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) -{ - std::string bug = msg.getString(); - addGameTask(&Game::playerReportBug, player->getID(), bug); -} - -void ProtocolGame::parseDebugAssert(NetworkMessage& msg) -{ - if (debugAssertSent) { - return; - } - - 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); -} - -// Send methods -void ProtocolGame::sendOpenPrivateChannel(const std::string& receiver) -{ - NetworkMessage msg; - msg.addByte(0xAD); - msg.addString(receiver); - 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::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::sendCreatureSquare(const Creature* creature, SquareColor_t color) -{ - if (!canSee(creature)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x86); - msg.add(creature->getID()); - msg.addByte(color); - 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() -{ - NetworkMessage msg; - msg.addByte(0x28); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendStats() -{ - NetworkMessage msg; - AddPlayerStats(msg); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextMessage(MessageClasses mclass, const std::string& message) -{ - NetworkMessage msg; - msg.addByte(0xB4); - msg.addByte(mclass); - msg.addString(message); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendTextMessage(const TextMessage& message) -{ - NetworkMessage msg; - msg.addByte(0xB4); - msg.addByte(message.type); - 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); - 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) -{ - NetworkMessage msg; - msg.addByte(0xAC); - msg.add(channelId); - msg.addString(channelName); - 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); - - msg.addItem(container); - msg.addString(container->getName()); - - msg.addByte(container->capacity()); - - msg.addByte(hasParent ? 0x01 : 0x00); - - msg.addByte(std::min(0xFF, container->size())); - - uint32_t i = 0; - const ItemDeque& itemList = container->getItemList(); - for (ItemDeque::const_iterator it = itemList.begin() + firstIndex, end = itemList.end(); i < 0xFF && it != end; ++it, ++i) { - msg.addItem(*it); - } - 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()); - 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); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendChangeSpeed(const Creature* creature, uint32_t speed) -{ - NetworkMessage msg; - msg.addByte(0x8F); - msg.add(creature->getID()); - msg.add(speed); - 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(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, const Item* item) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x6A); - msg.addPosition(pos); - 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::sendFightModes() -{ - NetworkMessage msg; - msg.addByte(0xA7); - msg.addByte(player->fightMode); - msg.addByte(player->chaseMode); - msg.addByte(player->secureMode); - 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); - - 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(0x0A); - - msg.add(player->getID()); - msg.addByte(0x32); // beat duration (50) - msg.addByte(0x00); - - // can report bugs? - if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) { - msg.addByte(0x01); - } else { - msg.addByte(0x00); - } - - if (player->hasFlag(PlayerFlag_CanAnswerRuleViolations)) { - msg.addByte(0x0B); - - for (uint8_t i = 0; i < 32; i++) { - msg.addByte(0xFF); - } - } - - writeToOutputBuffer(msg); - - 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, 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, vipStatus); - } - } - - 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, const Item* item) -{ - NetworkMessage msg; - msg.addByte(0x70); - msg.addByte(cid); - 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.addByte(slot); - msg.addItem(item); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendRemoveContainerItem(uint8_t cid, uint16_t slot) -{ - NetworkMessage msg; - msg.addByte(0x72); - msg.addByte(cid); - msg.addByte(slot); - 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(); - 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() == 50) { // Game client doesn't allow more than 50 outfits - break; - } - } - - msg.addByte(protocolOutfits.size()); - for (const ProtocolOutfit& outfit : protocolOutfits) { - msg.add(outfit.lookType); - msg.addString(*outfit.name); - msg.addByte(outfit.addons); - } - - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendUpdatedVIPStatus(uint32_t guid, VipStatus_t newStatus) -{ - NetworkMessage msg; - msg.addByte(newStatus ? 0xD3 : 0xD4); - msg.add(guid); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendVIP(uint32_t guid, const std::string& name, VipStatus_t status) -{ - NetworkMessage msg; - msg.addByte(0xD2); - msg.add(guid); - msg.addString(name); - msg.addByte(status); - writeToOutputBuffer(msg); -} - -void ProtocolGame::sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color) -{ - if (!canSee(pos)) { - return; - } - - NetworkMessage msg; - msg.addByte(0x84); - msg.addPosition(pos); - msg.addByte(color); - msg.addString(message); - writeToOutputBuffer(msg); -} - -////////////// Add common messages -void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bool known, uint32_t remove) -{ - 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.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()); - - msg.addByte(player->getSkullClient(otherPlayer)); - msg.addByte(player->getPartyShield(otherPlayer)); -} - -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(std::min(player->getExperience(), 0x7FFFFFFF)); - - msg.add(player->getLevel()); - msg.addByte(player->getPlayerInfo(PLAYERINFO_LEVELPERCENT)); - - 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(player->getPlayerInfo(PLAYERINFO_MAGICLEVELPERCENT)); - - msg.addByte(player->getSoul()); - - msg.add(player->getStaminaMinutes()); -} - -void ProtocolGame::AddPlayerSkills(NetworkMessage& msg) -{ - msg.addByte(0xA1); - - for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; ++i) { - msg.addByte(std::min(player->getSkillLevel(i), std::numeric_limits::max())); - 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); - } -} - -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::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_8_0/src/protocolgame.h b/path_8_0/src/protocolgame.h deleted file mode 100644 index ffb467e5d..000000000 --- a/path_8_0/src/protocolgame.h +++ /dev/null @@ -1,292 +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 - 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 parseQuestLine(NetworkMessage& msg); - - void parseInviteToParty(NetworkMessage& msg); - void parseJoinParty(NetworkMessage& msg); - void parseRevokePartyInvite(NetworkMessage& msg); - void parsePassPartyLeadership(NetworkMessage& msg); - void parseEnableSharedPartyExperience(NetworkMessage& msg); - - //trade methods - void parseRequestTrade(NetworkMessage& msg); - void parseLookInTrade(NetworkMessage& msg); - - //VIP methods - void parseAddVip(NetworkMessage& msg); - void parseRemoveVip(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 sendClosePrivate(uint16_t channelId); - void sendCreatePrivateChannel(uint16_t channelId, const std::string& channelName); - void sendChannelsDialog(); - void sendChannel(uint16_t channelId, const std::string& channelName); - 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 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 sendTextMessage(MessageClasses mclass, const std::string& message); - void sendTextMessage(const TextMessage& message); - void sendReLoginWindow(); - - void sendAddMarker(const Position& pos, uint8_t markType, const std::string& desc); - - void sendCreatureShield(const Creature* creature); - void sendCreatureSkull(const Creature* creature); - - 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, VipStatus_t status); - - void sendFightModes(); - - void sendCreatureLight(const Creature* creature); - void sendWorldLight(const LightInfo& lightInfo); - - void sendCreatureSquare(const Creature* creature, SquareColor_t color); - - //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, const Item* item); - void sendUpdateContainerItem(uint8_t cid, uint16_t slot, const Item* item); - void sendRemoveContainerItem(uint8_t cid, uint16_t slot); - - 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 sendAnimatedText(const std::string& message, const Position& pos, TextColor_t color); - - //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); - - //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; - uint16_t version; - - bool debugAssertSent; - bool acceptPackets; -}; - -#endif diff --git a/path_8_0/src/protocollogin.cpp b/path_8_0/src/protocollogin.cpp deleted file mode 100644 index 5b2895b8c..000000000 --- a/path_8_0/src/protocollogin.cpp +++ /dev/null @@ -1,181 +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 "tasks.h" - -#include "configmanager.h" -#include "iologindata.h" -#include "ban.h" -#include -#include "game.h" - -extern ConfigManager g_config; -extern IPList serverIPs; -extern Game g_game; - -void ProtocolLogin::disconnectClient(const std::string& message) -{ - auto output = OutputMessagePool::getOutputMessage(); - - output->addByte(0x0A); - output->addString(message); - send(output); - - disconnect(); -} - -void ProtocolLogin::getCharacterList(uint32_t accountName, const std::string& password) -{ - uint32_t serverIp = serverIPs[0].first; - for (uint32_t i = 0; i < serverIPs.size(); i++) { - if ((serverIPs[i].first & serverIPs[i].second) == (getConnection()->getIP() & serverIPs[i].second)) { - serverIp = serverIPs[i].first; - break; - } - } - - Account account; - if (!IOLoginData::loginserverAuthentication(accountName, password, account)) { - disconnectClient("Account name or password is not correct."); - 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 char list - output->addByte(0x64); - - uint8_t size = std::min(std::numeric_limits::max(), account.characters.size()); - output->addByte(size); - for (uint8_t i = 0; i < size; i++) { - output->addString(account.characters[i]); - output->addString(g_config.getString(ConfigManager::SERVER_NAME)); - output->add(serverIp); - output->add(g_config.getNumber(ConfigManager::GAME_PORT)); - } - - //Add premium days - if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) { - output->add(0xFFFF); //client displays free premium - } else { - output->add(account.premiumDays); - } - - send(output); - - disconnect(); -} - -void ProtocolLogin::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); - /* - * 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!"); - 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); - - uint32_t accountName = msg.get(); - std::string password = msg.getString(); - - 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.\nPlease re-connect in a while."); - 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()); - return; - } - - if (accountName == 0) { - disconnectClient("Invalid account name."); - return; - } - - auto thisPtr = std::dynamic_pointer_cast(shared_from_this()); - g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountName, password))); -} diff --git a/path_8_0/src/protocollogin.h b/path_8_0/src/protocollogin.h deleted file mode 100644 index 01469157c..000000000 --- a/path_8_0/src/protocollogin.h +++ /dev/null @@ -1,48 +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}; - 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); - - void getCharacterList(uint32_t accountName, const std::string& password); -}; - -#endif diff --git a/path_8_0/src/protocolstatus.cpp b/path_8_0/src/protocolstatus.cpp deleted file mode 100644 index afb1a722b..000000000 --- a/path_8_0/src/protocolstatus.cpp +++ /dev/null @@ -1,228 +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 "outputmessage.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_8_0/src/protocolstatus.h b/path_8_0/src/protocolstatus.h deleted file mode 100644 index a29febfef..000000000 --- a/path_8_0/src/protocolstatus.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_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}; - 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_8_0/src/pugicast.h b/path_8_0/src/pugicast.h deleted file mode 100644 index e8b7fd515..000000000 --- a/path_8_0/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_8_0/src/quests.cpp b/path_8_0/src/quests.cpp deleted file mode 100644 index a105bde4b..000000000 --- a/path_8_0/src/quests.cpp +++ /dev/null @@ -1,228 +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 (!mainDescription.empty()) { - std::string desc = mainDescription; - replaceString(desc, "|STATE|", std::to_string(value)); - replaceString(desc, "\\n", "\n"); - return desc; - } - - if (ignoreEndValue) { - for (int32_t current = endValue; current >= startValue; current--) { - if (value >= current) { - auto sit = descriptions.find(current); - if (sit != descriptions.end()) { - return sit->second; - } - } - } - } else { - for (int32_t current = endValue; current >= startValue; current--) { - if (value == current) { - auto sit = descriptions.find(current); - if (sit != descriptions.end()) { - return sit->second; - } - } - } - } - 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 mainDescription = 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 (mainDescription.empty()) { - for (auto missionStateNode : missionNode.children()) { - int32_t missionId = pugi::cast(missionStateNode.attribute("id").value()); - mission.descriptions.emplace(missionId, missionStateNode.attribute("description").as_string()); - } - } else { - mission.mainDescription = mainDescription; - } - } - } - 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.getStorageId() == key && value >= mission.getStartStorageValue() && value <= mission.getEndStorageValue()) { - return mission.mainDescription.empty() || oldValue < mission.getStartStorageValue() || oldValue > mission.getEndStorageValue(); - } - } - } - return false; -} diff --git a/path_8_0/src/quests.h b/path_8_0/src/quests.h deleted file mode 100644 index b4787f86b..000000000 --- a/path_8_0/src/quests.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_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 -#define FS_QUESTS_H_16E44051F23547BE8097F8EA9FCAACA0 - -#include "player.h" -#include "networkmessage.h" - -class Mission; -class Quest; - -typedef std::list MissionsList; -typedef std::list QuestsList; - -class Mission -{ - public: - Mission(std::string name, int32_t storageID, int32_t startValue, int32_t endValue, bool ignoreEndValue) - : 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 descriptions; - std::string mainDescription; - - 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_8_0/src/raids.cpp b/path_8_0/src/raids.cpp deleted file mode 100644 index 6de28ad0d..000000000 --- a/path_8_0/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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - ScriptEvent::onRaid] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - scriptInterface->pushFunction(scriptId); - - return scriptInterface->callFunction(0); -} diff --git a/path_8_0/src/raids.h b/path_8_0/src/raids.h deleted file mode 100644 index 2773fd7b8..000000000 --- a/path_8_0/src/raids.h +++ /dev/null @@ -1,233 +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; - } - - 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_8_0/src/rsa.cpp b/path_8_0/src/rsa.cpp deleted file mode 100644 index dadb42d88..000000000 --- a/path_8_0/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_8_0/src/rsa.h b/path_8_0/src/rsa.h deleted file mode 100644 index c356a9d64..000000000 --- a/path_8_0/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_8_0/src/scheduler.cpp b/path_8_0/src/scheduler.cpp deleted file mode 100644 index 5a275b215..000000000 --- a/path_8_0/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_8_0/src/scheduler.h b/path_8_0/src/scheduler.h deleted file mode 100644 index 0a0f9a9f5..000000000 --- a/path_8_0/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_8_0/src/scriptmanager.cpp b/path_8_0/src/scriptmanager.cpp deleted file mode 100644 index 0f44b04c1..000000000 --- a/path_8_0/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_8_0/src/scriptmanager.h b/path_8_0/src/scriptmanager.h deleted file mode 100644 index 5a3f26fb2..000000000 --- a/path_8_0/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_8_0/src/server.cpp b/path_8_0/src/server.cpp deleted file mode 100644 index 820ffe722..000000000 --- a/path_8_0/src/server.cpp +++ /dev/null @@ -1,219 +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(NetworkMessage& msg, const Connection_ptr& connection) const -{ - uint8_t protocolID = msg.getByte(); - for (auto& service : services) { - if (protocolID != service->get_protocol_identifier()) { - continue; - } - - 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_8_0/src/server.h b/path_8_0/src/server.h deleted file mode 100644 index 86ee1b83d..000000000 --- a/path_8_0/src/server.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_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 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; - } - 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(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_8_0/src/spawn.cpp b/path_8_0/src/spawn.cpp deleted file mode 100644 index 56fab6664..000000000 --- a/path_8_0/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_8_0/src/spawn.h b/path_8_0/src/spawn.h deleted file mode 100644 index c04aa1187..000000000 --- a/path_8_0/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_8_0/src/spells.cpp b/path_8_0/src/spells.cpp deleted file mode 100644 index a168d28a8..000000000 --- a/path_8_0/src/spells.cpp +++ /dev/null @@ -1,1985 +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(): - scriptInterface("Spell Interface") -{ - 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(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Spells::getScriptInterface() -{ - return 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(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "instant") == 0) { - return new InstantSpell(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "conjure") == 0) { - return new ConjureSpell(&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 (!scripted) { - delete combat; - } -} - -bool CombatSpell::loadScriptCombat() -{ - combat = g_luaEnvironment.getCombatObject(g_luaEnvironment.lastCombatId); - return combat != nullptr; -} - -bool CombatSpell::castSpell(Creature* creature) -{ - if (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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - CombatSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return scriptInterface->callFunction(2); -} - -Spell::Spell() -{ - spellId = 0; - level = 0; - magLevel = 0; - mana = 0; - manaPercent = 0; - soul = 0; - range = -1; - cooldown = 1000; - fist = 0; - club = 0; - sword = 0; - axe = 0; - distance = 0; - shield = 0; - fish = 0; - needTarget = false; - needWeapon = false; - selfTarget = false; - blockingSolid = false; - blockingCreature = false; - premium = false; - enabled = true; - aggressive = true; - learnable = false; -} - -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("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("exhaustion")) || (attr = node.attribute("cooldown"))) { - cooldown = 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("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()); - } - - 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->hasFlag(PlayerFlag_HasNoExhaustion)) { - bool exhaust = false; - if (aggressive) { - if (player->hasCondition(CONDITION_EXHAUST_COMBAT)) { - exhaust = true; - } - } else { - if (player->hasCondition(CONDITION_EXHAUST_HEAL)) { - exhaust = true; - } - } - - if (exhaust) { - 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->hasFlag(TILESTATE_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->hasFlag(TILESTATE_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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - if (!player->hasFlag(PlayerFlag_NotGainInFight)) { - 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; - } - - 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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - 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) { - if (aggressive) { - player->addCombatExhaust(cooldown); - } else { - player->addHealExhaust(cooldown); - } - } - - 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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - InstantSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - return 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->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.getZ() - 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID | TILESTATE_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->hasFlag(TILESTATE_BLOCKSOLID))) { - tmpTile = g_game.map.getTile(destPos.x, destPos.y, destPos.z + 1); - if (tmpTile && tmpTile->getGround() && !tmpTile->hasFlag(TILESTATE_IMMOVABLEBLOCKSOLID | TILESTATE_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&) -{ - 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 (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; - } - - 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.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 (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 (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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - RuneSpell::executeCastSpell] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, creature); - LuaScriptInterface::setCreatureMetatable(L, -1, creature); - - LuaScriptInterface::pushVariant(L, var); - - LuaScriptInterface::pushBoolean(L, isHotkey); - - return scriptInterface->callFunction(3); -} diff --git a/path_8_0/src/spells.h b/path_8_0/src/spells.h deleted file mode 100644 index 3d67debc1..000000000 --- a/path_8_0/src/spells.h +++ /dev/null @@ -1,329 +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 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; - - 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_8_0/src/talkaction.cpp b/path_8_0/src/talkaction.cpp deleted file mode 100644 index 28a65ea45..000000000 --- a/path_8_0/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() - : scriptInterface("TalkAction Interface") -{ - scriptInterface.initState(); -} - -TalkActions::~TalkActions() -{ - clear(); -} - -void TalkActions::clear() -{ - for (TalkAction* talkAction : talkActions) { - delete talkAction; - } - talkActions.clear(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& TalkActions::getScriptInterface() -{ - return 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(&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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - TalkAction::executeSay] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - - LuaScriptInterface::pushString(L, words); - LuaScriptInterface::pushString(L, param); - lua_pushnumber(L, type); - - return scriptInterface->callFunction(4); -} diff --git a/path_8_0/src/talkaction.h b/path_8_0/src/talkaction.h deleted file mode 100644 index 5cc50af59..000000000 --- a/path_8_0/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 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_8_0/src/tasks.cpp b/path_8_0/src/tasks.cpp deleted file mode 100644 index e1b9e014b..000000000 --- a/path_8_0/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_8_0/src/tasks.h b/path_8_0/src/tasks.h deleted file mode 100644 index 33b68d00f..000000000 --- a/path_8_0/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_8_0/src/teleport.cpp b/path_8_0/src/teleport.cpp deleted file mode 100644 index ba0a8a2f0..000000000 --- a/path_8_0/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_8_0/src/teleport.h b/path_8_0/src/teleport.h deleted file mode 100644 index 41aad9260..000000000 --- a/path_8_0/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_8_0/src/thing.cpp b/path_8_0/src/thing.cpp deleted file mode 100644 index 24e8c95c5..000000000 --- a/path_8_0/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_8_0/src/thing.h b/path_8_0/src/thing.h deleted file mode 100644 index 47c04a686..000000000 --- a/path_8_0/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_8_0/src/thread_holder_base.h b/path_8_0/src/thread_holder_base.h deleted file mode 100644 index 79ce284d5..000000000 --- a/path_8_0/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_8_0/src/tile.cpp b/path_8_0/src/tile.cpp deleted file mode 100644 index 80e042ec7..000000000 --- a/path_8_0/src/tile.cpp +++ /dev/null @@ -1,1583 +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 "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) -{ - 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) -{ - 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) -{ - 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) && hasFlag(TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (creature->isMoveLocked() || ground == nullptr) { - return RETURNVALUE_NOTPOSSIBLE; - } - - if (const Monster* monster = creature->getMonster()) { - if (hasFlag(TILESTATE_PROTECTIONZONE | TILESTATE_FLOORCHANGE | TILESTATE_TELEPORT)) { - 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()) { - 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 (hasFlag(TILESTATE_FLOORCHANGE_DOWN)) { - 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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_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->hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { - ++dy; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) { - --dy; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) { - dy -= 2; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST)) { - --dx; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_EAST_ALT)) { - dx -= 2; - } - - if (downTile->hasFlag(TILESTATE_FLOORCHANGE_WEST)) { - ++dx; - } - - destTile = g_game.map.getTile(dx, dy, dz); - } - } - } - } else if (hasFlag(TILESTATE_FLOORCHANGE)) { - uint16_t dx = tilePos.x; - uint16_t dy = tilePos.y; - uint8_t dz = tilePos.z - 1; - - if (hasFlag(TILESTATE_FLOORCHANGE_NORTH)) { - --dy; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH)) { - ++dy; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_EAST)) { - ++dx; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_WEST)) { - --dx; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_SOUTH_ALT)) { - dy += 2; - } - - if (hasFlag(TILESTATE_FLOORCHANGE_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->end(), 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.floorChange != 0) { - setFlag(it.floorChange); - } - } - - 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.floorChange != 0) { - resetFlag(TILESTATE_FLOORCHANGE); - } - - 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_8_0/src/tile.h b/path_8_0/src/tile.h deleted file mode 100644 index 8978d3d56..000000000 --- a/path_8_0/src/tile.h +++ /dev/null @@ -1,419 +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 = 0, - - TILESTATE_FLOORCHANGE_DOWN = 1 << 0, - TILESTATE_FLOORCHANGE_NORTH = 1 << 1, - TILESTATE_FLOORCHANGE_SOUTH = 1 << 2, - TILESTATE_FLOORCHANGE_EAST = 1 << 3, - TILESTATE_FLOORCHANGE_WEST = 1 << 4, - TILESTATE_FLOORCHANGE_SOUTH_ALT = 1 << 5, - TILESTATE_FLOORCHANGE_EAST_ALT = 1 << 6, - TILESTATE_PROTECTIONZONE = 1 << 7, - TILESTATE_NOPVPZONE = 1 << 8, - TILESTATE_NOLOGOUT = 1 << 9, - TILESTATE_PVPZONE = 1 << 10, - TILESTATE_TELEPORT = 1 << 11, - TILESTATE_MAGICFIELD = 1 << 12, - TILESTATE_MAILBOX = 1 << 13, - TILESTATE_TRASHHOLDER = 1 << 14, - TILESTATE_BED = 1 << 15, - TILESTATE_DEPOT = 1 << 16, - TILESTATE_BLOCKSOLID = 1 << 17, - TILESTATE_BLOCKPATH = 1 << 18, - TILESTATE_IMMOVABLEBLOCKSOLID = 1 << 19, - TILESTATE_IMMOVABLEBLOCKPATH = 1 << 20, - TILESTATE_IMMOVABLENOFIELDBLOCKPATH = 1 << 21, - TILESTATE_NOFIELDBLOCKPATH = 1 << 22, - TILESTATE_SUPPORTS_HANGABLE = 1 << 23, - - TILESTATE_FLOORCHANGE = TILESTATE_FLOORCHANGE_DOWN | TILESTATE_FLOORCHANGE_NORTH | TILESTATE_FLOORCHANGE_SOUTH | TILESTATE_FLOORCHANGE_EAST | TILESTATE_FLOORCHANGE_WEST | TILESTATE_FLOORCHANGE_SOUTH_ALT | TILESTATE_FLOORCHANGE_EAST_ALT, -}; - -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; - - inline bool hasFlag(uint32_t flag) const { - return hasBitSet(flag, this->flags); - } - inline void setFlag(uint32_t flag) { - this->flags |= flag; - } - inline void resetFlag(uint32_t flag) { - this->flags &= ~flag; - } - - 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 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), - 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) -{ -} - -inline DynamicTile::~DynamicTile() -{ - for (Item* item : items) { - item->decrementReferenceCounter(); - } -} - -#endif diff --git a/path_8_0/src/tools.cpp b/path_8_0/src/tools.cpp deleted file mode 100644 index feee45974..000000000 --- a/path_8_0/src/tools.cpp +++ /dev/null @@ -1,1128 +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; -} - -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); - } - - int32_t increment; - const int32_t diff = maxNumber - minNumber; - const float v = normalRand(getRandomGenerator()); - if (v < 0.0) { - increment = diff / 2; - } else if (v > 1.0) { - increment = (diff + 1) / 2; - } else { - increment = round(v * diff); - } - return minNumber + increment; -} - -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}, -}; - -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}, -}; - -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}, -}; - -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"; - } -} - -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_8_0/src/tools.h b/path_8_0/src/tools.h deleted file mode 100644 index c28afd2db..000000000 --- a/path_8_0/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); -inline bool hasBitSet(uint32_t flag, uint32_t flags) { - return (flags & flag) != 0; -} - -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); - -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_8_0/src/town.h b/path_8_0/src/town.h deleted file mode 100644 index 3d9b34acd..000000000 --- a/path_8_0/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_8_0/src/trashholder.cpp b/path_8_0/src/trashholder.cpp deleted file mode 100644 index 7b688c102..000000000 --- a/path_8_0/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_8_0/src/trashholder.h b/path_8_0/src/trashholder.h deleted file mode 100644 index 45a7cbc96..000000000 --- a/path_8_0/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_8_0/src/vocation.cpp b/path_8_0/src/vocation.cpp deleted file mode 100644 index ca575c8c7..000000000 --- a/path_8_0/src/vocation.cpp +++ /dev/null @@ -1,252 +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()); - } - - if ((attr = vocationNode.attribute("lessloss"))) { - voc.lessLoss = 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_8_0/src/vocation.h b/path_8_0/src/vocation.h deleted file mode 100644 index b7fd7407b..000000000 --- a/path_8_0/src/vocation.h +++ /dev/null @@ -1,141 +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; - } - - uint32_t getLessLoss() const { - return lessLoss; - } - - 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; - float lessLoss; - - 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_8_0/src/waitlist.cpp b/path_8_0/src/waitlist.cpp deleted file mode 100644 index 48cb94f8e..000000000 --- a/path_8_0/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_8_0/src/waitlist.h b/path_8_0/src/waitlist.h deleted file mode 100644 index 9b7fe02e6..000000000 --- a/path_8_0/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_8_0/src/weapons.cpp b/path_8_0/src/weapons.cpp deleted file mode 100644 index a3e25f149..000000000 --- a/path_8_0/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(): - scriptInterface("Weapon Interface") -{ - 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(); - - scriptInterface.reInitState(); -} - -LuaScriptInterface& Weapons::getScriptInterface() -{ - return 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(&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(&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(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "distance") == 0) { - return new WeaponDistance(&scriptInterface); - } else if (strcasecmp(nodeName.c_str(), "wand") == 0) { - return new WeaponWand(&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) -{ - 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 (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 (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) { - Weapon::decrementItemCount(item); - return; - } - - switch (action) { - case WEAPONACTION_REMOVECOUNT: - Weapon::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 (!scriptInterface->reserveScriptEnv()) { - std::cout << "[Error - Weapon::executeUseWeapon] Call stack overflow" << std::endl; - return false; - } - - ScriptEnvironment* env = scriptInterface->getScriptEnv(); - env->setScriptId(scriptId, scriptInterface); - - lua_State* L = scriptInterface->getLuaState(); - - scriptInterface->pushFunction(scriptId); - LuaScriptInterface::pushUserdata(L, player); - LuaScriptInterface::setMetatable(L, -1, "Player"); - scriptInterface->pushVariant(L, var); - - return scriptInterface->callFunction(2); -} - -void Weapon::decrementItemCount(Item* item) -{ - 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->hasFlag(TILESTATE_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_8_0/src/weapons.h b/path_8_0/src/weapons.h deleted file mode 100644 index 67172f05c..000000000 --- a/path_8_0/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 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: - static void decrementItemCount(Item* item); - - 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_8_0/src/wildcardtree.cpp b/path_8_0/src/wildcardtree.cpp deleted file mode 100644 index 542da0669..000000000 --- a/path_8_0/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_8_0/src/wildcardtree.h b/path_8_0/src/wildcardtree.h deleted file mode 100644 index ed8eaddce..000000000 --- a/path_8_0/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_8_0/vc14/TheForgottenServer.rc b/path_8_0/vc14/TheForgottenServer.rc deleted file mode 100644 index 5147602ee..000000000 --- a/path_8_0/vc14/TheForgottenServer.rc +++ /dev/null @@ -1 +0,0 @@ -MAINICON ICON "TheForgottenServer.ico" \ No newline at end of file diff --git a/path_8_0/vc14/arch32.props b/path_8_0/vc14/arch32.props deleted file mode 100644 index d2adc41ef..000000000 --- a/path_8_0/vc14/arch32.props +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - $(TFS_LIBS) - true - - - - \ No newline at end of file diff --git a/path_8_0/vc14/arch64.props b/path_8_0/vc14/arch64.props deleted file mode 100644 index 6c086a54a..000000000 --- a/path_8_0/vc14/arch64.props +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - $(TFS_LIBS64) - - - - \ No newline at end of file diff --git a/path_8_0/vc14/debug.props b/path_8_0/vc14/debug.props deleted file mode 100644 index ab4fb7de3..000000000 --- a/path_8_0/vc14/debug.props +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - true - - - - false - false - EnableFastChecks - MultiThreadedDebugDLL - $(IntDir)\obj_d\ - - - $(TFS_LIBDEPS_D) - - - - - diff --git a/path_8_0/vc14/release.props b/path_8_0/vc14/release.props deleted file mode 100644 index 1a6520d97..000000000 --- a/path_8_0/vc14/release.props +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - false - - - - Full - $(IntDir)\obj_r\ - - - UseLinkTimeCodeGeneration - - - - - diff --git a/path_8_0/vc14/settings.props b/path_8_0/vc14/settings.props deleted file mode 100644 index b7fc74a9a..000000000 --- a/path_8_0/vc14/settings.props +++ /dev/null @@ -1,74 +0,0 @@ - - - - - $(TFSSDKDir)\LuaJIT\ - $(TFSSDKDir)\mpir\ - $(TFSSDKDir)\mysql-connector-c\ - $(TFSSDKDir)\pugixml\ - _CRT_SECURE_NO_WARNINGS; - $(BOOST_ROOT);$(LUA_DIR)\include;$(GMP_DIR)\include;$(MYSQLC_DIR)\include;$(PUGIXML_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_8_0/vc14/theforgottenserver.ico b/path_8_0/vc14/theforgottenserver.ico deleted file mode 100644 index 78af5e576..000000000 Binary files a/path_8_0/vc14/theforgottenserver.ico and /dev/null differ diff --git a/path_8_0/vc14/theforgottenserver.sln b/path_8_0/vc14/theforgottenserver.sln deleted file mode 100644 index 4c37956c6..000000000 --- a/path_8_0/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_8_0/vc14/theforgottenserver.vcxproj b/path_8_0/vc14/theforgottenserver.vcxproj deleted file mode 100644 index b84cefa8b..000000000 --- a/path_8_0/vc14/theforgottenserver.vcxproj +++ /dev/null @@ -1,294 +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_8_6/data/world/forgotten-spawn.xml b/path_8_6/data/world/forgotten-spawn.xml index d431dcd87..5b1d35f36 100644 --- a/path_8_6/data/world/forgotten-spawn.xml +++ b/path_8_6/data/world/forgotten-spawn.xml @@ -1307,7 +1307,7 @@ - + diff --git a/path_8_6/src/definitions.h b/path_8_6/src/definitions.h index 9a1dcc656..10c7436c9 100644 --- a/path_8_6/src/definitions.h +++ b/path_8_6/src/definitions.h @@ -23,7 +23,7 @@ #define STATUS_SERVER_NAME "OTX Server" #define STATUS_SERVER_VERSION "3" #define MINOR_VERSION "4" -#define REVISION_VERSION "-" +#define REVISION_VERSION "612" #define SOFTWARE_CODENAME "LORD ZEDD" #define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" #define GIT_REPO "https://github.com/mattyx14/otxserver/" diff --git a/path_8_7/data/world/forgotten-spawn.xml b/path_8_7/data/world/forgotten-spawn.xml index d431dcd87..5b1d35f36 100644 --- a/path_8_7/data/world/forgotten-spawn.xml +++ b/path_8_7/data/world/forgotten-spawn.xml @@ -1307,7 +1307,7 @@ - + diff --git a/path_8_7/src/definitions.h b/path_8_7/src/definitions.h index f73112dc9..c7e0ad0c4 100644 --- a/path_8_7/src/definitions.h +++ b/path_8_7/src/definitions.h @@ -23,7 +23,7 @@ #define STATUS_SERVER_NAME "OTX Server" #define STATUS_SERVER_VERSION "3" #define MINOR_VERSION "4" -#define REVISION_VERSION "-" +#define REVISION_VERSION "612" #define SOFTWARE_CODENAME "LORD ZEDD" #define STATUS_SERVER_DEVELOPERS "Mattyx14 and TFS Developers" #define GIT_REPO "https://github.com/mattyx14/otxserver/"