Merge fixes

This commit is contained in:
KimLS 2019-08-24 23:39:31 -07:00
commit 307923598b
132 changed files with 8355 additions and 4964 deletions

View File

@ -1,42 +1,24 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.10) CMAKE_MINIMUM_REQUIRED(VERSION 3.10)
IF(POLICY CMP0074)
cmake_policy(SET CMP0074 NEW)
ENDIF()
#FindMySQL is located here so lets make it so CMake can find it
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH}) SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/" ${CMAKE_MODULE_PATH})
#Our project name is EQEmu
PROJECT(EQEmu) PROJECT(EQEmu)
#Default build type is set to RelWithDebInfo for generators that honor that like makefiles
IF(NOT CMAKE_BUILD_TYPE) IF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE) SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Choose the type of build." FORCE)
ENDIF(NOT CMAKE_BUILD_TYPE) ENDIF(NOT CMAKE_BUILD_TYPE)
SET(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/dependencies" "${CMAKE_PREFIX_PATH}")
SET(CMAKE_CXX_STANDARD 14) SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_CXX_STANDARD_REQUIRED ON) SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_EXTENSIONS OFF) SET(CMAKE_CXX_EXTENSIONS OFF)
IF(MSVC) IF(MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
#crash logging currently only works on windows x86/x64
OPTION(EQEMU_ENABLE_CRASH_LOGGING "Enable crash logging" ON)
IF(EQEMU_ENABLE_CRASH_LOGGING)
ADD_DEFINITIONS(-DCRASH_LOGGING)
ENDIF(EQEMU_ENABLE_CRASH_LOGGING)
OPTION(EQEMU_BUILD_MSVC_MP "Enable build with multiple processes." ON)
IF(EQEMU_BUILD_MSVC_MP)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
ENDIF(EQEMU_BUILD_MSVC_MP)
ADD_DEFINITIONS(-DNOMINMAX) ADD_DEFINITIONS(-DNOMINMAX)
ADD_DEFINITIONS(-DCRASH_LOGGING)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
ELSE(MSVC) ELSE(MSVC)
#Normally set by perl but we don't use the perl flags anymore so we set it.
ADD_DEFINITIONS(-DHAS_UNION_SEMUN) ADD_DEFINITIONS(-DHAS_UNION_SEMUN)
ENDIF(MSVC) ENDIF(MSVC)
@ -53,35 +35,13 @@ IF(UNIX)
ENDIF(CMAKE_SYSTEM_NAME MATCHES "Darwin") ENDIF(CMAKE_SYSTEM_NAME MATCHES "Darwin")
ENDIF(UNIX) ENDIF(UNIX)
#NPC Types Cache Behavior
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
#Bots are a compile time option so on/off
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
#Enable GM Command log system
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS)
ENDIF(EQEMU_ENABLE_BOTS)
#What to build
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_HC "Build the headless client." OFF)
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) ADD_DEFINITIONS(-DGLM_FORCE_RADIANS)
ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT) ADD_DEFINITIONS(-DGLM_FORCE_CTOR_INIT)
ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL) ADD_DEFINITIONS(-DGLM_ENABLE_EXPERIMENTAL)
#Find everything we need #Find everything we need
FIND_PACKAGE(MySQL REQUIRED) FIND_PACKAGE(MySQL)
FIND_PACKAGE(MariaDB)
FIND_PACKAGE(Boost REQUIRED) FIND_PACKAGE(Boost REQUIRED)
FIND_PACKAGE(ZLIB) FIND_PACKAGE(ZLIB)
FIND_PACKAGE(OpenSSL) FIND_PACKAGE(OpenSSL)
@ -94,18 +54,24 @@ MESSAGE(STATUS "**************************************************")
MESSAGE(STATUS "* Library Detection *") MESSAGE(STATUS "* Library Detection *")
MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "**************************************************")
IF(MYSQL_FOUND)
MESSAGE(STATUS "* MySQL: FOUND *")
ELSE()
MESSAGE(STATUS "* MySQL: MISSING *")
ENDIF()
IF(MARIADB_FOUND)
MESSAGE(STATUS "* MariaDB: FOUND *")
ELSE()
MESSAGE(STATUS "* MariaDB: MISSING *")
ENDIF()
IF(ZLIB_FOUND) IF(ZLIB_FOUND)
MESSAGE(STATUS "* ZLIB: FOUND *") MESSAGE(STATUS "* ZLIB: FOUND *")
ELSE() ELSE()
MESSAGE(STATUS "* ZLIB: MISSING *") MESSAGE(STATUS "* ZLIB: MISSING *")
ENDIF() ENDIF()
IF(OpenSSL_FOUND)
MESSAGE(STATUS "* OpenSSL: FOUND *")
ELSE()
MESSAGE(STATUS "* OpenSSL: MISSING *")
ENDIF()
IF(Lua51_FOUND) IF(Lua51_FOUND)
MESSAGE(STATUS "* Lua: FOUND *") MESSAGE(STATUS "* Lua: FOUND *")
ELSE() ELSE()
@ -124,6 +90,12 @@ ELSE()
MESSAGE(STATUS "* libsodium: MISSING *") MESSAGE(STATUS "* libsodium: MISSING *")
ENDIF() ENDIF()
IF(OpenSSL_FOUND)
MESSAGE(STATUS "* OpenSSL: FOUND *")
ELSE()
MESSAGE(STATUS "* OpenSSL: MISSING *")
ENDIF()
IF(MBEDTLS_FOUND) IF(MBEDTLS_FOUND)
MESSAGE(STATUS "* mbedTLS: FOUND *") MESSAGE(STATUS "* mbedTLS: FOUND *")
ELSE() ELSE()
@ -132,7 +104,171 @@ ENDIF()
MESSAGE(STATUS "**************************************************") MESSAGE(STATUS "**************************************************")
SET(SERVER_LIBS common debug ${MySQL_LIBRARY_DEBUG} optimized ${MySQL_LIBRARY_RELEASE} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour) #options
OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON)
OPTION(EQEMU_ENABLE_BOTS "Enable Bots" OFF)
OPTION(EQEMU_COMMANDS_LOGGING "Enable GM Command logs" ON)
OPTION(EQEMU_BUILD_SERVER "Build the game server." ON)
OPTION(EQEMU_BUILD_HC "Build the headless client." OFF)
OPTION(EQEMU_BUILD_TESTS "Build utility tests." OFF)
OPTION(EQEMU_BUILD_CLIENT_FILES "Build Client Import/Export Data Programs." ON)
IF(EQEMU_COMMANDS_LOGGING)
ADD_DEFINITIONS(-DCOMMANDS_LOGGING)
ENDIF(EQEMU_COMMANDS_LOGGING)
IF(EQEMU_ENABLE_BOTS)
ADD_DEFINITIONS(-DBOTS)
ENDIF(EQEMU_ENABLE_BOTS)
#database
#prefer mariadb to mysql (arbitrary)
IF(MySQL_FOUND AND MariaDB_FOUND)
SET(DATABASE_LIBRARY_TYPE "MariaDB")
SET(DATABASE_LIBRARY_LIBS ${MariaDB_LIBRARIES})
SET(DATABASE_LIBRARY_INCLUDE ${MariaDB_INCLUDE_DIR})
ELSEIF(MariaDB_FOUND)
SET(DATABASE_LIBRARY_TYPE "MariaDB")
SET(DATABASE_LIBRARY_LIBS ${MariaDB_LIBRARIES})
SET(DATABASE_LIBRARY_INCLUDE ${MariaDB_INCLUDE_DIR})
ELSEIF(MySQL_FOUND)
SET(DATABASE_LIBRARY_TYPE " MySQL")
SET(DATABASE_LIBRARY_LIBS ${MySQL_LIBRARIES})
SET(DATABASE_LIBRARY_INCLUDE ${MySQL_INCLUDE_DIR})
ELSE()
MESSAGE(FATAL_ERROR "One of MySQL or MariaDB is a required dependency.")
ENDIF()
#security
#prefer openssl to mbedtls (arbitrary)
IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
SET(SSL_LIBRARY_TYPE " OpenSSL")
SET(SSL_LIBRARY_ENABLED ON)
SET(SSL_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
SET(SSL_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
ELSEIF(OpenSSL_FOUND)
SET(SSL_LIBRARY_TYPE " OpenSSL")
SET(SSL_LIBRARY_ENABLED ON)
SET(SSL_LIBRARY_LIBS ${OPENSSL_LIBRARIES})
SET(SSL_LIBRARY_INCLUDE ${OPENSSL_INCLUDE_DIR})
ELSEIF(MBEDTLS_FOUND)
SET(SSL_LIBRARY_TYPE " mbedTLS")
SET(SSL_LIBRARY_ENABLED ON)
SET(SSL_LIBRARY_LIBS ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
SET(SSL_LIBRARY_INCLUDE ${MBEDTLS_INCLUDE_DIR})
ELSE()
SET(SSL_LIBRARY_TYPE "Disabled")
SET(SSL_LIBRARY_ENABLED OFF)
ENDIF()
IF(SODIUM_FOUND)
SET(SODIUM_LIBRARY_TYPE "Libsodium")
SET(SODIUM_LIBRARY_ENABLED ON)
SET(SODIUM_LIBRARY_LIBS ${SODIUM_LIBRARIES})
SET(SODIUM_LIBRARY_INCLUDE ${SODIUM_INCLUDE_DIRS})
ADD_DEFINITIONS(-DENABLE_SECURITY)
ELSE()
SET(SODIUM_LIBRARY_TYPE " Disabled")
SET(SODIUM_LIBRARY_ENABLED OFF)
ENDIF()
IF(Lua51_FOUND)
SET(LUA_LIBRARY_TYPE " Lua 5.1")
SET(LUA_LIBRARY_LIBS ${LUA_LIBRARY} luabind)
SET(LUA_LIBRARY_INCLUDE ${LUA_INCLUDE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind")
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
IF(EQEMU_BUILD_LUA)
ADD_DEFINITIONS(-DLUA_EQEMU)
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
ENDIF()
ENDIF()
ELSE()
SET(LUA_LIBRARY_TYPE "Disabled")
ENDIF()
IF(PerlLibs_FOUND)
SET(PERL_LIBRARY_TYPE " Perl")
SET(PERL_LIBRARY_LIBS ${PERL_LIBRARY})
SET(PERL_LIBRARY_INCLUDE ${PERL_INCLUDE_PATH})
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL)
ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
ENDIF()
ELSE()
SET(PERL_LIBRARY_TYPE "Disabled")
ENDIF()
#use zlib if exists
IF(ZLIB_FOUND)
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF)
IF(EQEMU_BUILD_ZLIB)
SET(ZLIB_LIBRARY_TYPE "zlib-ng")
SET(ZLIB_LIBRARY_LIBS "zlibstatic")
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/submodules/zlibng")
ELSE()
SET(ZLIB_LIBRARY_TYPE " zlib")
SET(ZLIB_LIBRARY_LIBS ${ZLIB_LIBRARY})
SET(ZLIB_LIBRARY_INCLUDE ${ZLIB_INCLUDE_DIRS})
ENDIF()
ELSE()
SET(ZLIB_LIBRARY_TYPE "zlib-ng")
SET(ZLIB_LIBRARY_LIBS "zlibstatic")
SET(ZLIB_LIBRARY_INCLUDE "${CMAKE_CURRENT_SOURCE_DIR}/submodules/zlibng")
ENDIF()
MESSAGE(STATUS "")
MESSAGE(STATUS "**************************************************")
MESSAGE(STATUS "* Library Usage *")
MESSAGE(STATUS "**************************************************")
MESSAGE(STATUS "* Database: ${DATABASE_LIBRARY_TYPE} *")
MESSAGE(STATUS "* TLS: ${SSL_LIBRARY_TYPE} *")
MESSAGE(STATUS "* Sodium: ${SODIUM_LIBRARY_TYPE} *")
MESSAGE(STATUS "* Lua: ${LUA_LIBRARY_TYPE} *")
MESSAGE(STATUS "* Perl: ${PERL_LIBRARY_TYPE} *")
MESSAGE(STATUS "* zlib: ${ZLIB_LIBRARY_TYPE} *")
MESSAGE(STATUS "**************************************************")
#setup server libs and headers
SET(SERVER_LIBS common ${DATABASE_LIBRARY_LIBS} ${ZLIB_LIBRARY_LIBS} ${Boost_LIBRARIES} uv_a fmt RecastNavigation::Detour)
INCLUDE_DIRECTORIES(SYSTEM "${DATABASE_LIBRARY_INCLUDE}")
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_LIBRARY_INCLUDE}")
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Detour/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
IF(SSL_LIBRARY_ENABLED)
SET(SERVER_LIBS ${SERVER_LIBS} ${SSL_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${SSL_LIBRARY_INCLUDE}")
ENDIF()
IF(SODIUM_LIBRARY_ENABLED)
SET(SERVER_LIBS ${SERVER_LIBS} ${SODIUM_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_LIBRARY_INCLUDE}")
ENDIF()
IF(EQEMU_BUILD_LUA)
SET(SERVER_LIBS ${SERVER_LIBS} ${LUA_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${LUA_LIBRARY_INCLUDE}")
ENDIF()
IF(EQEMU_BUILD_PERL)
SET(SERVER_LIBS ${SERVER_LIBS} ${PERL_LIBRARY_LIBS})
INCLUDE_DIRECTORIES(SYSTEM "${PERL_LIBRARY_INCLUDE}")
ENDIF()
IF(WIN32) IF(WIN32)
SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv") SET(SERVER_LIBS ${SERVER_LIBS} "ws2_32" "psapi" "iphlpapi" "userenv")
@ -146,101 +282,10 @@ IF(UNIX)
SET(SERVER_LIBS ${SERVER_LIBS} "uuid") SET(SERVER_LIBS ${SERVER_LIBS} "uuid")
ENDIF() ENDIF()
IF(ZLIB_FOUND) IF(EQEMU_BUILD_LOGIN AND NOT SSL_LIBRARY_ENABLED)
OPTION(EQEMU_BUILD_ZLIB "Build internal version of zlib." OFF) MESSAGE(FATAL_ERROR "Login server requires a SSL Library to build.")
IF(EQEMU_BUILD_ZLIB)
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/zlibng")
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
ELSE()
INCLUDE_DIRECTORIES(SYSTEM "${ZLIB_INCLUDE_DIRS}")
SET(SERVER_LIBS ${SERVER_LIBS} ${ZLIB_LIBRARY})
ENDIF()
ELSE()
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/zlibng")
SET(SERVER_LIBS ${SERVER_LIBS} "zlibstatic")
ENDIF() ENDIF()
IF(PerlLibs_FOUND)
OPTION(EQEMU_BUILD_PERL "Build Perl parser." ON)
IF(EQEMU_BUILD_PERL)
INCLUDE_DIRECTORIES(SYSTEM "${PERL_INCLUDE_PATH}")
SET(SERVER_LIBS ${SERVER_LIBS} "${PERL_LIBRARY}")
ADD_DEFINITIONS(-DEMBPERL)
ADD_DEFINITIONS(-DEMBPERL_PLUGIN)
ENDIF(EQEMU_BUILD_PERL)
ENDIF()
IF(Lua51_FOUND)
OPTION(EQEMU_BUILD_LUA "Build Lua parser." ON)
IF(EQEMU_BUILD_LUA)
INCLUDE_DIRECTORIES(SYSTEM "${LUA_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/libs/luabind")
SET(SERVER_LIBS ${SERVER_LIBS} "${LUA_LIBRARY}" luabind)
ADD_DEFINITIONS(-DLUA_EQEMU)
OPTION(EQEMU_SANITIZE_LUA_LIBS "Sanitize Lua Libraries (Remove OS and IO standard libraries from being able to run)." ON)
IF(EQEMU_SANITIZE_LUA_LIBS)
ADD_DEFINITIONS(-DSANITIZE_LUA_LIBS)
ENDIF(EQEMU_SANITIZE_LUA_LIBS)
ENDIF(EQEMU_BUILD_LUA)
ENDIF()
IF(OpenSSL_FOUND OR MBEDTLS_FOUND)
OPTION(EQEMU_BUILD_LOGIN "Build the login server." ON)
IF(OpenSSL_FOUND AND MBEDTLS_FOUND)
SET(EQEMU_CRYPTO_LIB mbedTLS CACHE STRING "Crypto library to use:
OpenSSL
mbedTLS"
)
IF(EQEMU_CRYPTO_LIB STREQUAL "OpenSSL")
INCLUDE_DIRECTORIES(SYSTEM "${OPENSSL_INCLUDE_DIR}")
SET(SERVER_LIBS ${SERVER_LIBS} ${OPENSSL_LIBRARIES})
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
ELSEIF(EQEMU_CRYPTO_LIB STREQUAL "mbedTLS")
INCLUDE_DIRECTORIES(SYSTEM "${MBEDTLS_INCLUDE_DIR}")
SET(SERVER_LIBS ${SERVER_LIBS} ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS)
ELSE()
MESSAGE(FATAL_ERROR "Unknown crypto library set, must be one of these: mbedTLS, OpenSSL")
ENDIF()
ELSEIF(OpenSSL_FOUND)
INCLUDE_DIRECTORIES(SYSTEM "${OPENSSL_INCLUDE_DIR}")
SET(SERVER_LIBS ${SERVER_LIBS} ${OPENSSL_LIBRARIES})
ADD_DEFINITIONS(-DEQEMU_USE_OPENSSL)
ELSEIF(MBEDTLS_FOUND)
INCLUDE_DIRECTORIES(SYSTEM "${MBEDTLS_INCLUDE_DIR}")
SET(SERVER_LIBS ${SERVER_LIBS} ${MBEDTLS_LIBRARY} ${MBEDX509_LIBRARY} ${MBEDCRYPTO_LIBRARY})
ADD_DEFINITIONS(-DEQEMU_USE_MBEDTLS)
ENDIF()
ENDIF()
IF(SODIUM_FOUND AND EQEMU_BUILD_LOGIN)
OPTION(EQEMU_ENABLE_SECURITY "Use libsodium for stronger password hashing" ON)
IF(EQEMU_ENABLE_SECURITY)
INCLUDE_DIRECTORIES(SYSTEM "${SODIUM_INCLUDE_DIRS}")
SET(SERVER_LIBS ${SERVER_LIBS} ${SODIUM_LIBRARIES})
ADD_DEFINITIONS(-DENABLE_SECURITY)
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(SYSTEM "${MySQL_INCLUDE_DIR}")
INCLUDE_DIRECTORIES(SYSTEM "${Boost_INCLUDE_DIRS}")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/glm")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/cereal/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/fmt/include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/libuv/include" )
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DebugUtils/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Detour/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourCrowd/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/DetourTileCache/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/recastnavigation/Recast/Include")
INCLUDE_DIRECTORIES(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/submodules/websocketpp")
IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
ADD_SUBDIRECTORY(common) ADD_SUBDIRECTORY(common)
ADD_SUBDIRECTORY(libs) ADD_SUBDIRECTORY(libs)
@ -258,6 +303,9 @@ IF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_H
SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples") SET(RECASTNAVIGATION_EXAMPLES OFF CACHE BOOL "Build examples")
ADD_SUBDIRECTORY(submodules/recastnavigation) ADD_SUBDIRECTORY(submodules/recastnavigation)
ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC) ENDIF(EQEMU_BUILD_SERVER OR EQEMU_BUILD_LOGIN OR EQEMU_BUILD_TESTS OR EQEMU_BUILD_HC)
MESSAGE(STATUS "Libs: ${SERVER_LIBS}")
IF(EQEMU_BUILD_SERVER) IF(EQEMU_BUILD_SERVER)
ADD_SUBDIRECTORY(shared_memory) ADD_SUBDIRECTORY(shared_memory)
ADD_SUBDIRECTORY(world) ADD_SUBDIRECTORY(world)
@ -266,6 +314,7 @@ IF(EQEMU_BUILD_SERVER)
ADD_SUBDIRECTORY(queryserv) ADD_SUBDIRECTORY(queryserv)
ADD_SUBDIRECTORY(eqlaunch) ADD_SUBDIRECTORY(eqlaunch)
ENDIF(EQEMU_BUILD_SERVER) ENDIF(EQEMU_BUILD_SERVER)
IF(EQEMU_BUILD_LOGIN) IF(EQEMU_BUILD_LOGIN)
ADD_SUBDIRECTORY(loginserver) ADD_SUBDIRECTORY(loginserver)
ENDIF(EQEMU_BUILD_LOGIN) ENDIF(EQEMU_BUILD_LOGIN)

View File

@ -70,3 +70,9 @@ forum, although pull requests will be much quicker and easier on all parties.
* GPL Perl - GPL / ActiveState (under the assumption that this is a free project) * GPL Perl - GPL / ActiveState (under the assumption that this is a free project)
* CPPUnit - GLP StringUtilities - Apache * CPPUnit - GLP StringUtilities - Apache
* LUA - MIT * LUA - MIT
## Contributors
<a href="https://github.com/EQEmu/server/graphs/contributors">
<img src="https://contributors-img.firebaseapp.com/image?repo=EQEmu/server" />
</a>

3
SECURITY.md Normal file
View File

@ -0,0 +1,3 @@
# Security Policy - Reporting Vulnerabilities
When reporting active hacks, exploits and other vulnerabilities, please describe how to reproduce said report and if you can provide context into a possible solution

View File

@ -1,5 +1,26 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 8/16/2019 ==
Akkadius: Simplified the use of roamboxes and improved the AI for roambox pathing https://i.imgur.com/z33u7y9.gif
Akkadius: Implemented command #roambox set <box_size> [move_delay]
Akkadius: Implemented command #roambox remove
Akkadius: Implemented LUA NPC:SetSimpleRoamBox(box_size, [move_distance], [move_delay]);
Akkadius: Implemented Perl $npc->SetSimpleRoamBox(box_size, [move_distance], [move_delay]);
Akkadius: Spawngroup data now hot reloads on #repop
Akkadius: Command #npceditmass now lists column options when one isn't properly specified
Akkadius: Implemented command #spawneditmass <search> <option> <value> with options [respawn_time] currently implemented
== 8/11/2019 ==
Akkadius: Added bulk edit command #npceditmass <column-to-search> <column-search-value> <change-column> <change-value>
Akkadius: Modified #findzone to include clickable saylinks to both regular zone (if able) and private gmzone instances
Akkadius: Added #findzone expansion <expansion-number> to show zones via expansion
== 8/6/2019 ==
Akkadius: Optimizations to movement updates to eliminate ghosting possibilities in larger zones
== 7/22/2019 ==
Uleat: Added script 'vcxproj_dependencies.py' - a script to help determine conflicting project dependencies (alpha-stage)
== 7/10/2019 == == 7/10/2019 ==
Akkadius: Add #npcedit flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating] Akkadius: Add #npcedit flymode [0 = ground, 1 = flying, 2 = levitate, 3 = water, 4 = floating]

87
cmake/FindMariaDB.cmake Normal file
View File

@ -0,0 +1,87 @@
# - Find mariadbclient
#
# -*- cmake -*-
#
# Find the native MariaDB includes and library
#
# MariaDB_INCLUDE_DIR - where to find mysql.h, etc.
# MariaDB_LIBRARIES - List of libraries when using MariaDB.
# MariaDB_FOUND - True if MariaDB found.
# The following can be used as a hint as to where to search:
# MARIADB_ROOT
IF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARIES)
# Already in cache, be silent
SET(MariaDB_FIND_QUIETLY TRUE)
ENDIF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARIES)
# Include dir
IF(MARIADB_ROOT)
FIND_PATH(MariaDB_INCLUDE_DIR
NAMES mariadb_version.h
PATHS ${MARIADB_ROOT}/include
PATH_SUFFIXES mysql mariadb
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_PATH(MariaDB_INCLUDE_DIR
NAMES mariadb_version.h
PATH_SUFFIXES mysql mariadb
)
ELSE(MARIADB_ROOT)
FIND_PATH(MariaDB_INCLUDE_DIR
NAMES mariadb_version.h
PATH_SUFFIXES mysql mariadb
)
ENDIF(MARIADB_ROOT)
# Library
SET(MariaDB_NAMES libmariadb)
IF(MARIADB_ROOT)
FIND_LIBRARY(MariaDB_LIBRARY
NAMES ${MariaDB_NAMES}
PATHS ${MARIADB_ROOT}/lib
PATH_SUFFIXES mysql mariadb
NO_DEFAULT_PATH
NO_SYSTEM_ENVIRONMENT_PATH
)
FIND_LIBRARY(MariaDB_LIBRARY
NAMES ${MariaDB_NAMES}
PATH_SUFFIXES mysql mariadb
)
ELSE(MARIADB_ROOT)
FIND_LIBRARY(MariaDB_LIBRARY
NAMES ${MariaDB_NAMES} mariadbclient_r mariadbclient
PATHS /usr/lib /usr/local/lib /usr/lib64 /usr/local/lib64
PATH_SUFFIXES mysql mariadb
)
ENDIF(MARIADB_ROOT)
IF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY)
SET(MariaDB_FOUND TRUE)
SET(MariaDB_LIBRARIES ${MariaDB_LIBRARY})
ELSE (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY)
SET(MariaDB_FOUND FALSE)
SET(MariaDB_LIBRARIES)
ENDIF (MariaDB_INCLUDE_DIR AND MariaDB_LIBRARY)
# handle the QUIETLY and REQUIRED arguments and set MariaDB_FOUND to TRUE if
# all listed variables are TRUE
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(MariaDB DEFAULT_MSG MariaDB_LIBRARY MariaDB_INCLUDE_DIR)
IF(MariaDB_FOUND)
SET( MariaDB_LIBRARY_RELEASE ${MariaDB_LIBRARY} )
SET( MariaDB_LIBRARY_DEBUG ${MariaDB_LIBRARY} )
SET( MariaDB_LIBRARIES ${MariaDB_LIBRARY_RELEASE} ${MariaDB_LIBRARY_DEBUG} )
ELSE(MariaDB_FOUND)
SET( MariaDB_LIBRARIES )
ENDIF(MariaDB_FOUND)
MARK_AS_ADVANCED(
MariaDB_LIBRARY_DEBUG
MariaDB_LIBRARY_RELEASE
MariaDB_INCLUDE_DIR
)

View File

@ -75,6 +75,7 @@ public:
uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; } uint32 ReadUInt32() { uint32 value = *(uint32 *)(pBuffer + _rpos); _rpos += sizeof(uint32); return value; }
uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; } uint32 ReadUInt32(uint32 Offset) const { uint32 value = *(uint32 *)(pBuffer + Offset); return value; }
void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; } void ReadString(char *str) { uint32 len = static_cast<uint32>(strlen((char *)(pBuffer + _rpos))) + 1; memcpy(str, pBuffer + _rpos, len); _rpos += len; }
void ReadString(std::string &str) { str = reinterpret_cast<char *>(pBuffer + _rpos); _rpos += str.length() + 1; }
void ReadString(char *str, uint32 Offset, uint32 MaxLength) const; void ReadString(char *str, uint32 Offset, uint32 MaxLength) const;
uint32 GetWritePosition() { return _wpos; } uint32 GetWritePosition() { return _wpos; }

View File

@ -84,6 +84,8 @@ struct VarCache_Struct {
class PTimerList; class PTimerList;
# define _ISNAN_(a) std::isnan(a) # define _ISNAN_(a) std::isnan(a)
#define SQL(...) #__VA_ARGS__
class Database : public DBcore { class Database : public DBcore {
public: public:
Database(); Database();

View File

@ -476,7 +476,7 @@ bool Database::CheckDatabaseConversions() {
CheckDatabaseConvertCorpseDeblob(); CheckDatabaseConvertCorpseDeblob();
/* Run EQEmu Server script (Checks for database updates) */ /* Run EQEmu Server script (Checks for database updates) */
system("perl eqemu_server.pl ran_from_world"); if(system("perl eqemu_server.pl ran_from_world"));
return true; return true;
} }

View File

@ -77,6 +77,10 @@ namespace EQEmu
} // namespace invtype } // namespace invtype
namespace DevTools {
const int32 GM_ACCOUNT_STATUS_LEVEL = 150;
}
namespace popupresponse { namespace popupresponse {
const int32 SERVER_INTERNAL_USE_BASE = 2000000000; const int32 SERVER_INTERNAL_USE_BASE = 2000000000;
const int32 MOB_INFO_DISMISS = 2000000001; const int32 MOB_INFO_DISMISS = 2000000001;

View File

@ -71,7 +71,7 @@
//#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2) //#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)
// animations for AT_Anim // animations for AT_Anim
#define ANIM_FREEZE 102 #define ANIM_FREEZE 102
#define ANIM_STAND 0x64 #define ANIM_STAND 0x64
#define ANIM_SIT 0x6e #define ANIM_SIT 0x6e
#define ANIM_CROUCH 0x6f #define ANIM_CROUCH 0x6f
@ -87,199 +87,114 @@ typedef enum {
_eaMaxAppearance _eaMaxAppearance
} EmuAppearance; } EmuAppearance;
// msg_type's for custom usercolors namespace Chat {
#define MT_Say 256 const uint16 White = 0;
#define MT_Tell 257 const uint16 DimGray = 1;
#define MT_Group 258 const uint16 Default = 1;
#define MT_Guild 259 const uint16 Green = 2;
#define MT_OOC 260 const uint16 BrightBlue = 3;
#define MT_Auction 261 const uint16 LightBlue = 4;
#define MT_Shout 262 const uint16 Magenta = 5;
#define MT_Emote 263 const uint16 Gray = 6;
#define MT_Spells 264 const uint16 LightGray = 7;
#define MT_YouHitOther 265 const uint16 NPCQuestSay = 10;
#define MT_OtherHitsYou 266 const uint16 DarkGray = 12;
#define MT_YouMissOther 267 const uint16 Red = 13;
#define MT_OtherMissesYou 268 const uint16 Lime = 14;
#define MT_Broadcasts 269 const uint16 Yellow = 15;
#define MT_Skills 270 const uint16 Blue = 16;
#define MT_Disciplines 271 const uint16 LightNavy = 17;
#define MT_Unused1 272 const uint16 Cyan = 18;
#define MT_DefaultText 273 const uint16 Black = 20;
#define MT_Unused2 274
#define MT_MerchantOffer 275
#define MT_MerchantBuySell 276
#define MT_YourDeath 277
#define MT_OtherDeath 278
#define MT_OtherHits 279
#define MT_OtherMisses 280
#define MT_Who 281
#define MT_YellForHelp 282
#define MT_NonMelee 283
#define MT_WornOff 284
#define MT_MoneySplit 285
#define MT_LootMessages 286
#define MT_DiceRoll 287
#define MT_OtherSpells 288
#define MT_SpellFailure 289
#define MT_Chat 290
#define MT_Channel1 291
#define MT_Channel2 292
#define MT_Channel3 293
#define MT_Channel4 294
#define MT_Channel5 295
#define MT_Channel6 296
#define MT_Channel7 297
#define MT_Channel8 298
#define MT_Channel9 299
#define MT_Channel10 300
#define MT_CritMelee 301
#define MT_SpellCrits 302
#define MT_TooFarAway 303
#define MT_NPCRampage 304
#define MT_NPCFlurry 305
#define MT_NPCEnrage 306
#define MT_SayEcho 307
#define MT_TellEcho 308
#define MT_GroupEcho 309
#define MT_GuildEcho 310
#define MT_OOCEcho 311
#define MT_AuctionEcho 312
#define MT_ShoutECho 313
#define MT_EmoteEcho 314
#define MT_Chat1Echo 315
#define MT_Chat2Echo 316
#define MT_Chat3Echo 317
#define MT_Chat4Echo 318
#define MT_Chat5Echo 319
#define MT_Chat6Echo 320
#define MT_Chat7Echo 321
#define MT_Chat8Echo 322
#define MT_Chat9Echo 323
#define MT_Chat10Echo 324
#define MT_DoTDamage 325
#define MT_ItemLink 326
#define MT_RaidSay 327
#define MT_MyPet 328
#define MT_DS 329
#define MT_Leadership 330
#define MT_PetFlurry 331
#define MT_PetCrit 332
#define MT_FocusEffect 333
#define MT_Experience 334
#define MT_System 335
#define MT_PetSpell 336
#define MT_PetResponse 337
#define MT_ItemSpeech 338
#define MT_StrikeThrough 339
#define MT_Stun 340
// TODO: Really should combine above and below into one /**
* User colors
//from showeq */
enum ChatColor const uint16 Say = 256;
{ const uint16 Tell = 257;
/* const uint16 Group = 258;
CC_Default = 0, const uint16 Guild = 259;
CC_DarkGrey = 1, const uint16 OOC = 260;
CC_DarkGreen = 2, const uint16 Auction = 261;
CC_DarkBlue = 3, const uint16 Shout = 262;
CC_Purple = 5, const uint16 Emote = 263;
CC_LightGrey = 6, const uint16 Spells = 264;
*/ const uint16 YouHitOther = 265;
const uint16 OtherHitYou = 266;
CC_WhiteSmoke = 0, // FF|F0F0F0 const uint16 YouMissOther = 267;
CC_Green = 2, // FF|008000 const uint16 OtherMissYou = 268;
CC_BrightBlue = 3, // FF|0040FF const uint16 Broadcasts = 269;
CC_Magenta = 5, // FF|F000F0 const uint16 Skills = 270;
CC_Gray = 6, // FF|808080 const uint16 Disciplines = 271;
CC_LightGray = 7, // FF|E0E0E0 const uint16 Unused1 = 272;
//CC_WhiteSmoke2 = 10, // FF|F0F0F0 const uint16 DefaultText = 273;
CC_DarkGray = 12, // FF|A0A0A0 const uint16 Unused2 = 274;
CC_Red = 13, // FF|F00000 const uint16 MerchantOffer = 275;
CC_Lime = 14, // FF|00F000 const uint16 MerchantExchange = 276;
CC_Yellow = 15, // FF|F0F000 const uint16 YourDeath = 277;
CC_Blue = 16, // FF|0000F0 const uint16 OtherDeath = 278;
CC_LightNavy = 17, // FF|0000AF const uint16 OtherHitOther = 279;
CC_Cyan = 18, // FF|00F0F0 const uint16 OtherMissOther = 280;
CC_Black = 20, // FF|000000 const uint16 Who = 281;
const uint16 YellForHelp = 282;
// any index <= 255 that is not defined above const uint16 NonMelee = 283;
CC_DimGray = 1, // FF|606060 const uint16 SpellWornOff = 284;
CC_Default = 1, const uint16 MoneySplit = 285;
const uint16 Loot = 286;
CC_User_Say = 256, const uint16 DiceRoll = 287;
CC_User_Tell = 257, const uint16 OtherSpells = 288;
CC_User_Group = 258, const uint16 SpellFailure = 289;
CC_User_Guild = 259, const uint16 ChatChannel = 290;
CC_User_OOC = 260, const uint16 Chat1 = 291;
CC_User_Auction = 261, const uint16 Chat2 = 292;
CC_User_Shout = 262, const uint16 Chat3 = 293;
CC_User_Emote = 263, const uint16 Chat4 = 294;
CC_User_Spells = 264, const uint16 Chat5 = 295;
CC_User_YouHitOther = 265, const uint16 Chat6 = 296;
CC_User_OtherHitYou = 266, const uint16 Chat7 = 297;
CC_User_YouMissOther = 267, const uint16 Chat8 = 298;
CC_User_OtherMissYou = 268, const uint16 Chat9 = 299;
CC_User_Duels = 269, const uint16 Chat10 = 300;
CC_User_Skills = 270, const uint16 MeleeCrit = 301;
CC_User_Disciplines = 271, const uint16 SpellCrit = 302;
CC_User_Default = 273, const uint16 TooFarAway = 303;
CC_User_MerchantOffer = 275, const uint16 NPCRampage = 304;
CC_User_MerchantExchange = 276, const uint16 NPCFlurry = 305;
CC_User_YourDeath = 277, const uint16 NPCEnrage = 306;
CC_User_OtherDeath = 278, const uint16 EchoSay = 307;
CC_User_OtherHitOther = 279, const uint16 EchoTell = 308;
CC_User_OtherMissOther = 280, const uint16 EchoGroup = 309;
CC_User_Who = 281, const uint16 EchoGuild = 310;
CC_User_Yell = 282, const uint16 EchoOOC = 311;
CC_User_NonMelee = 283, const uint16 EchoAuction = 312;
CC_User_SpellWornOff = 284, const uint16 EchoShout = 313;
CC_User_MoneySplit = 285, const uint16 EchoEmote = 314;
CC_User_Loot = 286, const uint16 EchoChat1 = 315;
CC_User_Random = 287, const uint16 EchoChat2 = 316;
CC_User_OtherSpells = 288, const uint16 EchoChat3 = 317;
CC_User_SpellFailure = 289, const uint16 EchoChat4 = 318;
CC_User_ChatChannel = 290, const uint16 EchoChat5 = 319;
CC_User_Chat1 = 291, const uint16 EchoChat6 = 320;
CC_User_Chat2 = 292, const uint16 EchoChat7 = 321;
CC_User_Chat3 = 293, const uint16 EchoChat8 = 322;
CC_User_Chat4 = 294, const uint16 EchoChat9 = 323;
CC_User_Chat5 = 295, const uint16 EchoChat10 = 324;
CC_User_Chat6 = 296, const uint16 DotDamage = 325;
CC_User_Chat7 = 297, const uint16 ItemLink = 326;
CC_User_Chat8 = 298, const uint16 RaidSay = 327;
CC_User_Chat9 = 299, const uint16 MyPet = 328;
CC_User_Chat10 = 300, const uint16 DamageShield = 329;
CC_User_MeleeCrit = 301, const uint16 LeaderShip = 330;
CC_User_SpellCrit = 302, const uint16 PetFlurry = 331;
CC_User_TooFarAway = 303, const uint16 PetCritical = 332;
CC_User_NPCRampage = 304, const uint16 FocusEffect = 333;
CC_User_NPCFurry = 305, const uint16 Experience = 334;
CC_User_NPCEnrage = 306, const uint16 System = 335;
CC_User_EchoSay = 307, const uint16 PetSpell = 336;
CC_User_EchoTell = 308, const uint16 PetResponse = 337;
CC_User_EchoGroup = 309, const uint16 ItemSpeech = 338;
CC_User_EchoGuild = 310, const uint16 StrikeThrough = 339;
CC_User_EchoOOC = 311, const uint16 Stun = 340;
CC_User_EchoAuction = 312,
CC_User_EchoShout = 313,
CC_User_EchoEmote = 314,
CC_User_EchoChat1 = 315,
CC_User_EchoChat2 = 316,
CC_User_EchoChat3 = 317,
CC_User_EchoChat4 = 318,
CC_User_EchoChat5 = 319,
CC_User_EchoChat6 = 320,
CC_User_EchoChat7 = 321,
CC_User_EchoChat8 = 322,
CC_User_EchoChat9 = 323,
CC_User_EchoChat10 = 324,
CC_User_UnusedAtThisTime = 325,
CC_User_ItemTags = 326,
CC_User_RaidSay = 327,
CC_User_MyPet = 328,
CC_User_DamageShield = 329,
}; };
//ZoneChange_Struct->success values //ZoneChange_Struct->success values
@ -523,4 +438,25 @@ static const uint8 SkillDamageTypes[EQEmu::skills::HIGHEST_SKILL + 1] = // chang
static const uint32 MAX_SPELL_DB_ID_VAL = 65535; static const uint32 MAX_SPELL_DB_ID_VAL = 65535;
enum ChatChannelNames : uint16
{
ChatChannel_Guild = 0,
ChatChannel_Group = 2,
ChatChannel_Shout = 3,
ChatChannel_Auction = 4,
ChatChannel_OOC = 5,
ChatChannel_Broadcast = 6,
ChatChannel_Tell = 7,
ChatChannel_Say = 8,
ChatChannel_Petition = 10,
ChatChannel_GMSAY = 11,
ChatChannel_TellEcho = 14,
ChatChannel_Raid = 15,
ChatChannel_UNKNOWN_Guild = 17,
ChatChannel_UNKNOWN_GMSAY = 18,
ChatChannel_UCSRelay = 20,
ChatChannel_Emotes = 22
};
#endif /*COMMON_EQ_CONSTANTS_H*/ #endif /*COMMON_EQ_CONSTANTS_H*/

View File

@ -1188,6 +1188,20 @@ struct SpecialMesg_Struct
/*24*/ char message[1]; // What is being said? /*24*/ char message[1]; // What is being said?
}; };
struct SpecialMesgHeader_Struct
{
/*00*/ char SpeakMode; // 2 shouts, 4 %1 %2, 3 %2, 5 tells group, 0 copy, default says
/*01*/ char JournalMode; // 1 and 2 go to journal
/*02*/ char language;
/*03*/ uint32 msg_type; // Color of text (see MT_*** below)
/*07*/ uint32 target_spawn_id; // Who is it being said to?
/*11*/ // speaker's name
/*xx*/ // unknown, location, client doesn't care
/*xx*/ // unknown
/*xx*/ // unknown
/*xx*/ // message
};
/* /*
** When somebody changes what they're wearing or give a pet a weapon (model changes) ** When somebody changes what they're wearing or give a pet a weapon (model changes)
** Length: 19 Bytes ** Length: 19 Bytes

View File

@ -81,14 +81,6 @@ namespace Console {
}; };
} }
enum GameChatColor {
yellow = 15,
red = 13,
light_green = 14,
light_cyan = 258,
light_purple = 5
};
/** /**
* EQEmuLogSys Constructor * EQEmuLogSys Constructor
*/ */
@ -306,22 +298,22 @@ uint16 EQEmuLogSys::GetGMSayColorFromCategory(uint16 log_category)
switch (log_category) { switch (log_category) {
case Logs::Status: case Logs::Status:
case Logs::Normal: case Logs::Normal:
return GameChatColor::yellow; return Chat::Yellow;
case Logs::MySQLError: case Logs::MySQLError:
case Logs::Error: case Logs::Error:
return GameChatColor::red; return Chat::Red;
case Logs::MySQLQuery: case Logs::MySQLQuery:
case Logs::Debug: case Logs::Debug:
return GameChatColor::light_green; return Chat::Lime;
case Logs::Quests: case Logs::Quests:
return GameChatColor::light_cyan; return Chat::Group;
case Logs::Commands: case Logs::Commands:
case Logs::Mercenaries: case Logs::Mercenaries:
return GameChatColor::light_purple; return Chat::Magenta;
case Logs::Crash: case Logs::Crash:
return GameChatColor::red; return Chat::Red;
default: default:
return GameChatColor::yellow; return Chat::Yellow;
} }
} }

View File

@ -257,7 +257,7 @@ namespace EQ
resend_delay_min = 150; resend_delay_min = 150;
resend_delay_max = 5000; resend_delay_max = 5000;
connect_delay_ms = 500; connect_delay_ms = 500;
stale_connection_ms = 90000; stale_connection_ms = 60000;
connect_stale_ms = 5000; connect_stale_ms = 5000;
crc_length = 2; crc_length = 2;
max_packet_size = 512; max_packet_size = 512;
@ -269,7 +269,7 @@ namespace EQ
simulated_in_packet_loss = 0; simulated_in_packet_loss = 0;
simulated_out_packet_loss = 0; simulated_out_packet_loss = 0;
tic_rate_hertz = 60.0; tic_rate_hertz = 60.0;
resend_timeout = 90000; resend_timeout = 30000;
connection_close_time = 2000; connection_close_time = 2000;
outgoing_data_rate = 0.0; outgoing_data_rate = 0.0;
} }

View File

@ -3199,43 +3199,35 @@ namespace RoF
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name); // NPC names max out at 63 chars
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToRoFSayLink(new_message, old_message); ServerToRoFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_Stun) ENCODE(OP_Stun)

View File

@ -3266,43 +3266,35 @@ namespace RoF2
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name); // NPC names max out at 63 chars
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToRoF2SayLink(new_message, old_message); ServerToRoF2SayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_Stun) ENCODE(OP_Stun)

View File

@ -2069,43 +2069,35 @@ namespace SoD
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name); // NPC names max out at 63 chars
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToSoDSayLink(new_message, old_message); ServerToSoDSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_Stun) ENCODE(OP_Stun)

View File

@ -1116,7 +1116,10 @@ namespace SoF
} }
OUT(deity); OUT(deity);
OUT(intoxication); OUT(intoxication);
OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT);
eq->spellSlotRefresh[9] = 0; // 10th slot is not valid in this release
OUT(abilitySlotRefresh); OUT(abilitySlotRefresh);
OUT(points); // Relocation Test OUT(points); // Relocation Test
// OUT(unknown0166[4]); // OUT(unknown0166[4]);
@ -1177,7 +1180,10 @@ namespace SoF
} }
// OUT(unknown4184[128]); // OUT(unknown4184[128]);
OUT_array(mem_spells, spells::SPELL_GEM_COUNT); OUT_array(mem_spells, spells::SPELL_GEM_COUNT);
eq->mem_spells[9] = 0xFFFFFFFFU; // 10th slot is not valid in this release
// OUT(unknown04396[32]); // OUT(unknown04396[32]);
OUT(platinum); OUT(platinum);
OUT(gold); OUT(gold);
@ -1720,43 +1726,35 @@ namespace SoF
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name);
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToSoFSayLink(new_message, old_message); ServerToSoFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_Stun) ENCODE(OP_Stun)

View File

@ -328,7 +328,11 @@ namespace SoF
const int SPELL_ID_MAX = 15999; const int SPELL_ID_MAX = 15999;
const int SPELLBOOK_SIZE = 480; const int SPELLBOOK_SIZE = 480;
// Be careful not to confuse these two..SoF disc release has a special requirement...
// - The number of available spell gems HAS NOT increased from 9 at this point
// - The profile allocation HAS increased to 10 at this point
const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems); const int SPELL_GEM_COUNT = static_cast<uint32>(CastingSlot::MaxGems);
const int SPELL_GEM_PROFILE_SIZE = 10; // special case declaration
const int LONG_BUFFS = 25; const int LONG_BUFFS = 25;
const int SHORT_BUFFS = 15; const int SHORT_BUFFS = 15;

View File

@ -885,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets
/*00060*/ BindStruct binds[5]; // Bind points (primary is first) /*00060*/ BindStruct binds[5]; // Bind points (primary is first)
/*00160*/ uint32 deity; // deity /*00160*/ uint32 deity; // deity
/*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?)
/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each /*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_PROFILE_SIZE]; // Refresh time (millis) - 4 Octets Each
/*00208*/ uint32 abilitySlotRefresh; /*00208*/ uint32 abilitySlotRefresh;
/*00212*/ uint8 haircolor; // Player hair color /*00212*/ uint8 haircolor; // Player hair color
/*00213*/ uint8 beardcolor; // Player beard color /*00213*/ uint8 beardcolor; // Player beard color
@ -912,7 +912,7 @@ struct PlayerProfile_Struct //23576 Octets
/*04173*/ uint8 unknown02264[147]; // was [139] /*04173*/ uint8 unknown02264[147]; // was [139]
/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages /*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages
/*06232*/ uint8 unknown4184[128]; // was [136] /*06232*/ uint8 unknown4184[128]; // was [136]
/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized /*06396*/ uint32 mem_spells[spells::SPELL_GEM_PROFILE_SIZE]; // List of spells memorized
/*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28]
/*06464*/ uint32 platinum; // Platinum Pieces on player /*06464*/ uint32 platinum; // Platinum Pieces on player
/*06468*/ uint32 gold; // Gold Pieces on player /*06468*/ uint32 gold; // Gold Pieces on player
@ -3768,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct {
}; };
struct LoadSpellSet_Struct { struct LoadSpellSet_Struct {
uint32 spell[spells::SPELL_GEM_COUNT]; uint32 spell[spells::SPELL_GEM_PROFILE_SIZE];
uint32 unknown; uint32 unknown;
}; };

View File

@ -1420,43 +1420,35 @@ namespace Titanium
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name); // NPC names max out at 63 chars
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToTitaniumSayLink(new_message, old_message); ServerToTitaniumSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_TaskDescription) ENCODE(OP_TaskDescription)

View File

@ -2369,43 +2369,35 @@ namespace UF
EQApplicationPacket *in = *p; EQApplicationPacket *in = *p;
*p = nullptr; *p = nullptr;
SpecialMesg_Struct *emu = (SpecialMesg_Struct *)in->pBuffer; SerializeBuffer buf(in->size);
buf.WriteInt8(in->ReadUInt8()); // speak mode
buf.WriteInt8(in->ReadUInt8()); // journal mode
buf.WriteInt8(in->ReadUInt8()); // language
buf.WriteInt32(in->ReadUInt32()); // message type
buf.WriteInt32(in->ReadUInt32()); // target spawn id
unsigned char *__emu_buffer = in->pBuffer; std::string name;
// break strlen optimizations! in->ReadString(name); // NPC names max out at 63 chars
char *message = emu->sayer;
auto sayer_length = std::char_traits<char>::length(message);
message += sayer_length + 1 + 12; // skip over sayer name, null term, and 3 floats
std::string old_message = message; buf.WriteString(name);
buf.WriteInt32(in->ReadUInt32()); // loc
buf.WriteInt32(in->ReadUInt32());
buf.WriteInt32(in->ReadUInt32());
std::string old_message;
std::string new_message; std::string new_message;
in->ReadString(old_message);
ServerToUFSayLink(new_message, old_message); ServerToUFSayLink(new_message, old_message);
//in->size = 3 + 4 + 4 + strlen(emu->sayer) + 1 + 12 + new_message.length() + 1; buf.WriteString(new_message);
in->size = sayer_length + new_message.length() + 25;
in->pBuffer = new unsigned char[in->size];
char *OutBuffer = (char *)in->pBuffer; auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[0]); dest->FastQueuePacket(&outapp, ack_req);
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[1]); delete in;
VARSTRUCT_ENCODE_TYPE(uint8, OutBuffer, emu->header[2]);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->msg_type);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->target_spawn_id);
VARSTRUCT_ENCODE_STRING(OutBuffer, emu->sayer);
// TODO: figure this shit out
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0.0f);
VARSTRUCT_ENCODE_STRING(OutBuffer, new_message.c_str());
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
} }
ENCODE(OP_Stun) ENCODE(OP_Stun)

View File

@ -205,6 +205,7 @@ RULE_CATEGORY_END()
RULE_CATEGORY(GM) RULE_CATEGORY(GM)
RULE_INT(GM, MinStatusToSummonItem, 250) RULE_INT(GM, MinStatusToSummonItem, 250)
RULE_INT(GM, MinStatusToZoneAnywhere, 250) RULE_INT(GM, MinStatusToZoneAnywhere, 250)
RULE_INT(GM, MinStatusToLevelTarget, 100)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(World) RULE_CATEGORY(World)
@ -225,8 +226,6 @@ RULE_BOOL(World, MaxClientsSetByStatus, false) // If True, IP Limiting will be s
RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP) RULE_BOOL(World, EnableIPExemptions, false) // If True, ip_exemptions table is used, if there is no entry for the IP it will default to RuleI(World, MaxClientsPerIP)
RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots. RULE_BOOL(World, ClearTempMerchantlist, true) // Clears temp merchant items when world boots.
RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks. RULE_BOOL(World, DeleteStaleCorpeBackups, true) // Deletes stale corpse backups older than 2 weeks.
RULE_INT(World, AccountSessionLimit, -1) //Max number of characters allowed on at once from a single account (-1 is disabled)
RULE_INT(World, ExemptAccountLimitStatus, -1) //Min status required to be exempt from multi-session per account limiting (-1 is disabled)
RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts. RULE_BOOL(World, GMAccountIPList, false) // Check ip list against GM Accounts, AntiHack GM Accounts.
RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list RULE_INT(World, MinGMAntiHackStatus, 1) //Minimum GM status to check against AntiHack list
RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled) RULE_INT(World, SoFStartZoneID, -1) //Sets the Starting Zone for SoF Clients separate from Titanium Clients (-1 is disabled)
@ -241,10 +240,11 @@ RULE_BOOL (World, IPLimitDisconnectAll, false)
RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules. RULE_BOOL(World, MaxClientsSimplifiedLogic, false) // New logic that only uses ExemptMaxClientsStatus and MaxClientsPerIP. Done on the loginserver. This mimics the P99-style special IP rules.
RULE_INT (World, TellQueueSize, 20) RULE_INT (World, TellQueueSize, 20)
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind? RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone ALWAYS be the same location as your bind?
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false)
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY(Zone) RULE_CATEGORY(Zone)
RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection RULE_INT(Zone, ClientLinkdeadMS, 90000) //the time a client remains link dead on the server after a sudden disconnection
RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone
RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on.
RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses. RULE_BOOL(Zone, UsePlayerCorpseBackups, true) // Keeps backups of player corpses.

View File

@ -80,6 +80,7 @@
#define ServerOP_GroupJoin 0x003e //for joining ooz folks #define ServerOP_GroupJoin 0x003e //for joining ooz folks
#define ServerOP_UpdateSpawn 0x003f #define ServerOP_UpdateSpawn 0x003f
#define ServerOP_SpawnStatusChange 0x0040 #define ServerOP_SpawnStatusChange 0x0040
#define ServerOP_DropClient 0x0041 // DropClient
#define ServerOP_ReloadTasks 0x0060 #define ServerOP_ReloadTasks 0x0060
#define ServerOP_DepopAllPlayersCorpses 0x0061 #define ServerOP_DepopAllPlayersCorpses 0x0061
#define ServerOP_ReloadTitles 0x0062 #define ServerOP_ReloadTitles 0x0062
@ -213,6 +214,15 @@ enum { QSG_LFGuild_PlayerMatches = 0, QSG_LFGuild_UpdatePlayerInfo, QSG_LFGuild_
#define ServerOP_Speech 0x4513 #define ServerOP_Speech 0x4513
enum {
UserToWorldStatusWorldUnavail = 0,
UserToWorldStatusSuccess = 1,
UserToWorldStatusSuspended = -1,
UserToWorldStatusBanned = -2,
UserToWorldStatusWorldAtCapacity = -3,
UserToWorldStatusAlreadyOnline = -4
};
/************ PACKET RELATED STRUCT ************/ /************ PACKET RELATED STRUCT ************/
class ServerPacket class ServerPacket
{ {
@ -308,11 +318,17 @@ struct ServerZoneIncomingClient_Struct {
uint32 accid; uint32 accid;
int16 admin; int16 admin;
uint32 charid; uint32 charid;
uint32 lsid;
bool tellsoff; bool tellsoff;
char charname[64]; char charname[64];
char lskey[30]; char lskey[30];
}; };
struct ServerZoneDropClient_Struct
{
uint32 lsid;
};
struct ServerChangeWID_Struct { struct ServerChangeWID_Struct {
uint32 charid; uint32 charid;
uint32 newwid; uint32 newwid;
@ -343,7 +359,8 @@ struct ServerChannelMessage_Struct {
bool noreply; bool noreply;
uint16 chan_num; uint16 chan_num;
uint32 guilddbid; uint32 guilddbid;
uint16 language; uint8 language;
uint8 lang_skill;
uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline uint8 queued; // 0 = not queued, 1 = queued, 2 = queue full, 3 = offline
char message[0]; char message[0];
}; };
@ -856,6 +873,8 @@ struct ServerRaidGroupAction_Struct { //add / remove depends on opcode.
struct ServerRaidMessage_Struct { struct ServerRaidMessage_Struct {
uint32 rid; uint32 rid;
uint32 gid; uint32 gid;
uint8 language;
uint8 lang_skill;
char from[64]; char from[64];
char message[0]; char message[0];
}; };

View File

@ -27,6 +27,8 @@
#else #else
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <iostream>
#endif #endif
#ifndef va_copy #ifndef va_copy
@ -123,6 +125,25 @@ std::vector<std::string> SplitString(const std::string &str, char delim) {
return ret; return ret;
} }
std::string implode(std::string glue, std::vector<std::string> src)
{
if (src.empty()) {
return {};
}
std::ostringstream output;
std::vector<std::string>::iterator src_iter;
for (src_iter = src.begin(); src_iter != src.end(); src_iter++) {
output << *src_iter << glue;
}
std::string final_output = output.str();
final_output.resize (output.str().size () - glue.size());
return final_output;
}
std::string EscapeString(const std::string &s) { std::string EscapeString(const std::string &s) {
std::string ret; std::string ret;

View File

@ -30,6 +30,7 @@ const std::string ucfirst(std::string s);
std::vector<std::string> split(std::string str_to_split, char delimiter); std::vector<std::string> split(std::string str_to_split, char delimiter);
const std::string StringFormat(const char* format, ...); const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args); const std::string vStringFormat(const char* format, va_list args);
std::string implode(std::string glue, std::vector<std::string> src);
std::vector<std::string> SplitString(const std::string &s, char delim); std::vector<std::string> SplitString(const std::string &s, char delim);
std::string EscapeString(const char *src, size_t sz); std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s); std::string EscapeString(const std::string &s);

View File

@ -1,2 +0,0 @@
*.*
*

865
libs/zlibng/CMakeLists.txt Normal file
View File

@ -0,0 +1,865 @@
cmake_minimum_required(VERSION 3.5.1)
if(CMAKE_VERSION VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_VERSION})
else()
cmake_policy(VERSION 3.5.1...3.13.2)
endif()
set(CMAKE_MACOSX_RPATH 1)
# If not specified on the command line, enable C99 as the default
# Configuration items that affect the global compiler envirionment standards
# should be issued before the "project" command.
if(NOT CMAKE_C_STANDARD)
set (CMAKE_C_STANDARD 99) # The C standard whose features are requested to build this target
endif()
if(NOT CMAKE_C_STANDARD_REQUIRED)
set (CMAKE_C_STANDARD_REQUIRED ON) # Boolean describing whether the value of C_STANDARD is a requirement
endif()
if(NOT CMAKE_C_EXTENSIONS)
set (CMAKE_C_EXTENSIONS OFF) # Boolean specifying whether compiler specific extensions are requested
endif()
set(VALID_C_STANDARDS "99" "11")
if(NOT CMAKE_C_STANDARD IN_LIST VALID_C_STANDARDS )
MESSAGE(FATAL_ERROR "CMAKE_C_STANDARD:STRING=${CMAKE_C_STANDARD} not in know standards list\n ${VALID_C_STANDARDS}")
endif()
# Parse the full version number from zlib.h and include in ZLIB_FULL_VERSION
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/zlib${SUFFIX}.h _zlib_h_contents)
string(REGEX REPLACE ".*#define[ \t]+ZLIB_VERSION[ \t]+\"([0-9]+.[0-9]+.[0-9]+).*\".*"
"\\1" ZLIB_HEADER_VERSION ${_zlib_h_contents})
string(REGEX REPLACE ".*#define[ \t]+ZLIBNG_VERSION[ \t]+\"([-0-9A-Za-z.]+)\".*"
"\\1" ZLIBNG_HEADER_VERSION ${_zlib_h_contents})
message(STATUS "ZLIB_HEADER_VERSION: ${ZLIB_HEADER_VERSION}")
message(STATUS "ZLIBNG_HEADER_VERSION: ${ZLIBNG_HEADER_VERSION}")
project(zlib
VERSION ${ZLIB_HEADER_VERSION}
LANGUAGES C)
set(INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables")
set(INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Installation directory for libraries")
set(INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers")
set(INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages")
set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files")
include(CheckTypeSize)
include(CheckSymbolExists)
include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckCSourceCompiles)
include(CheckCSourceRuns)
include(CMakeDependentOption)
include(FeatureSummary)
# Make sure we use an appropriate BUILD_TYPE by default, "Release" to be exact
# this should select the maximum generic optimisation on the current platform (i.e. -O3 for gcc/clang)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, standard options are: Debug Release RelWithDebInfo MinSizeRel."
FORCE)
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (default)")
else()
add_feature_info(CMAKE_BUILD_TYPE 1 "Build type: ${CMAKE_BUILD_TYPE} (selected)")
endif()
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(stddef.h HAVE_STDDEF_H)
check_include_file(sys/sdt.h HAVE_SYS_SDT_H)
if(CMAKE_OSX_ARCHITECTURES)
# If multiple architectures are requested (universal build), pick only the first
list(GET CMAKE_OSX_ARCHITECTURES 0 ARCH)
else()
set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif()
message(STATUS "Architecture: ${ARCH}")
if(CMAKE_TOOLCHAIN_FILE)
message(STATUS "Using cmake toolchain: ${CMAKE_TOOLCHAIN_FILE}")
endif()
#
# Options parsing
#
option(WITH_GZFILEOP "Compile with support for gzFile related functions" OFF)
option(ZLIB_COMPAT "Compile with zlib compatible API" OFF)
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
option(WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer" OFF)
option(WITH_MSAN "Build with memory sanitizer" OFF)
option(WITH_FUZZERS "Build test/fuzz" OFF)
option(WITH_OPTIM "Build with optimisation" ON)
option(WITH_NEW_STRATEGIES "Use new strategies" ON)
option(WITH_NATIVE_INSTRUCTIONS
"Instruct the compiler to use the full instruction set on this host (gcc/clang -march=native)" OFF)
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
option(WITH_ACLE "Build with ACLE CRC" ON)
option(WITH_NEON "Build with NEON intrinsics" ON)
elseif("${ARCH}" MATCHES "s390x")
option(WITH_DFLTCC_DEFLATE "Use DEFLATE CONVERSION CALL instruction for compression on IBM Z" OFF)
option(WITH_DFLTCC_INFLATE "Use DEFLATE CONVERSION CALL instruction for decompression on IBM Z" OFF)
endif()
add_feature_info(ZLIB_COMPAT ZLIB_COMPAT "Provide a zlib-compatible API")
add_feature_info(WITH_GZFILEOP WITH_GZFILEOP "Compile with support for gzFile-related functions")
add_feature_info(WITH_OPTIM WITH_OPTIM "Build with optimisation")
add_feature_info(WITH_SANITIZERS WITH_SANITIZERS "Build with address sanitizer and all supported sanitizers other than memory sanitizer")
add_feature_info(WITH_MSAN WITH_MSAN "Build with memory sanitizer")
add_feature_info(WITH_FUZZERS WITH_FUZZERS "Build test/fuzz")
add_feature_info(WITH_NEW_STRATEGIES WITH_NEW_STRATEGIES "Use new strategies")
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
add_feature_info(WITH_ACLE WITH_ACLE "Build with ACLE CRC")
add_feature_info(WITH_NEON WITH_NEON "Build with NEON intrinsics")
endif()
if (ZLIB_COMPAT)
add_definitions(-DZLIB_COMPAT)
set(WITH_GZFILEOP ON)
set(LIBNAME1 libz)
set(LIBNAME2 zlib)
set(SUFFIX "")
else()
set(LIBNAME1 libz-ng)
set(LIBNAME2 zlib-ng)
set(SUFFIX "-ng")
endif()
if(WITH_GZFILEOP)
add_definitions(-DWITH_GZFILEOP)
endif()
if(${CMAKE_C_COMPILER} MATCHES "icc" OR ${CMAKE_C_COMPILER} MATCHES "icpc" OR ${CMAKE_C_COMPILER} MATCHES "icl")
if(WITH_NATIVE_INSTRUCTIONS)
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
endif()
if(CMAKE_HOST_UNIX)
if(NOT SSE2FLAG)
set(SSE2FLAG "-msse2")
endif()
if(NOT SSE4FLAG)
set(SSE4FLAG "-msse4.2")
endif()
else()
if(NOT SSE2FLAG)
set(SSE2FLAG "/arch:SSE2")
endif()
if(NOT SSE4FLAG)
set(SSE4FLAG "/arch:SSE4.2")
endif()
endif()
elseif(MSVC)
# TODO. ICC can be used through MSVC. I'm not sure if we'd ever see that combination
# (who'd use cmake from an IDE...) but checking for ICC before checking for MSVC should
# avoid mistakes.
# /Oi ?
if(NOT ${ARCH} MATCHES "AMD64")
set(SSE2FLAG "/arch:SSE2")
endif()
if("${ARCH}" MATCHES "arm")
add_definitions("-D_ARM_WINAPI_PARTITION_DESKTOP_SDK_AVAILABLE=1")
set(NEONFLAG "/arch:VFPv4")
endif()
if(WITH_NATIVE_INSTRUCTIONS)
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not supported on this configuration")
endif()
else()
# catch all GNU C compilers as well as Clang and AppleClang
if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
set(__GNUC__ ON)
endif()
if(WITH_NATIVE_INSTRUCTIONS)
if(__GNUC__)
set(NATIVEFLAG "-march=native")
else()
message(STATUS "Ignoring WITH_NATIVE_INSTRUCTIONS; not implemented yet on this configuration")
endif()
endif()
if(__GNUC__ AND "${ARCH}" MATCHES "arm")
execute_process(COMMAND ${CMAKE_C_COMPILER} "-dumpmachine"
OUTPUT_VARIABLE GCC_MACHINE)
if ("${GCC_MACHINE}" MATCHES "eabihf")
set(FLOATABI "-mfloat-abi=hard")
else()
set(FLOATABI "-mfloat-abi=softfp")
endif()
endif()
if(NOT NATIVEFLAG)
if(NOT SSE2FLAG)
if(__GNUC__)
set(SSE2FLAG "-msse2")
endif()
endif()
if(NOT SSE4FLAG)
if(__GNUC__)
set(SSE4FLAG "-msse4")
endif()
endif()
if(NOT PCLMULFLAG)
if(__GNUC__)
set(PCLMULFLAG "-mpclmul")
endif()
endif()
if("${ARCH}" MATCHES "arm")
set(ACLEFLAG "-march=armv8-a+crc")
set(NEONFLAG "${FLOATABI} -mfpu=neon")
elseif("${ARCH}" MATCHES "aarch64")
set(ACLEFLAG "-march=armv8-a+crc")
set(NEONFLAG "-march=armv8-a+crc+simd")
endif()
else()
set(SSE2FLAG ${NATIVEFLAG})
set(SSE4FLAG ${NATIVEFLAG})
set(PCLMULFLAG ${NATIVEFLAG})
if("${ARCH}" MATCHES "arm")
set(ACLEFLAG "${NATIVEFLAG}")
set(NEONFLAG "${FLOATABI} -mfpu=neon")
elseif("${ARCH}" MATCHES "aarch64")
set(ACLEFLAG "${NATIVEFLAG}")
set(NEONFLAG "${NATIVEFLAG}")
endif()
endif()
endif()
#
# Check to see if we have large file support
#
set(CMAKE_REQUIRED_DEFINITIONS -D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
# We add these other definitions here because CheckTypeSize.cmake
# in CMake 2.4.x does not automatically do so and we want
# compatibility with CMake 2.4.x.
if(HAVE_SYS_TYPES_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_SYS_TYPES_H)
endif()
if(HAVE_STDINT_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDINT_H)
endif()
if(HAVE_STDDEF_H)
list(APPEND CMAKE_REQUIRED_DEFINITIONS -DHAVE_STDDEF_H)
endif()
check_type_size(off64_t OFF64_T)
if(HAVE_OFF64_T)
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
else()
check_type_size(_off64_t _OFF64_T)
if(HAVE__OFF64_T)
add_definitions(-D_LARGEFILE64_SOURCE=1 -D__USE_LARGEFILE64)
else()
check_type_size(__off64_t __OFF64_T)
endif()
endif()
set(CMAKE_REQUIRED_DEFINITIONS) # clear variable
#
# Check for fseeko and other optional functions
#
check_function_exists(fseeko HAVE_FSEEKO)
if(NOT HAVE_FSEEKO)
add_definitions(-DNO_FSEEKO)
endif()
check_function_exists(strerror HAVE_STRERROR)
if(NOT HAVE_STRERROR)
add_definitions(-DNO_STRERROR)
endif()
#
# Check for unistd.h and stdarg.h
#
check_include_file(unistd.h Z_HAVE_UNISTD_H)
if(WITH_SANITIZERS AND WITH_MSAN)
message(FATAL_ERROR "Memory sanitizer is incompatible with address sanitizer")
endif()
if(WITH_MSAN)
set(CMAKE_REQUIRED_FLAGS "-fsanitize=memory")
check_c_source_compiles("int main() { return 0; }" HAS_MSAN FAIL_REGEX "not supported")
if(${HAS_MSAN})
set(SANITIZERS_FLAGS "-fsanitize=memory")
message(STATUS "Adding memory sanitizer flag: ${SANITIZERS_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
endif()
endif()
if(WITH_SANITIZERS)
set(_sanitize_flags
bool
address
array-bounds
float-divide-by-zero
function
integer-divide-by-zero
return
shift
signed-integer-overflow
undefined
unsigned-integer-overflow
vla-bound
vptr
)
set(SANITIZERS_FLAGS "")
foreach(_flag ${_sanitize_flags})
set(CMAKE_REQUIRED_FLAGS "-fsanitize=${_flag}")
check_c_source_compiles("int main() { return 0; }"
HAS_SANITIZER_${_flag} FAIL_REGEX "not supported")
if(${HAS_SANITIZER_${_flag}})
if("${SANITIZERS_FLAGS}" STREQUAL "")
set(SANITIZERS_FLAGS "-fsanitize=${_flag}")
else()
set(SANITIZERS_FLAGS "${SANITIZERS_FLAGS},${_flag}")
endif()
endif()
set(CMAKE_REQUIRED_FLAGS)
endforeach()
message(STATUS "Adding sanitizers flags: ${SANITIZERS_FLAGS}")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZERS_FLAGS}")
endif()
#
# Check if we can hide zlib internal symbols that are linked between separate source files using hidden
#
check_c_source_compiles(
"#define ZLIB_INTERNAL __attribute__((visibility (\"hidden\")))
int ZLIB_INTERNAL foo;
int main()
{
return 0;
}"
HAVE_ATTRIBUTE_VISIBILITY_HIDDEN FAIL_REGEX "not supported")
if(HAVE_ATTRIBUTE_VISIBILITY_HIDDEN)
add_definitions(-DHAVE_HIDDEN)
endif()
#
# Check if we can hide zlib internal symbols that are linked between separate source files using internal
#
check_c_source_compiles(
"#define ZLIB_INTERNAL __attribute__((visibility (\"internal\")))
int ZLIB_INTERNAL foo;
int main()
{
return 0;
}"
HAVE_ATTRIBUTE_VISIBILITY_INTERNAL FAIL_REGEX "not supported")
if(HAVE_ATTRIBUTE_VISIBILITY_INTERNAL)
add_definitions(-DHAVE_INTERNAL)
endif()
#
# check for __builtin_ctzl() support in the compiler
#
check_c_source_compiles(
"int main(void)
{
unsigned int zero = 0;
long test = __builtin_ctzl(zero);
(void)test;
return 0;
}"
HAVE_BUILTIN_CTZL
)
if(HAVE_BUILTIN_CTZL)
add_definitions(-DHAVE_BUILTIN_CTZL)
endif()
#
# check for ptrdiff_t support
#
check_c_source_compiles(
"#include <stddef.h>
int main() { ptrdiff_t *a; return 0; }"
HAVE_PTRDIFF_T
)
if(NOT HAVE_PTRDIFF_T)
set(NEED_PTRDIFF_T 1)
check_type_size("void *" SIZEOF_DATA_PTR)
message(STATUS "sizeof(void *) is ${SIZEOF_DATA_PTR} bytes")
if(${SIZEOF_DATA_PTR} MATCHES "4")
set(PTRDIFF_TYPE "uint32_t")
elseif(${SIZEOF_DATA_PTR} MATCHES "8")
set(PTRDIFF_TYPE "uint64_t")
else()
message(FATAL_ERROR "sizeof(void *) is neither 32 nor 64 bit")
endif()
endif()
# Macro to check if source compiles when cross-compiling
# or runs when compiling natively
macro(check_c_source_compile_or_run source flag)
if(CMAKE_CROSSCOMPILING)
check_c_source_compiles("${source}" ${flag})
else()
check_c_source_runs("${source}" ${flag})
endif()
endmacro()
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DZLIB_DEBUG")
if(MSVC)
set(CMAKE_DEBUG_POSTFIX "d")
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
else()
#
# Not MSVC, so we need to check if we have the MS-style SSE etc. intrinsics
#
if(WITH_NATIVE_INSTRUCTIONS)
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
else()
set(CMAKE_REQUIRED_FLAGS "${SSE2FLAG}")
endif()
check_c_source_compile_or_run(
"#include <immintrin.h>
int main(void)
{
__m128i zero = _mm_setzero_si128();
(void)zero;
return 0;
}"
HAVE_SSE2_INTRIN
)
set(CMAKE_REQUIRED_FLAGS)
if(WITH_NATIVE_INSTRUCTIONS)
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
else()
# Use the generic SSE4 enabler option to check for the SSE4.2 instruction we require:
set(CMAKE_REQUIRED_FLAGS "${SSE4FLAG}")
endif()
check_c_source_compile_or_run(
"int main(void)
{
unsigned val = 0, h = 0;
__asm__ __volatile__ ( \"crc32 %1,%0\" : \"+r\" (h) : \"r\" (val) );
return (int) h;
}"
HAVE_SSE42_INTRIN
)
check_c_source_compile_or_run(
"int main(void)
{
unsigned crc = 0;
char c = 'c';
crc = __builtin_ia32_crc32qi(crc, c);
(void)crc;
return 0;
}"
HAVE_SSE42CRC_INTRIN
)
set(CMAKE_REQUIRED_FLAGS)
if(WITH_NATIVE_INSTRUCTIONS)
set(CMAKE_REQUIRED_FLAGS "${NATIVEFLAG}")
else()
set(CMAKE_REQUIRED_FLAGS "${PCLMULFLAG}")
endif()
if(NOT (APPLE AND ${ARCH} MATCHES "i386"))
# The pclmul code currently crashes on Mac in 32bit mode. Avoid for now.
check_c_source_compile_or_run(
"#include <immintrin.h>
#include <wmmintrin.h>
int main(void)
{
__m128i a = _mm_setzero_si128();
__m128i b = _mm_setzero_si128();
__m128i c = _mm_clmulepi64_si128(a, b, 0x10);
(void)c;
return 0;
}"
HAVE_PCLMULQDQ_INTRIN
)
else()
set(HAVE_PCLMULQDQ_INTRIN NO)
endif()
set(CMAKE_REQUIRED_FLAGS)
endif()
# Check whether -mfpu=neon is available
set(CMAKE_REQUIRED_FLAGS "-mfpu=neon")
check_c_source_compiles(
"int main()
{
return 0;
}"
MFPU_NEON_AVAILABLE FAIL_REGEX "not supported")
set(CMAKE_REQUIRED_FLAGS)
# FORCE_SSE2 option will only be shown if HAVE_SSE2_INTRIN is true
if("${ARCH}" MATCHES "i[3-6]86")
cmake_dependent_option(FORCE_SSE2 "Always assume CPU is SSE2 capable" OFF "HAVE_SSE2_INTRIN" OFF)
endif()
#
# Enable deflate_medium at level 4-6
#
if(NOT WITH_NEW_STRATEGIES)
add_definitions(-DNO_MEDIUM_STRATEGY)
endif()
#
# Macro to add either the given intrinsics option to the global compiler options,
# or ${NATIVEFLAG} (-march=native) if that is appropriate and possible.
# An alternative version of this macro would take a file argument, and set ${flag}
# only for that file as opposed to ${NATIVEFLAG} globally, to limit side-effect of
# using ${flag} globally.
#
macro(add_intrinsics_option flag)
if(WITH_NATIVE_INSTRUCTIONS AND NATIVEFLAG)
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${NATIVEFLAG} .*")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NATIVEFLAG}")
endif()
else()
if (NOT "${CMAKE_C_FLAGS} " MATCHES ".*${flag} .*")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}")
endif()
endif()
endmacro()
set(ZLIB_ARCH_SRCS)
set(ARCHDIR "arch/generic")
if("${ARCH}" MATCHES "x86_64" OR "${ARCH}" MATCHES "AMD64" OR "${ARCH}" MATCHES "i[3-6]86")
set(ARCHDIR "arch/x86")
add_definitions(-DUNALIGNED_OK)
add_feature_info(SSE2 1 "Support the SSE2 instruction set, using \"${SSE2FLAG}\"")
elseif("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
set(ARCHDIR "arch/arm")
add_definitions(-DUNALIGNED_OK)
elseif("${ARCH}" MATCHES "s390x")
set(ARCHDIR "arch/s390")
else()
message(STATUS "No optimized architecture: using ${ARCHDIR}")
endif()
if("${ARCH}" MATCHES "arm" OR "${ARCH}" MATCHES "aarch64")
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/armfeature.c ${ARCHDIR}/fill_window_arm.c)
endif()
if(WITH_OPTIM)
if("${ARCH}" MATCHES "arm")
if(WITH_ACLE)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
add_definitions("-DARM_ACLE_CRC_HASH")
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
endif()
if(WITH_NEON)
if(MFPU_NEON_AVAILABLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
endif()
add_definitions("-DARM_NEON_ADLER32")
if(MSVC)
add_definitions("-D__ARM_NEON__=1")
endif(MSVC)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
endif()
elseif("${ARCH}" MATCHES "aarch64")
if(WITH_ACLE)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc32_acle.c ${ARCHDIR}/insert_string_acle.c)
add_definitions("-DARM_ACLE_CRC_HASH")
add_feature_info(ACLE_CRC 1 "Support CRC hash generation using the ACLE instruction set, using \"${ACLEFLAG}\"")
endif()
# We need to check WITH_NEON first
if(WITH_NEON)
add_definitions("-DARM_NEON_ADLER32")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${NEONFLAG}")
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/adler32_neon.c)
add_feature_info(NEON_FILLWINDOW 1 "Support NEON instructions in fill_window_arm, using \"${NEONFLAG}\"")
elseif(WITH_ACLE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ACLEFLAG}")
endif()
elseif("${ARCHDIR}" MATCHES "arch/x86")
add_definitions("-DX86_CPUID")
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/x86.c)
if(HAVE_SSE42_INTRIN)
add_definitions(-DX86_SSE4_2_CRC_HASH)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/insert_string_sse.c)
add_feature_info(SSE4_CRC 1 "Support CRC hash generation using the SSE4.2 instruction set, using \"${SSE4FLAG}\"")
add_intrinsics_option("${SSE4FLAG}")
if(HAVE_SSE42CRC_INTRIN)
add_definitions(-DX86_SSE4_2_CRC_INTRIN)
endif()
if(WITH_NEW_STRATEGIES)
add_definitions(-DX86_QUICK_STRATEGY)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/deflate_quick.c)
add_feature_info(SSE4DEFLATE 1 "Support SSE4.2-accelerated quick compression")
endif()
endif()
if(HAVE_SSE2_INTRIN)
add_definitions(-DX86_SSE2)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/fill_window_sse.c)
if(NOT ${ARCH} MATCHES "x86_64")
add_intrinsics_option("${SSE2FLAG}")
add_feature_info(FORCE_SSE2 FORCE_SSE2 "Assume CPU is SSE2 capable")
if(FORCE_SSE2)
add_definitions(-DX86_NOCHECK_SSE2)
endif()
endif()
endif()
if(HAVE_PCLMULQDQ_INTRIN)
add_definitions(-DX86_PCLMULQDQ_CRC)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/crc_folding.c)
add_intrinsics_option("${PCLMULFLAG}")
if(HAVE_SSE42_INTRIN)
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG}\"")
else()
add_feature_info(PCLMUL_CRC 1 "Support CRC hash generation using PCLMULQDQ, using \"${PCLMULFLAG} ${SSE4FLAG}\"")
endif()
endif()
elseif("${ARCH}" MATCHES "s390x")
if(WITH_DFLTCC_DEFLATE OR WITH_DFLTCC_INFLATE)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_common.c)
endif()
if(WITH_DFLTCC_DEFLATE)
add_definitions(-DS390_DFLTCC_DEFLATE)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_deflate.c)
endif()
if(WITH_DFLTCC_INFLATE)
add_definitions(-DS390_DFLTCC_INFLATE)
set(ZLIB_ARCH_SRCS ${ZLIB_ARCH_SRCS} ${ARCHDIR}/dfltcc_inflate.c)
endif()
endif()
endif()
message(STATUS "Architecture-specific source files: ${ZLIB_ARCH_SRCS}")
#============================================================================
# zconf.h
#============================================================================
macro(generate_cmakein input output)
file(REMOVE ${output})
file(STRINGS ${input} _lines)
foreach(_line IN LISTS _lines)
file(APPEND ${output} "${_line}\n")
if (_line STREQUAL "#define ZCONF_H" OR _line STREQUAL "#define ZCONFNG_H")
file(APPEND ${output} "#cmakedefine Z_HAVE_UNISTD_H\n")
if(NOT HAVE_PTRDIFF_T)
file(APPEND ${output} "#cmakedefine NEED_PTRDIFF_T\n")
file(APPEND ${output} "#cmakedefine PTRDIFF_TYPE ${PTRDIFF_TYPE}\n")
endif()
endif()
endforeach()
endmacro(generate_cmakein)
generate_cmakein( ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.in ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein )
if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR)
# If we're doing an out of source build and the user has a zconf.h
# in their source tree...
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h)
message(STATUS "Renaming")
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h")
message(STATUS "to 'zconf${SUFFIX}.h.included' because this file is included with zlib")
message(STATUS "but CMake generates it automatically in the build directory.")
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.included)
endif()
# If we're doing an out of source build and the user has a zconf.h.cmakein
# in their source tree...
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein)
message(STATUS "Renaming")
message(STATUS " ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein")
message(STATUS "to 'zconf${SUFFIX}.h.cmakeincluded' because this file is included with zlib")
message(STATUS "but CMake generates it automatically in the build directory.")
file(RENAME ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakein ${CMAKE_CURRENT_SOURCE_DIR}/zconf${SUFFIX}.h.cmakeincluded)
endif()
endif()
set(ZLIB_PC ${CMAKE_CURRENT_BINARY_DIR}/${LIBNAME2}.pc)
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zlib.pc.cmakein
${ZLIB_PC} @ONLY)
configure_file(${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h.cmakein
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h @ONLY)
#============================================================================
# zlib
#============================================================================
set(ZLIB_PUBLIC_HDRS
${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h
zlib${SUFFIX}.h
)
set(ZLIB_PRIVATE_HDRS
crc32.h
deflate.h
functable.h
gzguts.h
inffast.h
inffixed.h
inflate.h
inftrees.h
trees.h
zutil.h
)
set(ZLIB_SRCS
adler32.c
compress.c
crc32.c
deflate.c
deflate_fast.c
deflate_medium.c
deflate_slow.c
functable.c
inflate.c
infback.c
inftrees.c
inffast.c
trees.c
uncompr.c
zutil.c
)
set(ZLIB_GZFILE_SRCS
gzclose.c
gzlib.c
gzread.c
gzwrite.c
)
if(NOT MINGW AND NOT MSYS)
set(ZLIB_DLL_SRCS
win32/zlib${SUFFIX}1.rc # If present will override custom build rule below.
)
endif()
if(MINGW OR MSYS)
# This gets us DLL resource information when compiling on MinGW.
if(NOT CMAKE_RC_COMPILER)
set(CMAKE_RC_COMPILER windres.exe)
endif()
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
COMMAND ${CMAKE_RC_COMPILER}
-D GCC_WINDRES
-I ${CMAKE_CURRENT_SOURCE_DIR}
-I ${CMAKE_CURRENT_BINARY_DIR}
-o ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj
-i ${CMAKE_CURRENT_SOURCE_DIR}/win32/zlib${SUFFIX}1.rc)
set(ZLIB_DLL_SRCS ${CMAKE_CURRENT_BINARY_DIR}/zlib1rc.obj)
endif()
add_library(zlib SHARED ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_DLL_SRCS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlib PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
add_library(zlibstatic STATIC ${ZLIB_SRCS} ${ZLIB_ARCH_SRCS} ${ZLIB_ASMS} ${ZLIB_PUBLIC_HDRS} ${ZLIB_PRIVATE_HDRS})
target_include_directories(zlibstatic PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
if(WITH_GZFILEOP)
target_sources(zlib PRIVATE ${ZLIB_GZFILE_SRCS})
target_sources(zlibstatic PRIVATE ${ZLIB_GZFILE_SRCS})
endif()
set_target_properties(zlib PROPERTIES DEFINE_SYMBOL ZLIB_DLL)
set_target_properties(zlib PROPERTIES SOVERSION 1)
if (ZLIB_COMPAT)
set(ZLIB_FULL_VERSION ${ZLIB_HEADER_VERSION})
else()
set(ZLIB_FULL_VERSION ${ZLIBNG_HEADER_VERSION})
endif()
if(NOT CYGWIN)
# This property causes shared libraries on Linux to have the full version
# encoded into their final filename. We disable this on Cygwin because
# it causes cygz-${ZLIB_FULL_VERSION}.dll to be created when cygz.dll
# seems to be the default.
#
# This has no effect with MSVC, on that platform the version info for
# the DLL comes from the resource file win32/zlib1.rc
set_target_properties(zlib PROPERTIES VERSION ${ZLIB_FULL_VERSION})
endif()
if(UNIX)
# On unix-like platforms the library is almost always called libz
set_target_properties(zlib zlibstatic PROPERTIES OUTPUT_NAME z${SUFFIX})
if(NOT APPLE)
set_target_properties(zlib PROPERTIES LINK_FLAGS "-Wl,--version-script,\"${CMAKE_CURRENT_SOURCE_DIR}/${LIBNAME2}.map\"")
endif()
elseif(MSYS)
# Suppress version number from shared library name
set(CMAKE_SHARED_LIBRARY_NAME_WITH_VERSION 0)
elseif(BUILD_SHARED_LIBS AND WIN32)
# Creates zlib1.dll when building shared library version
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
endif()
if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL )
install(TARGETS zlib zlibstatic
RUNTIME DESTINATION "${INSTALL_BIN_DIR}"
ARCHIVE DESTINATION "${INSTALL_LIB_DIR}"
LIBRARY DESTINATION "${INSTALL_LIB_DIR}" )
endif()
if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL )
install(FILES zlib${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zlib${SUFFIX}.h)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/zconf${SUFFIX}.h DESTINATION "${INSTALL_INC_DIR}" RENAME zconf${SUFFIX}.h)
endif()
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
install(FILES zlib.3 DESTINATION "${INSTALL_MAN_DIR}/man3" RENAME zlib${SUFFIX}.3)
endif()
if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
install(FILES ${ZLIB_PC} DESTINATION "${INSTALL_PKGCONFIG_DIR}")
endif()
#============================================================================
# Example binaries
#============================================================================
option(ZLIB_ENABLE_TESTS "Build test binaries" ON)
if (ZLIB_ENABLE_TESTS)
enable_testing()
macro(configure_test_executable target)
target_link_libraries(${target} zlib)
if(NOT WITH_GZFILEOP)
target_compile_definitions(${target} PUBLIC -DWITH_GZFILEOP)
target_sources(${target} PRIVATE ${ZLIB_GZFILE_SRCS})
endif()
endmacro()
add_executable(example test/example.c)
configure_test_executable(example)
add_test(NAME example COMMAND example${CMAKE_EXECUTABLE_SUFFIX})
add_executable(minigzip test/minigzip.c)
configure_test_executable(minigzip)
if(HAVE_OFF64_T)
add_executable(example64 test/example.c)
configure_test_executable(example64)
set_target_properties(example64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
add_test(NAME example64 COMMAND example64${CMAKE_EXECUTABLE_SUFFIX})
add_executable(minigzip64 test/minigzip.c)
configure_test_executable(minigzip64)
set_target_properties(minigzip64 PROPERTIES COMPILE_FLAGS "-D_FILE_OFFSET_BITS=64")
endif()
if(WITH_FUZZERS)
set(FUZZERS checksum compress example_small example_large example_flush example_dict minigzip)
file(GLOB ALL_SRC_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*")
foreach(FUZZER ${FUZZERS})
add_executable(${FUZZER}_fuzzer test/fuzz/${FUZZER}_fuzzer.c test/fuzz/standalone_fuzz_target_runner.c)
configure_test_executable(${FUZZER}_fuzzer)
add_test(${FUZZER}_fuzzer ${FUZZER}_fuzzer${CMAKE_EXECUTABLE_SUFFIX} ${ALL_SRC_FILES})
endforeach()
endif()
set(CVES CVE-2002-0059 CVE-2004-0797 CVE-2005-1849 CVE-2005-2096)
foreach(CVE ${CVES})
set(CVE_COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:minigzip> -d)
add_test(NAME ${CVE}
COMMAND ${CMAKE_COMMAND}
"-DCOMMAND=${CVE_COMMAND}"
-DINPUT=${CMAKE_CURRENT_SOURCE_DIR}/test/${CVE}/test.gz
"-DSUCCESS_EXIT=0;1"
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run-and-redirect.cmake)
endforeach()
if(NOT WIN32 AND ZLIB_COMPAT)
add_executable(CVE-2003-0107 test/CVE-2003-0107.c)
target_link_libraries(CVE-2003-0107 zlib)
add_test(NAME CVE-2003-0107 COMMAND CVE-2003-0107)
endif()
endif()
# FEATURE_SUMMARY(WHAT ALL INCLUDE_QUIET_PACKAGES)

View File

@ -165,21 +165,26 @@ void WorldServer::ProcessUsertoWorldResp(uint16_t opcode, const EQ::Net::Packet
switch (utwr->response) switch (utwr->response)
{ {
case 1: case UserToWorldStatusSuccess:
per->Message = 101; per->Message = 101;
break; break;
case 0: case UserToWorldStatusWorldUnavail:
per->Message = 326; per->Message = 326;
break; break;
case -1: case UserToWorldStatusSuspended:
per->Message = 337; per->Message = 337;
break; break;
case -2: case UserToWorldStatusBanned:
per->Message = 338; per->Message = 338;
break; break;
case -3: case UserToWorldStatusWorldAtCapacity:
per->Message = 303; per->Message = 339;
break; break;
case UserToWorldStatusAlreadyOnline:
per->Message = 111;
break;
default:
per->Message = 102;
} }
if (server.options.IsTraceOn()) if (server.options.IsTraceOn())

View File

@ -379,6 +379,7 @@ void Database::LogMerchantTransaction(QSMerchantLogTransaction_Struct* QS, uint3
} }
// this function does not delete the ServerPacket, so it must be handled at call site
void Database::GeneralQueryReceive(ServerPacket *pack) { void Database::GeneralQueryReceive(ServerPacket *pack) {
/* /*
These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again These are general queries passed from anywhere in zone instead of packing structures and breaking them down again and again
@ -393,7 +394,6 @@ void Database::GeneralQueryReceive(ServerPacket *pack) {
Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str()); Log(Logs::Detail, Logs::QS_Server, "%s", query.c_str());
} }
safe_delete(pack);
safe_delete_array(queryBuffer); safe_delete_array(queryBuffer);
} }

View File

@ -471,7 +471,7 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) {
Clientlist::Clientlist(int ChatPort) { Clientlist::Clientlist(int ChatPort) {
EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false); EQStreamManagerInterfaceOptions chat_opts(ChatPort, false, false);
chat_opts.opcode_size = 1; chat_opts.opcode_size = 1;
chat_opts.daybreak_options.stale_connection_ms = 300000; chat_opts.daybreak_options.stale_connection_ms = 600000;
chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS); chat_opts.daybreak_options.resend_delay_ms = RuleI(Network, ResendDelayBaseMS);
chat_opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor); chat_opts.daybreak_options.resend_delay_factor = RuleR(Network, ResendDelayFactor);
chat_opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS); chat_opts.daybreak_options.resend_delay_min = RuleI(Network, ResendDelayMinMS);

View File

@ -130,7 +130,7 @@
int32 GetFollowID(); int32 GetFollowID();
virtual void Message(int32 type, const char* message, ...); virtual void Message(int32 type, const char* message, ...);
virtual void Message_StringID(int32 type, int32 string_id, int32 distance = 0); virtual void MessageString(int32 type, int32 string_id, int32 distance = 0);
void Say(const char *format, ...); void Say(const char *format, ...);
void Shout(const char *format, ...); void Shout(const char *format, ...);
void Emote(const char *format, ...); void Emote(const char *format, ...);

View File

@ -1 +1,2 @@
opcode_handlers_output opcode_handlers_output
vcxproj_dependencies_output

View File

@ -454,6 +454,7 @@ sub do_installer_routines {
fetch_latest_windows_appveyor(); fetch_latest_windows_appveyor();
get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1);
get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1);
get_remote_file($install_repository_request_url . "zlib1.pdb", "zlib1.pdb", 1);
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
} }
@ -1587,22 +1588,24 @@ sub add_login_server_firewall_rules {
print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n";
print "\n"; print "\n";
print "[Install] Instructions \n"; print "[Install] Instructions \n";
print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.json to your local server similar to the following:\n";
print " print "
<loginserver1> \"loginserver1\" : {
<host>login.eqemulator.net</host> \"account\" : \"\",
<port>5998</port> \"host\" : \"login.eqemulator.net\",
<account></account> \"password\" : \"\",
<password></password> \"port\" : \"5998\",
</loginserver1> \"legacy\": \"1\"
<loginserver2> },
<host>127.0.0.1</host> \"loginserver2\" : {
<port>5998</port> \"account\" : \"\",
<account></account> \"host\" : \"192.168.197.129\",
<password></password> \"password\" : \"\",
</loginserver2> \"port\" : \"5998\"
},
\"localaddress\" : \"192.168.197.129\",
"; ";
print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 192.168.197.129) in the eqhosts.txt file\n";
} }
} }
@ -1640,9 +1643,10 @@ sub check_windows_firewall_rules {
} }
sub fetch_server_dlls { sub fetch_server_dlls {
print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; print "[Download] Fetching lua51.dll, zlib1.dll, zlib1.pdb, libmysql.dll...\n";
get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1);
get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1);
get_remote_file($install_repository_request_url . "zlib1.pdb", "zlib1.pdb", 1);
get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1);
} }

View File

@ -0,0 +1,793 @@
#! /usr/bin/env python
#
"""
'VCXProj-Dependencies' for EQEmulator
This script locates external dependency paths and generates lists for each
project. In addition, it will cross-check these lists to determine if any
discrepancies exist for any dependencies globally and across all projects.
"""
import sys
import os
import fnmatch
try:
import xml.etree.cElementTree as ElementTree
except ImportError:
import xml.etree.ElementTree as ElementTree
from time import time, ctime
QUIET_REPORT = True
include_projects = []
exclude_projects = ['VCTargetsPath', 'CompilerIdC', 'CompilerIdCXX'] # these three should be left in by default
base_path = os.getcwd()[:-14] # '/utils/scripts'
base_path = base_path.replace('\\', '/')
file_extensions = ['vcxproj']
project_paths = []
master_dependencies = []
# {[project]:{[build]:{[resource]:{[reference]:[paths]}}}}
project_dependencies = {}
out_files = {}
col1 = '{0}'.format(' ' * 0)
col2 = '{0}'.format(' ' * 2)
col3 = '{0}'.format(' ' * 4)
col4 = '{0}'.format(' ' * 6)
col5 = '{0}'.format(' ' * 8)
def main():
""" main """
if not create_output_directory():
exit()
if not open_output_files():
exit()
print 'Locating project paths...'
locate_project_paths()
print '..project count: {0}'.format(len(project_paths))
print 'Parsing project files...'
parse_project_files()
print 'Building master dependencies...'
build_master_dependencies()
print '..dependency count: {0}'.format(len(master_dependencies))
print 'Checking for version discrepancies...'
check_for_version_discrepancies()
close_output_files()
print '\n__fin__'
return
def create_output_directory():
""" Check for output directory - create if does not exist """
try:
output_path = '{0}/utils/scripts/vcxproj_dependencies_output'.format(base_path)
if not os.path.exists(output_path):
os.mkdir(output_path)
return True
except IOError:
print('(Exception Error: {0}) create_output_directory()'.format(sys.exc_info()[0]))
return False
def open_output_files():
""" Open all output files """
try:
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectPaths.txt'.format(base_path)
out_files['ProjectPaths'] = open(file_name, 'w')
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/MasterDependencies.txt'.format(base_path)
out_files['MasterDependencies'] = open(file_name, 'w')
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ProjectDependencies.txt'.format(base_path)
out_files['ProjectDependencies'] = open(file_name, 'w')
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/ContextTree.txt'.format(base_path)
out_files['ContextTree'] = open(file_name, 'w')
file_name = '{0}/utils/scripts/vcxproj_dependencies_output/DiscrepancyReport.txt'.format(base_path)
out_files['DiscrepancyReport'] = open(file_name, 'w')
for file in out_files:
out_files[file].write('>> \'VCXProj-Dependencies\' {0} file\n'.format(file))
out_files[file].write('>> file generated @ {0}\n\n'.format(ctime(time())))
return True
except IOError:
print('(Exception Error: {0}) open_output_files()'.format(sys.exc_info()[0]))
close_output_files()
return False
def locate_project_paths():
""" Locate vcxproj files in the build folder """
for root, dirs, files in os.walk('{0}/build'.format(base_path)):
for name in files:
project = name.split('.')[0]
if not len(include_projects) == 0 and project not in include_projects:
continue
if not len(exclude_projects) == 0 and project in exclude_projects:
continue
for extension in file_extensions:
if fnmatch.fnmatch(name, '*.{0}'.format(extension)):
project_paths.append(os.path.join(root, name).replace('\\', '/').lower())
for path in project_paths:
out_files['ProjectPaths'].write('{0};\n'.format(path))
return
def fixup_path(project_path, dependency_path):
""" Fix-up malformed dependency paths """
trailing = dependency_path.replace('\\', '/')
if '../' in trailing:
if trailing[:3] == '../': # windows
leading = project_path[:project_path.rfind('/')]
while trailing[:3] == '../':
leading = leading[:leading.rfind('/')]
trailing = trailing[3:]
trailing = trailing.lower()
trailing = '{0}/{1}'.format(leading, trailing)
else: # unix
print '..processing unix-style path fix-up'
while '../' in trailing:
backout = trailing.find('../')
backdir = trailing.rfind('/', 0, backout - 1)
trailing = trailing.replace(trailing[backdir:backout + 2], '', 1)
trailing = trailing.lower()
else:
trailing = trailing.lower()
return trailing
def parse_project_files():
""" Parse each vcxproj file's xml data """
for key1 in project_paths:
with open(key1, 'r') as vcxproj_file:
project_dependencies[key1] = {}
xml_tree = ElementTree.ElementTree(file=vcxproj_file)
for element1 in xml_tree.getroot():
if not element1.tag[-19:] == 'ItemDefinitionGroup':
continue
# add '.split('|')[0]' to remove the '|Win##' attribute
key2 = element1.attrib['Condition'].split('==')[1][1:-1]
project_dependencies[key1][key2] = {}
for element2 in element1.getiterator():
if element2.tag[-9:] == 'ClCompile':
key3 = element2.tag[-9:]
project_dependencies[key1][key2][key3] = {}
for element3 in element2.getiterator():
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
key4 = element3.tag[-28:]
project_dependencies[key1][key2][key3][key4] = []
paths = element3.text.split(';')
for path in paths:
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
elif element2.tag[-15:] == 'ResourceCompile':
key3 = element2.tag[-15:]
project_dependencies[key1][key2][key3] = {}
for element3 in element2.getiterator():
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
key4 = element3.tag[-28:]
project_dependencies[key1][key2][key3][key4] = []
paths = element3.text.split(';')
for path in paths:
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
elif element2.tag[-4:] == 'Midl':
key3 = element2.tag[-4:]
project_dependencies[key1][key2][key3] = {}
for element3 in element2.getiterator():
if element3.tag[-28:] == 'AdditionalIncludeDirectories':
key4 = element3.tag[-28:]
project_dependencies[key1][key2][key3][key4] = []
paths = element3.text.split(';')
for path in paths:
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
elif element2.tag[-4:] == 'Link':
key3 = element2.tag[-4:]
project_dependencies[key1][key2][key3] = {}
for element3 in element2.getiterator():
if element3.tag[-22:] == 'AdditionalDependencies':
key4 = element3.tag[-22:]
project_dependencies[key1][key2][key3][key4] = []
paths = element3.text.split(';')
for path in paths:
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
if element3.tag[-28:] == 'AdditionalLibraryDirectories':
key4 = element3.tag[-28:]
project_dependencies[key1][key2][key3][key4] = []
paths = element3.text.split(';')
for path in paths:
project_dependencies[key1][key2][key3][key4].append(fixup_path(key1, path))
vcxproj_file.close()
return
def build_master_dependencies():
""" Build master dependencies list """
def write(message):
""" internal 'ProjectDependencies' write method - performed here so processing takes place after fix-up """
out_files['ProjectDependencies'].write('{0}\n'.format(message))
return
for key1 in project_dependencies:
write('{0}<Project Path="{1}">'.format(col1, key1))
for key2 in project_dependencies[key1]:
write('{0}<Build Type="{1}">'.format(col2, key2))
for key3 in project_dependencies[key1][key2]:
write('{0}<Resource Type="{1}">'.format(col3, key3))
for key4 in project_dependencies[key1][key2][key3]:
write('{0}<Reference Type="{1}">'.format(col4, key4))
for path in project_dependencies[key1][key2][key3][key4]:
write('{0}{1}'.format(col4, path))
if path not in master_dependencies:
master_dependencies.append(path)
write('{0}</Reference>'.format(col4))
write('{0}</Resource>'.format(col3))
write('{0}</Build>'.format(col2))
write('{0}</Project>'.format(col1))
master_dependencies.sort()
for path in master_dependencies:
out_files['MasterDependencies'].write('{0}\n'.format(path))
return
def check_for_version_discrepancies():
""" Check for dependency version discrepancies """
def twrite(message):
""" internal 'ContextTree' write method """
out_files['ContextTree'].write('{0}\n'.format(message))
return
def rwrite(message):
""" internal 'DiscrepancyReport' write method """
out_files['DiscrepancyReport'].write('{0}\n'.format(message))
return
libraries = [
'mysql',
'zlib',
'perl',
'lua',
'boost',
'sodium',
'openssl'
]
references = [
'include',
'source',
'library'
]
priorities = {
0: 'NOT FOUND',
1: 'install',
2: 'dependencies',
3: 'libs',
4: 'vcpkg',
5: 'static',
6: 'submodule'
}
# use all lowercase for path description
# use forward slash ('/') for directory name separators
# use '|' token for multiple hints ('my_file_path_1|my_file_path_2')
# use '!!' token for explicit argument ('/perl/core!!' will find '../perl/core' but not '../perl/core/perl512.lib')
# use '##' token for joined hints ('my_file_##_1')
# use '&&', '^' and '@' tokens for multiple argument hints ('my_file_&&path_1^path_2^path_3@')
# (i.e., 'my_file_path_1|my_file_##_2|my_##_##&&_3^_4!!@')
# {[library]:{[reference]:[[priority]:hint]}}
hints = {
# Notes:
'mysql': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/dependencies/mysql_##/include', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'dependencies/mysql_##/lib', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
},
'zlib': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/zlib_x##/include', # 'dependencies'
# not sure if this should be '/libs/zlibng' or '/build/libs/zlibng' based on cmake behavior
'/server/build/libs/zlibng!!', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'/server/build/libs/zlibng!!', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'/server/libs/zlibng!!', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/zlib_x##/lib/zdll.lib', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/zlib.lib!!'
'^debug/lib/zlibd.lib!!@', # 'vcpkg'
'/server/build/libs/zlibng/&&debug/zlibstaticd.lib!!^minsizerel/zlibstatic.lib!!'
'^release/zlibstatic.lib!!^relwithdebinfo/zlibstatic.lib!!@', # 'static'
'' # 'submodule'
]
},
'perl': {
'include': [
'', # 'NOT FOUND'
'/perl/lib/core!!', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'/perl/lib/core/perl51##.lib', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
},
'lua': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/luaj_x##/src', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/luaj_x##/src', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/luaj_x##/bin/lua51.lib', # 'dependencies'
'', # 'libs'
# debug lua package likely incorrect..should be 'lua51d.lib' - or whatever debug version is
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/lua51.lib!!'
'^debug/lib/lua51.lib!!@', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
},
'boost': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/boost', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/boost', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/lib!!', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
},
'sodium': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/libsodium/include', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/libsodium/##/dynamic/libsodium.lib', # 'dependencies'
'', # 'libs'
# debug libsodium package likely incorrect..should be 'libsodiumd.lib' - or whatever debug version is
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libsodium.lib!!^'
'debug/lib/libsodium.lib!!@', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
},
'openssl': {
'include': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/openssl_x##/include', # 'dependencies'
'', # 'libs'
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/include', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'source': [
'', # 'NOT FOUND'
'', # 'install'
'', # 'dependencies'
'', # 'libs'
'', # 'vcpkg'
'', # 'static'
'' # 'submodule'
],
'library': [
'', # 'NOT FOUND'
'', # 'install'
'/server/dependencies/openssl_x##/lib/VC/&&libeay32MD.lib!!^libeay32MDd.lib!!^'
'ssleay32MD.lib!!^ssleay32MDd.lib!!@', # 'dependencies'
'', # 'libs'
# debug openssl package likely incorrect..should be
# 'libeay32d.lib' and 'ssleay32d.lib' - or whatever debug versions are
'/server/vcpkg/vcpkg-export-##/installed/x##-windows/&&lib/libeay32.lib!!^'
'lib/ssleay32.lib!!^debug/lib/libeay32.lib!!^debug/lib/ssleay32.lib!!@', # 'vcpkg'
'', # 'static'
'' # 'submodule'
]
}
}
# {[project]:{[build]:{[resource]:{[library]:{[reference]:priority}}}}}
context_tree = {}
# {[library]:priority}
global_priorities = {}
# {[build]:{[library]:priority}}
build_priorities = {}
# loop for discovering first occurence dependency sources (assumes same search precedence as compiler includes)
for project in project_dependencies:
if project not in context_tree.keys():
context_tree[project] = {}
for build in project_dependencies[project]:
if build not in context_tree[project].keys():
context_tree[project][build] = {}
if build not in build_priorities.keys():
build_priorities[build] = {}
for resource in project_dependencies[project][build]:
if resource not in context_tree[project][build].keys():
context_tree[project][build][resource] = {}
for reference_project in project_dependencies[project][build][resource]:
for path in project_dependencies[project][build][resource][reference_project]:
for library in libraries:
if library not in context_tree[project][build][resource].keys():
context_tree[project][build][resource][library] = {}
if library not in build_priorities[build].keys():
build_priorities[build][library] = 0
if library not in global_priorities.keys():
global_priorities[library] = 0
for reference in references:
if reference not in context_tree[project][build][resource][library].keys():
context_tree[project][build][resource][library][reference] = 0
elif not context_tree[project][build][resource][library][reference] == 0:
continue
for priority in priorities:
if hints[library][reference][priority] == '':
continue
hint_found = False
for hint in hints[library][reference][priority].split('|'):
if not find_hint_in_path(hint, path) == -1:
context_tree[project][build][resource][library][reference] = priority
if context_tree[project][build][resource][library][reference] >\
build_priorities[build][library]:
build_priorities[build][library] =\
context_tree[project][build][resource][library][reference]
if context_tree[project][build][resource][library][reference] >\
global_priorities[library]:
global_priorities[library] =\
context_tree[project][build][resource][library][reference]
hint_found = True
break
if hint_found is True:
break
# loop for hack to fix odd behavior caused by 'FindZLIB.cmake' - ref: '../server/build/libs/zlibng/zconf.h'
# this does not change anything in the build files..only silences a false discrepancy due to mixing priority types
if global_priorities['zlib'] == 5:
for project in context_tree:
for build in context_tree[project]:
for resource in context_tree[project][build]:
if context_tree[project][build][resource]['zlib']['source'] == 3:
context_tree[project][build][resource]['zlib']['source'] = 5
if context_tree[project][build][resource]['zlib']['include'] == 3:
context_tree[project][build][resource]['zlib']['include'] = 5
# loop for dumping 'global_priorities'
twrite('{0}<Global>'.format(col1))
for library in libraries:
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, global_priorities[library]))
twrite('{0}</Global>'.format(col1))
twrite('')
# loop for dumping 'build_priorities'
for build in build_priorities:
twrite('{0}<Build Type="{1}">'.format(col1, build))
for library in libraries:
twrite('{0}<Library Name="{1}">{2}</Library>'.format(col2, library, build_priorities[build][library]))
twrite('{0}</Build>'.format(col1))
twrite('')
# loop for dumping 'context_tree'
for project in context_tree:
twrite('{0}<Project Path="{1}">'.format(col1, project))
for build in context_tree[project]:
twrite('{0}<Built Type="{1}">'.format(col2, build))
for resource in context_tree[project][build]:
twrite('{0}<Resource Name="{1}">'.format(col3, resource))
for library in context_tree[project][build][resource]:
twrite('{0}<Library Name="{1}">'.format(col4, library))
for reference in context_tree[project][build][resource][library]:
twrite(
'{0}<Reference Name="{1}">{2}</Reference>'.format(
col5,
reference,
context_tree[project][build][resource][library][reference]
)
)
twrite('{0}</Library>'.format(col4))
twrite('{0}</Resource>'.format(col3))
twrite('{0}</Build>'.format(col2))
twrite('{0}</Project>'.format(col1))
if QUIET_REPORT is False:
for library in libraries:
rwrite(
'> Global Library \'{0}\' status: \'{1}\' ({2})'.format(
library,
priorities[global_priorities[library]],
global_priorities[library]
)
)
# loop for identifying dependency discrepancies
for project in context_tree:
for build in context_tree[project]:
for resource in context_tree[project][build]:
for library in context_tree[project][build][resource]:
if global_priorities[library] == 0:
if QUIET_REPORT is False:
rwrite(
'> No Global Library \'{0}\' .. skipping Project:Build:Resource'
' "{1}":"{2}":"{3}"'.format(
library,
project,
build,
resource
)
)
continue
if build_priorities[build][library] == 0:
if QUIET_REPORT is False:
rwrite(
'> No Build Library \'{0}\' .. skipping Project:Build:Resource'
' "{1}":"{2}":"{3}"'.format(
library,
project,
build,
resource
)
)
continue
for reference in context_tree[project][build][resource][library]:
if context_tree[project][build][resource][library][reference] == 0:
continue
if not global_priorities[library] == context_tree[project][build][resource][library][reference]:
rwrite(
'> Global-Project Library \'{0}\' mis-match \'{1}!={2}\''
' ({3}!={4}) Project:Build:Resource "{5}":"{6}":"{7}"'.format(
library,
priorities[global_priorities[library]],
priorities[context_tree[project][build][resource][library][reference]],
global_priorities[library],
context_tree[project][build][resource][library][reference],
project,
build,
resource
)
)
# 'builds' are allowed to have different dependencies..so, we'll start crossing at 'resource'
for cross_resource in context_tree[project][build]:
for cross_reference in context_tree[project][build][cross_resource][library]:
if cross_resource == resource and cross_reference == reference:
continue
if context_tree[project][build][cross_resource][library][cross_reference] == 0:
continue
if QUIET_REPORT is False and\
not context_tree[project][build][cross_resource][library][cross_reference] ==\
context_tree[project][build][resource][library][reference]:
rwrite(
'> Project Library \'{0}\' mis-match \'{1}:{2}:{3}!={4}:{5}:{6}\''
' ({7}!={8}) Project:Build "{9}":"{10}"'.format(
library,
resource,
reference,
priorities[context_tree[project][build][resource][library][reference]],
cross_resource,
cross_reference,
priorities[context_tree[project][build][cross_resource][library]
[cross_reference]],
context_tree[project][build][resource][library][reference],
context_tree[project][build][cross_resource][library][cross_reference],
project,
build
)
)
return
def find_hint_in_path(hint, path):
"""
Helper function for parsing and checking for hints in paths
Hints strings should be split ('|') and passed as a singular hint into this function
"""
if hint == '' or path == '':
return -1
joined_index = hint.find('##')
pretext_index = hint.find('&&')
if joined_index == -1 and pretext_index == -1:
if '^' in hint or '@' in hint:
print '..malformed or improper handling of hint: \'{0}\' path: \'{1}\''.format(hint, path)
return -1
explicit_index = hint.find('!!')
if explicit_index == -1:
return path.find(hint)
else:
explicit_hint = hint[:explicit_index]
found_index = path.find(explicit_hint)
if (len(explicit_hint) + found_index) == len(path):
return found_index
else:
return -1
elif (not joined_index == -1 and pretext_index == -1) or\
(not joined_index == -1 and not pretext_index == -1 and joined_index < pretext_index):
start_index = 0
for partial_hint in hint.split('##', 1):
if partial_hint == '':
continue
found_index = find_hint_in_path(partial_hint, path[start_index:])
if found_index == -1:
return found_index
start_index = found_index + len(partial_hint)
return start_index
elif (joined_index == -1 and not pretext_index == -1) or\
(not joined_index == -1 and not pretext_index == -1 and joined_index > pretext_index):
pretext_hints = hint.split('&&', 1)
found_index = 0
if not pretext_hints[0] == '':
found_index = find_hint_in_path(pretext_hints[0], path)
if found_index == -1:
return found_index
start_index = found_index + len(pretext_hints[0])
partial_hints = pretext_hints[1].split('@', 1)
for partial_hint in partial_hints:
if partial_hint == '':
continue
for alt_hint in partial_hint.split('^'):
if alt_hint == '':
continue
found_index = find_hint_in_path(alt_hint, path[start_index:])
if found_index == 0:
if not partial_hints[1] == '':
print '..unhandled hint method: \'{0}\''.format(partial_hints[1])
else:
return found_index
return -1
else:
return -1
def close_output_files():
""" Close all output files """
while not len(out_files) == 0:
key = out_files.keys()[0]
out_files[key].close()
del out_files[key]
return
if __name__ == '__main__':
main()

View File

@ -393,7 +393,7 @@
9137|2018_12_12_client_faction_tables.sql|SHOW TABLES LIKE 'faction_base_data'|empty| 9137|2018_12_12_client_faction_tables.sql|SHOW TABLES LIKE 'faction_base_data'|empty|
9138|2018_12_12_convert_to_client_functions.sql|SELECT `id` FROM `faction_list` WHERE `id` > 4999|empty| 9138|2018_12_12_convert_to_client_functions.sql|SELECT `id` FROM `faction_list` WHERE `id` > 4999|empty|
9139|2019_03_25_optional_npc_model.sql|SHOW COLUMNS FROM `npc_types` LIKE 'model'|empty| 9139|2019_03_25_optional_npc_model.sql|SHOW COLUMNS FROM `npc_types` LIKE 'model'|empty|
9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `npc_types` LIKE 'max_movement_update_range'|empty| 9140|2019_07_03_update_range.sql|SHOW COLUMNS FROM `zone` LIKE 'max_movement_update_range'|empty|
9141|2019_07_10_npc_flymode.sql|SHOW COLUMNS FROM `npc_types` LIKE 'flymode'|empty| 9141|2019_07_10_npc_flymode.sql|SHOW COLUMNS FROM `npc_types` LIKE 'flymode'|empty|
# Upgrade conditions: # Upgrade conditions:

View File

@ -0,0 +1,2 @@
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`)
VALUES (1, 'GM:MinStatusToLevelTarget', '100', 'GM status needed to use #level on your target');

View File

@ -0,0 +1,2 @@
UPDATE `rule_values` SET `rule_value`='90000' WHERE `rule_name`='Zone:ClientLinkdeadMS';
INSERT INTO `rule_values` (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES (1, 'DisallowDuplicateAccountLogins', 'true', 'Requires account logins to be unique.');

View File

@ -122,7 +122,7 @@ bool Adventure::Process()
else if(status == AS_WaitingForPrimaryEndTime) else if(status == AS_WaitingForPrimaryEndTime)
{ {
//Do partial failure: send a message to the clients that they can only get a certain amount of points. //Do partial failure: send a message to the clients that they can only get a certain amount of points.
SendAdventureMessage(13, "You failed to complete your adventure in time. Complete your adventure goal within 30 minutes to " SendAdventureMessage(Chat::Red, "You failed to complete your adventure in time. Complete your adventure goal within 30 minutes to "
"receive a lesser reward. This adventure will end in 30 minutes and your party will be ejected from the dungeon."); "receive a lesser reward. This adventure will end in 30 minutes and your party will be ejected from the dungeon.");
SetStatus(AS_WaitingForSecondaryEndTime); SetStatus(AS_WaitingForSecondaryEndTime);
} }
@ -287,7 +287,7 @@ void Adventure::Finished(AdventureWinStatus ws)
ClientListEntry *current = client_list.FindCharacter((*iter).c_str()); ClientListEntry *current = client_list.FindCharacter((*iter).c_str());
if(current) if(current)
{ {
if(current->Online() == CLE_Status_InZone) if(current->Online() == CLE_Status::InZone)
{ {
//We can send our packets only. //We can send our packets only.
auto pack = auto pack =

View File

@ -88,7 +88,6 @@ extern volatile bool UCSServerAvailable_;
Client::Client(EQStreamInterface* ieqs) Client::Client(EQStreamInterface* ieqs)
: autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)), : autobootup_timeout(RuleI(World, ZoneAutobootTimeoutMS)),
CLE_keepalive_timer(RuleI(World, ClientKeepaliveTimeoutMS)),
connect(1000), connect(1000),
eqs(ieqs) eqs(ieqs)
{ {
@ -105,6 +104,7 @@ Client::Client(EQStreamInterface* ieqs)
char_name[0] = 0; char_name[0] = 0;
charid = 0; charid = 0;
zone_waiting_for_bootup = 0; zone_waiting_for_bootup = 0;
enter_world_triggered = false;
StartInTutorial = false; StartInTutorial = false;
m_ClientVersion = eqs->ClientVersion(); m_ClientVersion = eqs->ClientVersion();
@ -115,7 +115,7 @@ Client::Client(EQStreamInterface* ieqs)
Client::~Client() { Client::~Client() {
if (RunLoops && cle && zone_id == 0) if (RunLoops && cle && zone_id == 0)
cle->SetOnline(CLE_Status_Offline); cle->SetOnline(CLE_Status::Offline);
numclients--; numclients--;
@ -185,7 +185,7 @@ void Client::SendExpansionInfo() {
void Client::SendCharInfo() { void Client::SendCharInfo() {
if (cle) { if (cle) {
cle->SetOnline(CLE_Status_CharSelect); cle->SetOnline(CLE_Status::CharSelect);
} }
if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) { if (m_ClientVersionBit & EQEmu::versions::maskRoFAndLater) {
@ -461,7 +461,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
// Track who is in and who is out of the game // Track who is in and who is out of the game
char *inout= (char *) ""; char *inout= (char *) "";
if (cle->GetOnline() == CLE_Status_Never){ if (cle->GetOnline() == CLE_Status::Never){
// Desktop -> Char Select // Desktop -> Char Select
inout = (char *) "In"; inout = (char *) "In";
} }
@ -474,7 +474,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) {
// Either from a fresh client launch or coming back from the game. // Either from a fresh client launch or coming back from the game.
// Exiting the game entirely does not come through here. // Exiting the game entirely does not come through here.
// Could use a Logging Out Completely message somewhere. // Could use a Logging Out Completely message somewhere.
cle->SetOnline(CLE_Status_CharSelect); cle->SetOnline(CLE_Status::CharSelect);
Log(Logs::General, Logs::World_Server, Log(Logs::General, Logs::World_Server,
"Account (%s) Logging(%s) to character select :: LSID: %d ", "Account (%s) Logging(%s) to character select :: LSID: %d ",
@ -1076,7 +1076,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) {
{ {
// I don't see this getting executed on logout // I don't see this getting executed on logout
eqs->Close(); eqs->Close();
cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction. cle->SetOnline(CLE_Status::Offline); //allows this player to log in again without an ip restriction.
return false; return false;
} }
case OP_ZoneChange: case OP_ZoneChange:
@ -1119,15 +1119,15 @@ bool Client::Process() {
Log(Logs::General, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow."); Log(Logs::General, Logs::World_Server, "Zone bootup timer expired, bootup failed or too slow.");
TellClientZoneUnavailable(); TellClientZoneUnavailable();
} }
if(connect.Check()){ if(connect.Check()){
SendGuildList();// Send OPCode: OP_GuildsList SendGuildList();// Send OPCode: OP_GuildsList
SendApproveWorld(); SendApproveWorld();
connect.Disable(); connect.Disable();
} }
if (CLE_keepalive_timer.Check()) {
if (cle) if (cle)
cle->KeepAlive(); cle->KeepAlive();
}
/************ Get all packets from packet manager out queue and process them ************/ /************ Get all packets from packet manager out queue and process them ************/
EQApplicationPacket *app = 0; EQApplicationPacket *app = 0;
@ -1191,11 +1191,18 @@ void Client::EnterWorld(bool TryBootup) {
else else
zone_server = zoneserver_list.FindByZoneID(zone_id); zone_server = zoneserver_list.FindByZoneID(zone_id);
const char *zone_name = database.GetZoneName(zone_id, true); const char *zone_name = database.GetZoneName(zone_id, true);
if (zone_server) { if (zone_server) {
// warn the world we're comming, so it knows not to shutdown if (false == enter_world_triggered) {
zone_server->IncomingClient(this); //Drop any clients we own in other zones.
zoneserver_list.DropClient(GetLSID(), zone_server);
// warn the zone we're coming
zone_server->IncomingClient(this);
//tell the server not to trigger this multiple times before we get a zone unavailable
enter_world_triggered = true;
}
} }
else { else {
if (TryBootup) { if (TryBootup) {
@ -1214,9 +1221,17 @@ void Client::EnterWorld(bool TryBootup) {
return; return;
} }
} }
zone_waiting_for_bootup = 0; zone_waiting_for_bootup = 0;
if(!cle) { if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) {
Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked.");
TellClientZoneUnavailable();
return;
}
if (!cle) {
TellClientZoneUnavailable();
return; return;
} }
@ -1233,12 +1248,6 @@ void Client::EnterWorld(bool TryBootup) {
); );
if (seen_character_select) { if (seen_character_select) {
if (GetAdmin() < 80 && zoneserver_list.IsZoneLocked(zone_id)) {
Log(Logs::General, Logs::World_Server, "Enter world failed. Zone is locked.");
TellClientZoneUnavailable();
return;
}
auto pack = new ServerPacket; auto pack = new ServerPacket;
pack->opcode = ServerOP_AcceptWorldEntrance; pack->opcode = ServerOP_AcceptWorldEntrance;
pack->size = sizeof(WorldToZone_Struct); pack->size = sizeof(WorldToZone_Struct);
@ -1344,7 +1353,7 @@ void Client::Clearance(int8 response)
safe_delete(outapp); safe_delete(outapp);
if (cle) if (cle)
cle->SetOnline(CLE_Status_Zoning); cle->SetOnline(CLE_Status::Zoning);
} }
void Client::TellClientZoneUnavailable() { void Client::TellClientZoneUnavailable() {
@ -1358,6 +1367,7 @@ void Client::TellClientZoneUnavailable() {
zone_id = 0; zone_id = 0;
zone_waiting_for_bootup = 0; zone_waiting_for_bootup = 0;
enter_world_triggered = false;
autobootup_timeout.Disable(); autobootup_timeout.Disable();
} }

View File

@ -82,6 +82,7 @@ private:
bool is_player_zoning; bool is_player_zoning;
Timer autobootup_timeout; Timer autobootup_timeout;
uint32 zone_waiting_for_bootup; uint32 zone_waiting_for_bootup;
bool enter_world_triggered;
bool StartInTutorial; bool StartInTutorial;
EQEmu::versions::ClientVersion m_ClientVersion; EQEmu::versions::ClientVersion m_ClientVersion;
@ -94,7 +95,6 @@ private:
void SetClassLanguages(PlayerProfile_Struct *pp); void SetClassLanguages(PlayerProfile_Struct *pp);
ClientListEntry* cle; ClientListEntry* cle;
Timer CLE_keepalive_timer;
Timer connect; Timer connect;
bool firstlogin; bool firstlogin;
bool seen_character_select; bool seen_character_select;

View File

@ -73,7 +73,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, uint32 iAccID, const char* iAccNa
memset(pLFGComments, 0, 64); memset(pLFGComments, 0, 64);
} }
ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline)
: id(in_id) : id(in_id)
{ {
ClearVars(true); ClearVars(true);
@ -94,7 +94,7 @@ ClientListEntry::ClientListEntry(uint32 in_id, ZoneServer* iZS, ServerClientList
pLFGMatchFilter = false; pLFGMatchFilter = false;
memset(pLFGComments, 0, 64); memset(pLFGComments, 0, 64);
if (iOnline >= CLE_Status_Zoning) if (iOnline >= CLE_Status::Zoning)
Update(iZS, scl, iOnline); Update(iZS, scl, iOnline);
else else
SetOnline(iOnline); SetOnline(iOnline);
@ -115,22 +115,24 @@ void ClientListEntry::SetChar(uint32 iCharID, const char* iCharName) {
strn0cpy(pname, iCharName, sizeof(pname)); strn0cpy(pname, iCharName, sizeof(pname));
} }
void ClientListEntry::SetOnline(ZoneServer* iZS, int8 iOnline) { void ClientListEntry::SetOnline(ZoneServer* iZS, CLE_Status iOnline) {
if (iZS == this->Server()) if (iZS == this->Server())
SetOnline(iOnline); SetOnline(iOnline);
} }
void ClientListEntry::SetOnline(int8 iOnline) { void ClientListEntry::SetOnline(CLE_Status iOnline) {
if (iOnline >= CLE_Status_Online && pOnline < CLE_Status_Online) Log(Logs::General, Logs::World_Server, "ClientListEntry::SetOnline for %s(%i) = %i", AccountName(), AccountID(), iOnline);
if (iOnline >= CLE_Status::Online && pOnline < CLE_Status::Online)
numplayers++; numplayers++;
else if (iOnline < CLE_Status_Online && pOnline >= CLE_Status_Online) { else if (iOnline < CLE_Status::Online && pOnline >= CLE_Status::Online) {
numplayers--; numplayers--;
} }
if (iOnline != CLE_Status_Online || pOnline < CLE_Status_Online) if (iOnline != CLE_Status::Online || pOnline < CLE_Status::Online)
pOnline = iOnline; pOnline = iOnline;
if (iOnline < CLE_Status_Zoning) if (iOnline < CLE_Status::Zoning)
Camp(); Camp();
if (pOnline >= CLE_Status_Online) if (pOnline >= CLE_Status::Online)
stale = 0; stale = 0;
} }
void ClientListEntry::LSUpdate(ZoneServer* iZS){ void ClientListEntry::LSUpdate(ZoneServer* iZS){
@ -161,7 +163,7 @@ void ClientListEntry::LSZoneChange(ZoneToZone_Struct* ztz){
safe_delete(pack); safe_delete(pack);
} }
} }
void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline) { void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline) {
if (pzoneserver != iZS) { if (pzoneserver != iZS) {
if (pzoneserver){ if (pzoneserver){
pzoneserver->RemovePlayer(); pzoneserver->RemovePlayer();
@ -208,7 +210,7 @@ void ClientListEntry::Update(ZoneServer* iZS, ServerClientList_Struct* scl, int8
SetOnline(iOnline); SetOnline(iOnline);
} }
void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) { void ClientListEntry::LeavingZone(ZoneServer* iZS, CLE_Status iOnline) {
if (iZS != 0 && iZS != pzoneserver) if (iZS != 0 && iZS != pzoneserver)
return; return;
SetOnline(iOnline); SetOnline(iOnline);
@ -223,7 +225,7 @@ void ClientListEntry::LeavingZone(ZoneServer* iZS, int8 iOnline) {
void ClientListEntry::ClearVars(bool iAll) { void ClientListEntry::ClearVars(bool iAll) {
if (iAll) { if (iAll) {
pOnline = CLE_Status_Never; pOnline = CLE_Status::Never;
stale = 0; stale = 0;
pLSID = 0; pLSID = 0;
@ -269,10 +271,10 @@ void ClientListEntry::Camp(ZoneServer* iZS) {
bool ClientListEntry::CheckStale() { bool ClientListEntry::CheckStale() {
stale++; stale++;
if (stale > 20) { if (stale > 20) {
if (pOnline > CLE_Status_Offline) if (pOnline > CLE_Status::Offline)
SetOnline(CLE_Status_Offline); SetOnline(CLE_Status::Offline);
else
return true; return true;
} }
return false; return false;
} }

View File

@ -8,13 +8,15 @@
#include "../common/rulesys.h" #include "../common/rulesys.h"
#include <vector> #include <vector>
typedef enum
#define CLE_Status_Never -1 {
#define CLE_Status_Offline 0 Never,
#define CLE_Status_Online 1 // Will not overwrite more specific online status Offline,
#define CLE_Status_CharSelect 2 Online,
#define CLE_Status_Zoning 3 CharSelect,
#define CLE_Status_InZone 4 Zoning,
InZone
} CLE_Status;
class ZoneServer; class ZoneServer;
struct ServerClientList_Struct; struct ServerClientList_Struct;
@ -23,25 +25,25 @@ class ClientListEntry {
public: public:
ClientListEntry(uint32 id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0); ClientListEntry(uint32 id, uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0); ClientListEntry(uint32 id, uint32 iAccID, const char* iAccName, MD5& iMD5Pass, int16 iAdmin = 0);
ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, int8 iOnline); ClientListEntry(uint32 id, ZoneServer* iZS, ServerClientList_Struct* scl, CLE_Status iOnline);
~ClientListEntry(); ~ClientListEntry();
bool CheckStale(); bool CheckStale();
void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, int8 iOnline = CLE_Status_InZone); void Update(ZoneServer* zoneserver, ServerClientList_Struct* scl, CLE_Status iOnline = CLE_Status::InZone);
void LSUpdate(ZoneServer* zoneserver); void LSUpdate(ZoneServer* zoneserver);
void LSZoneChange(ZoneToZone_Struct* ztz); void LSZoneChange(ZoneToZone_Struct* ztz);
bool CheckAuth(uint32 iLSID, const char* key); bool CheckAuth(uint32 iLSID, const char* key);
bool CheckAuth(const char* iName, MD5& iMD5Password); bool CheckAuth(const char* iName, MD5& iMD5Password);
bool CheckAuth(uint32 id, const char* key, uint32 ip); bool CheckAuth(uint32 id, const char* key, uint32 ip);
void SetOnline(ZoneServer* iZS, int8 iOnline); void SetOnline(ZoneServer* iZS, CLE_Status iOnline);
void SetOnline(int8 iOnline = CLE_Status_Online); void SetOnline(CLE_Status iOnline = CLE_Status::Online);
void SetChar(uint32 iCharID, const char* iCharName); void SetChar(uint32 iCharID, const char* iCharName);
inline int8 Online() { return pOnline; } inline CLE_Status Online() { return pOnline; }
inline const uint32 GetID() const { return id; } inline const uint32 GetID() const { return id; }
inline const uint32 GetIP() const { return pIP; } inline const uint32 GetIP() const { return pIP; }
inline void SetIP(const uint32& iIP) { pIP = iIP; } inline void SetIP(const uint32& iIP) { pIP = iIP; }
inline void KeepAlive() { stale = 0; } inline void KeepAlive() { stale = 0; }
inline uint8 GetStaleCounter() const { return stale; } inline uint8 GetStaleCounter() const { return stale; }
void LeavingZone(ZoneServer* iZS = 0, int8 iOnline = CLE_Status_Offline); void LeavingZone(ZoneServer* iZS = 0, CLE_Status iOnline = CLE_Status::Offline);
void Camp(ZoneServer* iZS = 0); void Camp(ZoneServer* iZS = 0);
// Login Server stuff // Login Server stuff
@ -50,7 +52,7 @@ public:
inline const char* LSName() const { return plsname; } inline const char* LSName() const { return plsname; }
inline int16 WorldAdmin() const { return pworldadmin; } inline int16 WorldAdmin() const { return pworldadmin; }
inline const char* GetLSKey() const { return plskey; } inline const char* GetLSKey() const { return plskey; }
inline const int8 GetOnline() const { return pOnline; } inline const CLE_Status GetOnline() const { return pOnline; }
// Account stuff // Account stuff
inline uint32 AccountID() const { return paccountid; } inline uint32 AccountID() const { return paccountid; }
@ -93,7 +95,7 @@ private:
const uint32 id; const uint32 id;
uint32 pIP; uint32 pIP;
int8 pOnline; CLE_Status pOnline;
uint8 stale; uint8 stale;
// Login Server stuff // Login Server stuff

View File

@ -41,7 +41,7 @@ extern ZSList zoneserver_list;
uint32 numplayers = 0; //this really wants to be a member variable of ClientList... uint32 numplayers = 0; //this really wants to be a member variable of ClientList...
ClientList::ClientList() ClientList::ClientList()
: CLStale_timer(45000) : CLStale_timer(10000)
{ {
NextCLEID = 1; NextCLEID = 1;
@ -64,8 +64,6 @@ void ClientList::Process() {
struct in_addr in; struct in_addr in;
in.s_addr = iterator.GetData()->GetIP(); in.s_addr = iterator.GetData()->GetIP();
Log(Logs::Detail, Logs::World_Server,"Removing client from %s:%d", inet_ntoa(in), iterator.GetData()->GetPort()); Log(Logs::Detail, Logs::World_Server,"Removing client from %s:%d", inet_ntoa(in), iterator.GetData()->GetPort());
//the client destructor should take care of this.
// iterator.GetData()->Free();
iterator.RemoveCurrent(); iterator.RemoveCurrent();
} }
else else
@ -99,52 +97,6 @@ ClientListEntry* ClientList::GetCLE(uint32 iID) {
return 0; return 0;
} }
//Account Limiting Code to limit the number of characters allowed on from a single account at once.
void ClientList::EnforceSessionLimit(uint32 iLSAccountID) {
ClientListEntry* ClientEntry = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist, BACKWARD);
int CharacterCount = 0;
iterator.Reset();
while(iterator.MoreElements()) {
ClientEntry = iterator.GetData();
if ((ClientEntry->LSAccountID() == iLSAccountID) &&
((ClientEntry->Admin() <= (RuleI(World, ExemptAccountLimitStatus))) || (RuleI(World, ExemptAccountLimitStatus) < 0))) {
CharacterCount++;
if (CharacterCount >= (RuleI(World, AccountSessionLimit))){
// If we have a char name, they are in a zone, so send a kick to the zone server
if(strlen(ClientEntry->name())) {
auto pack =
new ServerPacket(ServerOP_KickPlayer, sizeof(ServerKickPlayer_Struct));
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
strcpy(skp->adminname, "SessionLimit");
strcpy(skp->name, ClientEntry->name());
skp->adminrank = 255;
zoneserver_list.SendPacket(pack);
safe_delete(pack);
}
ClientEntry->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;
}
}
iterator.Advance();
}
}
//Check current CLE Entry IPs against incoming connection //Check current CLE Entry IPs against incoming connection
void ClientList::GetCLEIP(uint32 iIP) { void ClientList::GetCLEIP(uint32 iIP) {
@ -168,7 +120,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
return; return;
} else { } else {
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); countCLEIPs->SetOnline(CLE_Status::Offline);
iterator.RemoveCurrent(); iterator.RemoveCurrent();
continue; continue;
} }
@ -184,7 +136,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
return; return;
} else { } else {
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
iterator.RemoveCurrent(); iterator.RemoveCurrent();
continue; continue;
} }
@ -196,7 +148,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
return; return;
} else { } else {
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
iterator.RemoveCurrent(); iterator.RemoveCurrent();
continue; continue;
} }
@ -207,7 +159,7 @@ void ClientList::GetCLEIP(uint32 iIP) {
return; return;
} else { } else {
Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str()); Log(Logs::General, Logs::Client_Login, "Disconnect: Account %s on IP %s.", countCLEIPs->LSName(), long2ip(countCLEIPs->GetIP()).c_str());
countCLEIPs->SetOnline(CLE_Status_Offline); // Remove the connection countCLEIPs->SetOnline(CLE_Status::Offline); // Remove the connection
iterator.RemoveCurrent(); iterator.RemoveCurrent();
continue; continue;
} }
@ -228,7 +180,7 @@ uint32 ClientList::GetCLEIPCount(uint32 iIP) {
while (iterator.MoreElements()) { while (iterator.MoreElements()) {
countCLEIPs = iterator.GetData(); countCLEIPs = iterator.GetData();
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status_Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt) if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0)) && countCLEIPs->Online() >= CLE_Status::Online) { // If the IP matches, and the connection admin status is below the exempt status, or exempt status is less than 0 (no-one is exempt)
IPInstances++; // Increment the occurences of this IP address IPInstances++; // Increment the occurences of this IP address
} }
iterator.Advance(); iterator.Advance();
@ -254,7 +206,7 @@ void ClientList::DisconnectByIP(uint32 iIP) {
zoneserver_list.SendPacket(pack); zoneserver_list.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
} }
countCLEIPs->SetOnline(CLE_Status_Offline); countCLEIPs->SetOnline(CLE_Status::Offline);
iterator.RemoveCurrent(); iterator.RemoveCurrent();
} }
iterator.Advance(); iterator.Advance();
@ -272,7 +224,7 @@ ClientListEntry* ClientList::FindCharacter(const char* name) {
} }
iterator.Advance(); iterator.Advance();
} }
return 0; return nullptr;
} }
ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) { ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) {
@ -285,7 +237,7 @@ ClientListEntry* ClientList::FindCLEByAccountID(uint32 iAccID) {
} }
iterator.Advance(); iterator.Advance();
} }
return 0; return nullptr;
} }
ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) { ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
@ -298,7 +250,7 @@ ClientListEntry* ClientList::FindCLEByCharacterID(uint32 iCharID) {
} }
iterator.Advance(); iterator.Advance();
} }
return 0; return nullptr;
} }
void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) { void ClientList::SendCLEList(const int16& admin, const char* to, WorldTCPConnection* connection, const char* iName) {
@ -376,10 +328,10 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
if (iterator.GetData()->GetID() == scl->wid) { if (iterator.GetData()->GetID() == scl->wid) {
cle = iterator.GetData(); cle = iterator.GetData();
if (scl->remove == 2){ if (scl->remove == 2){
cle->LeavingZone(zoneserver, CLE_Status_Offline); cle->LeavingZone(zoneserver, CLE_Status::Offline);
} }
else if (scl->remove == 1) else if (scl->remove == 1)
cle->LeavingZone(zoneserver, CLE_Status_Zoning); cle->LeavingZone(zoneserver, CLE_Status::Zoning);
else else
cle->Update(zoneserver, scl); cle->Update(zoneserver, scl);
return; return;
@ -387,11 +339,11 @@ void ClientList::ClientUpdate(ZoneServer* zoneserver, ServerClientList_Struct* s
iterator.Advance(); iterator.Advance();
} }
if (scl->remove == 2) if (scl->remove == 2)
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Online); cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Online);
else if (scl->remove == 1) else if (scl->remove == 1)
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_Zoning); cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::Zoning);
else else
cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status_InZone); cle = new ClientListEntry(GetNextCLEID(), zoneserver, scl, CLE_Status::InZone);
clientlist.Insert(cle); clientlist.Insert(cle);
zoneserver->ChangeWID(scl->charid, cle->GetID()); zoneserver->ChangeWID(scl->charid, cle->GetID());
} }
@ -571,7 +523,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
countcle = countclients.GetData(); countcle = countclients.GetData();
const char* tmpZone = database.GetZoneName(countcle->zone()); const char* tmpZone = database.GetZoneName(countcle->zone());
if ( if (
(countcle->Online() >= CLE_Status_Zoning) && (countcle->Online() >= CLE_Status::Zoning) &&
(!countcle->GetGM() || countcle->Anon() != 1 || admin >= countcle->Admin()) && (!countcle->GetGM() || countcle->Anon() != 1 || admin >= countcle->Admin()) &&
(whom == 0 || ( (whom == 0 || (
((countcle->Admin() >= 80 && countcle->GetGM()) || whom->gmlookup == 0xFFFF) && ((countcle->Admin() >= 80 && countcle->GetGM()) || whom->gmlookup == 0xFFFF) &&
@ -651,7 +603,7 @@ void ClientList::SendWhoAll(uint32 fromid,const char* to, int16 admin, Who_All_S
const char* tmpZone = database.GetZoneName(cle->zone()); const char* tmpZone = database.GetZoneName(cle->zone());
if ( if (
(cle->Online() >= CLE_Status_Zoning) && (cle->Online() >= CLE_Status::Zoning) &&
(!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) && (!cle->GetGM() || cle->Anon() != 1 || admin >= cle->Admin()) &&
(whom == 0 || ( (whom == 0 || (
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) && ((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
@ -824,7 +776,7 @@ void ClientList::SendFriendsWho(ServerFriendsWho_Struct *FriendsWho, WorldTCPCon
Friend_[Seperator - FriendsPointer] = 0; Friend_[Seperator - FriendsPointer] = 0;
ClientListEntry* CLE = FindCharacter(Friend_); ClientListEntry* CLE = FindCharacter(Friend_);
if(CLE && CLE->name() && (CLE->Online() >= CLE_Status_Zoning) && !(CLE->GetGM() && CLE->Anon())) { if(CLE && CLE->name() && (CLE->Online() >= CLE_Status::Zoning) && !(CLE->GetGM() && CLE->Anon())) {
FriendsCLEs.push_back(CLE); FriendsCLEs.push_back(CLE);
TotalLength += strlen(CLE->name()); TotalLength += strlen(CLE->name());
int GuildNameLength = strlen(guild_mgr.GetGuildName(CLE->GuildID())); int GuildNameLength = strlen(guild_mgr.GetGuildName(CLE->GuildID()));
@ -1036,7 +988,7 @@ void ClientList::ConsoleSendWhoAll(const char* to, int16 admin, Who_All_Struct*
cle = iterator.GetData(); cle = iterator.GetData();
const char* tmpZone = database.GetZoneName(cle->zone()); const char* tmpZone = database.GetZoneName(cle->zone());
if ( if (
(cle->Online() >= CLE_Status_Zoning) (cle->Online() >= CLE_Status::Zoning)
&& (whom == 0 || ( && (whom == 0 || (
((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) && ((cle->Admin() >= 80 && cle->GetGM()) || whom->gmlookup == 0xFFFF) &&
(whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) && (whom->lvllow == 0xFFFF || (cle->level() >= whom->lvllow && cle->level() <= whom->lvlhigh)) &&
@ -1310,7 +1262,32 @@ void ClientList::UpdateClientGuild(uint32 char_id, uint32 guild_id) {
} }
} }
void ClientList::RemoveCLEByLSID(uint32 iLSID)
{
LinkedListIterator<ClientListEntry*> iterator(clientlist);
iterator.Reset();
while (iterator.MoreElements()) {
if (iterator.GetData()->LSAccountID() == iLSID) {
iterator.RemoveCurrent();
}
else
iterator.Advance();
}
}
bool ClientList::IsAccountInGame(uint32 iLSID) {
LinkedListIterator<ClientListEntry*> iterator(clientlist);
while (iterator.MoreElements()) {
if (iterator.GetData()->LSID() == iLSID && iterator.GetData()->Online() == CLE_Status::InZone) {
return true;
}
iterator.Advance();
}
return false;
}
int ClientList::GetClientCount() { int ClientList::GetClientCount() {
return(numplayers); return(numplayers);

View File

@ -61,11 +61,12 @@ public:
void GetCLEIP(uint32 iIP); void GetCLEIP(uint32 iIP);
uint32 GetCLEIPCount(uint32 iLSAccountID); uint32 GetCLEIPCount(uint32 iLSAccountID);
void DisconnectByIP(uint32 iIP); void DisconnectByIP(uint32 iIP);
void EnforceSessionLimit(uint32 iLSAccountID);
void CLCheckStale(); void CLCheckStale();
void CLEKeepAlive(uint32 numupdates, uint32* wid); void CLEKeepAlive(uint32 numupdates, uint32* wid);
void CLEAdd(uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0); void CLEAdd(uint32 iLSID, const char* iLoginName, const char* iLoginKey, int16 iWorldAdmin = 0, uint32 ip = 0, uint8 local=0);
void UpdateClientGuild(uint32 char_id, uint32 guild_id); void UpdateClientGuild(uint32 char_id, uint32 guild_id);
void RemoveCLEByLSID(uint32 iLSID);
bool IsAccountInGame(uint32 iLSID);
int GetClientCount(); int GetClientCount();
void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into); void GetClients(const char *zone_name, std::vector<ClientListEntry *> &into);

View File

@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "worlddb.h" #include "worlddb.h"
#include "zonelist.h" #include "zonelist.h"
#include "clientlist.h" #include "clientlist.h"
#include "cliententry.h"
#include "world_config.h" #include "world_config.h"
extern ZSList zoneserver_list; extern ZSList zoneserver_list;
@ -65,38 +66,54 @@ void LoginServer::ProcessUsertoWorldReq(uint16_t opcode, EQ::Net::Packet &p) {
uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid); uint32 id = database.GetAccountIDFromLSID(utwr->lsaccountid);
int16 status = database.CheckStatus(id); int16 status = database.CheckStatus(id);
auto outpack = new ServerPacket; ServerPacket outpack;
outpack->opcode = ServerOP_UsertoWorldResp; outpack.opcode = ServerOP_UsertoWorldResp;
outpack->size = sizeof(UsertoWorldResponse_Struct); outpack.size = sizeof(UsertoWorldResponse_Struct);
outpack->pBuffer = new uchar[outpack->size]; outpack.pBuffer = new uchar[outpack.size];
memset(outpack->pBuffer, 0, outpack->size); memset(outpack.pBuffer, 0, outpack.size);
UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack->pBuffer; UsertoWorldResponse_Struct* utwrs = (UsertoWorldResponse_Struct*)outpack.pBuffer;
utwrs->lsaccountid = utwr->lsaccountid; utwrs->lsaccountid = utwr->lsaccountid;
utwrs->ToID = utwr->FromID; utwrs->ToID = utwr->FromID;
utwrs->worldid = utwr->worldid;
utwrs->response = UserToWorldStatusSuccess;
if (Config->Locked == true) if (Config->Locked == true)
{ {
if ((status == 0 || status < 100) && (status != -2 || status != -1)) if (status < 100) {
utwrs->response = 0; utwrs->response = UserToWorldStatusWorldUnavail;
if (status >= 100) SendPacket(&outpack);
utwrs->response = 1; return;
} }
else {
utwrs->response = 1;
} }
int32 x = Config->MaxClients; int32 x = Config->MaxClients;
if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80) if ((int32)numplayers >= x && x != -1 && x != 255 && status < 80) {
utwrs->response = -3; utwrs->response = UserToWorldStatusWorldAtCapacity;
SendPacket(&outpack);
return;
}
if (status == -1) if (status == -1) {
utwrs->response = -1; utwrs->response = UserToWorldStatusSuspended;
if (status == -2) SendPacket(&outpack);
utwrs->response = -2; return;
}
utwrs->worldid = utwr->worldid; if (status == -2) {
SendPacket(outpack); utwrs->response = UserToWorldStatusBanned;
delete outpack; SendPacket(&outpack);
return;
}
if (RuleB(World, EnforceCharacterLimitAtLogin)) {
if (client_list.IsAccountInGame(utwr->lsaccountid)) {
utwrs->response = UserToWorldStatusAlreadyOnline;
SendPacket(&outpack);
return;
}
}
SendPacket(&outpack);
} }
void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) { void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
@ -105,13 +122,6 @@ void LoginServer::ProcessLSClientAuth(uint16_t opcode, EQ::Net::Packet &p) {
try { try {
auto slsca = p.GetSerialize<ClientAuth_Struct>(0); auto slsca = p.GetSerialize<ClientAuth_Struct>(0);
if (RuleI(World, AccountSessionLimit) >= 0) {
// Enforce the limit on the number of characters on the same account that can be
// online at the same time.
client_list.EnforceSessionLimit(slsca.lsaccount_id);
}
client_list.CLEAdd(slsca.lsaccount_id, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local); client_list.CLEAdd(slsca.lsaccount_id, slsca.name, slsca.key, slsca.worldadmin, slsca.ip, slsca.local);
} }
catch (std::exception &ex) { catch (std::exception &ex) {

View File

@ -123,7 +123,7 @@ int main(int argc, char** argv) {
if (!std::ifstream("eqemu_config.json")) { if (!std::ifstream("eqemu_config.json")) {
CheckForServerScript(true); CheckForServerScript(true);
/* Run EQEmu Server script (Checks for database updates) */ /* Run EQEmu Server script (Checks for database updates) */
system("perl eqemu_server.pl convert_xml"); if(system("perl eqemu_server.pl convert_xml"));
} }
else { else {
/* Download EQEmu Server Maintenance Script if doesn't exist */ /* Download EQEmu Server Maintenance Script if doesn't exist */
@ -627,9 +627,9 @@ void CheckForServerScript(bool force_download) {
std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl; std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl;
#ifdef _WIN32 #ifdef _WIN32
system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""); if(system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""));
#else #else
system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); if(system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"));
#endif #endif
} }
} }

View File

@ -708,6 +708,18 @@ void ZSList::WorldShutDown(uint32 time, uint32 interval)
} }
} }
void ZSList::DropClient(uint32 lsid, ZoneServer *ignore_zoneserver) {
ServerPacket packet(ServerOP_DropClient, sizeof(ServerZoneDropClient_Struct));
auto drop = (ServerZoneDropClient_Struct*)packet.pBuffer;
drop->lsid = lsid;
for (auto &zs : zone_server_list) {
if (zs.get() != ignore_zoneserver) {
zs->SendPacket(&packet);
}
}
}
void ZSList::OnTick(EQ::Timer *t) void ZSList::OnTick(EQ::Timer *t)
{ {
if (!EventSubscriptionWatcher::Get()->IsSubscribed("EQW::ZoneUpdate")) { if (!EventSubscriptionWatcher::Get()->IsSubscribed("EQW::ZoneUpdate")) {

View File

@ -57,6 +57,7 @@ public:
void SOPZoneBootup(const char *adminname, uint32 ZoneServerID, const char *zonename, bool iMakeStatic = false); void SOPZoneBootup(const char *adminname, uint32 ZoneServerID, const char *zonename, bool iMakeStatic = false);
void UpdateUCSServerAvailable(bool ucss_available = true); void UpdateUCSServerAvailable(bool ucss_available = true);
void WorldShutDown(uint32 time, uint32 interval); void WorldShutDown(uint32 time, uint32 interval);
void DropClient(uint32 lsid, ZoneServer *ignore_zoneserver);
ZoneServer* FindByPort(uint16 port); ZoneServer* FindByPort(uint16 port);
ZoneServer* FindByID(uint32 ZoneID); ZoneServer* FindByID(uint32 ZoneID);

View File

@ -409,12 +409,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
if (pack->size < sizeof(ServerChannelMessage_Struct)) if (pack->size < sizeof(ServerChannelMessage_Struct))
break; break;
ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*)pack->pBuffer; ServerChannelMessage_Struct* scm = (ServerChannelMessage_Struct*)pack->pBuffer;
if (scm->chan_num == 20) if (scm->chan_num == ChatChannel_UCSRelay)
{ {
UCSLink.SendMessage(scm->from, scm->message); UCSLink.SendMessage(scm->from, scm->message);
break; break;
} }
if (scm->chan_num == 7 || scm->chan_num == 14) { if (scm->chan_num == ChatChannel_Tell || scm->chan_num == ChatChannel_TellEcho) {
if (scm->deliverto[0] == '*') { if (scm->deliverto[0] == '*') {
if (console) { if (console) {
@ -437,7 +437,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
} }
ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); ClientListEntry* cle = client_list.FindCharacter(scm->deliverto);
if (cle == 0 || cle->Online() < CLE_Status_Zoning || if (cle == 0 || cle->Online() < CLE_Status::Zoning ||
(cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) {
if (!scm->noreply) { if (!scm->noreply) {
ClientListEntry* sender = client_list.FindCharacter(scm->from); ClientListEntry* sender = client_list.FindCharacter(scm->from);
@ -450,7 +450,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
sender->Server()->SendPacket(pack); sender->Server()->SendPacket(pack);
} }
} }
else if (cle->Online() == CLE_Status_Zoning) { else if (cle->Online() == CLE_Status::Zoning) {
if (!scm->noreply) { if (!scm->noreply) {
ClientListEntry* sender = client_list.FindCharacter(scm->from); ClientListEntry* sender = client_list.FindCharacter(scm->from);
if (cle->TellQueueFull()) { if (cle->TellQueueFull()) {
@ -486,7 +486,8 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
cle->Server()->SendPacket(pack); cle->Server()->SendPacket(pack);
} }
else { else {
if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) { if (scm->chan_num == ChatChannel_OOC || scm->chan_num == ChatChannel_Broadcast
|| scm->chan_num == ChatChannel_GMSAY) {
if (console) { if (console) {
console->SendChannelMessage(scm, [&scm]() { console->SendChannelMessage(scm, [&scm]() {
auto pack = new ServerPacket(ServerOP_ChannelMessage, auto pack = new ServerPacket(ServerOP_ChannelMessage,
@ -517,7 +518,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
ClientListEntry* cle = client_list.FindCharacter(svm->To); ClientListEntry* cle = client_list.FindCharacter(svm->To);
if (!cle || (cle->Online() < CLE_Status_Zoning) || !cle->Server()) { if (!cle || (cle->Online() < CLE_Status::Zoning) || !cle->Server()) {
zoneserver_list.SendEmoteMessage(svm->From, 0, 0, 0, "'%s is not online at this time'", svm->To); zoneserver_list.SendEmoteMessage(svm->From, 0, 0, 0, "'%s is not online at this time'", svm->To);
@ -1456,6 +1457,7 @@ void ZoneServer::IncomingClient(Client* client) {
s->accid = client->GetAccountID(); s->accid = client->GetAccountID();
s->admin = client->GetAdmin(); s->admin = client->GetAdmin();
s->charid = client->GetCharID(); s->charid = client->GetCharID();
s->lsid = client->GetLSID();
if (client->GetCLE()) if (client->GetCLE())
s->tellsoff = client->GetCLE()->TellsOff(); s->tellsoff = client->GetCLE()->TellsOff();
strn0cpy(s->charname, client->GetCharName(), sizeof(s->charname)); strn0cpy(s->charname, client->GetCharName(), sizeof(s->charname));

View File

@ -58,7 +58,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record)) if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record))
{ {
Log(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); Log(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id);
Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); Message(Chat::Red, "Unable to find data for pet %s", spells[spell_id].teleport_zone);
return; return;
} }
@ -489,7 +489,7 @@ void Client::ResetAA() {
database.DeleteCharacterLeadershipAAs(CharacterID()); database.DeleteCharacterLeadershipAAs(CharacterID());
// undefined for these clients // undefined for these clients
if (ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier) if (ClientVersionBit() & EQEmu::versions::maskTitaniumAndEarlier)
Kick(); Kick("AA Reset on client that doesn't support it");
} }
void Client::SendClearAA() void Client::SendClearAA()
@ -1091,7 +1091,7 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
SendAlternateAdvancementStats(); SendAlternateAdvancementStats();
if(rank->prev) { if(rank->prev) {
Message_StringID(15, AA_IMPROVE, MessageString(Chat::Yellow, AA_IMPROVE,
std::to_string(rank->title_sid).c_str(), std::to_string(rank->title_sid).c_str(),
std::to_string(rank->prev->current_value).c_str(), std::to_string(rank->prev->current_value).c_str(),
std::to_string(cost).c_str(), std::to_string(cost).c_str(),
@ -1104,7 +1104,7 @@ void Client::FinishAlternateAdvancementPurchase(AA::Rank *rank, bool ignore_cost
} }
} }
else { else {
Message_StringID(15, AA_GAIN_ABILITY, MessageString(Chat::Yellow, AA_GAIN_ABILITY,
std::to_string(rank->title_sid).c_str(), std::to_string(rank->title_sid).c_str(),
std::to_string(cost).c_str(), std::to_string(cost).c_str(),
cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str()); cost == 1 ? std::to_string(AA_POINT).c_str() : std::to_string(AA_POINTS).c_str());
@ -1179,11 +1179,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
uint32 aaremain_sec = aaremain % 60; uint32 aaremain_sec = aaremain % 60;
if(aaremain_hr >= 1) { if(aaremain_hr >= 1) {
Message(13, "You can use this ability again in %u hour(s) %u minute(s) %u seconds", Message(Chat::Red, "You can use this ability again in %u hour(s) %u minute(s) %u seconds",
aaremain_hr, aaremain_min, aaremain_sec); aaremain_hr, aaremain_min, aaremain_sec);
} }
else { else {
Message(13, "You can use this ability again in %u minute(s) %u seconds", Message(Chat::Red, "You can use this ability again in %u minute(s) %u seconds",
aaremain_min, aaremain_sec); aaremain_min, aaremain_sec);
} }
@ -1200,7 +1200,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
CommonBreakInvisible(); CommonBreakInvisible();
if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { if (spells[rank->spell].sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); MessageString(Chat::SpellFailure, SNEAK_RESTRICT);
return; return;
} }
// //
@ -1214,7 +1214,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) {
SetAppearance(eaStanding, false); SetAppearance(eaStanding, false);
if (GetAppearance() != eaStanding) { if (GetAppearance() != eaStanding) {
Message_StringID(MT_SpellFailure, STAND_TO_CAST); MessageString(Chat::SpellFailure, STAND_TO_CAST);
return; return;
} }
} }

View File

@ -52,12 +52,12 @@ void EntityList::CheckClientAggro(Client *around)
void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbose) { void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbose) {
float d2 = d*d; float d2 = d*d;
towho->Message(0, "Describing aggro for %s", from_who->GetName()); towho->Message(Chat::White, "Describing aggro for %s", from_who->GetName());
bool engaged = from_who->IsEngaged(); bool engaged = from_who->IsEngaged();
if(engaged) { if(engaged) {
Mob *top = from_who->GetHateTop(); Mob *top = from_who->GetHateTop();
towho->Message(0, ".. I am currently fighting with %s", top == nullptr?"(nullptr)":top->GetName()); towho->Message(Chat::White, ".. I am currently fighting with %s", top == nullptr?"(nullptr)":top->GetName());
} }
bool check_npcs = from_who->WillAggroNPCs(); bool check_npcs = from_who->WillAggroNPCs();
@ -77,7 +77,7 @@ void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbo
if(!database.GetFactionName(my_primary, namebuf, sizeof(namebuf))) if(!database.GetFactionName(my_primary, namebuf, sizeof(namebuf)))
strcpy(namebuf, "(Unknown)"); strcpy(namebuf, "(Unknown)");
} }
towho->Message(0, ".. I am on faction %s (%d)\n", namebuf, my_primary); towho->Message(Chat::White, ".. I am on faction %s (%d)\n", namebuf, my_primary);
} }
for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { for (auto it = mob_list.begin(); it != mob_list.end(); ++it) {
@ -91,11 +91,11 @@ void EntityList::DescribeAggro(Client *towho, NPC *from_who, float d, bool verbo
if (engaged) { if (engaged) {
uint32 amm = from_who->GetHateAmount(mob); uint32 amm = from_who->GetHateAmount(mob);
if (amm == 0) if (amm == 0)
towho->Message(0, "... %s is not on my hate list.", mob->GetName()); towho->Message(Chat::White, "... %s is not on my hate list.", mob->GetName());
else else
towho->Message(0, "... %s is on my hate list with value %lu", mob->GetName(), (unsigned long)amm); towho->Message(Chat::White, "... %s is on my hate list with value %lu", mob->GetName(), (unsigned long)amm);
} else if (!check_npcs && mob->IsNPC()) { } else if (!check_npcs && mob->IsNPC()) {
towho->Message(0, "... %s is an NPC and my npc_aggro is disabled.", mob->GetName()); towho->Message(Chat::White, "... %s is an NPC and my npc_aggro is disabled.", mob->GetName());
} else { } else {
from_who->DescribeAggro(towho, mob, verbose); from_who->DescribeAggro(towho, mob, verbose);
} }
@ -114,13 +114,13 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
if(( t1 > iAggroRange) if(( t1 > iAggroRange)
|| ( t2 > iAggroRange) || ( t2 > iAggroRange)
|| ( t3 > iAggroRange) ) { || ( t3 > iAggroRange) ) {
towho->Message(0, "...%s is out of range (fast). distances (%.3f,%.3f,%.3f), range %.3f", mob->GetName(), towho->Message(Chat::White, "...%s is out of range (fast). distances (%.3f,%.3f,%.3f), range %.3f", mob->GetName(),
t1, t2, t3, iAggroRange); t1, t2, t3, iAggroRange);
return; return;
} }
if(mob->IsInvisible(this)) { if(mob->IsInvisible(this)) {
towho->Message(0, "...%s is invisible to me. ", mob->GetName()); towho->Message(Chat::White, "...%s is invisible to me. ", mob->GetName());
return; return;
} }
if((mob->IsClient() && if((mob->IsClient() &&
@ -131,13 +131,13 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
) )
)) ))
{ {
towho->Message(0, "...%s is my owner. ", mob->GetName()); towho->Message(Chat::White, "...%s is my owner. ", mob->GetName());
return; return;
} }
if(mob == GetOwner()) { if(mob == GetOwner()) {
towho->Message(0, "...%s a GM or is not connected. ", mob->GetName()); towho->Message(Chat::White, "...%s a GM or is not connected. ", mob->GetName());
return; return;
} }
@ -145,7 +145,7 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
float iAggroRange2 = iAggroRange*iAggroRange; float iAggroRange2 = iAggroRange*iAggroRange;
if( dist2 > iAggroRange2 ) { if( dist2 > iAggroRange2 ) {
towho->Message(0, "...%s is out of range. %.3f > %.3f ", mob->GetName(), towho->Message(Chat::White, "...%s is out of range. %.3f > %.3f ", mob->GetName(),
dist2, iAggroRange2); dist2, iAggroRange2);
return; return;
} }
@ -154,14 +154,14 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
{ {
if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3) if (GetLevel() < RuleI(Aggro, MinAggroLevel) && mob->GetLevelCon(GetLevel()) == CON_GRAY && GetBodyType() != 3)
{ {
towho->Message(0, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2); towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(), dist2, iAggroRange2);
return; return;
} }
} }
else else
{ {
if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY ) { if(GetINT() > RuleI(Aggro, IntAggroThreshold) && mob->GetLevelCon(GetLevel()) == CON_GRAY ) {
towho->Message(0, "...%s is red to me (basically)", mob->GetName(), towho->Message(Chat::White, "...%s is red to me (basically)", mob->GetName(),
dist2, iAggroRange2); dist2, iAggroRange2);
return; return;
} }
@ -178,9 +178,9 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
mob_primary = own->GetPrimaryFaction(); mob_primary = own->GetPrimaryFaction();
if(mob_primary == 0) { if(mob_primary == 0) {
towho->Message(0, "...%s has no primary faction", mob->GetName()); towho->Message(Chat::White, "...%s has no primary faction", mob->GetName());
} else if(mob_primary < 0) { } else if(mob_primary < 0) {
towho->Message(0, "...%s is on special faction %d", mob->GetName(), mob_primary); towho->Message(Chat::White, "...%s is on special faction %d", mob->GetName(), mob_primary);
} else { } else {
char namebuf[256]; char namebuf[256];
if(!database.GetFactionName(mob_primary, namebuf, sizeof(namebuf))) if(!database.GetFactionName(mob_primary, namebuf, sizeof(namebuf)))
@ -193,22 +193,22 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
struct NPCFaction* fac = *cur; struct NPCFaction* fac = *cur;
if ((int32)fac->factionID == mob_primary) { if ((int32)fac->factionID == mob_primary) {
if (fac->npc_value > 0) { if (fac->npc_value > 0) {
towho->Message(0, "...%s is on ALLY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value); towho->Message(Chat::White, "...%s is on ALLY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value);
res = true; res = true;
break; break;
} else if (fac->npc_value < 0) { } else if (fac->npc_value < 0) {
towho->Message(0, "...%s is on ENEMY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value); towho->Message(Chat::White, "...%s is on ENEMY faction %s (%d) with %d", mob->GetName(), namebuf, mob_primary, fac->npc_value);
res = true; res = true;
break; break;
} else { } else {
towho->Message(0, "...%s is on NEUTRAL faction %s (%d) with 0", mob->GetName(), namebuf, mob_primary); towho->Message(Chat::White, "...%s is on NEUTRAL faction %s (%d) with 0", mob->GetName(), namebuf, mob_primary);
res = true; res = true;
break; break;
} }
} }
} }
if(!res) { if(!res) {
towho->Message(0, "...%s is on faction %s (%d), which I have no entry for.", mob->GetName(), namebuf, mob_primary); towho->Message(Chat::White, "...%s is on faction %s (%d), which I have no entry for.", mob->GetName(), namebuf, mob_primary);
} }
} }
} }
@ -222,18 +222,18 @@ void NPC::DescribeAggro(Client *towho, Mob *mob, bool verbose) {
|| ||
fv == FACTION_THREATENLY fv == FACTION_THREATENLY
)) { )) {
towho->Message(0, "...%s faction not low enough. value='%s'", mob->GetName(), FactionValueToString(fv)); towho->Message(Chat::White, "...%s faction not low enough. value='%s'", mob->GetName(), FactionValueToString(fv));
return; return;
} }
if(fv == FACTION_THREATENLY) { if(fv == FACTION_THREATENLY) {
towho->Message(0, "...%s threatening to me, so they only have a %d chance per check of attacking.", mob->GetName()); towho->Message(Chat::White, "...%s threatening to me, so they only have a %d chance per check of attacking.", mob->GetName());
} }
if(!CheckLosFN(mob)) { if(!CheckLosFN(mob)) {
towho->Message(0, "...%s is out of sight.", mob->GetName()); towho->Message(Chat::White, "...%s is out of sight.", mob->GetName());
} }
towho->Message(0, "...%s meets all conditions, I should be attacking them.", mob->GetName()); towho->Message(Chat::White, "...%s meets all conditions, I should be attacking them.", mob->GetName());
} }
/* /*
@ -973,11 +973,13 @@ bool Mob::CombatRange(Mob* other)
} }
//Father Nitwit's LOS code //Father Nitwit's LOS code
bool Mob::CheckLosFN(Mob* other) { bool Mob::CheckLosFN(Mob *other)
{
bool Result = false; bool Result = false;
if(other) if (other) {
Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize()); Result = CheckLosFN(other->GetX(), other->GetY(), other->GetZ(), other->GetSize());
}
SetLastLosState(Result); SetLastLosState(Result);

View File

@ -225,7 +225,7 @@ Json::Value ApiGetNpcListDetail(EQ::Net::WebsocketServerConnection *connection,
row["sec_skill"] = npc->GetSecSkill(); row["sec_skill"] = npc->GetSecSkill();
row["silver"] = npc->GetSilver(); row["silver"] = npc->GetSilver();
row["slow_mitigation"] = npc->GetSlowMitigation(); row["slow_mitigation"] = npc->GetSlowMitigation();
row["sp2"] = npc->GetSp2(); row["spawn_group_id"] = npc->GetSpawnGroupId();
row["swarm_owner"] = npc->GetSwarmOwner(); row["swarm_owner"] = npc->GetSwarmOwner();
row["swarm_target"] = npc->GetSwarmTarget(); row["swarm_target"] = npc->GetSwarmTarget();
row["waypoint_max"] = npc->GetWaypointMax(); row["waypoint_max"] = npc->GetWaypointMax();

View File

@ -34,6 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "lua_parser.h" #include "lua_parser.h"
#include "fastmath.h" #include "fastmath.h"
#include "mob.h" #include "mob.h"
#include "npc.h"
#include <assert.h> #include <assert.h>
@ -1319,7 +1320,7 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts)
if (other->AvoidDamage(this, hit)) { if (other->AvoidDamage(this, hit)) {
int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough;
if (strike_through && zone->random.Roll(strike_through)) { if (strike_through && zone->random.Roll(strike_through)) {
Message_StringID(MT_StrikeThrough, MessageString(Chat::StrikeThrough,
STRIKETHROUGH_STRING); // You strike through your opponents defenses! STRIKETHROUGH_STRING); // You strike through your opponents defenses!
hit.damage_done = 1; // set to one, we will check this to continue hit.damage_done = 1; // set to one, we will check this to continue
} }
@ -1340,9 +1341,9 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts)
int stun_resist2 = other->spellbonuses.FrontalStunResist + other->itembonuses.FrontalStunResist + other->aabonuses.FrontalStunResist; int stun_resist2 = other->spellbonuses.FrontalStunResist + other->itembonuses.FrontalStunResist + other->aabonuses.FrontalStunResist;
int stun_resist = other->spellbonuses.StunResist + other->itembonuses.StunResist + other->aabonuses.StunResist; int stun_resist = other->spellbonuses.StunResist + other->itembonuses.StunResist + other->aabonuses.StunResist;
if (zone->random.Roll(stun_resist2)) { if (zone->random.Roll(stun_resist2)) {
other->Message_StringID(MT_Stun, AVOID_STUNNING_BLOW); other->MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
} else if (zone->random.Roll(stun_resist)) { } else if (zone->random.Roll(stun_resist)) {
other->Message_StringID(MT_Stun, SHAKE_OFF_STUN); other->MessageString(Chat::Stun, SHAKE_OFF_STUN);
} else { } else {
other->Stun(3000); // yuck -- 3 seconds other->Stun(3000); // yuck -- 3 seconds
} }
@ -1392,7 +1393,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b
if (DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm if (DivineAura() && !GetGM()) {//cant attack while invulnerable unless your a gm
Log(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect."); Log(Logs::Detail, Logs::Combat, "Attack canceled, Divine Aura is in effect.");
Message_StringID(MT_DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable! MessageString(Chat::DefaultText, DIVINE_AURA_NO_ATK); //You can't attack while invulnerable!
return false; return false;
} }
@ -1615,16 +1616,16 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk
if (killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { if (killerMob && killerMob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
char val1[20] = { 0 }; char val1[20] = { 0 };
entity_list.MessageClose_StringID( entity_list.MessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, DamageMessages), RuleI(Range, DamageMessages),
MT_NonMelee, /* 283 */ Chat::NonMelee, /* 283 */
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
killerMob->GetCleanName(), /* Message1 */ killerMob->GetCleanName(), /* Message1 */
GetCleanName(), /* Message2 */ GetCleanName(), /* Message2 */
ConvertArray(damage, val1)/* Message3 */ ConvertArray(damage, val1)/* Message3 */
); );
} }
int exploss = 0; int exploss = 0;
@ -1914,7 +1915,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool
//Check that we can attack before we calc heading and face our target //Check that we can attack before we calc heading and face our target
if (!IsAttackAllowed(other)) { if (!IsAttackAllowed(other)) {
if (this->GetOwnerID()) if (this->GetOwnerID())
this->Say_StringID(NOT_LEGAL_TARGET); this->SayString(NOT_LEGAL_TARGET);
if (other) { if (other) {
if (other->IsClient()) if (other->IsClient())
other->CastToClient()->RemoveXTarget(this, false); other->CastToClient()->RemoveXTarget(this, false);
@ -2129,7 +2130,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill
{ {
if (IsLDoNTrapped()) if (IsLDoNTrapped())
{ {
Message_StringID(13, LDON_ACCIDENT_SETOFF2); MessageString(Chat::Red, LDON_ACCIDENT_SETOFF2);
SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false);
SetLDoNTrapSpellID(0); SetLDoNTrapSpellID(0);
SetLDoNTrapped(false); SetLDoNTrapped(false);
@ -2169,16 +2170,16 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil
if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) { if (killer_mob->IsClient() && (spell != SPELL_UNKNOWN) && damage > 0) {
char val1[20] = { 0 }; char val1[20] = { 0 };
entity_list.MessageClose_StringID( entity_list.MessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, DamageMessages), RuleI(Range, DamageMessages),
MT_NonMelee, /* 283 */ Chat::NonMelee, /* 283 */
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
killer_mob->GetCleanName(), /* Message1 */ killer_mob->GetCleanName(), /* Message1 */
GetCleanName(), /* Message2 */ GetCleanName(), /* Message2 */
ConvertArray(damage, val1) /* Message3 */ ConvertArray(damage, val1) /* Message3 */
); );
} }
} }
else { else {
@ -3425,7 +3426,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
//we used to do a message to the client, but its gone now. //we used to do a message to the client, but its gone now.
// emote goes with every one ... even npcs // emote goes with every one ... even npcs
entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), MT_Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName()); entity_list.MessageClose(this, true, RuleI(Range, SpellMessages), Chat::Emote, "%s beams a smile at %s", attacker->GetCleanName(), this->GetCleanName());
} }
} //end `if there is some damage being done and theres anattacker person involved` } //end `if there is some damage being done and theres anattacker person involved`
@ -3439,7 +3440,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
Log(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName()); Log(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName());
pet->AddToHateList(attacker, 1, 0, true, false, false, spell_id); pet->AddToHateList(attacker, 1, 0, true, false, false, spell_id);
pet->SetTarget(attacker); pet->SetTarget(attacker);
Message_StringID(10, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName()); MessageString(Chat::NPCQuestSay, PET_ATTACKING, pet->GetCleanName(), attacker->GetCleanName());
} }
} }
@ -3459,7 +3460,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker); damage = AffectMagicalDamage(damage, spell_id, iBuffTic, attacker);
if (origdmg != damage && attacker && attacker->IsClient()) { if (origdmg != damage && attacker && attacker->IsClient()) {
if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)
attacker->Message(15, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg); attacker->Message(Chat::Yellow, "The Spellshield absorbed %d of %d points of damage", origdmg - damage, origdmg);
} }
if (damage == 0 && attacker && origdmg != damage && IsClient()) { if (damage == 0 && attacker && origdmg != damage && IsClient()) {
//Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes. //Kayen: Probably need to add a filter for this - Not sure if this msg is correct but there should be a message for spell negate/runes.
@ -3507,15 +3508,15 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
//fade mez if we are mezzed //fade mez if we are mezzed
if (IsMezzed() && attacker) { if (IsMezzed() && attacker) {
Log(Logs::Detail, Logs::Combat, "Breaking mez due to attack."); Log(Logs::Detail, Logs::Combat, "Breaking mez due to attack.");
entity_list.MessageClose_StringID( entity_list.MessageCloseString(
this, /* Sender */ this, /* Sender */
true, /* Skip Sender */ true, /* Skip Sender */
RuleI(Range, SpellMessages), RuleI(Range, SpellMessages),
MT_WornOff, /* 284 */ Chat::SpellWornOff, /* 284 */
HAS_BEEN_AWAKENED, // %1 has been awakened by %2. HAS_BEEN_AWAKENED, // %1 has been awakened by %2.
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
attacker->GetCleanName() /* Message2 */ attacker->GetCleanName() /* Message2 */
); );
BuffFadeByEffect(SE_Mez); BuffFadeByEffect(SE_Mez);
} }
@ -3564,13 +3565,13 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
else { else {
// stun resist passed! // stun resist passed!
if (IsClient()) if (IsClient())
Message_StringID(MT_Stun, SHAKE_OFF_STUN); MessageString(Chat::Stun, SHAKE_OFF_STUN);
} }
} }
else { else {
// stun resist 2 passed! // stun resist 2 passed!
if (IsClient()) if (IsClient())
Message_StringID(MT_Stun, AVOID_STUNNING_BLOW); MessageString(Chat::Stun, AVOID_STUNNING_BLOW);
} }
} }
else { else {
@ -3650,7 +3651,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) { if (((spell_id != SPELL_UNKNOWN) || (FromDamageShield)) && damage>0) {
//special crap for spell damage, looks hackish to me //special crap for spell damage, looks hackish to me
char val1[20] = { 0 }; char val1[20] = { 0 };
owner->Message_StringID(MT_NonMelee, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); owner->MessageString(Chat::NonMelee, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
} }
else { else {
if (damage > 0) { if (damage > 0) {
@ -3680,19 +3681,19 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
char val1[20] = { 0 }; char val1[20] = { 0 };
if (FromDamageShield) { if (FromDamageShield) {
if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide) if (attacker->CastToClient()->GetFilter(FilterDamageShields) != FilterHide)
attacker->Message_StringID(MT_DS, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1)); attacker->MessageString(Chat::DamageShield, OTHER_HIT_NONMELEE, GetCleanName(), ConvertArray(damage, val1));
} }
else { else {
entity_list.MessageClose_StringID( entity_list.MessageCloseString(
this, /* Sender */ this, /* Sender */
true, /* Skip Sender */ true, /* Skip Sender */
RuleI(Range, SpellMessages), RuleI(Range, SpellMessages),
MT_NonMelee, /* 283 */ Chat::NonMelee, /* 283 */
HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */ HIT_NON_MELEE, /* %1 hit %2 for %3 points of non-melee damage. */
attacker->GetCleanName(), /* Message1 */ attacker->GetCleanName(), /* Message1 */
GetCleanName(), /* Message2 */ GetCleanName(), /* Message2 */
ConvertArray(damage, val1) /* Message3 */ ConvertArray(damage, val1) /* Message3 */
); );
} }
} }
else { else {
@ -3754,22 +3755,22 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const
// So we can see our dot dmg like live shows it. // So we can see our dot dmg like live shows it.
if (spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) { if (spell_id != SPELL_UNKNOWN && damage > 0 && attacker && attacker != this && attacker->IsClient()) {
//might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it //might filter on (attack_skill>200 && attack_skill<250), but I dont think we need it
attacker->FilteredMessage_StringID(attacker, MT_DoTDamage, FilterDOT, attacker->FilteredMessageString(attacker, Chat::DotDamage, FilterDOT,
YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name); YOUR_HIT_DOT, GetCleanName(), itoa(damage), spells[spell_id].name);
/* older clients don't have the below String ID, but it will be filtered */ /* older clients don't have the below String ID, but it will be filtered */
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
attacker, /* Sender */ attacker, /* Sender */
true, /* Skip Sender */ true, /* Skip Sender */
RuleI(Range, SpellMessages), RuleI(Range, SpellMessages),
MT_DoTDamage, /* Type: 325 */ Chat::DotDamage, /* Type: 325 */
FilterDOT, /* FilterType: 19 */ FilterDOT, /* FilterType: 19 */
OTHER_HIT_DOT, /* MessageFormat: %1 has taken %2 damage from %3 by %4. */ OTHER_HIT_DOT, /* MessageFormat: %1 has taken %2 damage from %3 by %4. */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(damage), /* Message2 */ itoa(damage), /* Message2 */
attacker->GetCleanName(), /* Message3 */ attacker->GetCleanName(), /* Message3 */
spells[spell_id].name /* Message4 */ spells[spell_id].name /* Message4 */
); );
} }
} //end packet sending } //end packet sending
@ -3792,42 +3793,42 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
// message to caster // message to caster
if (caster->IsClient() && caster == this) { if (caster->IsClient() && caster == this) {
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater) if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime,
HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name); HOT_HEAL_SELF, itoa(acthealed), spells[spell_id].name);
else else
FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime,
YOU_HEALED, GetCleanName(), itoa(acthealed)); YOU_HEALED, GetCleanName(), itoa(acthealed));
} }
else if (caster->IsClient() && caster != this) { else if (caster->IsClient() && caster != this) {
if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater) if (caster->CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, caster->FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime,
HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed), HOT_HEAL_OTHER, GetCleanName(), itoa(acthealed),
spells[spell_id].name); spells[spell_id].name);
else else
caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterHealOverTime, caster->FilteredMessageString(caster, Chat::NonMelee, FilterHealOverTime,
YOU_HEAL, GetCleanName(), itoa(acthealed)); YOU_HEAL, GetCleanName(), itoa(acthealed));
} }
// message to target // message to target
if (IsClient() && caster != this) { if (IsClient() && caster != this) {
if (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater) if (CastToClient()->ClientVersionBit() & EQEmu::versions::maskSoFAndLater)
FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, FilteredMessageString(this, Chat::NonMelee, FilterHealOverTime,
HOT_HEALED_OTHER, caster->GetCleanName(), HOT_HEALED_OTHER, caster->GetCleanName(),
itoa(acthealed), spells[spell_id].name); itoa(acthealed), spells[spell_id].name);
else else
FilteredMessage_StringID(this, MT_NonMelee, FilterHealOverTime, FilteredMessageString(this, Chat::NonMelee, FilterHealOverTime,
YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); YOU_HEALED, caster->GetCleanName(), itoa(acthealed));
} }
} }
else { // normal heals else { // normal heals
FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
YOU_HEALED, caster->GetCleanName(), itoa(acthealed)); YOU_HEALED, caster->GetCleanName(), itoa(acthealed));
if (caster != this) if (caster != this)
caster->FilteredMessage_StringID(caster, MT_NonMelee, FilterSpellDamage, caster->FilteredMessageString(caster, Chat::NonMelee, FilterSpellDamage,
YOU_HEAL, GetCleanName(), itoa(acthealed)); YOU_HEAL, GetCleanName(), itoa(acthealed));
} }
} }
else { else {
Message(MT_NonMelee, "You have been healed for %d points of damage.", acthealed); Message(Chat::NonMelee, "You have been healed for %d points of damage.", acthealed);
} }
} }
@ -3993,10 +3994,10 @@ void Mob::TryWeaponProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *
if (IsPet()) { if (IsPet()) {
Mob *own = GetOwner(); Mob *own = GetOwner();
if (own) if (own)
own->Message_StringID(13, PROC_PETTOOLOW); own->MessageString(Chat::Red, PROC_PETTOOLOW);
} }
else { else {
Message_StringID(13, PROC_TOOLOW); MessageString(Chat::Red, PROC_TOOLOW);
} }
} }
else { else {
@ -4030,10 +4031,10 @@ void Mob::TryWeaponProc(const EQEmu::ItemInstance *inst, const EQEmu::ItemData *
if (IsPet()) { if (IsPet()) {
Mob *own = GetOwner(); Mob *own = GetOwner();
if (own) if (own)
own->Message_StringID(13, PROC_PETTOOLOW); own->MessageString(Chat::Red, PROC_PETTOOLOW);
} }
else { else {
Message_StringID(13, PROC_TOOLOW); MessageString(Chat::Red, PROC_TOOLOW);
} }
} }
else { else {
@ -4183,16 +4184,16 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit)
hit.damage_done += 5; hit.damage_done += 5;
hit.damage_done = (hit.damage_done * critMod) / 100; hit.damage_done = (hit.damage_done * critMod) / 100;
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
} }
} }
@ -4243,29 +4244,29 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
/* Female */ /* Female */
if (GetGender() == 1) { if (GetGender() == 1) {
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */ FEMALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses her target!(%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
} }
/* Males and Neuter */ /* Males and Neuter */
else { else {
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */ MALE_SLAYUNDEAD, /* MessageFormat: %1's holy blade cleanses his target!(%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
} }
return; return;
} }
@ -4340,16 +4341,16 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
} }
hit.damage_done = hit.damage_done * 200 / 100; hit.damage_done = hit.damage_done * 200 / 100;
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */ DEADLY_STRIKE, /* MessageFormat: %1 scores a Deadly Strike!(%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
return; return;
} }
} }
@ -4368,16 +4369,16 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
hit.damage_done += og_damage * 119 / 100; hit.damage_done += og_damage * 119 / 100;
Log(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done); Log(Logs::Detail, Logs::Combat, "Crip damage %d", hit.damage_done);
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */ CRIPPLING_BLOW, /* MessageFormat: %1 lands a Crippling Blow!(%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
// Crippling blows also have a chance to stun // Crippling blows also have a chance to stun
// Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a // Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a
@ -4390,16 +4391,16 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *
} }
/* Normal Critical hit message */ /* Normal Critical hit message */
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */ CRITICAL_HIT, /* MessageFormat: %1 scores a critical hit! (%2) */
GetCleanName(), /* Message1 */ GetCleanName(), /* Message1 */
itoa(hit.damage_done + hit.min_damage) /* Message2 */ itoa(hit.damage_done + hit.min_damage) /* Message2 */
); );
} }
} }
} }
@ -4427,15 +4428,15 @@ bool Mob::TryFinishingBlow(Mob *defender, int &damage)
(ProcChance >= zone->random.Int(1, 1000))) { (ProcChance >= zone->random.Int(1, 1000))) {
/* Finishing Blow Critical Message */ /* Finishing Blow Critical Message */
entity_list.FilteredMessageClose_StringID( entity_list.FilteredMessageCloseString(
this, /* Sender */ this, /* Sender */
false, /* Skip Sender */ false, /* Skip Sender */
RuleI(Range, CriticalDamage), RuleI(Range, CriticalDamage),
MT_CritMelee, /* Type: 301 */ Chat::MeleeCrit, /* Type: 301 */
FilterMeleeCrits, /* FilterType: 12 */ FilterMeleeCrits, /* FilterType: 12 */
FINISHING_BLOW, /* MessageFormat: %1 scores a Finishing Blow!!) */ FINISHING_BLOW, /* MessageFormat: %1 scores a Finishing Blow!!) */
GetCleanName() /* Message1 */ GetCleanName() /* Message1 */
); );
damage = FB_Dmg; damage = FB_Dmg;
return true; return true;
@ -4453,7 +4454,7 @@ void Mob::DoRiposte(Mob *defender)
// so ahhh the angle you can riposte is larger than the angle you can hit :P // so ahhh the angle you can riposte is larger than the angle you can hit :P
if (!defender->IsFacingMob(this)) { if (!defender->IsFacingMob(this)) {
defender->Message_StringID(MT_TooFarAway, CANT_SEE_TARGET); defender->MessageString(Chat::TooFarAway, CANT_SEE_TARGET);
return; return;
} }
@ -5042,7 +5043,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac
else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot
if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) { if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) {
hit.damage_done *= 2; hit.damage_done *= 2;
Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); MessageString(Chat::MeleeCrit, BOW_DOUBLE_DAMAGE);
} }
} }
} }
@ -5347,7 +5348,7 @@ void Client::DoAttackRounds(Mob *target, int hand, bool IsFromSpell)
Attack(target, hand, false, false, IsFromSpell); Attack(target, hand, false, false, IsFromSpell);
if (zone->random.Roll(flurrychance)) if (zone->random.Roll(flurrychance))
Attack(target, hand, false, false, IsFromSpell); Attack(target, hand, false, false, IsFromSpell);
Message_StringID(MT_NPCFlurry, YOU_FLURRY); MessageString(Chat::NPCFlurry, YOU_FLURRY);
} }
} }
} }

View File

@ -710,13 +710,13 @@ void Mob::MakeAura(uint16 spell_id)
AuraRecord record; AuraRecord record;
if (!database.GetAuraEntry(spell_id, record)) { if (!database.GetAuraEntry(spell_id, record)) {
Message(13, "Unable to find data for aura %s", spells[spell_id].name); Message(Chat::Red, "Unable to find data for aura %s", spells[spell_id].name);
Log(Logs::General, Logs::Error, "Unable to find data for aura %d, check auras table.", spell_id); Log(Logs::General, Logs::Error, "Unable to find data for aura %d, check auras table.", spell_id);
return; return;
} }
if (!IsValidSpell(record.spell_id)) { if (!IsValidSpell(record.spell_id)) {
Message(13, "Casted spell (%d) is not valid for aura %s", record.spell_id, spells[spell_id].name); Message(Chat::Red, "Casted spell (%d) is not valid for aura %s", record.spell_id, spells[spell_id].name);
Log(Logs::General, Logs::Error, "Casted spell (%d) is not valid for aura %d, check auras table.", Log(Logs::General, Logs::Error, "Casted spell (%d) is not valid for aura %d, check auras table.",
record.spell_id, spell_id); record.spell_id, spell_id);
return; return;
@ -744,7 +744,7 @@ void Mob::MakeAura(uint16 spell_id)
const auto base = database.LoadNPCTypesData(record.npc_type); const auto base = database.LoadNPCTypesData(record.npc_type);
if (base == nullptr) { if (base == nullptr) {
Message(13, "Unable to load NPC data for aura %s", spells[spell_id].teleport_zone); Message(Chat::Red, "Unable to load NPC data for aura %s", spells[spell_id].teleport_zone);
Log(Logs::General, Logs::Error, Log(Logs::General, Logs::Error,
"Unable to load NPC data for aura %s (NPC ID %d), check auras and npc_types tables.", "Unable to load NPC data for aura %s (NPC ID %d), check auras and npc_types tables.",
spells[spell_id].teleport_zone, record.npc_type); spells[spell_id].teleport_zone, record.npc_type);
@ -841,10 +841,10 @@ void Mob::AddTrap(Aura *aura, AuraRecord &record)
bool Mob::CanSpawnAura(bool trap) bool Mob::CanSpawnAura(bool trap)
{ {
if (trap && !HasFreeTrapSlots()) { if (trap && !HasFreeTrapSlots()) {
Message_StringID(MT_SpellFailure, NO_MORE_TRAPS); MessageString(Chat::SpellFailure, NO_MORE_TRAPS);
return false; return false;
} else if (!trap && !HasFreeAuraSlots()) { } else if (!trap && !HasFreeAuraSlots()) {
Message_StringID(MT_SpellFailure, NO_MORE_AURAS); MessageString(Chat::SpellFailure, NO_MORE_AURAS);
return false; return false;
} }
@ -878,8 +878,6 @@ void Mob::RemoveAllAuras()
} }
trap_mgr.count = 0; trap_mgr.count = 0;
return;
} }
void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired) void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired)
@ -891,7 +889,7 @@ void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired)
aura.aura->Depop(skip_strip); aura.aura->Depop(skip_strip);
if (expired && IsClient()) { if (expired && IsClient()) {
CastToClient()->SendColoredText( CastToClient()->SendColoredText(
CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color Chat::Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color
// need to update client UI too // need to update client UI too
auto app = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraDestory_Struct)); auto app = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraDestory_Struct));
auto ads = (AuraDestory_Struct *)app->pBuffer; auto ads = (AuraDestory_Struct *)app->pBuffer;
@ -920,7 +918,7 @@ void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired)
aura.aura->Depop(skip_strip); aura.aura->Depop(skip_strip);
if (expired && IsClient()) if (expired && IsClient())
CastToClient()->SendColoredText( CastToClient()->SendColoredText(
CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color Chat::Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color
while (trap_mgr.count - 1 > i) { while (trap_mgr.count - 1 > i) {
i++; i++;
aura.spawn_id = trap_mgr.auras[i].spawn_id; aura.spawn_id = trap_mgr.auras[i].spawn_id;

View File

@ -159,9 +159,9 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
bool stance_flag = false; bool stance_flag = false;
if (!database.botdb.LoadStance(this, stance_flag) && bot_owner) if (!database.botdb.LoadStance(this, stance_flag) && bot_owner)
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadStance(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadStance(), GetCleanName());
if (!stance_flag && bot_owner) if (!stance_flag && bot_owner)
bot_owner->Message(13, "Could not locate stance for '%s'", GetCleanName()); bot_owner->Message(Chat::Red, "Could not locate stance for '%s'", GetCleanName());
SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == EQEmu::constants::stanceAggressive)); SetTaunting((GetClass() == WARRIOR || GetClass() == PALADIN || GetClass() == SHADOWKNIGHT) && (GetBotStance() == EQEmu::constants::stanceAggressive));
SetPauseAI(false); SetPauseAI(false);
@ -178,17 +178,17 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct)); memset(&_botInspectMessage, 0, sizeof(InspectMessage_Struct));
if (!database.botdb.LoadInspectMessage(GetBotID(), _botInspectMessage) && bot_owner) if (!database.botdb.LoadInspectMessage(GetBotID(), _botInspectMessage) && bot_owner)
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadInspectMessage(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadInspectMessage(), GetCleanName());
if (!database.botdb.LoadGuildMembership(GetBotID(), _guildId, _guildRank, _guildName) && bot_owner) if (!database.botdb.LoadGuildMembership(GetBotID(), _guildId, _guildRank, _guildName) && bot_owner)
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadGuildMembership(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadGuildMembership(), GetCleanName());
std::string error_message; std::string error_message;
EquipBot(&error_message); EquipBot(&error_message);
if(!error_message.empty()) { if(!error_message.empty()) {
if(bot_owner) if(bot_owner)
bot_owner->Message(13, error_message.c_str()); bot_owner->Message(Chat::Red, error_message.c_str());
error_message.clear(); error_message.clear();
} }
@ -206,12 +206,12 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to
GenerateBaseStats(); GenerateBaseStats();
if (!database.botdb.LoadTimers(this) && bot_owner) if (!database.botdb.LoadTimers(this) && bot_owner)
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadTimers(), GetCleanName());
LoadAAs(); LoadAAs();
if (!database.botdb.LoadBuffs(this) && bot_owner) if (!database.botdb.LoadBuffs(this) && bot_owner)
bot_owner->Message(13, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "&s for '%s'", BotDatabase::fail::LoadBuffs(), GetCleanName());
CalcBotStats(false); CalcBotStats(false);
hp_regen = CalcHPRegen(); hp_regen = CalcHPRegen();
@ -1701,28 +1701,28 @@ bool Bot::Save()
if(!GetBotID()) { // New bot record if(!GetBotID()) { // New bot record
uint32 bot_id = 0; uint32 bot_id = 0;
if (!database.botdb.SaveNewBot(this, bot_id) || !bot_id) { if (!database.botdb.SaveNewBot(this, bot_id) || !bot_id) {
bot_owner->Message(13, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName()); bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::SaveNewBot(), GetCleanName());
return false; return false;
} }
SetBotID(bot_id); SetBotID(bot_id);
} }
else { // Update existing bot record else { // Update existing bot record
if (!database.botdb.SaveBot(this)) { if (!database.botdb.SaveBot(this)) {
bot_owner->Message(13, "%s '%s'", BotDatabase::fail::SaveBot(), GetCleanName()); bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::SaveBot(), GetCleanName());
return false; return false;
} }
} }
// All of these continue to process if any fail // All of these continue to process if any fail
if (!database.botdb.SaveBuffs(this)) if (!database.botdb.SaveBuffs(this))
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveBuffs(), GetCleanName());
if (!database.botdb.SaveTimers(this)) if (!database.botdb.SaveTimers(this))
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveTimers(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveTimers(), GetCleanName());
if (!database.botdb.SaveStance(this)) if (!database.botdb.SaveStance(this))
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::SaveStance(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveStance(), GetCleanName());
if (!SavePet()) if (!SavePet())
bot_owner->Message(13, "Failed to save pet for '%s'", GetCleanName()); bot_owner->Message(Chat::Red, "Failed to save pet for '%s'", GetCleanName());
return true; return true;
} }
@ -1734,26 +1734,26 @@ bool Bot::DeleteBot()
return false; return false;
if (!database.botdb.DeleteHealRotation(GetBotID())) { if (!database.botdb.DeleteHealRotation(GetBotID())) {
bot_owner->Message(13, "%s", BotDatabase::fail::DeleteHealRotation()); bot_owner->Message(Chat::Red, "%s", BotDatabase::fail::DeleteHealRotation());
return false; return false;
} }
std::string query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `bot_id` = '%u'", GetBotID()); std::string query = StringFormat("DELETE FROM `bot_heal_rotation_members` WHERE `bot_id` = '%u'", GetBotID());
auto results = database.QueryDatabase(query); auto results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
bot_owner->Message(13, "Failed to delete heal rotation member '%s'", GetCleanName()); bot_owner->Message(Chat::Red, "Failed to delete heal rotation member '%s'", GetCleanName());
return false; return false;
} }
query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `target_name` LIKE '%s'", GetCleanName()); query = StringFormat("DELETE FROM `bot_heal_rotation_targets` WHERE `target_name` LIKE '%s'", GetCleanName());
results = database.QueryDatabase(query); results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
bot_owner->Message(13, "Failed to delete heal rotation target '%s'", GetCleanName()); bot_owner->Message(Chat::Red, "Failed to delete heal rotation target '%s'", GetCleanName());
return false; return false;
} }
if (!DeletePet()) { if (!DeletePet()) {
bot_owner->Message(13, "Failed to delete pet for '%s'", GetCleanName()); bot_owner->Message(Chat::Red, "Failed to delete pet for '%s'", GetCleanName());
return false; return false;
} }
@ -1763,32 +1763,32 @@ bool Bot::DeleteBot()
std::string error_message; std::string error_message;
if (!database.botdb.RemoveMemberFromBotGroup(GetBotID())) { if (!database.botdb.RemoveMemberFromBotGroup(GetBotID())) {
bot_owner->Message(13, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), GetCleanName()); bot_owner->Message(Chat::Red, "%s - '%s'", BotDatabase::fail::RemoveMemberFromBotGroup(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeleteItems(GetBotID())) { if (!database.botdb.DeleteItems(GetBotID())) {
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteItems(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteItems(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeleteTimers(GetBotID())) { if (!database.botdb.DeleteTimers(GetBotID())) {
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteTimers(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteTimers(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeleteBuffs(GetBotID())) { if (!database.botdb.DeleteBuffs(GetBotID())) {
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteBuffs(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeleteStance(GetBotID())) { if (!database.botdb.DeleteStance(GetBotID())) {
bot_owner->Message(13, "%s for '%s'", BotDatabase::fail::DeleteStance(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::DeleteStance(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeleteBot(GetBotID())) { if (!database.botdb.DeleteBot(GetBotID())) {
bot_owner->Message(13, "%s '%s'", BotDatabase::fail::DeleteBot(), GetCleanName()); bot_owner->Message(Chat::Red, "%s '%s'", BotDatabase::fail::DeleteBot(), GetCleanName());
return false; return false;
} }
@ -1832,7 +1832,7 @@ bool Bot::LoadPet()
uint32 pet_index = 0; uint32 pet_index = 0;
if (!database.botdb.LoadPetIndex(GetBotID(), pet_index)) { if (!database.botdb.LoadPetIndex(GetBotID(), pet_index)) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetIndex(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetIndex(), GetCleanName());
return false; return false;
} }
if (!pet_index) if (!pet_index)
@ -1840,10 +1840,10 @@ bool Bot::LoadPet()
uint32 saved_pet_spell_id = 0; uint32 saved_pet_spell_id = 0;
if (!database.botdb.LoadPetSpellID(GetBotID(), saved_pet_spell_id)) { if (!database.botdb.LoadPetSpellID(GetBotID(), saved_pet_spell_id)) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetSpellID(), GetCleanName());
} }
if (!IsValidSpell(saved_pet_spell_id)) { if (!IsValidSpell(saved_pet_spell_id)) {
bot_owner->Message(13, "Invalid spell id for %s's pet", GetCleanName()); bot_owner->Message(Chat::Red, "Invalid spell id for %s's pet", GetCleanName());
DeletePet(); DeletePet();
return false; return false;
} }
@ -1854,7 +1854,7 @@ bool Bot::LoadPet()
uint32 pet_spell_id = 0; uint32 pet_spell_id = 0;
if (!database.botdb.LoadPetStats(GetBotID(), pet_name, pet_mana, pet_hp, pet_spell_id)) { if (!database.botdb.LoadPetStats(GetBotID(), pet_name, pet_mana, pet_hp, pet_spell_id)) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetStats(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetStats(), GetCleanName());
return false; return false;
} }
@ -1869,12 +1869,12 @@ bool Bot::LoadPet()
SpellBuff_Struct pet_buffs[PET_BUFF_COUNT]; SpellBuff_Struct pet_buffs[PET_BUFF_COUNT];
memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT)); memset(pet_buffs, 0, (sizeof(SpellBuff_Struct) * PET_BUFF_COUNT));
if (!database.botdb.LoadPetBuffs(GetBotID(), pet_buffs)) if (!database.botdb.LoadPetBuffs(GetBotID(), pet_buffs))
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetBuffs(), GetCleanName());
uint32 pet_items[EQEmu::invslot::EQUIPMENT_COUNT]; uint32 pet_items[EQEmu::invslot::EQUIPMENT_COUNT];
memset(pet_items, 0, (sizeof(uint32) * EQEmu::invslot::EQUIPMENT_COUNT)); memset(pet_items, 0, (sizeof(uint32) * EQEmu::invslot::EQUIPMENT_COUNT));
if (!database.botdb.LoadPetItems(GetBotID(), pet_items)) if (!database.botdb.LoadPetItems(GetBotID(), pet_items))
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::LoadPetItems(), GetCleanName());
pet_inst->SetPetState(pet_buffs, pet_items); pet_inst->SetPetState(pet_buffs, pet_items);
pet_inst->CalcBonuses(); pet_inst->CalcBonuses();
@ -1913,14 +1913,14 @@ bool Bot::SavePet()
std::string error_message; std::string error_message;
if (!database.botdb.SavePetStats(GetBotID(), pet_name_str, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) { if (!database.botdb.SavePetStats(GetBotID(), pet_name_str, pet_inst->GetMana(), pet_inst->GetHP(), pet_inst->GetPetSpellID())) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetStats(), GetCleanName());
return false; return false;
} }
if (!database.botdb.SavePetBuffs(GetBotID(), pet_buffs)) if (!database.botdb.SavePetBuffs(GetBotID(), pet_buffs))
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetBuffs(), GetCleanName());
if (!database.botdb.SavePetItems(GetBotID(), pet_items)) if (!database.botdb.SavePetItems(GetBotID(), pet_items))
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::SavePetItems(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::SavePetItems(), GetCleanName());
return true; return true;
} }
@ -1934,15 +1934,15 @@ bool Bot::DeletePet()
std::string error_message; std::string error_message;
if (!database.botdb.DeletePetItems(GetBotID())) { if (!database.botdb.DeletePetItems(GetBotID())) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetItems(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetItems(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeletePetBuffs(GetBotID())) { if (!database.botdb.DeletePetBuffs(GetBotID())) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetBuffs(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetBuffs(), GetCleanName());
return false; return false;
} }
if (!database.botdb.DeletePetStats(GetBotID())) { if (!database.botdb.DeletePetStats(GetBotID())) {
bot_owner->Message(13, "%s for %s's pet", BotDatabase::fail::DeletePetStats(), GetCleanName()); bot_owner->Message(Chat::Red, "%s for %s's pet", BotDatabase::fail::DeletePetStats(), GetCleanName());
return false; return false;
} }
@ -2276,12 +2276,12 @@ void Bot::AI_Process() {
// Berserk updates should occur if primary AI criteria are met // Berserk updates should occur if primary AI criteria are met
if (GetClass() == WARRIOR || GetClass() == BERSERKER) { if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
if (!berserk && GetHP() > 0 && GetHPRatio() < 30.0f) { if (!berserk && GetHP() > 0 && GetHPRatio() < 30.0f) {
entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName());
berserk = true; berserk = true;
} }
if (berserk && GetHPRatio() >= 30.0f) { if (berserk && GetHPRatio() >= 30.0f) {
entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName());
berserk = false; berserk = false;
} }
} }
@ -2808,7 +2808,7 @@ void Bot::AI_Process() {
int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance); int32 flurrychance = (aabonuses.FlurryChance + spellbonuses.FlurryChance + itembonuses.FlurryChance);
if (flurrychance) { if (flurrychance) {
if (zone->random.Int(0, 100) < flurrychance) { if (zone->random.Int(0, 100) < flurrychance) {
Message_StringID(MT_NPCFlurry, YOU_FLURRY); MessageString(Chat::NPCFlurry, YOU_FLURRY);
Attack(tar, EQEmu::invslot::slotPrimary, false); Attack(tar, EQEmu::invslot::slotPrimary, false);
TEST_TARGET(); TEST_TARGET();
@ -3256,9 +3256,9 @@ bool Bot::Spawn(Client* botCharacterOwner) {
this->texture = 0; //0xFF; this->texture = 0; //0xFF;
if(this->Save()) if(this->Save())
this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName()); this->GetBotOwner()->CastToClient()->Message(Chat::White, "%s saved.", this->GetCleanName());
else else
this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName()); this->GetBotOwner()->CastToClient()->Message(Chat::Red, "%s save failed!", this->GetCleanName());
// Spawn the bot at the bow owner's loc // Spawn the bot at the bow owner's loc
this->m_Position.x = botCharacterOwner->GetX(); this->m_Position.x = botCharacterOwner->GetX();
@ -3331,7 +3331,7 @@ uint32 Bot::GetBotItemBySlot(uint32 slotID)
if (!database.botdb.LoadItemBySlot(GetBotID(), slotID, item_id)) { if (!database.botdb.LoadItemBySlot(GetBotID(), slotID, item_id)) {
if (GetBotOwner() && GetBotOwner()->IsClient()) if (GetBotOwner() && GetBotOwner()->IsClient())
GetBotOwner()->CastToClient()->Message(13, "%s", BotDatabase::fail::LoadItemBySlot()); GetBotOwner()->CastToClient()->Message(Chat::Red, "%s", BotDatabase::fail::LoadItemBySlot());
} }
return item_id; return item_id;
@ -3434,7 +3434,7 @@ void Bot::LoadAndSpawnAllZonedBots(Client* botOwner) {
std::list<uint32> ActiveBots; std::list<uint32> ActiveBots;
// Modified LoadGroupedBotsByGroupID to require a CharacterID // Modified LoadGroupedBotsByGroupID to require a CharacterID
if (!database.botdb.LoadGroupedBotsByGroupID(botOwner->CharacterID(), TempGroupId, ActiveBots)) { if (!database.botdb.LoadGroupedBotsByGroupID(botOwner->CharacterID(), TempGroupId, ActiveBots)) {
botOwner->Message(13, "%s", BotDatabase::fail::LoadGroupedBotsByGroupID()); botOwner->Message(Chat::Red, "%s", BotDatabase::fail::LoadGroupedBotsByGroupID());
return; return;
} }
@ -3838,32 +3838,32 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
} }
if (client != GetOwner()) { if (client != GetOwner()) {
client->Message(CC_Red, "You are not the owner of this bot - Trade Canceled."); client->Message(Chat::Red, "You are not the owner of this bot - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if ((beginSlotID != invslot::TRADE_BEGIN) && (beginSlotID != invslot::slotCursor)) { if ((beginSlotID != invslot::TRADE_BEGIN) && (beginSlotID != invslot::slotCursor)) {
client->Message(CC_Red, "Trade request processing from illegal 'begin' slot - Trade Canceled."); client->Message(Chat::Red, "Trade request processing from illegal 'begin' slot - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if ((endSlotID != invslot::TRADE_END) && (endSlotID != invslot::slotCursor)) { if ((endSlotID != invslot::TRADE_END) && (endSlotID != invslot::slotCursor)) {
client->Message(CC_Red, "Trade request processing from illegal 'end' slot - Trade Canceled."); client->Message(Chat::Red, "Trade request processing from illegal 'end' slot - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if (((beginSlotID == invslot::slotCursor) && (endSlotID != invslot::slotCursor)) || ((beginSlotID != invslot::slotCursor) && (endSlotID == invslot::slotCursor))) { if (((beginSlotID == invslot::slotCursor) && (endSlotID != invslot::slotCursor)) || ((beginSlotID != invslot::slotCursor) && (endSlotID == invslot::slotCursor))) {
client->Message(CC_Red, "Trade request processing illegal slot range - Trade Canceled."); client->Message(Chat::Red, "Trade request processing illegal slot range - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if (endSlotID < beginSlotID) { if (endSlotID < beginSlotID) {
client->Message(CC_Red, "Trade request processing in reverse slot order - Trade Canceled."); client->Message(Chat::Red, "Trade request processing in reverse slot order - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if (client->IsEngaged() || IsEngaged()) { if (client->IsEngaged() || IsEngaged()) {
client->Message(CC_Yellow, "You may not perform a trade while engaged - Trade Canceled!"); client->Message(Chat::Yellow, "You may not perform a trade while engaged - Trade Canceled!");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
@ -3879,23 +3879,23 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
if (!trade_instance->GetItem()) { if (!trade_instance->GetItem()) {
// TODO: add logging // TODO: add logging
client->Message(CC_Red, "A server error was encountered while processing client slot %i - Trade Canceled.", trade_index); client->Message(Chat::Red, "A server error was encountered while processing client slot %i - Trade Canceled.", trade_index);
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if ((trade_index != invslot::slotCursor) && !trade_instance->IsDroppable()) { if ((trade_index != invslot::slotCursor) && !trade_instance->IsDroppable()) {
// TODO: add logging // TODO: add logging
client->Message(CC_Red, "Trade hack detected - Trade Canceled."); client->Message(Chat::Red, "Trade hack detected - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if (trade_instance->IsStackable() && (trade_instance->GetCharges() < trade_instance->GetItem()->StackSize)) { // temp until partial stacks are implemented if (trade_instance->IsStackable() && (trade_instance->GetCharges() < trade_instance->GetItem()->StackSize)) { // temp until partial stacks are implemented
client->Message(CC_Yellow, "'%s' is only a partially stacked item - Trade Canceled!", trade_instance->GetItem()->Name); client->Message(Chat::Yellow, "'%s' is only a partially stacked item - Trade Canceled!", trade_instance->GetItem()->Name);
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if (CheckLoreConflict(trade_instance->GetItem())) { if (CheckLoreConflict(trade_instance->GetItem())) {
client->Message(CC_Yellow, "This bot already has lore equipment matching the item '%s' - Trade Canceled!", trade_instance->GetItem()->Name); client->Message(Chat::Yellow, "This bot already has lore equipment matching the item '%s' - Trade Canceled!", trade_instance->GetItem()->Name);
client->ResetTrade(); client->ResetTrade();
return; return;
} }
@ -3925,13 +3925,13 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup == -1) && (check_iterator.tradeItemInstance->GetItem()->ID == trade_iterator.tradeItemInstance->GetItem()->ID)) { if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup == -1) && (check_iterator.tradeItemInstance->GetItem()->ID == trade_iterator.tradeItemInstance->GetItem()->ID)) {
// TODO: add logging // TODO: add logging
client->Message(CC_Red, "Trade hack detected - Trade Canceled."); client->Message(Chat::Red, "Trade hack detected - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup > 0) && (check_iterator.tradeItemInstance->GetItem()->LoreGroup == trade_iterator.tradeItemInstance->GetItem()->LoreGroup)) { if ((trade_iterator.tradeItemInstance->GetItem()->LoreGroup > 0) && (check_iterator.tradeItemInstance->GetItem()->LoreGroup == trade_iterator.tradeItemInstance->GetItem()->LoreGroup)) {
// TODO: add logging // TODO: add logging
client->Message(CC_Red, "Trade hack detected - Trade Canceled."); client->Message(Chat::Red, "Trade hack detected - Trade Canceled.");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
@ -4040,14 +4040,14 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
if (!return_instance->GetItem()) { if (!return_instance->GetItem()) {
// TODO: add logging // TODO: add logging
client->Message(CC_Red, "A server error was encountered while processing bot slot %i - Trade Canceled.", return_iterator.fromBotSlot); client->Message(Chat::Red, "A server error was encountered while processing bot slot %i - Trade Canceled.", return_iterator.fromBotSlot);
client->ResetTrade(); client->ResetTrade();
return; return;
} }
// non-failing checks above are causing this to trigger (i.e., !ItemClassCommon and !IsEquipable{race, class, min_level}) // non-failing checks above are causing this to trigger (i.e., !ItemClassCommon and !IsEquipable{race, class, min_level})
// this process is hindered by not having bots use the inventory trade method (TODO: implement bot inventory use) // this process is hindered by not having bots use the inventory trade method (TODO: implement bot inventory use)
if (client->CheckLoreConflict(return_instance->GetItem())) { if (client->CheckLoreConflict(return_instance->GetItem())) {
client->Message(CC_Yellow, "You already have lore equipment matching the item '%s' - Trade Canceled!", return_instance->GetItem()->Name); client->Message(Chat::Yellow, "You already have lore equipment matching the item '%s' - Trade Canceled!", return_instance->GetItem()->Name);
client->ResetTrade(); client->ResetTrade();
return; return;
} }
@ -4104,7 +4104,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
} }
if (return_iterator.toClientSlot == invslot::SLOT_INVALID) { if (return_iterator.toClientSlot == invslot::SLOT_INVALID) {
client->Message(CC_Yellow, "You do not have room to complete this trade - Trade Canceled!"); client->Message(Chat::Yellow, "You do not have room to complete this trade - Trade Canceled!");
client->ResetTrade(); client->ResetTrade();
return; return;
} }
@ -4130,7 +4130,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
//} //}
if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.fromBotSlot)) if (!database.botdb.DeleteItemBySlot(GetBotID(), return_iterator.fromBotSlot))
client->Message(CC_Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::DeleteItemBySlot(), return_iterator.fromBotSlot, (return_instance ? return_instance->GetItem()->Name : "nullptr")); client->Message(Chat::Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::DeleteItemBySlot(), return_iterator.fromBotSlot, (return_instance ? return_instance->GetItem()->Name : "nullptr"));
BotRemoveEquipItem(return_iterator.fromBotSlot); BotRemoveEquipItem(return_iterator.fromBotSlot);
if (return_instance) if (return_instance)
@ -4145,7 +4145,7 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
// TODO: code for stackables // TODO: code for stackables
if (!database.botdb.SaveItemBySlot(this, trade_iterator.toBotSlot, trade_iterator.tradeItemInstance)) if (!database.botdb.SaveItemBySlot(this, trade_iterator.toBotSlot, trade_iterator.tradeItemInstance))
client->Message(CC_Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::SaveItemBySlot(), trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetItem()->Name : "nullptr")); client->Message(Chat::Red, "%s (slot: %i, name: '%s')", BotDatabase::fail::SaveItemBySlot(), trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetItem()->Name : "nullptr"));
m_inv.PutItem(trade_iterator.toBotSlot, *trade_iterator.tradeItemInstance); m_inv.PutItem(trade_iterator.toBotSlot, *trade_iterator.tradeItemInstance);
this->BotAddEquipItem(trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetID() : 0)); this->BotAddEquipItem(trade_iterator.toBotSlot, (trade_iterator.tradeItemInstance ? trade_iterator.tradeItemInstance->GetID() : 0));
@ -4165,17 +4165,17 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli
// trade messages // trade messages
for (const auto& return_iterator : client_return) { for (const auto& return_iterator : client_return) {
if (return_iterator.failedItemName.size()) if (return_iterator.failedItemName.size())
client->Message(MT_Tell, "%s tells you, \"%s, I can't use this '%s.'\"", GetCleanName(), client->GetName(), return_iterator.failedItemName.c_str()); client->Message(Chat::Tell, "%s tells you, \"%s, I can't use this '%s.'\"", GetCleanName(), client->GetName(), return_iterator.failedItemName.c_str());
} }
for (const auto& trade_iterator : client_trade) { for (const auto& trade_iterator : client_trade) {
if (trade_iterator.acceptedItemName.size()) if (trade_iterator.acceptedItemName.size())
client->Message(MT_Tell, "%s tells you, \"Thank you for the '%s,' %s!\"", GetCleanName(), trade_iterator.acceptedItemName.c_str(), client->GetName()); client->Message(Chat::Tell, "%s tells you, \"Thank you for the '%s,' %s!\"", GetCleanName(), trade_iterator.acceptedItemName.c_str(), client->GetName());
} }
size_t accepted_count = client_trade.size(); size_t accepted_count = client_trade.size();
size_t returned_count = client_return.size(); size_t returned_count = client_return.size();
client->Message(CC_Lime, "Trade with '%s' resulted in %i accepted item%s, %i returned item%s.", GetCleanName(), accepted_count, ((accepted_count == 1) ? "" : "s"), returned_count, ((returned_count == 1) ? "" : "s")); client->Message(Chat::Lime, "Trade with '%s' resulted in %i accepted item%s, %i returned item%s.", GetCleanName(), accepted_count, ((accepted_count == 1) ? "" : "s"), returned_count, ((returned_count == 1) ? "" : "s"));
if (accepted_count) if (accepted_count)
CalcBotStats(client->GetBotOptionStatsUpdate()); CalcBotStats(client->GetBotOptionStatsUpdate());
@ -4190,9 +4190,9 @@ bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::Sk
Mob *my_owner = GetBotOwner(); Mob *my_owner = GetBotOwner();
if (my_owner && my_owner->IsClient() && my_owner->CastToClient()->GetBotOptionDeathMarquee()) { if (my_owner && my_owner->IsClient() && my_owner->CastToClient()->GetBotOptionDeathMarquee()) {
if (killerMob) if (killerMob)
my_owner->CastToClient()->SendMarqueeMessage(CC_Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain by %s", GetCleanName(), killerMob->GetCleanName())); my_owner->CastToClient()->SendMarqueeMessage(Chat::Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain by %s", GetCleanName(), killerMob->GetCleanName()));
else else
my_owner->CastToClient()->SendMarqueeMessage(CC_Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName())); my_owner->CastToClient()->SendMarqueeMessage(Chat::Yellow, 510, 0, 1000, 3000, StringFormat("%s has been slain", GetCleanName()));
} }
Mob *give_exp = hate_list.GetDamageTopOnHateList(this); Mob *give_exp = hate_list.GetDamageTopOnHateList(this);
@ -4281,7 +4281,7 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT
int healed = GetActSpellHealing(spell_id, damage); int healed = GetActSpellHealing(spell_id, damage);
Log(Logs::Detail, Logs::Combat, "Applying lifetap heal of %d to %s", healed, GetCleanName()); Log(Logs::Detail, Logs::Combat, "Applying lifetap heal of %d to %s", healed, GetCleanName());
HealDamage(healed); HealDamage(healed);
entity_list.MessageClose(this, true, 300, MT_Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() ); entity_list.MessageClose(this, true, 300, Chat::Spells, "%s beams a smile at %s", GetCleanName(), from->GetCleanName() );
} }
CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special); CommonDamage(from, damage, spell_id, attack_skill, avoidable, buffslot, iBuffTic, special);
@ -5364,7 +5364,7 @@ bool Bot::TryFinishingBlow(Mob *defender, int &damage)
if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(1, 1000))) { if (defender->GetLevel() <= levelreq && (chance >= zone->random.Int(1, 1000))) {
Log(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d", Log(Logs::Detail, Logs::Combat, "Landed a finishing blow: levelreq at %d, other level %d",
levelreq, defender->GetLevel()); levelreq, defender->GetLevel());
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, FINISHING_BLOW, GetName()); entity_list.MessageCloseString(this, false, 200, Chat::MeleeCrit, FINISHING_BLOW, GetName());
damage = fb_damage; damage = fb_damage;
return true; return true;
} else { } else {
@ -5572,7 +5572,7 @@ void Bot::TryBackstab(Mob *other, int ReuseTime) {
if (bIsBehind || bCanFrontalBS) { if (bIsBehind || bCanFrontalBS) {
int chance = (10 + (GetDEX() / 10) + (itembonuses.HeroicDEX / 10)); int chance = (10 + (GetDEX() / 10) + (itembonuses.HeroicDEX / 10));
if(level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) { if(level >= 60 && other->GetLevel() <= 45 && !other->CastToNPC()->IsEngaged() && other->GetHP()<= 32000 && other->IsNPC() && zone->random.Real(0, 99) < chance) {
entity_list.MessageClose_StringID(this, false, 200, MT_CritMelee, ASSASSINATES, GetName()); entity_list.MessageCloseString(this, false, 200, Chat::MeleeCrit, ASSASSINATES, GetName());
RogueAssassinate(other); RogueAssassinate(other);
} else { } else {
RogueBackstab(other); RogueBackstab(other);
@ -5940,12 +5940,12 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) {
if(guildOfficer && botToGuild) { if(guildOfficer && botToGuild) {
if(!botToGuild->IsInAGuild()) { if(!botToGuild->IsInAGuild()) {
if (!guild_mgr.CheckPermission(guildOfficer->GuildID(), guildOfficer->GuildRank(), GUILD_INVITE)) { if (!guild_mgr.CheckPermission(guildOfficer->GuildID(), guildOfficer->GuildRank(), GUILD_INVITE)) {
guildOfficer->Message(13, "You dont have permission to invite."); guildOfficer->Message(Chat::Red, "You dont have permission to invite.");
return; return;
} }
if (!database.botdb.SaveGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER)) { if (!database.botdb.SaveGuildMembership(botToGuild->GetBotID(), guildOfficer->GuildID(), GUILD_MEMBER)) {
guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::SaveGuildMembership(), botToGuild->GetCleanName()); guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::SaveGuildMembership(), botToGuild->GetCleanName());
return; return;
} }
@ -5958,7 +5958,7 @@ void Bot::ProcessGuildInvite(Client* guildOfficer, Bot* botToGuild) {
safe_delete(pack); safe_delete(pack);
} else { } else {
guildOfficer->Message(13, "Bot is in a guild."); guildOfficer->Message(Chat::Red, "Bot is in a guild.");
return; return;
} }
} }
@ -5974,10 +5974,10 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) {
} else { } else {
uint32 ownerId = 0; uint32 ownerId = 0;
if (!database.botdb.LoadOwnerID(botName, ownerId)) if (!database.botdb.LoadOwnerID(botName, ownerId))
guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::LoadOwnerID(), botName.c_str()); guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadOwnerID(), botName.c_str());
uint32 botId = 0; uint32 botId = 0;
if (!database.botdb.LoadBotID(ownerId, botName, botId)) if (!database.botdb.LoadBotID(ownerId, botName, botId))
guildOfficer->Message(13, "%s for '%s'", BotDatabase::fail::LoadBotID(), botName.c_str()); guildOfficer->Message(Chat::Red, "%s for '%s'", BotDatabase::fail::LoadBotID(), botName.c_str());
if (botId && database.botdb.SaveGuildMembership(botId, 0, 0)) if (botId && database.botdb.SaveGuildMembership(botId, 0, 0))
Result = true; Result = true;
} }
@ -5987,7 +5987,7 @@ bool Bot::ProcessGuildRemoval(Client* guildOfficer, std::string botName) {
GuildManageRemove_Struct* gm = (GuildManageRemove_Struct*) outapp->pBuffer; GuildManageRemove_Struct* gm = (GuildManageRemove_Struct*) outapp->pBuffer;
gm->guildeqid = guildOfficer->GuildID(); gm->guildeqid = guildOfficer->GuildID();
strcpy(gm->member, botName.c_str()); strcpy(gm->member, botName.c_str());
guildOfficer->Message(0, "%s successfully removed from your guild.", botName.c_str()); guildOfficer->Message(Chat::White, "%s successfully removed from your guild.", botName.c_str());
entity_list.QueueClientsGuild(guildOfficer, outapp, false, gm->guildeqid); entity_list.QueueClientsGuild(guildOfficer, outapp, false, gm->guildeqid);
safe_delete(outapp); safe_delete(outapp);
} }
@ -6125,7 +6125,7 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5)
value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100); value += (GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value) * ratio / 100);
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s delivers a critical blast! (%d)", GetName(), -value); entity_list.MessageClose(this, false, 100, Chat::SpellCrit, "%s delivers a critical blast! (%d)", GetName(), -value);
return value; return value;
} }
@ -6179,7 +6179,7 @@ int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
value += (value * target->GetHealRate(spell_id, this) / 100); value += (value * target->GetHealRate(spell_id, this) / 100);
if (Critical) if (Critical)
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value); entity_list.MessageClose(this, false, 100, Chat::SpellCrit, "%s performs an exceptional heal! (%d)", GetName(), value);
return value; return value;
} else { } else {
@ -6444,11 +6444,11 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlo
if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) { if(!IsValidSpell(spell_id) || casting_spell_id || delaytimer || spellend_timer.Enabled() || IsStunned() || IsFeared() || IsMezzed() || (IsSilenced() && !IsDiscipline(spell_id)) || (IsAmnesiad() && IsDiscipline(spell_id))) {
Log(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() ); Log(Logs::Detail, Logs::Spells, "Spell casting canceled: not able to cast now. Valid? %d, casting %d, waiting? %d, spellend? %d, stunned? %d, feared? %d, mezed? %d, silenced? %d", IsValidSpell(spell_id), casting_spell_id, delaytimer, spellend_timer.Enabled(), IsStunned(), IsFeared(), IsMezzed(), IsSilenced() );
if(IsSilenced() && !IsDiscipline(spell_id)) if(IsSilenced() && !IsDiscipline(spell_id))
Message_StringID(13, SILENCED_STRING); MessageString(Chat::Red, SILENCED_STRING);
if(IsAmnesiad() && IsDiscipline(spell_id)) if(IsAmnesiad() && IsDiscipline(spell_id))
Message_StringID(13, MELEE_SILENCE); MessageString(Chat::Red, MELEE_SILENCE);
if(casting_spell_id) if(casting_spell_id)
AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot)); AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot));
@ -6458,7 +6458,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlo
} }
if(IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()){ if(IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()){
Message_StringID(13, SPELL_WOULDNT_HOLD); MessageString(Chat::Red, SPELL_WOULDNT_HOLD);
if(casting_spell_id) if(casting_spell_id)
AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot)); AI_Event_SpellCastFinished(false, static_cast<uint16>(casting_spell_slot));
@ -8155,13 +8155,13 @@ void Bot::CalcBotStats(bool showtext) {
return; return;
if(showtext) { if(showtext) {
GetBotOwner()->Message(15, "Updating %s...", GetCleanName()); GetBotOwner()->Message(Chat::Yellow, "Updating %s...", GetCleanName());
} }
if(!IsValidRaceClassCombo()) { if(!IsValidRaceClassCombo()) {
GetBotOwner()->Message(15, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceIDName(GetRace()), GetClassIDName(GetClass(), GetLevel())); GetBotOwner()->Message(Chat::Yellow, "A %s - %s bot was detected. Is this Race/Class combination allowed?.", GetRaceIDName(GetRace()), GetClassIDName(GetClass(), GetLevel()));
GetBotOwner()->Message(15, "Previous Bots Code releases did not check Race/Class combinations during create."); GetBotOwner()->Message(Chat::Yellow, "Previous Bots Code releases did not check Race/Class combinations during create.");
GetBotOwner()->Message(15, "Unless you are experiencing heavy lag, you should delete and remake this bot."); GetBotOwner()->Message(Chat::Yellow, "Unless you are experiencing heavy lag, you should delete and remake this bot.");
} }
if(GetBotOwner()->GetLevel() != GetLevel()) if(GetBotOwner()->GetLevel() != GetLevel())
@ -8170,37 +8170,37 @@ void Bot::CalcBotStats(bool showtext) {
GenerateSpecialAttacks(); GenerateSpecialAttacks();
if(showtext) { if(showtext) {
GetBotOwner()->Message(15, "Base stats:"); GetBotOwner()->Message(Chat::Yellow, "Base stats:");
GetBotOwner()->Message(15, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), base_hp, AC, max_mana, STR, STA, DEX, AGI, INT, WIS, CHA); GetBotOwner()->Message(Chat::Yellow, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), base_hp, AC, max_mana, STR, STA, DEX, AGI, INT, WIS, CHA);
GetBotOwner()->Message(15, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",MR,PR,FR,CR,DR,Corrup); GetBotOwner()->Message(Chat::Yellow, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",MR,PR,FR,CR,DR,Corrup);
// Test Code // Test Code
if(GetClass() == BARD) if(GetClass() == BARD)
GetBotOwner()->Message(15, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetBotOwner()->Message(Chat::Yellow, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i",
GetSkill(EQEmu::skills::SkillBrassInstruments), GetSkill(EQEmu::skills::SkillPercussionInstruments), GetSkill(EQEmu::skills::SkillSinging), GetSkill(EQEmu::skills::SkillStringedInstruments), GetSkill(EQEmu::skills::SkillWindInstruments)); GetSkill(EQEmu::skills::SkillBrassInstruments), GetSkill(EQEmu::skills::SkillPercussionInstruments), GetSkill(EQEmu::skills::SkillSinging), GetSkill(EQEmu::skills::SkillStringedInstruments), GetSkill(EQEmu::skills::SkillWindInstruments));
} }
//if(this->Save()) //if(this->Save())
// this->GetBotOwner()->CastToClient()->Message(0, "%s saved.", this->GetCleanName()); // this->GetBotOwner()->CastToClient()->Message(Chat::White, "%s saved.", this->GetCleanName());
//else //else
// this->GetBotOwner()->CastToClient()->Message(13, "%s save failed!", this->GetCleanName()); // this->GetBotOwner()->CastToClient()->Message(Chat::Red, "%s save failed!", this->GetCleanName());
CalcBonuses(); CalcBonuses();
AI_AddNPCSpells(this->GetBotSpellID()); AI_AddNPCSpells(this->GetBotSpellID());
if(showtext) { if(showtext) {
GetBotOwner()->Message(15, "%s has been updated.", GetCleanName()); GetBotOwner()->Message(Chat::Yellow, "%s has been updated.", GetCleanName());
GetBotOwner()->Message(15, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), max_hp, GetAC(), max_mana, GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); GetBotOwner()->Message(Chat::Yellow, "Level: %i HP: %i AC: %i Mana: %i STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetLevel(), max_hp, GetAC(), max_mana, GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA());
GetBotOwner()->Message(15, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",GetMR(),GetPR(),GetFR(),GetCR(),GetDR(),GetCorrup()); GetBotOwner()->Message(Chat::Yellow, "Resists-- Magic: %i, Poison: %i, Fire: %i, Cold: %i, Disease: %i, Corruption: %i.",GetMR(),GetPR(),GetFR(),GetCR(),GetDR(),GetCorrup());
// Test Code // Test Code
if(GetClass() == BARD) { if(GetClass() == BARD) {
GetBotOwner()->Message(15, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetBotOwner()->Message(Chat::Yellow, "Bard Skills-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i",
GetSkill(EQEmu::skills::SkillBrassInstruments) + GetBrassMod(), GetSkill(EQEmu::skills::SkillBrassInstruments) + GetBrassMod(),
GetSkill(EQEmu::skills::SkillPercussionInstruments) + GetPercMod(), GetSkill(EQEmu::skills::SkillPercussionInstruments) + GetPercMod(),
GetSkill(EQEmu::skills::SkillSinging) + GetSingMod(), GetSkill(EQEmu::skills::SkillSinging) + GetSingMod(),
GetSkill(EQEmu::skills::SkillStringedInstruments) + GetStringMod(), GetSkill(EQEmu::skills::SkillStringedInstruments) + GetStringMod(),
GetSkill(EQEmu::skills::SkillWindInstruments) + GetWindMod()); GetSkill(EQEmu::skills::SkillWindInstruments) + GetWindMod());
GetBotOwner()->Message(15, "Bard Skill Mods-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetBrassMod(), GetPercMod(), GetSingMod(), GetStringMod(), GetWindMod()); GetBotOwner()->Message(Chat::Yellow, "Bard Skill Mods-- Brass: %i, Percussion: %i, Singing: %i, Stringed: %i, Wind: %i", GetBrassMod(), GetPercMod(), GetSingMod(), GetStringMod(), GetWindMod());
} }
} }
} }
@ -8868,7 +8868,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) {
SetDisciplineRecastTimer(spells[spell_id].EndurTimerIndex, spell.recast_time); SetDisciplineRecastTimer(spells[spell_id].EndurTimerIndex, spell.recast_time);
} else { } else {
uint32 remain = (GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000); uint32 remain = (GetDisciplineRemainingTime(this, spells[spell_id].EndurTimerIndex) / 1000);
GetOwner()->Message(0, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), (remain / 60), (remain % 60)); GetOwner()->Message(Chat::White, "%s can use this discipline in %d minutes %d seconds.", GetCleanName(), (remain / 60), (remain % 60));
return false; return false;
} }
} }
@ -9070,7 +9070,7 @@ bool Bot::DyeArmor(int16 slot_id, uint32 rgb, bool all_flag, bool save_flag)
if (!database.botdb.SaveEquipmentColor(GetBotID(), save_slot, rgb)) { if (!database.botdb.SaveEquipmentColor(GetBotID(), save_slot, rgb)) {
if (GetBotOwner() && GetBotOwner()->IsClient()) if (GetBotOwner() && GetBotOwner()->IsClient())
GetBotOwner()->CastToClient()->Message(13, "%s", BotDatabase::fail::SaveEquipmentColor()); GetBotOwner()->CastToClient()->Message(Chat::Red, "%s", BotDatabase::fail::SaveEquipmentColor());
return false; return false;
} }
} }

View File

@ -84,12 +84,12 @@ namespace
{ {
//#define BCSTSPELLDUMP // only needed if you're adding/tailoring bot command spells and need a file dump //#define BCSTSPELLDUMP // only needed if you're adding/tailoring bot command spells and need a file dump
#define m_message CC_WhiteSmoke #define m_message Chat::White
#define m_action CC_Yellow #define m_action Chat::Yellow
#define m_note CC_Gray #define m_note Chat::Gray
#define m_usage CC_Cyan #define m_usage Chat::Cyan
#define m_fail CC_Red #define m_fail Chat::Red
#define m_unknown CC_Magenta #define m_unknown Chat::Magenta
#define HP_RATIO_DELTA 5.0f #define HP_RATIO_DELTA 5.0f
@ -4833,7 +4833,7 @@ void bot_subcommand_bot_inspect_message(Client *c, const Seperator *sep)
set_flag = true; set_flag = true;
} }
else if (strcasecmp(sep->arg[1], "clear")) { else if (strcasecmp(sep->arg[1], "clear")) {
c->Message(15, "This command requires a [set | clear] argument"); c->Message(Chat::Yellow, "This command requires a [set | clear] argument");
return; return;
} }
@ -7284,7 +7284,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName); int ab_mask = (ActionableBots::ABM_Target | ActionableBots::ABM_ByName);
if (c->GetTradeskillObject() || (c->trade->state == Trading)) { if (c->GetTradeskillObject() || (c->trade->state == Trading)) {
c->Message_StringID(MT_Tell, MERCHANT_BUSY); c->MessageString(Chat::Tell, MERCHANT_BUSY);
return; return;
} }
@ -7310,7 +7310,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
itm = itminst->GetItem(); itm = itminst->GetItem();
if (itminst && itm && c->CheckLoreConflict(itm)) { if (itminst && itm && c->CheckLoreConflict(itm)) {
c->Message_StringID(0, PICK_LORE); c->MessageString(Chat::White, PICK_LORE);
return; return;
} }
@ -7324,7 +7324,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep)
if (!c->CheckLoreConflict(itma->GetItem())) if (!c->CheckLoreConflict(itma->GetItem()))
continue; continue;
c->Message_StringID(0, PICK_LORE); c->MessageString(Chat::White, PICK_LORE);
return; return;
} }
@ -7454,7 +7454,7 @@ void bot_subcommand_pet_get_lost(Client *c, const Seperator *sep)
if (!bot_iter->GetPet() || bot_iter->GetPet()->IsCharmed()) if (!bot_iter->GetPet() || bot_iter->GetPet()->IsCharmed())
continue; continue;
bot_iter->GetPet()->Say_StringID(PET_GETLOST_STRING); bot_iter->GetPet()->SayString(PET_GETLOST_STRING);
bot_iter->GetPet()->Depop(false); bot_iter->GetPet()->Depop(false);
bot_iter->SetPetID(0); bot_iter->SetPetID(0);
database.botdb.DeletePetItems(bot_iter->GetBotID()); database.botdb.DeletePetItems(bot_iter->GetBotID());
@ -7500,7 +7500,7 @@ void bot_subcommand_pet_remove(Client *c, const Seperator *sep)
} }
if (bot_iter->GetPet()) { if (bot_iter->GetPet()) {
bot_iter->GetPet()->Say_StringID(PET_GETLOST_STRING); bot_iter->GetPet()->SayString(PET_GETLOST_STRING);
bot_iter->GetPet()->Depop(false); bot_iter->GetPet()->Depop(false);
bot_iter->SetPetID(0); bot_iter->SetPetID(0);
} }

File diff suppressed because it is too large Load Diff

View File

@ -90,23 +90,6 @@ public:
bool ack_req; bool ack_req;
}; };
enum { //Type arguments to the Message* routines.
//all not explicitly listed are the same grey color
clientMessageWhite0 = 0,
clientMessageLoot = 2, //dark green
clientMessageTradeskill = 4, //light blue
clientMessageTell = 5, //magenta
clientMessageWhite = 7,
clientMessageWhite2 = 10,
clientMessageLightGrey = 12,
clientMessageError = 13, //red
clientMessageGreen = 14,
clientMessageYellow = 15,
clientMessageBlue = 16,
clientMessageGroup = 18, //cyan
clientMessageWhite3 = 20,
};
#define SPELLBAR_UNLOCK 0x2bc #define SPELLBAR_UNLOCK 0x2bc
enum { //scribing argument to MemorizeSpell enum { //scribing argument to MemorizeSpell
memSpellUnknown = -1, // this modifies some state data memSpellUnknown = -1, // this modifies some state data
@ -295,11 +278,11 @@ public:
void SendBazaarWelcome(); void SendBazaarWelcome();
void DyeArmor(EQEmu::TintProfile* dye); void DyeArmor(EQEmu::TintProfile* dye);
uint8 SlotConvert(uint8 slot,bool bracer=false); uint8 SlotConvert(uint8 slot,bool bracer=false);
void Message_StringID(uint32 type, uint32 string_id, uint32 distance = 0); void MessageString(uint32 type, uint32 string_id, uint32 distance = 0);
void Message_StringID(uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0); void MessageString(uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0);
bool FilteredMessageCheck(Mob *sender, eqFilterType filter); bool FilteredMessageCheck(Mob *sender, eqFilterType filter);
void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id); void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id);
void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter,
uint32 string_id, const char *message1, const char *message2 = nullptr, uint32 string_id, const char *message1, const char *message2 = nullptr,
const char *message3 = nullptr, const char *message4 = nullptr, const char *message3 = nullptr, const char *message4 = nullptr,
const char *message5 = nullptr, const char *message6 = nullptr, const char *message5 = nullptr, const char *message6 = nullptr,
@ -338,11 +321,9 @@ public:
void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone); void QueuePacket(const EQApplicationPacket* app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL, eqFilterType filter=FilterNone);
void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL); void FastQueuePacket(EQApplicationPacket** app, bool ack_req = true, CLIENT_CONN_STATUS = CLIENT_CONNECTINGALL);
void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname=nullptr); void ChannelMessageReceived(uint8 chan_num, uint8 language, uint8 lang_skill, const char* orig_message, const char* targetname=nullptr);
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...);
void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...); void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
void Message(uint32 type, const char* message, ...); void Message(uint32 type, const char* message, ...);
void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...); void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...);
void QuestJournalledMessage(const char *npcname, const char* message);
void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber); void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber);
void SendSound(); void SendSound();
void LearnRecipe(uint32 recipeID); void LearnRecipe(uint32 recipeID);
@ -373,9 +354,9 @@ public:
inline bool ClientDataLoaded() const { return client_data_loaded; } inline bool ClientDataLoaded() const { return client_data_loaded; }
inline bool Connected() const { return (client_state == CLIENT_CONNECTED); } inline bool Connected() const { return (client_state == CLIENT_CONNECTED); }
inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); } inline bool InZone() const { return (client_state == CLIENT_CONNECTED || client_state == CLIENT_LINKDEAD); }
inline void Kick() { client_state = CLIENT_KICKED; }
inline void Disconnect() { eqs->Close(); client_state = DISCONNECTED; } inline void Disconnect() { eqs->Close(); client_state = DISCONNECTED; }
inline bool IsLD() const { return (bool) (client_state == CLIENT_LINKDEAD); } inline bool IsLD() const { return (bool) (client_state == CLIENT_LINKDEAD); }
void Kick(const std::string &reason);
void WorldKick(); void WorldKick();
inline uint8 GetAnon() const { return m_pp.anon; } inline uint8 GetAnon() const { return m_pp.anon; }
inline PlayerProfile_Struct& GetPP() { return m_pp; } inline PlayerProfile_Struct& GetPP() { return m_pp; }
@ -1311,6 +1292,9 @@ public:
uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns. uint32 trapid; //ID of trap player has triggered. This is cleared when the player leaves the trap's radius, or it despawns.
void SetLastPositionBeforeBulkUpdate(glm::vec4 in_last_position_before_bulk_update);
glm::vec4 &GetLastPositionBeforeBulkUpdate();
protected: protected:
friend class Mob; friend class Mob;
void CalcItemBonuses(StatBonuses* newbon); void CalcItemBonuses(StatBonuses* newbon);
@ -1519,6 +1503,7 @@ private:
Timer forget_timer; // our 2 min everybody forgets you timer Timer forget_timer; // our 2 min everybody forgets you timer
Timer autosave_timer; Timer autosave_timer;
Timer client_scan_npc_aggro_timer; Timer client_scan_npc_aggro_timer;
Timer client_zone_wide_full_position_update_timer;
Timer tribute_timer; Timer tribute_timer;
Timer proximity_timer; Timer proximity_timer;
@ -1541,6 +1526,7 @@ private:
Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */
glm::vec3 m_Proximity; glm::vec3 m_Proximity;
glm::vec4 last_position_before_bulk_update;
void BulkSendInventoryItems(); void BulkSendInventoryItems();

File diff suppressed because it is too large Load Diff

View File

@ -378,10 +378,10 @@ bool Client::Process() {
} }
if (!CombatRange(auto_attack_target)) { if (!CombatRange(auto_attack_target)) {
Message_StringID(MT_TooFarAway, TARGET_TOO_FAR); MessageString(Chat::TooFarAway, TARGET_TOO_FAR);
} }
else if (auto_attack_target == this) { else if (auto_attack_target == this) {
Message_StringID(MT_TooFarAway, TRY_ATTACKING_SOMEONE); MessageString(Chat::TooFarAway, TRY_ATTACKING_SOMEONE);
} }
else if (!los_status || !los_status_facing) { else if (!los_status || !los_status_facing) {
//you can't see your target //you can't see your target
@ -401,11 +401,11 @@ bool Client::Process() {
if (GetClass() == WARRIOR || GetClass() == BERSERKER) { if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
if (!dead && !IsBerserk() && GetHPRatio() < RuleI(Combat, BerserkerFrenzyStart)) { if (!dead && !IsBerserk() && GetHPRatio() < RuleI(Combat, BerserkerFrenzyStart)) {
entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName());
berserk = true; berserk = true;
} }
if (IsBerserk() && GetHPRatio() > RuleI(Combat, BerserkerFrenzyEnd)) { if (IsBerserk() && GetHPRatio() > RuleI(Combat, BerserkerFrenzyEnd)) {
entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName());
berserk = false; berserk = false;
} }
} }
@ -416,11 +416,11 @@ bool Client::Process() {
// Range check // Range check
if (!CombatRange(auto_attack_target)) { if (!CombatRange(auto_attack_target)) {
// this is a duplicate message don't use it. // this is a duplicate message don't use it.
//Message_StringID(MT_TooFarAway,TARGET_TOO_FAR); //MessageString(Chat::TooFarAway,TARGET_TOO_FAR);
} }
// Don't attack yourself // Don't attack yourself
else if (auto_attack_target == this) { else if (auto_attack_target == this) {
//Message_StringID(MT_TooFarAway,TRY_ATTACKING_SOMEONE); //MessageString(Chat::TooFarAway,TRY_ATTACKING_SOMEONE);
} }
else if (!los_status || !los_status_facing) else if (!los_status || !los_status_facing)
{ {
@ -465,7 +465,8 @@ bool Client::Process() {
{ {
if (!CombatRange(shield_target)) if (!CombatRange(shield_target))
{ {
entity_list.MessageClose_StringID(this, false, 100, 0, entity_list.MessageCloseString(
this, false, 100, 0,
END_SHIELDING, GetCleanName(), shield_target->GetCleanName()); END_SHIELDING, GetCleanName(), shield_target->GetCleanName());
for (int y = 0; y < 2; y++) for (int y = 0; y < 2; y++)
{ {
@ -592,8 +593,8 @@ bool Client::Process() {
// only if client is not feigned // only if client is not feigned
if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) { if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) {
int npc_scan_count = 0; int npc_scan_count = 0;
for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) { for (auto & close_mob : close_mobs) {
Mob *mob = it->first; Mob *mob = close_mob.first;
if (!mob) if (!mob)
continue; continue;
@ -604,6 +605,7 @@ bool Client::Process() {
if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) { if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) {
mob->AddToHateList(this, 25); mob->AddToHateList(this, 25);
} }
npc_scan_count++; npc_scan_count++;
} }
Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count); Log(Logs::General, Logs::Aggro, "Checking Reverse Aggro (client->npc) scanned_npcs (%i)", npc_scan_count);
@ -950,9 +952,9 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) {
sprintf(handy_id, "%i", greet_id); sprintf(handy_id, "%i", greet_id);
if (greet_id != MERCHANT_GREETING) if (greet_id != MERCHANT_GREETING)
Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName(), handyitem->Name); MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName(), handyitem->Name);
else else
Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName()); MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName());
} }
// safe_delete_array(cpi); // safe_delete_array(cpi);
@ -988,7 +990,7 @@ void Client::OPRezzAnswer(uint32 Action, uint32 SpellID, uint16 ZoneID, uint16 I
if(PendingRezzXP < 0) { if(PendingRezzXP < 0) {
// pendingrezexp is set to -1 if we are not expecting an OP_RezzAnswer // pendingrezexp is set to -1 if we are not expecting an OP_RezzAnswer
Log(Logs::Detail, Logs::Spells, "Unexpected OP_RezzAnswer. Ignoring it."); Log(Logs::Detail, Logs::Spells, "Unexpected OP_RezzAnswer. Ignoring it.");
Message(13, "You have already been resurrected.\n"); Message(Chat::Red, "You have already been resurrected.\n");
return; return;
} }
@ -1042,7 +1044,7 @@ void Client::OPTGB(const EQApplicationPacket *app)
uint32 tgb_flag = *(uint32 *)app->pBuffer; uint32 tgb_flag = *(uint32 *)app->pBuffer;
if(tgb_flag == 2) if(tgb_flag == 2)
Message_StringID(0, TGB() ? TGB_ON : TGB_OFF); MessageString(Chat::White, TGB() ? TGB_ON : TGB_OFF);
else else
tgb = tgb_flag; tgb = tgb_flag;
} }
@ -1060,7 +1062,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
if(!IsValidSpell(memspell->spell_id)) if(!IsValidSpell(memspell->spell_id))
{ {
Message(13, "Unexpected error: spell id out of range"); Message(Chat::Red, "Unexpected error: spell id out of range");
return; return;
} }
@ -1071,8 +1073,8 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
) )
{ {
char val1[20]={0}; char val1[20]={0};
Message_StringID(13,SPELL_LEVEL_TO_LOW,ConvertArray(spells[memspell->spell_id].classes[GetClass()-1],val1),spells[memspell->spell_id].name); MessageString(Chat::Red,SPELL_LEVEL_TO_LOW,ConvertArray(spells[memspell->spell_id].classes[GetClass()-1],val1),spells[memspell->spell_id].name);
//Message(13, "Unexpected error: Class cant use this spell at your level!"); //Message(Chat::Red, "Unexpected error: Class cant use this spell at your level!");
return; return;
} }
@ -1086,7 +1088,7 @@ void Client::OPMemorizeSpell(const EQApplicationPacket* app)
const EQEmu::ItemData* item = inst->GetItem(); const EQEmu::ItemData* item = inst->GetItem();
if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) { if (RuleB(Character, RestrictSpellScribing) && !item->IsEquipable(GetRace(), GetClass())) {
Message_StringID(13, CANNOT_USE_ITEM); MessageString(Chat::Red, CANNOT_USE_ITEM);
break; break;
} }
@ -1438,7 +1440,7 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
} }
else{ else{
if (to_bucket == &m_pp.platinum_shared || from_bucket == &m_pp.platinum_shared){ if (to_bucket == &m_pp.platinum_shared || from_bucket == &m_pp.platinum_shared){
this->Message(13, "::: WARNING! ::: SHARED BANK IS DISABLED AND YOUR PLATINUM WILL BE DESTROYED IF YOU PUT IT HERE"); this->Message(Chat::Red, "::: WARNING! ::: SHARED BANK IS DISABLED AND YOUR PLATINUM WILL BE DESTROYED IF YOU PUT IT HERE");
} }
} }
} }
@ -1454,8 +1456,8 @@ void Client::OPMoveCoin(const EQApplicationPacket* app)
with->trade->state = Trading; with->trade->state = Trading;
Client* recipient = trader->CastToClient(); Client* recipient = trader->CastToClient();
recipient->Message(15, "%s adds some coins to the trade.", GetName()); recipient->Message(Chat::Yellow, "%s adds some coins to the trade.", GetName());
recipient->Message(15, "The total trade is: %i PP, %i GP, %i SP, %i CP", recipient->Message(Chat::Yellow, "The total trade is: %i PP, %i GP, %i SP, %i CP",
trade->pp, trade->gp, trade->pp, trade->gp,
trade->sp, trade->cp trade->sp, trade->cp
); );
@ -1525,7 +1527,7 @@ void Client::OPGMTraining(const EQApplicationPacket *app)
// welcome message // welcome message
if (pTrainer && pTrainer->IsNPC()) if (pTrainer && pTrainer->IsNPC())
{ {
pTrainer->Say_StringID(zone->random.Int(1204, 1207), GetCleanName()); pTrainer->SayString(zone->random.Int(1204, 1207), GetCleanName());
} }
} }
@ -1554,7 +1556,7 @@ void Client::OPGMEndTraining(const EQApplicationPacket *app)
// goodbye message // goodbye message
if (pTrainer->IsNPC()) if (pTrainer->IsNPC())
{ {
pTrainer->Say_StringID(zone->random.Int(1208, 1211), GetCleanName()); pTrainer->SayString(zone->random.Int(1208, 1211), GetCleanName());
} }
} }
@ -1644,7 +1646,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
case EQEmu::skills::SkillJewelryMaking: case EQEmu::skills::SkillJewelryMaking:
case EQEmu::skills::SkillPottery: case EQEmu::skills::SkillPottery:
if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) { if(skilllevel >= RuleI(Skills, MaxTrainTradeskills)) {
Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
return; return;
} }
break; break;
@ -1654,7 +1656,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
case EQEmu::skills::SkillSpecializeDivination: case EQEmu::skills::SkillSpecializeDivination:
case EQEmu::skills::SkillSpecializeEvocation: case EQEmu::skills::SkillSpecializeEvocation:
if(skilllevel >= RuleI(Skills, MaxTrainSpecializations)) { if(skilllevel >= RuleI(Skills, MaxTrainSpecializations)) {
Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
return; return;
} }
default: default:
@ -1665,7 +1667,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
if (skilllevel >= MaxSkillValue) if (skilllevel >= MaxSkillValue)
{ {
// Don't allow training over max skill level // Don't allow training over max skill level
Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
return; return;
} }
@ -1675,7 +1677,7 @@ void Client::OPGMTrainSkill(const EQApplicationPacket *app)
if (skilllevel >= MaxSpecSkill) if (skilllevel >= MaxSpecSkill)
{ {
// Restrict specialization training to follow the rules // Restrict specialization training to follow the rules
Message_StringID(13, MORE_SKILLED_THAN_I, pTrainer->GetCleanName()); MessageString(Chat::Red, MORE_SKILLED_THAN_I, pTrainer->GetCleanName());
return; return;
} }
} }
@ -1918,7 +1920,7 @@ void Client::DoTracking()
Mob *m = entity_list.GetMob(TrackingID); Mob *m = entity_list.GetMob(TrackingID);
if (!m || m->IsCorpse()) { if (!m || m->IsCorpse()) {
Message_StringID(MT_Skills, TRACK_LOST_TARGET); MessageString(Chat::Skills, TRACK_LOST_TARGET);
TrackingID = 0; TrackingID = 0;
return; return;
} }
@ -1929,23 +1931,23 @@ void Client::DoTracking()
RelativeHeading += 512; RelativeHeading += 512;
if (RelativeHeading > 480) if (RelativeHeading > 480)
Message_StringID(MT_Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName()); MessageString(Chat::Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName());
else if (RelativeHeading > 416) else if (RelativeHeading > 416)
Message_StringID(MT_Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "left"); MessageString(Chat::Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "left");
else if (RelativeHeading > 352) else if (RelativeHeading > 352)
Message_StringID(MT_Skills, TRACK_TO_THE, m->GetCleanName(), "left"); MessageString(Chat::Skills, TRACK_TO_THE, m->GetCleanName(), "left");
else if (RelativeHeading > 288) else if (RelativeHeading > 288)
Message_StringID(MT_Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "left"); MessageString(Chat::Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "left");
else if (RelativeHeading > 224) else if (RelativeHeading > 224)
Message_StringID(MT_Skills, TRACK_BEHIND_YOU, m->GetCleanName()); MessageString(Chat::Skills, TRACK_BEHIND_YOU, m->GetCleanName());
else if (RelativeHeading > 160) else if (RelativeHeading > 160)
Message_StringID(MT_Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "right"); MessageString(Chat::Skills, TRACK_BEHIND_AND_TO, m->GetCleanName(), "right");
else if (RelativeHeading > 96) else if (RelativeHeading > 96)
Message_StringID(MT_Skills, TRACK_TO_THE, m->GetCleanName(), "right"); MessageString(Chat::Skills, TRACK_TO_THE, m->GetCleanName(), "right");
else if (RelativeHeading > 32) else if (RelativeHeading > 32)
Message_StringID(MT_Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "right"); MessageString(Chat::Skills, TRACK_AHEAD_AND_TO, m->GetCleanName(), "right");
else if (RelativeHeading >= 0) else if (RelativeHeading >= 0)
Message_StringID(MT_Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName()); MessageString(Chat::Skills, TRACK_STRAIGHT_AHEAD, m->GetCleanName());
} }
void Client::HandleRespawnFromHover(uint32 Option) void Client::HandleRespawnFromHover(uint32 Option)

File diff suppressed because it is too large Load Diff

View File

@ -182,6 +182,7 @@ void command_netstats(Client *c, const Seperator *sep);
void command_network(Client *c, const Seperator *sep); void command_network(Client *c, const Seperator *sep);
void command_npccast(Client *c, const Seperator *sep); void command_npccast(Client *c, const Seperator *sep);
void command_npcedit(Client *c, const Seperator *sep); void command_npcedit(Client *c, const Seperator *sep);
void command_npceditmass(Client *c, const Seperator *sep);
void command_npcemote(Client *c, const Seperator *sep); void command_npcemote(Client *c, const Seperator *sep);
void command_npcloot(Client *c, const Seperator *sep); void command_npcloot(Client *c, const Seperator *sep);
void command_npcsay(Client *c, const Seperator *sep); void command_npcsay(Client *c, const Seperator *sep);
@ -247,6 +248,7 @@ void command_repopclose(Client *c, const Seperator *sep);
void command_resetaa(Client* c,const Seperator *sep); void command_resetaa(Client* c,const Seperator *sep);
void command_resetaa_timer(Client *c, const Seperator *sep); void command_resetaa_timer(Client *c, const Seperator *sep);
void command_revoke(Client *c, const Seperator *sep); void command_revoke(Client *c, const Seperator *sep);
void command_roambox(Client *c, const Seperator *sep);
void command_rules(Client *c, const Seperator *sep); void command_rules(Client *c, const Seperator *sep);
void command_save(Client *c, const Seperator *sep); void command_save(Client *c, const Seperator *sep);
void command_scale(Client *c, const Seperator *sep); void command_scale(Client *c, const Seperator *sep);
@ -286,6 +288,7 @@ void command_showzonegloballoot(Client *c, const Seperator *sep);
void command_shutdown(Client *c, const Seperator *sep); void command_shutdown(Client *c, const Seperator *sep);
void command_size(Client *c, const Seperator *sep); void command_size(Client *c, const Seperator *sep);
void command_spawn(Client *c, const Seperator *sep); void command_spawn(Client *c, const Seperator *sep);
void command_spawneditmass(Client *c, const Seperator *sep);
void command_spawnfix(Client *c, const Seperator *sep); void command_spawnfix(Client *c, const Seperator *sep);
void command_spawnstatus(Client *c, const Seperator *sep); void command_spawnstatus(Client *c, const Seperator *sep);
void command_spellinfo(Client *c, const Seperator *sep); void command_spellinfo(Client *c, const Seperator *sep);

View File

@ -272,6 +272,31 @@ enum class LootRequestType : uint8 {
AllowedPVPDefined, AllowedPVPDefined,
}; };
namespace Journal {
enum class SpeakMode : uint8 {
Raw = 0, // this just uses the raw message
Say = 1, // prints with "%1 says,%2 '%3'" if in another language else "%1 says '%2'"
Shout = 2, // prints with "%1 shouts,%2 '%3'" if in another language else "%1 shouts '%2'"
EmoteAlt = 3, // prints "%2", this should just be the same as raw ...
Emote = 4, // prints "%1 %2" if message doesn't start with "\" or "@", else "%1%2"
Group = 5 // prints "%1 tells the group,%2 '%3'"
};
enum class Mode : uint8 {
None = 0,
Log1 = 1, // 1 and 2 log to journal
Log2 = 2, // our current code uses 2
};
struct Options {
SpeakMode speak_mode;
Mode journal_mode;
int8 language;
uint32 message_type;
uint32 target_spawn_id; // who the message is talking to (limits journaling)
};
};
//this is our internal representation of the BUFF struct, can put whatever we want in it //this is our internal representation of the BUFF struct, can put whatever we want in it
struct Buffs_Struct { struct Buffs_Struct {
uint16 spellid; uint16 spellid;

View File

@ -889,14 +889,14 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
if(IsPlayerCorpse() && !corpse_db_id) { // really should try to resave in this case if(IsPlayerCorpse() && !corpse_db_id) { // really should try to resave in this case
// SendLootReqErrorPacket(client, 0); // SendLootReqErrorPacket(client, 0);
client->Message(13, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!"); client->Message(Chat::Red, "Warning: Corpse's dbid = 0! Corpse will not survive zone shutdown!");
std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl; std::cout << "Error: PlayerCorpse::MakeLootRequestPackets: dbid = 0!" << std::endl;
// return; // return;
} }
if(is_locked && client->Admin() < 100) { if(is_locked && client->Admin() < 100) {
SendLootReqErrorPacket(client, LootResponse::SomeoneElse); SendLootReqErrorPacket(client, LootResponse::SomeoneElse);
client->Message(13, "Error: Corpse locked by GM."); client->Message(Chat::Red, "Error: Corpse locked by GM.");
return; return;
} }
@ -960,7 +960,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
loot_coin = (tmp[0] == 1 && tmp[1] == '\0'); loot_coin = (tmp[0] == 1 && tmp[1] == '\0');
if (loot_request_type == LootRequestType::GMPeek || loot_request_type == LootRequestType::GMAllowed) { if (loot_request_type == LootRequestType::GMPeek || loot_request_type == LootRequestType::GMAllowed) {
client->Message(15, "This corpse contains %u platinum, %u gold, %u silver and %u copper.", client->Message(Chat::Yellow, "This corpse contains %u platinum, %u gold, %u silver and %u copper.",
GetPlatinum(), GetGold(), GetSilver(), GetCopper()); GetPlatinum(), GetGold(), GetSilver(), GetCopper());
auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct)); auto outapp = new EQApplicationPacket(OP_MoneyOnCorpse, sizeof(moneyOnCorpseStruct));
@ -1035,7 +1035,7 @@ void Corpse::MakeLootRequestPackets(Client* client, const EQApplicationPacket* a
else { else {
Log(Logs::General, Logs::Inventory, "MakeLootRequestPackets() PlayerKillItem %i not found", pkitemid); Log(Logs::General, Logs::Inventory, "MakeLootRequestPackets() PlayerKillItem %i not found", pkitemid);
client->Message(CC_Red, "PlayerKillItem (id: %i) could not be found!", pkitemid); client->Message(Chat::Red, "PlayerKillItem (id: %i) could not be found!", pkitemid);
} }
client->QueuePacket(app); client->QueuePacket(app);
@ -1129,7 +1129,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
/* To prevent item loss for a player using 'Loot All' who doesn't have inventory space for all their items. */ /* To prevent item loss for a player using 'Loot All' who doesn't have inventory space for all their items. */
if (RuleB(Character, CheckCursorEmptyWhenLooting) && !client->GetInv().CursorEmpty()) { if (RuleB(Character, CheckCursorEmptyWhenLooting) && !client->GetInv().CursorEmpty()) {
client->Message(13, "You may not loot an item while you have an item on your cursor."); client->Message(Chat::Red, "You may not loot an item while you have an item on your cursor.");
client->QueuePacket(app); client->QueuePacket(app);
SendEndLootErrorPacket(client); SendEndLootErrorPacket(client);
/* Unlock corpse for others */ /* Unlock corpse for others */
@ -1146,7 +1146,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc && if (IsPlayerCorpse() && !CanPlayerLoot(client->CharacterID()) && !become_npc &&
(char_id != client->CharacterID() && client->Admin() < 150)) { (char_id != client->CharacterID() && client->Admin() < 150)) {
client->Message(13, "Error: This is a player corpse and you dont own it."); client->Message(Chat::Red, "Error: This is a player corpse and you dont own it.");
client->QueuePacket(app); client->QueuePacket(app);
SendEndLootErrorPacket(client); SendEndLootErrorPacket(client);
return; return;
@ -1155,13 +1155,13 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
if (is_locked && client->Admin() < 100) { if (is_locked && client->Admin() < 100) {
client->QueuePacket(app); client->QueuePacket(app);
SendLootReqErrorPacket(client, LootResponse::SomeoneElse); SendLootReqErrorPacket(client, LootResponse::SomeoneElse);
client->Message(13, "Error: Corpse locked by GM."); client->Message(Chat::Red, "Error: Corpse locked by GM.");
return; return;
} }
if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) && if (IsPlayerCorpse() && (char_id != client->CharacterID()) && CanPlayerLoot(client->CharacterID()) &&
GetPlayerKillItem() == 0) { GetPlayerKillItem() == 0) {
client->Message(13, "Error: You cannot loot any more items from this corpse."); client->Message(Chat::Red, "Error: You cannot loot any more items from this corpse.");
client->QueuePacket(app); client->QueuePacket(app);
SendEndLootErrorPacket(client); SendEndLootErrorPacket(client);
ResetLooter(); ResetLooter();
@ -1201,7 +1201,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
if (client && inst) { if (client && inst) {
if (client->CheckLoreConflict(item)) { if (client->CheckLoreConflict(item)) {
client->Message_StringID(0, LOOT_LORE_ERROR); client->MessageString(Chat::White, LOOT_LORE_ERROR);
client->QueuePacket(app); client->QueuePacket(app);
SendEndLootErrorPacket(client); SendEndLootErrorPacket(client);
ResetLooter(); ResetLooter();
@ -1214,7 +1214,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
EQEmu::ItemInstance *itm = inst->GetAugment(i); EQEmu::ItemInstance *itm = inst->GetAugment(i);
if (itm) { if (itm) {
if (client->CheckLoreConflict(itm->GetItem())) { if (client->CheckLoreConflict(itm->GetItem())) {
client->Message_StringID(0, LOOT_LORE_ERROR); client->MessageString(Chat::White, LOOT_LORE_ERROR);
client->QueuePacket(app); client->QueuePacket(app);
SendEndLootErrorPacket(client); SendEndLootErrorPacket(client);
ResetLooter(); ResetLooter();
@ -1236,7 +1236,7 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
args.push_back(this); args.push_back(this);
if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) { if (parse->EventPlayer(EVENT_LOOT, client, buf, 0, &args) != 0) {
lootitem->auto_loot = -1; lootitem->auto_loot = -1;
client->Message_StringID(CC_Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name); client->MessageString(Chat::Red, LOOT_NOT_ALLOWED, inst->GetItem()->Name);
client->QueuePacket(app); client->QueuePacket(app);
delete inst; delete inst;
return; return;
@ -1312,18 +1312,18 @@ void Corpse::LootItem(Client *client, const EQApplicationPacket *app)
linker.GenerateLink(); linker.GenerateLink();
client->Message_StringID(MT_LootMessages, LOOTED_MESSAGE, linker.Link().c_str()); client->MessageString(Chat::Loot, LOOTED_MESSAGE, linker.Link().c_str());
if (!IsPlayerCorpse()) { if (!IsPlayerCorpse()) {
Group *g = client->GetGroup(); Group *g = client->GetGroup();
if (g != nullptr) { if (g != nullptr) {
g->GroupMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, g->GroupMessageString(client, Chat::Loot, OTHER_LOOTED_MESSAGE,
client->GetName(), linker.Link().c_str()); client->GetName(), linker.Link().c_str());
} }
else { else {
Raid *r = client->GetRaid(); Raid *r = client->GetRaid();
if (r != nullptr) { if (r != nullptr) {
r->RaidMessage_StringID(client, MT_LootMessages, OTHER_LOOTED_MESSAGE, r->RaidMessageString(client, Chat::Loot, OTHER_LOOTED_MESSAGE,
client->GetName(), linker.Link().c_str()); client->GetName(), linker.Link().c_str());
} }
} }
@ -1371,7 +1371,7 @@ void Corpse::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) {
void Corpse::QueryLoot(Client* to) { void Corpse::QueryLoot(Client* to) {
int x = 0, y = 0; // x = visible items, y = total items int x = 0, y = 0; // x = visible items, y = total items
to->Message(0, "Coin: %ip, %ig, %is, %ic", platinum, gold, silver, copper); to->Message(Chat::White, "Coin: %ip, %ig, %is, %ic", platinum, gold, silver, copper);
ItemList::iterator cur,end; ItemList::iterator cur,end;
cur = itemlist.begin(); cur = itemlist.begin();
@ -1405,19 +1405,19 @@ void Corpse::QueryLoot(Client* to) {
const EQEmu::ItemData* item = database.GetItem(sitem->item_id); const EQEmu::ItemData* item = database.GetItem(sitem->item_id);
if (item) if (item)
to->Message(0, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges); to->Message(Chat::White, "LootSlot: %i Item: %s (%d), Count: %i", sitem->lootslot, item->Name, item->ID, sitem->charges);
else else
to->Message(0, "Error: 0x%04x", sitem->item_id); to->Message(Chat::White, "Error: 0x%04x", sitem->item_id);
y++; y++;
} }
} }
if (IsPlayerCorpse()) { if (IsPlayerCorpse()) {
to->Message(0, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetCorpseDBID()); to->Message(Chat::White, "%i visible %s (%i total) on %s (DBID: %i).", x, x==1?"item":"items", y, this->GetName(), this->GetCorpseDBID());
} }
else { else {
to->Message(0, "%i %s on %s.", y, y==1?"item":"items", this->GetName()); to->Message(Chat::White, "%i %s on %s.", y, y==1?"item":"items", this->GetName());
} }
} }
@ -1426,7 +1426,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
if (!spell) { if (!spell) {
if (this->GetCharID() == client->CharacterID()) { if (this->GetCharID() == client->CharacterID()) {
if (IsLocked() && client->Admin() < 100) { if (IsLocked() && client->Admin() < 100) {
client->Message(13, "That corpse is locked by a GM."); client->Message(Chat::Red, "That corpse is locked by a GM.");
return false; return false;
} }
if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) { if (!CheckDistance || (DistanceSquaredNoZ(m_Position, client->GetPosition()) <= dist2)) {
@ -1434,7 +1434,7 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
is_corpse_changed = true; is_corpse_changed = true;
} }
else { else {
client->Message(0, "Corpse is too far away."); client->Message(Chat::White, "Corpse is too far away.");
return false; return false;
} }
} }
@ -1449,14 +1449,14 @@ bool Corpse::Summon(Client* client, bool spell, bool CheckDistance) {
is_corpse_changed = true; is_corpse_changed = true;
} }
else { else {
client->Message(0, "Corpse is too far away."); client->Message(Chat::White, "Corpse is too far away.");
return false; return false;
} }
consented = true; consented = true;
} }
} }
if(!consented) { if(!consented) {
client->Message(0, "You do not have permission to move this corpse."); client->Message(Chat::White, "You do not have permission to move this corpse.");
return false; return false;
} }
} }

View File

@ -171,7 +171,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
if (RuleI(Adventure, ItemIDToEnablePorts) != 0) { if (RuleI(Adventure, ItemIDToEnablePorts) != 0) {
if (!sender->KeyRingCheck(RuleI(Adventure, ItemIDToEnablePorts))) { if (!sender->KeyRingCheck(RuleI(Adventure, ItemIDToEnablePorts))) {
if (sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == INVALID_INDEX) { if (sender->GetInv().HasItem(RuleI(Adventure, ItemIDToEnablePorts)) == INVALID_INDEX) {
sender->Message_StringID(13, DUNGEON_SEALED); sender->MessageString(Chat::Red, DUNGEON_SEALED);
safe_delete(outapp); safe_delete(outapp);
return; return;
} else { } else {
@ -267,7 +267,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
strcpy(door_message, "Door is locked by an unknown guild"); strcpy(door_message, "Door is locked by an unknown guild");
} }
sender->Message(4, door_message); sender->Message(Chat::LightBlue, door_message);
safe_delete(outapp); safe_delete(outapp);
return; return;
} }
@ -275,13 +275,13 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
/** /**
* Key required * Key required
*/ */
sender->Message(4, "This is locked..."); sender->Message(Chat::LightBlue, "This is locked...");
/** /**
* GM can always open locks * GM can always open locks
*/ */
if (sender->GetGM()) { if (sender->GetGM()) {
sender->Message_StringID(4, DOORS_GM); sender->MessageString(Chat::LightBlue, DOORS_GM);
if (!IsDoorOpen() || (open_type == 58)) { if (!IsDoorOpen() || (open_type == 58)) {
move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR);
@ -306,7 +306,7 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
sender->KeyRingAdd(player_key); sender->KeyRingAdd(player_key);
} }
sender->Message(4, "You got it open!"); sender->Message(Chat::LightBlue, "You got it open!");
if (!IsDoorOpen() || (open_type == 58)) { if (!IsDoorOpen() || (open_type == 58)) {
move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR);
@ -333,19 +333,19 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
} else { } else {
move_door_packet->action = static_cast<uint8>(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); move_door_packet->action = static_cast<uint8>(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR);
} }
sender->Message_StringID(4, DOORS_SUCCESSFUL_PICK); sender->MessageString(Chat::LightBlue, DOORS_SUCCESSFUL_PICK);
} else { } else {
sender->Message_StringID(4, DOORS_INSUFFICIENT_SKILL); sender->MessageString(Chat::LightBlue, DOORS_INSUFFICIENT_SKILL);
safe_delete(outapp); safe_delete(outapp);
return; return;
} }
} else { } else {
sender->Message_StringID(4, DOORS_NO_PICK); sender->MessageString(Chat::LightBlue, DOORS_NO_PICK);
safe_delete(outapp); safe_delete(outapp);
return; return;
} }
} else { } else {
sender->Message_StringID(4, DOORS_CANT_PICK); sender->MessageString(Chat::LightBlue, DOORS_CANT_PICK);
safe_delete(outapp); safe_delete(outapp);
return; return;
} }
@ -361,14 +361,14 @@ void Doors::HandleClick(Client* sender, uint8 trigger) {
*/ */
if (sender->KeyRingCheck(required_key_item)) { if (sender->KeyRingCheck(required_key_item)) {
player_key = required_key_item; player_key = required_key_item;
sender->Message(4, "You got it open!"); // more debug spam sender->Message(Chat::LightBlue, "You got it open!"); // more debug spam
if (!IsDoorOpen() || (open_type == 58)) { if (!IsDoorOpen() || (open_type == 58)) {
move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR); move_door_packet->action = static_cast<uint8>(invert_state == 0 ? OPEN_DOOR : OPEN_INVDOOR);
} else { } else {
move_door_packet->action = static_cast<uint8>(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR); move_door_packet->action = static_cast<uint8>(invert_state == 0 ? CLOSE_DOOR : CLOSE_INVDOOR);
} }
} else { } else {
sender->Message_StringID(4, DOORS_LOCKED); sender->MessageString(Chat::LightBlue, DOORS_LOCKED);
safe_delete(outapp); safe_delete(outapp);
return; return;
} }

View File

@ -122,11 +122,12 @@ int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
else if (IsNPC() && CastToNPC()->GetSpellScale()) else if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f); value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, entity_list.MessageCloseString(
OTHER_CRIT_BLAST, GetName(), itoa(-value)); this, true, 100, Chat::SpellCrit,
OTHER_CRIT_BLAST, GetName(), itoa(-value));
if (IsClient()) if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_BLAST, itoa(-value)); MessageString(Chat::SpellCrit, YOU_CRIT_BLAST, itoa(-value));
return value; return value;
} }
@ -306,11 +307,12 @@ int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f); value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f);
if (Critical) { if (Critical) {
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, entity_list.MessageCloseString(
OTHER_CRIT_HEAL, GetName(), itoa(value)); this, true, 100, Chat::SpellCrit,
OTHER_CRIT_HEAL, GetName(), itoa(value));
if (IsClient()) if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); MessageString(Chat::SpellCrit, YOU_CRIT_HEAL, itoa(value));
} }
return value; return value;
@ -432,13 +434,13 @@ bool Client::TrainDiscipline(uint32 itemid) {
//get the item info //get the item info
const EQEmu::ItemData *item = database.GetItem(itemid); const EQEmu::ItemData *item = database.GetItem(itemid);
if(item == nullptr) { if(item == nullptr) {
Message(13, "Unable to find the tome you turned in!"); Message(Chat::Red, "Unable to find the tome you turned in!");
Log(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid); Log(Logs::General, Logs::Error, "Unable to find turned in tome id %lu\n", (unsigned long)itemid);
return(false); return(false);
} }
if (!item->IsClassCommon() || item->ItemType != EQEmu::item::ItemTypeSpell) { if (!item->IsClassCommon() || item->ItemType != EQEmu::item::ItemTypeSpell) {
Message(13, "Invalid item type, you cannot learn from this item."); Message(Chat::Red, "Invalid item type, you cannot learn from this item.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -462,7 +464,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
item->Name[5] == ':' && item->Name[5] == ':' &&
item->Name[6] == ' ' item->Name[6] == ' '
)) { )) {
Message(13, "This item is not a tome."); Message(Chat::Red, "This item is not a tome.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -470,7 +472,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
int myclass = GetClass(); int myclass = GetClass();
if(myclass == WIZARD || myclass == ENCHANTER || myclass == MAGICIAN || myclass == NECROMANCER) { if(myclass == WIZARD || myclass == ENCHANTER || myclass == MAGICIAN || myclass == NECROMANCER) {
Message(13, "Your class cannot learn from this tome."); Message(Chat::Red, "Your class cannot learn from this tome.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -480,7 +482,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
//can we use the item? //can we use the item?
uint32 cbit = 1 << (myclass-1); uint32 cbit = 1 << (myclass-1);
if(!(item->Classes & cbit)) { if(!(item->Classes & cbit)) {
Message(13, "Your class cannot learn from this tome."); Message(Chat::Red, "Your class cannot learn from this tome.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -488,7 +490,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
uint32 spell_id = item->Scroll.Effect; uint32 spell_id = item->Scroll.Effect;
if(!IsValidSpell(spell_id)) { if(!IsValidSpell(spell_id)) {
Message(13, "This tome contains invalid knowledge."); Message(Chat::Red, "This tome contains invalid knowledge.");
return(false); return(false);
} }
@ -496,14 +498,14 @@ bool Client::TrainDiscipline(uint32 itemid) {
const SPDat_Spell_Struct &spell = spells[spell_id]; const SPDat_Spell_Struct &spell = spells[spell_id];
uint8 level_to_use = spell.classes[myclass - 1]; uint8 level_to_use = spell.classes[myclass - 1];
if(level_to_use == 255) { if(level_to_use == 255) {
Message(13, "Your class cannot learn from this tome."); Message(Chat::Red, "Your class cannot learn from this tome.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
} }
if(level_to_use > GetLevel()) { if(level_to_use > GetLevel()) {
Message(13, "You must be at least level %d to learn this discipline.", level_to_use); Message(Chat::Red, "You must be at least level %d to learn this discipline.", level_to_use);
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -513,7 +515,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
int r; int r;
for(r = 0; r < MAX_PP_DISCIPLINES; r++) { for(r = 0; r < MAX_PP_DISCIPLINES; r++) {
if(m_pp.disciplines.values[r] == spell_id) { if(m_pp.disciplines.values[r] == spell_id) {
Message(13, "You already know this discipline."); Message(Chat::Red, "You already know this discipline.");
//summon them the item back... //summon them the item back...
SummonItem(itemid); SummonItem(itemid);
return(false); return(false);
@ -525,7 +527,7 @@ bool Client::TrainDiscipline(uint32 itemid) {
return(true); return(true);
} }
} }
Message(13, "You have learned too many disciplines and can learn no more."); Message(Chat::Red, "You have learned too many disciplines and can learn no more.");
return(false); return(false);
} }
@ -537,7 +539,7 @@ void Client::TrainDiscBySpellID(int32 spell_id)
m_pp.disciplines.values[i] = spell_id; m_pp.disciplines.values[i] = spell_id;
database.SaveCharacterDisc(this->CharacterID(), i, spell_id); database.SaveCharacterDisc(this->CharacterID(), i, spell_id);
SendDisciplineUpdate(); SendDisciplineUpdate();
Message(15, "You have learned a new combat ability!"); Message(Chat::Yellow, "You have learned a new combat ability!");
return; return;
} }
} }
@ -581,7 +583,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
//make sure we can use it.. //make sure we can use it..
if(!IsValidSpell(spell_id)) { if(!IsValidSpell(spell_id)) {
Message(13, "This tome contains invalid knowledge."); Message(Chat::Red, "This tome contains invalid knowledge.");
return(false); return(false);
} }
@ -589,13 +591,13 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
const SPDat_Spell_Struct &spell = spells[spell_id]; const SPDat_Spell_Struct &spell = spells[spell_id];
uint8 level_to_use = spell.classes[GetClass() - 1]; uint8 level_to_use = spell.classes[GetClass() - 1];
if(level_to_use == 255) { if(level_to_use == 255) {
Message(13, "Your class cannot learn from this tome."); Message(Chat::Red, "Your class cannot learn from this tome.");
//should summon them a new one... //should summon them a new one...
return(false); return(false);
} }
if(level_to_use > GetLevel()) { if(level_to_use > GetLevel()) {
Message_StringID(13, DISC_LEVEL_USE_ERROR); MessageString(Chat::Red, DISC_LEVEL_USE_ERROR);
//should summon them a new one... //should summon them a new one...
return(false); return(false);
} }
@ -607,7 +609,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
// sneak attack discs require you to be hidden for 4 seconds before use // sneak attack discs require you to be hidden for 4 seconds before use
if (spell.sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) { if (spell.sneak && (!hidden || (hidden && (Timer::GetCurrentTime() - tmHidden) < 4000))) {
Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); MessageString(Chat::SpellFailure, SNEAK_RESTRICT);
return false; return false;
} }
@ -621,7 +623,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
/*char val1[20]={0};*/ //unused /*char val1[20]={0};*/ //unused
/*char val2[20]={0};*/ //unused /*char val2[20]={0};*/ //unused
uint32 remain = p_timers.GetRemainingTime(DiscTimer); uint32 remain = p_timers.GetRemainingTime(DiscTimer);
//Message_StringID(0, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2)); //MessageString(Chat::White, DISCIPLINE_CANUSEIN, ConvertArray((remain)/60,val1), ConvertArray(remain%60,val2));
Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60)); Message(0, "You can use this discipline in %d minutes %d seconds.", ((remain)/60), (remain%60));
return(false); return(false);
} }

View File

@ -155,12 +155,31 @@ XS(XS__say); // prototype to pass -Wmissing-prototypes
XS(XS__say) { XS(XS__say) {
dXSARGS; dXSARGS;
if (items == 1) Journal::Options opts;
quest_manager.say(SvPV_nolen(ST(0))); // we currently default to these
else if (items == 2) opts.speak_mode = Journal::SpeakMode::Say;
quest_manager.say(SvPV_nolen(ST(0)), (int) SvIV(ST(1))); opts.journal_mode = Journal::Mode::Log2;
else opts.language = 0;
Perl_croak(aTHX_ "Usage: quest::say(string message, int language_id])"); opts.message_type = Chat::NPCQuestSay;
if (items == 0 || items > 5) {
Perl_croak(aTHX_ "Usage: quest::say(string message, [int language_id], [int message_type], [int speak_mode], [int journal_mode])");
} else if (items == 2) {
opts.language = (int)SvIV(ST(1));
} else if (items == 3) {
opts.language = (int)SvIV(ST(1));
opts.message_type = (int)SvIV(ST(2));
} else if (items == 4) {
opts.language = (int)SvIV(ST(1));
opts.message_type = (int)SvIV(ST(2));
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
} else if (items == 5) {
opts.language = (int)SvIV(ST(1));
opts.message_type = (int)SvIV(ST(2));
opts.speak_mode = (Journal::SpeakMode)SvIV(ST(3));
opts.journal_mode = (Journal::Mode)SvIV(ST(4));
}
quest_manager.say(SvPV_nolen(ST(0)), opts);
XSRETURN_EMPTY; XSRETURN_EMPTY;
} }

View File

@ -1235,33 +1235,19 @@ void EntityList::ChannelMessage(Mob *from, uint8 chan_num, uint8 language,
while(it != client_list.end()) { while(it != client_list.end()) {
Client *client = it->second; Client *client = it->second;
eqFilterType filter = FilterNone; eqFilterType filter = FilterNone;
if (chan_num == 3) //shout if (chan_num == ChatChannel_Shout) //shout
filter = FilterShouts; filter = FilterShouts;
else if (chan_num == 4) //auction else if (chan_num == ChatChannel_Auction) //auction
filter = FilterAuctions; filter = FilterAuctions;
// //
// Only say is limited in range // Only say is limited in range
if (chan_num != 8 || Distance(client->GetPosition(), from->GetPosition()) < 200) if (chan_num != ChatChannel_Say || Distance(client->GetPosition(), from->GetPosition()) < 200)
if (filter == FilterNone || client->GetFilter(filter) != FilterHide) if (filter == FilterNone || client->GetFilter(filter) != FilterHide)
client->ChannelMessageSend(from->GetName(), 0, chan_num, language, lang_skill, buffer); client->ChannelMessageSend(from->GetName(), 0, chan_num, language, lang_skill, buffer);
++it; ++it;
} }
} }
void EntityList::ChannelMessageSend(Mob *to, uint8 chan_num, uint8 language, const char *message, ...)
{
if (!to->IsClient())
return;
va_list argptr;
char buffer[4096];
va_start(argptr, message);
vsnprintf(buffer, 4096, message, argptr);
va_end(argptr);
to->CastToClient()->ChannelMessageSend(0, 0, chan_num, language, buffer);
}
void EntityList::SendZoneSpawns(Client *client) void EntityList::SendZoneSpawns(Client *client)
{ {
EQApplicationPacket *app; EQApplicationPacket *app;
@ -1685,9 +1671,9 @@ void EntityList::DuelMessage(Mob *winner, Mob *loser, bool flee)
//might want some sort of distance check in here? //might want some sort of distance check in here?
if (cur != winner && cur != loser) { if (cur != winner && cur != loser) {
if (flee) if (flee)
cur->Message_StringID(15, DUEL_FLED, winner->GetName(),loser->GetName(),loser->GetName()); cur->MessageString(Chat::Yellow, DUEL_FLED, winner->GetName(),loser->GetName(),loser->GetName());
else else
cur->Message_StringID(15, DUEL_FINISHED, winner->GetName(),loser->GetName()); cur->MessageString(Chat::Yellow, DUEL_FINISHED, winner->GetName(),loser->GetName());
} }
++it; ++it;
} }
@ -1727,6 +1713,18 @@ Client *EntityList::GetClientByWID(uint32 iWID)
return nullptr; return nullptr;
} }
Client *EntityList::GetClientByLSID(uint32 iLSID)
{
auto it = client_list.begin();
while (it != client_list.end()) {
if (it->second->LSAccountID() == iLSID) {
return it->second;
}
++it;
}
return nullptr;
}
Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient) Client *EntityList::GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient)
{ {
std::vector<Client *> ClientsInRange; std::vector<Client *> ClientsInRange;
@ -1995,22 +1993,22 @@ Client *EntityList::GetClientByAccID(uint32 accid)
} }
void EntityList::ChannelMessageFromWorld(const char *from, const char *to, void EntityList::ChannelMessageFromWorld(const char *from, const char *to,
uint8 chan_num, uint32 guild_id, uint8 language, const char *message) uint8 chan_num, uint32 guild_id, uint8 language, uint8 lang_skill, const char *message)
{ {
for (auto it = client_list.begin(); it != client_list.end(); ++it) { for (auto it = client_list.begin(); it != client_list.end(); ++it) {
Client *client = it->second; Client *client = it->second;
if (chan_num == 0) { if (chan_num == ChatChannel_Guild) {
if (!client->IsInGuild(guild_id)) if (!client->IsInGuild(guild_id))
continue; continue;
if (!guild_mgr.CheckPermission(guild_id, client->GuildRank(), GUILD_HEAR)) if (!guild_mgr.CheckPermission(guild_id, client->GuildRank(), GUILD_HEAR))
continue; continue;
if (client->GetFilter(FilterGuildChat) == FilterHide) if (client->GetFilter(FilterGuildChat) == FilterHide)
continue; continue;
} else if (chan_num == 5) { } else if (chan_num == ChatChannel_OOC) {
if (client->GetFilter(FilterOOC) == FilterHide) if (client->GetFilter(FilterOOC) == FilterHide)
continue; continue;
} }
client->ChannelMessageSend(from, to, chan_num, language, message); client->ChannelMessageSend(from, to, chan_num, language, lang_skill, message);
} }
} }
@ -2073,7 +2071,7 @@ void EntityList::QueueClientsGuildBankItemUpdate(const GuildBankItemUpdate_Struc
void EntityList::MessageStatus(uint32 to_guild_id, int to_minstatus, uint32 type, const char *message, ...) void EntityList::MessageStatus(uint32 to_guild_id, int to_minstatus, uint32 type, const char *message, ...)
{ {
va_list argptr; va_list argptr;
char buffer[4096]; char buffer[4096];
va_start(argptr, message); va_start(argptr, message);
vsnprintf(buffer, 4096, message, argptr); vsnprintf(buffer, 4096, message, argptr);
@ -2082,75 +2080,242 @@ void EntityList::MessageStatus(uint32 to_guild_id, int to_minstatus, uint32 type
auto it = client_list.begin(); auto it = client_list.begin();
while (it != client_list.end()) { while (it != client_list.end()) {
Client *client = it->second; Client *client = it->second;
if ((to_guild_id == 0 || client->IsInGuild(to_guild_id)) && client->Admin() >= to_minstatus) if ((to_guild_id == 0 || client->IsInGuild(to_guild_id)) && client->Admin() >= to_minstatus) {
client->Message(type, buffer); client->Message(type, buffer);
}
++it; ++it;
} }
} }
// works much like MessageClose, but with formatted strings /**
void EntityList::MessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, uint32 string_id, const char* message1,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9) * @param sender
* @param skipsender
* @param dist
* @param type
* @param string_id
* @param message1
* @param message2
* @param message3
* @param message4
* @param message5
* @param message6
* @param message7
* @param message8
* @param message9
*/
void EntityList::MessageCloseString(
Mob *sender,
bool skipsender,
float dist,
uint32 type,
uint32 string_id,
const char *message1,
const char *message2,
const char *message3,
const char *message4,
const char *message5,
const char *message6,
const char *message7,
const char *message8,
const char *message9
)
{ {
Client *c; Client *c;
float dist2 = dist * dist; float dist2 = dist * dist;
for (auto it = client_list.begin(); it != client_list.end(); ++it) { for (auto & it : client_list) {
c = it->second; c = it.second;
if(c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) if (c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) {
c->Message_StringID(type, string_id, message1, message2, message3, message4, message5, message6, message7, message8, message9); c->MessageString(
type,
string_id,
message1,
message2,
message3,
message4,
message5,
message6,
message7,
message8,
message9
);
}
} }
} }
void EntityList::FilteredMessageClose_StringID(Mob *sender, bool skipsender, /**
float dist, uint32 type, eqFilterType filter, uint32 string_id, * @param sender
const char *message1, const char *message2, const char *message3, * @param skipsender
const char *message4, const char *message5, const char *message6, * @param dist
const char *message7, const char *message8, const char *message9) * @param type
* @param filter
* @param string_id
* @param message1
* @param message2
* @param message3
* @param message4
* @param message5
* @param message6
* @param message7
* @param message8
* @param message9
*/
void EntityList::FilteredMessageCloseString(
Mob *sender, bool skipsender,
float dist,
uint32 type,
eqFilterType filter,
uint32 string_id,
const char *message1,
const char *message2,
const char *message3,
const char *message4,
const char *message5,
const char *message6,
const char *message7,
const char *message8,
const char *message9
)
{ {
Client *c; Client *c;
float dist2 = dist * dist; float dist2 = dist * dist;
for (auto it = client_list.begin(); it != client_list.end(); ++it) { for (auto & it : client_list) {
c = it->second; c = it.second;
if (c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) if (c && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || c != sender)) {
c->FilteredMessage_StringID(sender, type, filter, string_id, c->FilteredMessageString(
message1, message2, message3, message4, message5, sender, type, filter, string_id,
message6, message7, message8, message9); message1, message2, message3, message4, message5,
message6, message7, message8, message9
);
}
} }
} }
void EntityList::Message_StringID(Mob *sender, bool skipsender, uint32 type, uint32 string_id, const char* message1,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9) /**
*
* @param sender
* @param skipsender
* @param type
* @param string_id
* @param message1
* @param message2
* @param message3
* @param message4
* @param message5
* @param message6
* @param message7
* @param message8
* @param message9
*/
void EntityList::MessageString(
Mob *sender,
bool skipsender,
uint32 type,
uint32 string_id,
const char *message1,
const char *message2,
const char *message3,
const char *message4,
const char *message5,
const char *message6,
const char *message7,
const char *message8,
const char *message9
)
{ {
Client *c; Client *c;
for (auto it = client_list.begin(); it != client_list.end(); ++it) { for (auto & it : client_list) {
c = it->second; c = it.second;
if(c && (!skipsender || c != sender)) if (c && (!skipsender || c != sender)) {
c->Message_StringID(type, string_id, message1, message2, message3, message4, message5, message6, message7, message8, message9); c->MessageString(
type,
string_id,
message1,
message2,
message3,
message4,
message5,
message6,
message7,
message8,
message9
);
}
} }
} }
void EntityList::FilteredMessage_StringID(Mob *sender, bool skipsender, /**
uint32 type, eqFilterType filter, uint32 string_id, *
const char *message1, const char *message2, const char *message3, * @param sender
const char *message4, const char *message5, const char *message6, * @param skipsender
const char *message7, const char *message8, const char *message9) * @param type
* @param filter
* @param string_id
* @param message1
* @param message2
* @param message3
* @param message4
* @param message5
* @param message6
* @param message7
* @param message8
* @param message9
*/
void EntityList::FilteredMessageString(
Mob *sender,
bool skipsender,
uint32 type,
eqFilterType filter,
uint32 string_id,
const char *message1,
const char *message2,
const char *message3,
const char *message4,
const char *message5,
const char *message6,
const char *message7,
const char *message8,
const char *message9
)
{ {
Client *c; Client *c;
for (auto it = client_list.begin(); it != client_list.end(); ++it) { for (auto & it : client_list) {
c = it->second; c = it.second;
if (c && (!skipsender || c != sender)) if (c && (!skipsender || c != sender)) {
c->FilteredMessage_StringID(sender, type, filter, string_id, c->FilteredMessageString(
message1, message2, message3, message4, message5, message6, sender,
message7, message8, message9); type,
filter,
string_id,
message1,
message2,
message3,
message4,
message5,
message6,
message7,
message8,
message9
);
}
} }
} }
void EntityList::MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...) /**
* @param sender
* @param skipsender
* @param dist
* @param type
* @param message
* @param ...
*/
void EntityList::MessageClose(Mob *sender, bool skipsender, float dist, uint32 type, const char *message, ...)
{ {
va_list argptr; va_list argptr;
char buffer[4096]; char buffer[4096];
va_start(argptr, message); va_start(argptr, message);
vsnprintf(buffer, 4095, message, argptr); vsnprintf(buffer, 4095, message, argptr);
@ -2160,16 +2325,26 @@ void EntityList::MessageClose(Mob* sender, bool skipsender, float dist, uint32 t
auto it = client_list.begin(); auto it = client_list.begin();
while (it != client_list.end()) { while (it != client_list.end()) {
if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || it->second != sender)) if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 &&
(!skipsender || it->second != sender)) {
it->second->Message(type, buffer); it->second->Message(type, buffer);
}
++it; ++it;
} }
} }
void EntityList::FilteredMessageClose(Mob *sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char *message, ...) void EntityList::FilteredMessageClose(
Mob *sender,
bool skipsender,
float dist,
uint32 type,
eqFilterType filter,
const char *message,
...
)
{ {
va_list argptr; va_list argptr;
char buffer[4096]; char buffer[4096];
va_start(argptr, message); va_start(argptr, message);
vsnprintf(buffer, 4095, message, argptr); vsnprintf(buffer, 4095, message, argptr);
@ -2179,8 +2354,10 @@ void EntityList::FilteredMessageClose(Mob *sender, bool skipsender, float dist,
auto it = client_list.begin(); auto it = client_list.begin();
while (it != client_list.end()) { while (it != client_list.end()) {
if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || it->second != sender)) if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 &&
it->second->FilteredMessage(sender, type, filter, buffer); (!skipsender || it->second != sender)) {
it->second->FilteredMessage(sender, type, filter, buffer);
}
++it; ++it;
} }
} }
@ -2725,15 +2902,15 @@ void EntityList::ListNPCCorpses(Client *client)
uint32 x = 0; uint32 x = 0;
auto it = corpse_list.begin(); auto it = corpse_list.begin();
client->Message(0, "NPC Corpses in the zone:"); client->Message(Chat::White, "NPC Corpses in the zone:");
while (it != corpse_list.end()) { while (it != corpse_list.end()) {
if (it->second->IsNPCCorpse()) { if (it->second->IsNPCCorpse()) {
client->Message(0, " %5d: %s", it->first, it->second->GetName()); client->Message(Chat::White, " %5d: %s", it->first, it->second->GetName());
x++; x++;
} }
++it; ++it;
} }
client->Message(0, "%d npc corpses listed.", x); client->Message(Chat::White, "%d npc corpses listed.", x);
} }
void EntityList::ListPlayerCorpses(Client *client) void EntityList::ListPlayerCorpses(Client *client)
@ -2741,15 +2918,15 @@ void EntityList::ListPlayerCorpses(Client *client)
uint32 x = 0; uint32 x = 0;
auto it = corpse_list.begin(); auto it = corpse_list.begin();
client->Message(0, "Player Corpses in the zone:"); client->Message(Chat::White, "Player Corpses in the zone:");
while (it != corpse_list.end()) { while (it != corpse_list.end()) {
if (it->second->IsPlayerCorpse()) { if (it->second->IsPlayerCorpse()) {
client->Message(0, " %5d: %s", it->first, it->second->GetName()); client->Message(Chat::White, " %5d: %s", it->first, it->second->GetName());
x++; x++;
} }
++it; ++it;
} }
client->Message(0, "%d player corpses listed.", x); client->Message(Chat::White, "%d player corpses listed.", x);
} }
// returns the number of corpses deleted. A negative number indicates an error code. // returns the number of corpses deleted. A negative number indicates an error code.
@ -2776,7 +2953,7 @@ void EntityList::CorpseFix(Client* c)
Corpse* corpse = it->second; Corpse* corpse = it->second;
if (corpse->IsNPCCorpse()) { if (corpse->IsNPCCorpse()) {
if (DistanceNoZ(c->GetPosition(), corpse->GetPosition()) < 100) { if (DistanceNoZ(c->GetPosition(), corpse->GetPosition()) < 100) {
c->Message(15, "Attempting to fix %s", it->second->GetCleanName()); c->Message(Chat::Yellow, "Attempting to fix %s", it->second->GetCleanName());
corpse->GMMove(corpse->GetX(), corpse->GetY(), c->GetZ() + 2, 0); corpse->GMMove(corpse->GetX(), corpse->GetY(), c->GetZ() + 2, 0);
} }
} }
@ -3551,7 +3728,7 @@ void EntityList::LimitAddNPC(NPC *npc)
SpawnLimitRecord r; SpawnLimitRecord r;
uint16 eid = npc->GetID(); uint16 eid = npc->GetID();
r.spawngroup_id = npc->GetSp2(); r.spawngroup_id = npc->GetSpawnGroupId();
r.npc_type = npc->GetNPCTypeID(); r.npc_type = npc->GetNPCTypeID();
npc_limit_list[eid] = r; npc_limit_list[eid] = r;
@ -3746,25 +3923,27 @@ bool Entity::CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z,
return false; return false;
} }
void EntityList::QuestJournalledSayClose(Mob *sender, Client *QuestInitiator, void EntityList::QuestJournalledSayClose(Mob *sender, float dist, const char *mobname, const char *message,
float dist, const char* mobname, const char* message) Journal::Options &opts)
{ {
Client *c = nullptr; SerializeBuffer buf(sizeof(SpecialMesgHeader_Struct) + 12 + 64 + 64);
float dist2 = dist * dist;
// Send the message to the quest initiator such that the client will enter it into the NPC Quest Journal buf.WriteInt8(static_cast<int8>(opts.speak_mode));
if (QuestInitiator) { buf.WriteInt8(static_cast<int8>(opts.journal_mode));
auto buf = new char[strlen(mobname) + strlen(message) + 10]; buf.WriteInt8(opts.language);
sprintf(buf, "%s says, '%s'", mobname, message); buf.WriteInt32(opts.message_type);
QuestInitiator->QuestJournalledMessage(mobname, buf); buf.WriteInt32(opts.target_spawn_id);
safe_delete_array(buf); buf.WriteString(mobname);
} buf.WriteInt32(0); // location, client doesn't seem to do anything with this
// Use the old method for all other nearby clients buf.WriteInt32(0);
for (auto it = client_list.begin(); it != client_list.end(); ++it) { buf.WriteInt32(0);
c = it->second; buf.WriteString(message);
if(c && (c != QuestInitiator) && DistanceSquared(c->GetPosition(), sender->GetPosition()) <= dist2)
c->Message_StringID(10, GENERIC_SAY, mobname, message); auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf);
}
// client only bothers logging if target spawn ID matches, safe to send to everyone
QueueCloseClients(sender, outapp, false, dist);
delete outapp;
} }
Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name) Corpse *EntityList::GetClosestCorpse(Mob *sender, const char *Name)
@ -3880,7 +4059,7 @@ void EntityList::GroupMessage(uint32 gid, const char *from, const char *message)
g = it->second->GetGroup(); g = it->second->GetGroup();
if (g) { if (g) {
if (g->GetID() == gid) if (g->GetID() == gid)
it->second->ChannelMessageSend(from, it->second->GetName(), 2, 0, message); it->second->ChannelMessageSend(from, it->second->GetName(), ChatChannel_Group, 0, 100, message);
} }
} }
++it; ++it;
@ -4632,7 +4811,7 @@ void EntityList::ExpeditionWarning(uint32 minutes_left)
auto it = client_list.begin(); auto it = client_list.begin();
while (it != client_list.end()) { while (it != client_list.end()) {
it->second->Message_StringID(15, EXPEDITION_MIN_REMAIN, itoa((int)minutes_left)); it->second->MessageString(Chat::Yellow, EXPEDITION_MIN_REMAIN, itoa((int)minutes_left));
it->second->QueuePacket(outapp); it->second->QueuePacket(outapp);
++it; ++it;
} }

View File

@ -29,6 +29,7 @@
#include "position.h" #include "position.h"
#include "zonedump.h" #include "zonedump.h"
#include "common.h"
class Encounter; class Encounter;
class Beacon; class Beacon;
@ -175,6 +176,7 @@ public:
} }
Client *GetClientByCharID(uint32 iCharID); Client *GetClientByCharID(uint32 iCharID);
Client *GetClientByWID(uint32 iWID); Client *GetClientByWID(uint32 iWID);
Client *GetClientByLSID(uint32 iLSID);
Client *GetClient(uint32 ip, uint16 port); Client *GetClient(uint32 ip, uint16 port);
Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr); Client *GetRandomClient(const glm::vec3& location, float Distance, Client *ExcludeClient = nullptr);
Group *GetGroupByMob(Mob* mob); Group *GetGroupByMob(Mob* mob);
@ -319,14 +321,42 @@ public:
void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...); void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...);
void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...); void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...);
void FilteredMessageClose(Mob* sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char* message, ...); void FilteredMessageClose(Mob* sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char* message, ...);
void Message_StringID(Mob *sender, bool skipsender, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); void MessageString(Mob *sender, bool skipsender, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
void FilteredMessage_StringID(Mob *sender, bool skipsender, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); void FilteredMessageString(Mob *sender, bool skipsender, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0);
void MessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); void MessageCloseString(
void FilteredMessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); Mob *sender,
void ChannelMessageFromWorld(const char* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, const char* message); bool skipsender,
float dist,
uint32 type,
uint32 string_id,
const char *message1 = 0,
const char *message2 = 0,
const char *message3 = 0,
const char *message4 = 0,
const char *message5 = 0,
const char *message6 = 0,
const char *message7 = 0,
const char *message8 = 0,
const char *message9 = 0);
void FilteredMessageCloseString(
Mob *sender,
bool skipsender,
float dist,
uint32 type,
eqFilterType filter,
uint32 string_id,
const char *message1 = 0,
const char *message2 = 0,
const char *message3 = 0,
const char *message4 = 0,
const char *message5 = 0,
const char *message6 = 0,
const char *message7 = 0,
const char *message8 = 0,
const char *message9 = 0);
void ChannelMessageFromWorld(const char* from, const char* to, uint8 chan_num, uint32 guilddbid, uint8 language, uint8 lang_skill, const char* message);
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, const char* message, ...); void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, const char* message, ...);
void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...); void ChannelMessage(Mob* from, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...);
void ChannelMessageSend(Mob* to, uint8 chan_num, uint8 language, const char* message, ...);
void SendZoneSpawns(Client*); void SendZoneSpawns(Client*);
void SendZonePVPUpdates(Client *); void SendZonePVPUpdates(Client *);
void SendZoneSpawnsBulk(Client* client); void SendZoneSpawnsBulk(Client* client);
@ -338,7 +368,7 @@ public:
void SendNimbusEffects(Client *c); void SendNimbusEffects(Client *c);
void SendUntargetable(Client *c); void SendUntargetable(Client *c);
void DuelMessage(Mob* winner, Mob* loser, bool flee); void DuelMessage(Mob* winner, Mob* loser, bool flee);
void QuestJournalledSayClose(Mob *sender, Client *QuestIntiator, float dist, const char* mobname, const char* message); void QuestJournalledSayClose(Mob *sender, float dist, const char* mobname, const char* message, Journal::Options &opts);
void GroupMessage(uint32 gid, const char *from, const char *message); void GroupMessage(uint32 gid, const char *from, const char *message);
void ExpeditionWarning(uint32 minutes_left); void ExpeditionWarning(uint32 minutes_left);

View File

@ -333,18 +333,18 @@ void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel)
uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f); uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f);
exp -= mentor_exp; exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); mentoree->MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP);
} }
if (exp > 0) if (exp > 0)
{ {
// possible if you mentor 100% to the other client // possible if you mentor 100% to the other client
AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP);
} }
} }
else else
{ {
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); MessageString(Chat::LeaderShip, MAX_GROUP_LEADERSHIP_POINTS);
} }
} }
else else
@ -357,11 +357,11 @@ void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel)
&& RuleI(Character, KillsPerRaidLeadershipAA) > 0) && RuleI(Character, KillsPerRaidLeadershipAA) > 0)
{ {
AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA)); AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA));
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP); MessageString(Chat::LeaderShip, GAIN_RAID_LEADERSHIP_EXP);
} }
else else
{ {
Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS); MessageString(Chat::LeaderShip, MAX_RAID_LEADERSHIP_POINTS);
} }
} }
else else
@ -378,17 +378,17 @@ void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel)
uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f); uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f);
exp -= mentor_exp; exp -= mentor_exp;
mentoree->AddLeadershipEXP(mentor_exp, 0); mentoree->AddLeadershipEXP(mentor_exp, 0);
mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); mentoree->MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP);
} }
if (exp > 0) if (exp > 0)
{ {
AddLeadershipEXP(exp, 0); AddLeadershipEXP(exp, 0);
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_EXP);
} }
} }
else else
{ {
Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); MessageString(Chat::LeaderShip, MAX_GROUP_LEADERSHIP_POINTS);
} }
} }
} }
@ -514,7 +514,7 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) {
// AA Sanity Checking for players who set aa exp and deleveled below allowed aa level. // AA Sanity Checking for players who set aa exp and deleveled below allowed aa level.
if (GetLevel() <= 50 && m_epp.perAA > 0) { if (GetLevel() <= 50 && m_epp.perAA > 0) {
Message(15, "You are below the level allowed to gain AA Experience. AA Experience set to 0%"); Message(Chat::Yellow, "You are below the level allowed to gain AA Experience. AA Experience set to 0%");
aaexp = 0; aaexp = 0;
m_epp.perAA = 0; m_epp.perAA = 0;
} }
@ -528,7 +528,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
auto max_AAXP = GetRequiredAAExperience(); auto max_AAXP = GetRequiredAAExperience();
if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) { if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) {
Message(13, "Error in Client::SetEXP. EXP not set."); Message(Chat::Red, "Error in Client::SetEXP. EXP not set.");
return; // Must be invalid class/race return; // Must be invalid class/race
} }
uint32 i = 0; uint32 i = 0;
@ -564,23 +564,23 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if (isrezzexp) { if (isrezzexp) {
if (RuleI(Character, ShowExpValues) > 0) if (RuleI(Character, ShowExpValues) > 0)
Message(MT_Experience, "You regain %s experience from resurrection. %s", exp_amount_message.c_str(), exp_percent_message.c_str()); Message(Chat::Experience, "You regain %s experience from resurrection. %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else Message_StringID(MT_Experience, REZ_REGAIN); else MessageString(Chat::Experience, REZ_REGAIN);
} else { } else {
if (membercount > 1) { if (membercount > 1) {
if (RuleI(Character, ShowExpValues) > 0) if (RuleI(Character, ShowExpValues) > 0)
Message(MT_Experience, "You have gained %s party experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); Message(Chat::Experience, "You have gained %s party experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else Message_StringID(MT_Experience, GAIN_GROUPXP); else MessageString(Chat::Experience, GAIN_GROUPXP);
} }
else if (IsRaidGrouped()) { else if (IsRaidGrouped()) {
if (RuleI(Character, ShowExpValues) > 0) if (RuleI(Character, ShowExpValues) > 0)
Message(MT_Experience, "You have gained %s raid experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); Message(Chat::Experience, "You have gained %s raid experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else Message_StringID(MT_Experience, GAIN_RAIDEXP); else MessageString(Chat::Experience, GAIN_RAIDEXP);
} }
else { else {
if (RuleI(Character, ShowExpValues) > 0) if (RuleI(Character, ShowExpValues) > 0)
Message(MT_Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); Message(Chat::Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str());
else Message_StringID(MT_Experience, GAIN_XP); else MessageString(Chat::Experience, GAIN_XP);
} }
} }
} }
@ -588,9 +588,9 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
uint32 exp_lost = m_pp.exp - set_exp; uint32 exp_lost = m_pp.exp - set_exp;
float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100; float exp_percent = (float)((float)exp_lost / (float)(GetEXPForLevel(GetLevel() + 1) - GetEXPForLevel(GetLevel())))*(float)100;
if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(15, "You have lost %i experience.", exp_lost); if (RuleI(Character, ShowExpValues) == 1 && exp_lost > 0) Message(Chat::Yellow, "You have lost %i experience.", exp_lost);
else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(15, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent); else if (RuleI(Character, ShowExpValues) == 2 && exp_lost > 0) Message(Chat::Yellow, "You have lost %i experience. (%.3f%%)", exp_lost, exp_percent);
else Message(15, "You have lost experience."); else Message(Chat::Yellow, "You have lost experience.");
} }
//check_level represents the level we should be when we have //check_level represents the level we should be when we have
@ -654,9 +654,9 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
//figure out how many points were actually gained //figure out how many points were actually gained
/*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused /*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused
//Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA); //Message(Chat::Yellow, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA);
char val1[20]={0}; char val1[20]={0};
Message_StringID(MT_Experience, GAIN_ABILITY_POINT, ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2. MessageString(Chat::Experience, GAIN_ABILITY_POINT, ConvertArray(m_pp.aapoints, val1),m_pp.aapoints == 1 ? "" : "(s)"); //You have gained an ability point! You now have %1 ability point%2.
/* QS: PlayerLogAARate */ /* QS: PlayerLogAARate */
if (RuleB(QueryServ, PlayerLogAARate)){ if (RuleB(QueryServ, PlayerLogAARate)){
@ -665,7 +665,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
QServ->SendQuery(query.c_str()); QServ->SendQuery(query.c_str());
} }
//Message(15, "You now have %d skill points available to spend.", m_pp.aapoints); //Message(Chat::Yellow, "You now have %d skill points available to spend.", m_pp.aapoints);
} }
uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1; uint8 maxlevel = RuleI(Character, MaxExpLevel) + 1;
@ -699,18 +699,18 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
if (level_increase) if (level_increase)
{ {
if (level_count == 1) if (level_count == 1)
Message_StringID(MT_Experience, GAIN_LEVEL, ConvertArray(check_level, val1)); MessageString(Chat::Experience, GAIN_LEVEL, ConvertArray(check_level, val1));
else else
Message(15, "Welcome to level %i!", check_level); Message(Chat::Yellow, "Welcome to level %i!", check_level);
if (check_level == RuleI(Character, DeathItemLossLevel)) if (check_level == RuleI(Character, DeathItemLossLevel))
Message_StringID(15, CORPSE_ITEM_LOST); MessageString(Chat::Yellow, CORPSE_ITEM_LOST);
if (check_level == RuleI(Character, DeathExpLossLevel)) if (check_level == RuleI(Character, DeathExpLossLevel))
Message_StringID(15, CORPSE_EXP_LOST); MessageString(Chat::Yellow, CORPSE_EXP_LOST);
} }
else else
Message_StringID(MT_Experience, LOSE_LEVEL, ConvertArray(check_level, val1)); MessageString(Chat::Experience, LOSE_LEVEL, ConvertArray(check_level, val1));
#ifdef BOTS #ifdef BOTS
uint8 myoldlevel = GetLevel(); uint8 myoldlevel = GetLevel();
@ -758,7 +758,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) {
char val1[20]={0}; char val1[20]={0};
char val2[20]={0}; char val2[20]={0};
char val3[20]={0}; char val3[20]={0};
Message_StringID(MT_Experience, GM_GAINXP, ConvertArray(set_aaxp,val1),ConvertArray(set_exp,val2),ConvertArray(GetEXPForLevel(GetLevel()+1),val3)); //[GM] You have gained %1 AXP and %2 EXP (%3). MessageString(Chat::Experience, GM_GAINXP, ConvertArray(set_aaxp,val1),ConvertArray(set_exp,val2),ConvertArray(GetEXPForLevel(GetLevel()+1),val3)); //[GM] You have gained %1 AXP and %2 EXP (%3).
} }
} }
@ -812,7 +812,7 @@ void Client::SetLevel(uint8 set_level, bool command)
m_pp.level = set_level; m_pp.level = set_level;
if (command){ if (command){
m_pp.exp = GetEXPForLevel(set_level); m_pp.exp = GetEXPForLevel(set_level);
Message(15, "Welcome to level %i!", set_level); Message(Chat::Yellow, "Welcome to level %i!", set_level);
lu->exp = 0; lu->exp = 0;
} }
else { else {
@ -1077,12 +1077,12 @@ void Client::SetLeadershipEXP(uint32 group_exp, uint32 raid_exp) {
while(group_exp >= GROUP_EXP_PER_POINT) { while(group_exp >= GROUP_EXP_PER_POINT) {
group_exp -= GROUP_EXP_PER_POINT; group_exp -= GROUP_EXP_PER_POINT;
m_pp.group_leadership_points++; m_pp.group_leadership_points++;
Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_POINT); MessageString(Chat::LeaderShip, GAIN_GROUP_LEADERSHIP_POINT);
} }
while(raid_exp >= RAID_EXP_PER_POINT) { while(raid_exp >= RAID_EXP_PER_POINT) {
raid_exp -= RAID_EXP_PER_POINT; raid_exp -= RAID_EXP_PER_POINT;
m_pp.raid_leadership_points++; m_pp.raid_leadership_points++;
Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_POINT); MessageString(Chat::LeaderShip, GAIN_RAID_LEADERSHIP_POINT);
} }
m_pp.group_leadership_exp = group_exp; m_pp.group_leadership_exp = group_exp;

View File

@ -161,14 +161,14 @@ bool Client::CanFish() {
if (!Pole || !Pole->IsClassCommon() || Pole->GetItem()->ItemType != EQEmu::item::ItemTypeFishingPole) { if (!Pole || !Pole->IsClassCommon() || Pole->GetItem()->ItemType != EQEmu::item::ItemTypeFishingPole) {
if (m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingPole, 1, invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)) //We have a fishing pole somewhere, just not equipped if (m_inv.HasItemByUse(EQEmu::item::ItemTypeFishingPole, 1, invWhereWorn | invWherePersonal | invWhereBank | invWhereSharedBank | invWhereTrading | invWhereCursor)) //We have a fishing pole somewhere, just not equipped
Message_StringID(MT_Skills, FISHING_EQUIP_POLE); //You need to put your fishing pole in your primary hand. MessageString(Chat::Skills, FISHING_EQUIP_POLE); //You need to put your fishing pole in your primary hand.
else //We don't have a fishing pole anywhere else //We don't have a fishing pole anywhere
Message_StringID(MT_Skills, FISHING_NO_POLE); //You can't fish without a fishing pole, go buy one. MessageString(Chat::Skills, FISHING_NO_POLE); //You can't fish without a fishing pole, go buy one.
return false; return false;
} }
if (!Bait || !Bait->IsClassCommon() || Bait->GetItem()->ItemType != EQEmu::item::ItemTypeFishingBait) { if (!Bait || !Bait->IsClassCommon() || Bait->GetItem()->ItemType != EQEmu::item::ItemTypeFishingBait) {
Message_StringID(MT_Skills, FISHING_NO_BAIT); //You can't fish without fishing bait, go buy some. MessageString(Chat::Skills, FISHING_NO_BAIT); //You can't fish without fishing bait, go buy some.
return false; return false;
} }
@ -190,7 +190,7 @@ bool Client::CanFish() {
float bestz = zone->zonemap->FindBestZ(rodPosition, nullptr); float bestz = zone->zonemap->FindBestZ(rodPosition, nullptr);
float len = m_Position.z - bestz; float len = m_Position.z - bestz;
if(len > LineLength || len < 0.0f) { if(len > LineLength || len < 0.0f) {
Message_StringID(MT_Skills, FISHING_LAND); MessageString(Chat::Skills, FISHING_LAND);
return false; return false;
} }
@ -203,7 +203,7 @@ bool Client::CanFish() {
bool in_water = zone->watermap->InWater(dest) || zone->watermap->InVWater(dest); bool in_water = zone->watermap->InWater(dest) || zone->watermap->InVWater(dest);
if (in_lava) { if (in_lava) {
Message_StringID(MT_Skills, FISHING_LAVA); //Trying to catch a fire elemental or something? MessageString(Chat::Skills, FISHING_LAVA); //Trying to catch a fire elemental or something?
return false; return false;
} }
@ -212,7 +212,7 @@ bool Client::CanFish() {
} }
} }
Message_StringID(MT_Skills, FISHING_LAND); MessageString(Chat::Skills, FISHING_LAND);
return false; return false;
} }
return true; return true;
@ -223,7 +223,7 @@ void Client::GoFish()
//TODO: generate a message if we're already fishing //TODO: generate a message if we're already fishing
/*if (!fishing_timer.Check()) { //this isn't the right check, may need to add something to the Client class like 'bool is_fishing' /*if (!fishing_timer.Check()) { //this isn't the right check, may need to add something to the Client class like 'bool is_fishing'
Message_StringID(0, ALREADY_FISHING); //You are already fishing! MessageString(Chat::White, ALREADY_FISHING); //You are already fishing!
return; return;
}*/ }*/
@ -293,12 +293,12 @@ void Client::GoFish()
entity_list.AddNPC(npc); entity_list.AddNPC(npc);
Message(MT_Emote, Message(Chat::Emote,
"You fish up a little more than you bargained for..."); "You fish up a little more than you bargained for...");
} }
} }
else { else {
Message(MT_Emote, "You notice something lurking just below the water's surface..."); Message(Chat::Emote, "You notice something lurking just below the water's surface...");
} }
} }
} }
@ -315,17 +315,17 @@ void Client::GoFish()
const EQEmu::ItemData* food_item = database.GetItem(food_id); const EQEmu::ItemData* food_item = database.GetItem(food_id);
if (food_item->ItemType != EQEmu::item::ItemTypeFood) { if (food_item->ItemType != EQEmu::item::ItemTypeFood) {
Message_StringID(MT_Skills, FISHING_SUCCESS); MessageString(Chat::Skills, FISHING_SUCCESS);
} }
else { else {
Message_StringID(MT_Skills, FISHING_SUCCESS_FISH_NAME, food_item->Name); MessageString(Chat::Skills, FISHING_SUCCESS_FISH_NAME, food_item->Name);
} }
EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1); EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1);
if(inst != nullptr) { if(inst != nullptr) {
if(CheckLoreConflict(inst->GetItem())) if(CheckLoreConflict(inst->GetItem()))
{ {
Message_StringID(0, DUP_LORE); MessageString(Chat::White, DUP_LORE);
safe_delete(inst); safe_delete(inst);
} }
else else
@ -351,13 +351,13 @@ void Client::GoFish()
//chance to use bait when you dont catch anything... //chance to use bait when you dont catch anything...
if (zone->random.Int(0, 4) == 1) { if (zone->random.Int(0, 4) == 1) {
DeleteItemInInventory(bslot, 1, true); //do we need client update? DeleteItemInInventory(bslot, 1, true); //do we need client update?
Message_StringID(MT_Skills, FISHING_LOST_BAIT); //You lost your bait! MessageString(Chat::Skills, FISHING_LOST_BAIT); //You lost your bait!
} else { } else {
if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it if (zone->random.Int(0, 15) == 1) //give about a 1 in 15 chance to spill your beer. we could make this a rule, but it doesn't really seem worth it
//TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default //TODO: check for & consume an alcoholic beverage from inventory when this triggers, and set it as a rule that's disabled by default
Message_StringID(MT_Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line. MessageString(Chat::Skills, FISHING_SPILL_BEER); //You spill your beer while bringing in your line.
else else
Message_StringID(MT_Skills, FISHING_FAILED); //You didn't catch anything. MessageString(Chat::Skills, FISHING_FAILED); //You didn't catch anything.
} }
parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0); parse->EventPlayer(EVENT_FISH_FAILURE, this, "", 0);
@ -367,7 +367,7 @@ void Client::GoFish()
//this is potentially exploitable in that they can fish //this is potentially exploitable in that they can fish
//and then swap out items in primary slot... too lazy to fix right now //and then swap out items in primary slot... too lazy to fix right now
if (zone->random.Int(0, 49) == 1) { if (zone->random.Int(0, 49) == 1) {
Message_StringID(MT_Skills, FISHING_POLE_BROKE); //Your fishing pole broke! MessageString(Chat::Skills, FISHING_POLE_BROKE); //Your fishing pole broke!
DeleteItemInInventory(EQEmu::invslot::slotPrimary, 0, true); DeleteItemInInventory(EQEmu::invslot::slotPrimary, 0, true);
} }
@ -434,13 +434,13 @@ void Client::ForageItem(bool guarantee) {
break; break;
} }
Message_StringID(MT_Skills, stringid); MessageString(Chat::Skills, stringid);
EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1); EQEmu::ItemInstance* inst = database.CreateItem(food_item, 1);
if(inst != nullptr) { if(inst != nullptr) {
// check to make sure it isn't a foraged lore item // check to make sure it isn't a foraged lore item
if(CheckLoreConflict(inst->GetItem())) if(CheckLoreConflict(inst->GetItem()))
{ {
Message_StringID(0, DUP_LORE); MessageString(Chat::White, DUP_LORE);
safe_delete(inst); safe_delete(inst);
} }
else { else {
@ -462,12 +462,12 @@ void Client::ForageItem(bool guarantee) {
int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems; int ChanceSecondForage = aabonuses.ForageAdditionalItems + itembonuses.ForageAdditionalItems + spellbonuses.ForageAdditionalItems;
if(!guarantee && zone->random.Roll(ChanceSecondForage)) { if(!guarantee && zone->random.Roll(ChanceSecondForage)) {
Message_StringID(MT_Skills, FORAGE_MASTERY); MessageString(Chat::Skills, FORAGE_MASTERY);
ForageItem(true); ForageItem(true);
} }
} else { } else {
Message_StringID(MT_Skills, FORAGE_FAILED); MessageString(Chat::Skills, FORAGE_FAILED);
parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0); parse->EventPlayer(EVENT_FORAGE_FAILURE, this, "", 0);
} }

View File

@ -21,14 +21,14 @@ std::vector<int> GlobalLootManager::GetGlobalLootTables(NPC *mob) const
void GlobalLootManager::ShowZoneGlobalLoot(Client *to) const void GlobalLootManager::ShowZoneGlobalLoot(Client *to) const
{ {
for (auto &e : m_entries) for (auto &e : m_entries)
to->Message(0, " %s : %d table %d", e.GetDescription().c_str(), e.GetID(), e.GetLootTableID()); to->Message(Chat::White, " %s : %d table %d", e.GetDescription().c_str(), e.GetID(), e.GetLootTableID());
} }
void GlobalLootManager::ShowNPCGlobalLoot(Client *to, NPC *who) const void GlobalLootManager::ShowNPCGlobalLoot(Client *to, NPC *who) const
{ {
for (auto &e : m_entries) { for (auto &e : m_entries) {
if (e.PassesRules(who)) if (e.PassesRules(who))
to->Message(0, " %s : %d table %d", e.GetDescription().c_str(), e.GetID(), e.GetLootTableID()); to->Message(Chat::White, " %s : %d table %d", e.GetDescription().c_str(), e.GetID(), e.GetLootTableID());
} }
} }

View File

@ -199,7 +199,7 @@ void Group::SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinu
Client *c = members[i]->CastToClient(); Client *c = members[i]->CastToClient();
//I could not get MoneyOnCorpse to work, so we use this //I could not get MoneyOnCorpse to work, so we use this
c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true); c->AddMoneyToPP(cpsplit, spsplit, gpsplit, ppsplit, true);
c->Message(2, msg.c_str()); c->Message(Chat::Green, msg.c_str());
} }
} }
} }
@ -910,7 +910,7 @@ void Group::GroupMessage(Mob* sender, uint8 language, uint8 lang_skill, const ch
continue; continue;
if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0) if (members[i]->IsClient() && members[i]->CastToClient()->GetFilter(FilterGroupChat)!=0)
members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),2,language,lang_skill,message); members[i]->CastToClient()->ChannelMessageSend(sender->GetName(),members[i]->GetName(),ChatChannel_Group,language,lang_skill,message);
} }
auto pack = auto pack =
@ -1236,7 +1236,7 @@ void Group::VerifyGroup() {
} }
} }
void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) { void Group::GroupMessageString(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2,const char* message3,const char* message4,const char* message5,const char* message6,const char* message7,const char* message8,const char* message9, uint32 distance) {
uint32 i; uint32 i;
for (i = 0; i < MAX_GROUP_MEMBERS; i++) { for (i = 0; i < MAX_GROUP_MEMBERS; i++) {
if(members[i] == nullptr) if(members[i] == nullptr)
@ -1248,7 +1248,7 @@ void Group::GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, co
if(!members[i]->IsClient()) if(!members[i]->IsClient())
continue; continue;
members[i]->Message_StringID(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0); members[i]->MessageString(type, string_id, message, message2, message3, message4, message5, message6, message7, message8, message9, 0);
} }
} }
@ -1680,9 +1680,9 @@ void Group::NotifyMainTank(Client *c, uint8 toggle)
if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD)
{ {
if(toggle) if(toggle)
c->Message(0, "%s is now Main Tank.", MainTankName.c_str()); c->Message(Chat::White, "%s is now Main Tank.", MainTankName.c_str());
else else
c->Message(0, "%s is no longer Main Tank.", MainTankName.c_str()); c->Message(Chat::White, "%s is no longer Main Tank.", MainTankName.c_str());
} }
else else
{ {
@ -1775,9 +1775,9 @@ void Group::NotifyPuller(Client *c, uint8 toggle)
if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD) if (c->ClientVersion() < EQEmu::versions::ClientVersion::SoD)
{ {
if(toggle) if(toggle)
c->Message(0, "%s is now Puller.", PullerName.c_str()); c->Message(Chat::White, "%s is now Puller.", PullerName.c_str());
else else
c->Message(0, "%s is no longer Puller.", PullerName.c_str()); c->Message(Chat::White, "%s is no longer Puller.", PullerName.c_str());
} }
else else
{ {

View File

@ -74,7 +74,7 @@ public:
void GroupBardPulse(Mob* caster,uint16 spellid); void GroupBardPulse(Mob* caster,uint16 spellid);
void SplitExp(uint32 exp, Mob* other); void SplitExp(uint32 exp, Mob* other);
void GroupMessage(Mob* sender,uint8 language,uint8 lang_skill,const char* message); void GroupMessage(Mob* sender,uint8 language,uint8 lang_skill,const char* message);
void GroupMessage_StringID(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0); void GroupMessageString(Mob* sender, uint32 type, uint32 string_id, const char* message,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0, uint32 distance = 0);
uint32 GetTotalGroupDamage(Mob* other); uint32 GetTotalGroupDamage(Mob* other);
void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr); void SplitMoney(uint32 copper, uint32 silver, uint32 gold, uint32 platinum, Client *splitter = nullptr);
inline void SetLeader(Mob* newleader){ leader=newleader; }; inline void SetLeader(Mob* newleader){ leader=newleader; };

View File

@ -189,7 +189,7 @@ uint8 *ZoneGuildManager::MakeGuildMembers(uint32 guild_id, const char *prefix_na
} }
void ZoneGuildManager::ListGuilds(Client *c) const { void ZoneGuildManager::ListGuilds(Client *c) const {
c->Message(0, "Listing guilds on the server:"); c->Message(Chat::White, "Listing guilds on the server:");
char leadername[64]; char leadername[64];
std::map<uint32, GuildInfo *>::const_iterator cur, end; std::map<uint32, GuildInfo *>::const_iterator cur, end;
cur = m_guilds.begin(); cur = m_guilds.begin();
@ -199,12 +199,12 @@ void ZoneGuildManager::ListGuilds(Client *c) const {
leadername[0] = '\0'; leadername[0] = '\0';
database.GetCharName(cur->second->leader_char_id, leadername); database.GetCharName(cur->second->leader_char_id, leadername);
if (leadername[0] == '\0') if (leadername[0] == '\0')
c->Message(0, " Guild #%i <%s>", cur->first, cur->second->name.c_str()); c->Message(Chat::White, " Guild #%i <%s>", cur->first, cur->second->name.c_str());
else else
c->Message(0, " Guild #%i <%s> Leader: %s", cur->first, cur->second->name.c_str(), leadername); c->Message(Chat::White, " Guild #%i <%s> Leader: %s", cur->first, cur->second->name.c_str(), leadername);
r++; r++;
} }
c->Message(0, "%i guilds listed.", r); c->Message(Chat::White, "%i guilds listed.", r);
} }
@ -212,17 +212,17 @@ void ZoneGuildManager::DescribeGuild(Client *c, uint32 guild_id) const {
std::map<uint32, GuildInfo *>::const_iterator res; std::map<uint32, GuildInfo *>::const_iterator res;
res = m_guilds.find(guild_id); res = m_guilds.find(guild_id);
if(res == m_guilds.end()) { if(res == m_guilds.end()) {
c->Message(0, "Guild %d not found.", guild_id); c->Message(Chat::White, "Guild %d not found.", guild_id);
return; return;
} }
const GuildInfo *info = res->second; const GuildInfo *info = res->second;
c->Message(0, "Guild info DB# %i <%s>", guild_id, info->name.c_str()); c->Message(Chat::White, "Guild info DB# %i <%s>", guild_id, info->name.c_str());
char leadername[64]; char leadername[64];
database.GetCharName(info->leader_char_id, leadername); database.GetCharName(info->leader_char_id, leadername);
c->Message(0, "Guild Leader: %s", leadername); c->Message(Chat::White, "Guild Leader: %s", leadername);
char permbuffer[256]; char permbuffer[256];
uint8 i; uint8 i;
@ -232,8 +232,8 @@ void ZoneGuildManager::DescribeGuild(Client *c, uint32 guild_id) const {
for(r = 0; r < _MaxGuildAction; r++) for(r = 0; r < _MaxGuildAction; r++)
permptr += sprintf(permptr, " %s: %c", GuildActionNames[r], info->ranks[i].permissions[r]?'Y':'N'); permptr += sprintf(permptr, " %s: %c", GuildActionNames[r], info->ranks[i].permissions[r]?'Y':'N');
c->Message(0, "Rank %i: %s", i, info->ranks[i].name.c_str()); c->Message(Chat::White, "Rank %i: %s", i, info->ranks[i].name.c_str());
c->Message(0, "Permissions: %s", permbuffer); c->Message(Chat::White, "Permissions: %s", permbuffer);
} }
} }
@ -537,14 +537,14 @@ void ZoneGuildManager::AddMemberApproval(uint32 refid,Client* name)
if(tmp != 0) if(tmp != 0)
{ {
if(!tmp->AddMemberApproval(name)) if(!tmp->AddMemberApproval(name))
name->Message(0,"Unable to add to list."); name->Message(Chat::White,"Unable to add to list.");
else else
{ {
name->Message(0,"Added to list."); name->Message(Chat::White,"Added to list.");
} }
} }
else else
name->Message(0,"Unable to find guild reference id."); name->Message(Chat::White,"Unable to find guild reference id.");
} }
ZoneGuildManager::~ZoneGuildManager() ZoneGuildManager::~ZoneGuildManager()
@ -1391,13 +1391,13 @@ bool GuildApproval::ProcessApproval()
{ {
if(owner && owner->GuildID() != 0) if(owner && owner->GuildID() != 0)
{ {
owner->Message(10,"You are already in a guild! Guild request deleted."); owner->Message(Chat::NPCQuestSay,"You are already in a guild! Guild request deleted.");
return false; return false;
} }
if(deletion_timer->Check() || !owner) if(deletion_timer->Check() || !owner)
{ {
if(owner) if(owner)
owner->Message(0,"You took too long! Your guild request has been deleted."); owner->Message(Chat::White,"You took too long! Your guild request has been deleted.");
return false; return false;
} }
@ -1414,7 +1414,7 @@ GuildApproval::GuildApproval(const char* guildname, Client* owner,uint32 id)
this->owner = owner; this->owner = owner;
this->refid = id; this->refid = id;
if(owner) if(owner)
owner->Message(0,"You can now start getting your guild approved, tell your %i members to #guildapprove %i, you have 30 minutes to create your guild.",tmp,GetID()); owner->Message(Chat::White,"You can now start getting your guild approved, tell your %i members to #guildapprove %i, you have 30 minutes to create your guild.",tmp,GetID());
for(int i=0;i<tmp;i++) for(int i=0;i<tmp;i++)
members[i] = 0; members[i] = 0;
} }
@ -1463,7 +1463,7 @@ void GuildApproval::ApprovedMembers(Client* requestee)
for(int i=0;i<tmp;i++) for(int i=0;i<tmp;i++)
{ {
if(members[i]) if(members[i])
requestee->Message(0,"%i: %s",i,members[i]->GetName()); requestee->Message(Chat::White,"%i: %s",i,members[i]->GetName());
} }
} }
@ -1484,8 +1484,8 @@ void GuildApproval::GuildApproved()
{ {
if(members[i]) if(members[i])
{ {
owner->Message(0, "%s",members[i]->GetName()); owner->Message(Chat::White, "%s",members[i]->GetName());
owner->Message(0, "%i",members[i]->CharacterID()); owner->Message(Chat::White, "%i",members[i]->CharacterID());
guild_mgr.SetGuild(members[i]->CharacterID(),tmpeq,0); guild_mgr.SetGuild(members[i]->CharacterID(),tmpeq,0);
size_t len = MBUFFER - strlen(gmembers)+1; size_t len = MBUFFER - strlen(gmembers)+1;
strncat(gmembers," ",len); strncat(gmembers," ",len);
@ -1521,7 +1521,7 @@ void GuildApproval::GuildApproved()
memcpy(pack->pBuffer, &tmpeq, 4); memcpy(pack->pBuffer, &tmpeq, 4);
worldserver.SendPacket(pack); worldserver.SendPacket(pack);
safe_delete(pack); safe_delete(pack);
owner->Message(0, "Your guild was created."); owner->Message(Chat::White, "Your guild was created.");
owner = 0; owner = 0;
} }

View File

@ -608,7 +608,7 @@ void HateList::PrintHateListToClient(Client *c)
while (iterator != list.end()) while (iterator != list.end())
{ {
struct_HateList *e = (*iterator); struct_HateList *e = (*iterator);
c->Message(0, "- name: %s, damage: %d, hate: %d", c->Message(Chat::White, "- name: %s, damage: %d, hate: %d",
(e->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)", (e->entity_on_hatelist && e->entity_on_hatelist->GetName()) ? e->entity_on_hatelist->GetName() : "(null)",
e->hatelist_damage, e->stored_hate_amount); e->hatelist_damage, e->stored_hate_amount);

View File

@ -118,7 +118,7 @@ const NPCType *Horse::BuildHorseType(uint16 spell_id) {
void Client::SummonHorse(uint16 spell_id) { void Client::SummonHorse(uint16 spell_id) {
if (GetHorseId() != 0) { if (GetHorseId() != 0) {
Message(13,"You already have a Horse. Get off, Fatbutt!"); Message(Chat::Red,"You already have a Horse. Get off, Fatbutt!");
return; return;
} }
if(!Horse::IsHorseSpell(spell_id)) { if(!Horse::IsHorseSpell(spell_id)) {

View File

@ -185,7 +185,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// make sure the item exists // make sure the item exists
if(item == nullptr) { if(item == nullptr) {
Message(13, "Item %u does not exist.", item_id); Message(Chat::Red, "Item %u does not exist.", item_id);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item_id, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item_id, aug1, aug2, aug3, aug4, aug5, aug6);
@ -194,13 +194,13 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check that there is not a lore conflict between base item and existing inventory // check that there is not a lore conflict between base item and existing inventory
else if(CheckLoreConflict(item)) { else if(CheckLoreConflict(item)) {
// DuplicateLoreMessage(item_id); // DuplicateLoreMessage(item_id);
Message(13, "You already have a lore %s (%i) in your inventory.", item->Name, item_id); Message(Chat::Red, "You already have a lore %s (%i) in your inventory.", item->Name, item_id);
return false; return false;
} }
// check to make sure we are augmenting an augmentable item // check to make sure we are augmenting an augmentable item
else if (((!item->IsClassCommon()) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5 | aug6)) { else if (((!item->IsClassCommon()) || (item->AugType > 0)) && (aug1 | aug2 | aug3 | aug4 | aug5 | aug6)) {
Message(13, "You can not augment an augment or a non-common class item."); Message(Chat::Red, "You can not augment an augment or a non-common class item.");
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an augment or a non-common class item.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug5: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an augment or a non-common class item.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug5: %u)\n",
GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -214,7 +214,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check to make sure we are a GM if the item is GM-only // check to make sure we are a GM if the item is GM-only
/* /*
else if(item->MinStatus && ((this->Admin() < item->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) { else if(item->MinStatus && ((this->Admin() < item->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) {
Message(13, "You are not a GM or do not have the status to summon this item."); Message(Chat::Red, "You are not a GM or do not have the status to summon this item.");
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create a GM-only item with a status of %i.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u, MinStatus: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create a GM-only item with a status of %i.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u, MinStatus: %u)\n",
GetName(), account_name, this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus); GetName(), account_name, this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus);
@ -237,7 +237,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
if(augtest == nullptr) { if(augtest == nullptr) {
if(augments[iter]) { if(augments[iter]) {
Message(13, "Augment %u (Aug%i) does not exist.", augments[iter], iter + 1); Message(Chat::Red, "Augment %u (Aug%i) does not exist.", augments[iter], iter + 1);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an augment (Aug%i) with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an augment (Aug%i) with an invalid id.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -248,13 +248,13 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check that there is not a lore conflict between augment and existing inventory // check that there is not a lore conflict between augment and existing inventory
if(CheckLoreConflict(augtest)) { if(CheckLoreConflict(augtest)) {
// DuplicateLoreMessage(augtest->ID); // DuplicateLoreMessage(augtest->ID);
Message(13, "You already have a lore %s (%u) in your inventory.", augtest->Name, augtest->ID); Message(Chat::Red, "You already have a lore %s (%u) in your inventory.", augtest->Name, augtest->ID);
return false; return false;
} }
// check that augment is an actual augment // check that augment is an actual augment
else if(augtest->AugType == 0) { else if(augtest->AugType == 0) {
Message(13, "%s (%u) (Aug%i) is not an actual augment.", augtest->Name, augtest->ID, iter + 1); Message(Chat::Red, "%s (%u) (Aug%i) is not an actual augment.", augtest->Name, augtest->ID, iter + 1);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to use a non-augment item (Aug%i) as an augment.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to use a non-augment item (Aug%i) as an augment.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item->ID, (iter + 1), aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, (iter + 1), aug1, aug2, aug3, aug4, aug5, aug6);
@ -266,7 +266,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check to make sure we are a GM if the augment is GM-only // check to make sure we are a GM if the augment is GM-only
/* /*
else if(augtest->MinStatus && ((this->Admin() < augtest->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) { else if(augtest->MinStatus && ((this->Admin() < augtest->MinStatus) || (this->Admin() < RuleI(GM, MinStatusToSummonItem)))) {
Message(13, "You are not a GM or do not have the status to summon this augment."); Message(Chat::Red, "You are not a GM or do not have the status to summon this augment.");
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create a GM-only augment (Aug%i) with a status of %i.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, MinStatus: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create a GM-only augment (Aug%i) with a status of %i.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, MinStatus: %u)\n",
GetName(), account_name, (iter + 1), this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus); GetName(), account_name, (iter + 1), this->Admin(), item->ID, aug1, aug2, aug3, aug4, aug5, aug6, item->MinStatus);
@ -277,7 +277,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check for augment type allowance // check for augment type allowance
if(enforcewear) { if(enforcewear) {
if ((item->AugSlotType[iter] == EQEmu::item::AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) { if ((item->AugSlotType[iter] == EQEmu::item::AugTypeNone) || !(((uint32)1 << (item->AugSlotType[iter] - 1)) & augtest->AugType)) {
Message(13, "Augment %u (Aug%i) is not acceptable wear on Item %u.", augments[iter], iter + 1, item->ID); Message(Chat::Red, "Augment %u (Aug%i) is not acceptable wear on Item %u.", augments[iter], iter + 1, item->ID);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an item with an unacceptable augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an item with an unacceptable augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -285,7 +285,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
} }
if(item->AugSlotVisible[iter] == 0) { if(item->AugSlotVisible[iter] == 0) {
Message(13, "Item %u has not evolved enough to accept Augment %u (Aug%i).", item->ID, augments[iter], iter + 1); Message(Chat::Red, "Item %u has not evolved enough to accept Augment %u (Aug%i).", item->ID, augments[iter], iter + 1);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an unevolved item with augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an unevolved item with augment type (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -462,7 +462,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
} }
if(restrictfail) { if(restrictfail) {
Message(13, "Augment %u (Aug%i) is restricted from wear on Item %u.", augments[iter], (iter + 1), item->ID); Message(Chat::Red, "Augment %u (Aug%i) is restricted from wear on Item %u.", augments[iter], (iter + 1), item->ID);
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an item with a restricted augment (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to augment an item with a restricted augment (Aug%i).\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, (iter + 1), item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -473,7 +473,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
if(enforceusable) { if(enforceusable) {
// check for class usability // check for class usability
if(item->Classes && !(classes &= augtest->Classes)) { if(item->Classes && !(classes &= augtest->Classes)) {
Message(13, "Augment %u (Aug%i) will result in an item not usable by any class.", augments[iter], (iter + 1)); Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable by any class.", augments[iter], (iter + 1));
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable by any class.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable by any class.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -482,7 +482,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check for race usability // check for race usability
if(item->Races && !(races &= augtest->Races)) { if(item->Races && !(races &= augtest->Races)) {
Message(13, "Augment %u (Aug%i) will result in an item not usable by any race.", augments[iter], (iter + 1)); Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable by any race.", augments[iter], (iter + 1));
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable by any race.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable by any race.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -491,7 +491,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
// check for slot usability // check for slot usability
if(item->Slots && !(slots &= augtest->Slots)) { if(item->Slots && !(slots &= augtest->Slots)) {
Message(13, "Augment %u (Aug%i) will result in an item not usable in any slot.", augments[iter], (iter + 1)); Message(Chat::Red, "Augment %u (Aug%i) will result in an item not usable in any slot.", augments[iter], (iter + 1));
Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable in any slot.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::Detail, Logs::Inventory, "Player %s on account %s attempted to create an item unusable in any slot.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -517,7 +517,7 @@ bool Client::SummonItem(uint32 item_id, int16 charges, uint32 aug1, uint32 aug2,
EQEmu::ItemInstance* inst = database.CreateItem(item, charges); EQEmu::ItemInstance* inst = database.CreateItem(item, charges);
if(inst == nullptr) { if(inst == nullptr) {
Message(13, "An unknown server error has occurred and your item was not created."); Message(Chat::Red, "An unknown server error has occurred and your item was not created.");
// this goes to logfile since this is a major error // this goes to logfile since this is a major error
Log(Logs::General, Logs::Error, "Player %s on account %s encountered an unknown item creation error.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n", Log(Logs::General, Logs::Error, "Player %s on account %s encountered an unknown item creation error.\n(Item: %u, Aug1: %u, Aug2: %u, Aug3: %u, Aug4: %u, Aug5: %u, Aug6: %u)\n",
GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6); GetName(), account_name, item->ID, aug1, aug2, aug3, aug4, aug5, aug6);
@ -652,7 +652,7 @@ void Client::DropItem(int16 slot_id, bool recurse)
} else { } else {
// Item doesn't exist in inventory! // Item doesn't exist in inventory!
Log(Logs::General, Logs::Inventory, "DropItem() - No item found in slot %i", slot_id); Log(Logs::General, Logs::Inventory, "DropItem() - No item found in slot %i", slot_id);
Message(13, "Error: Item not found in slot %i", slot_id); Message(Chat::Red, "Error: Item not found in slot %i", slot_id);
return; return;
} }
@ -752,14 +752,14 @@ void Client::DropInst(const EQEmu::ItemInstance* inst)
{ {
if (!inst) { if (!inst) {
// Item doesn't exist in inventory! // Item doesn't exist in inventory!
Message(13, "Error: Item not found"); Message(Chat::Red, "Error: Item not found");
return; return;
} }
if (inst->GetItem()->NoDrop == 0) if (inst->GetItem()->NoDrop == 0)
{ {
Message(13, "This item is NODROP. Deleting."); Message(Chat::Red, "This item is NODROP. Deleting.");
return; return;
} }
@ -853,7 +853,7 @@ void Client::SendCursorBuffer()
if (!lore_pass) { if (!lore_pass) {
Log(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor", Log(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor",
GetName(), test_item->Name, test_item->ID); GetName(), test_item->Name, test_item->ID);
Message_StringID(MT_LootMessages, 290); MessageString(Chat::Loot, 290);
parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0);
DeleteItemInInventory(EQEmu::invslot::slotCursor); DeleteItemInInventory(EQEmu::invslot::slotCursor);
SendCursorBuffer(); SendCursorBuffer();
@ -1520,7 +1520,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
if(!IsValidSlot(src_slot_check)){ if(!IsValidSlot(src_slot_check)){
// SoF+ sends a Unix timestamp (should be int32) for src and dst slots every 10 minutes for some reason. // SoF+ sends a Unix timestamp (should be int32) for src and dst slots every 10 minutes for some reason.
if(src_slot_check < 2147483647) if(src_slot_check < 2147483647)
Message(13, "Warning: Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check); Message(Chat::Red, "Warning: Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check);
Log(Logs::Detail, Logs::Inventory, "Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check); Log(Logs::Detail, Logs::Inventory, "Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check);
return false; return false;
} }
@ -1528,7 +1528,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
if(!IsValidSlot(dst_slot_check)) { if(!IsValidSlot(dst_slot_check)) {
// SoF+ sends a Unix timestamp (should be int32) for src and dst slots every 10 minutes for some reason. // SoF+ sends a Unix timestamp (should be int32) for src and dst slots every 10 minutes for some reason.
if(src_slot_check < 2147483647) if(src_slot_check < 2147483647)
Message(13, "Warning: Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check); Message(Chat::Red, "Warning: Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check);
Log(Logs::Detail, Logs::Inventory, "Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check); Log(Logs::Detail, Logs::Inventory, "Invalid slot move from slot %u to slot %u with %u charges!", src_slot_check, dst_slot_check, stack_count_check);
return false; return false;
} }
@ -1555,7 +1555,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
if (!lore_pass) { if (!lore_pass) {
Log(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor", Log(Logs::General, Logs::Inventory, "(%s) Duplicate lore items are not allowed - destroying item %s(id:%u) on cursor",
GetName(), test_item->Name, test_item->ID); GetName(), test_item->Name, test_item->ID);
Message_StringID(MT_LootMessages, 290); MessageString(Chat::Loot, 290);
parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0); parse->EventItem(EVENT_DESTROY_ITEM, this, test_inst, nullptr, "", 0);
DeleteItemInInventory(EQEmu::invslot::slotCursor, 0, true); DeleteItemInInventory(EQEmu::invslot::slotCursor, 0, true);
} }
@ -1608,7 +1608,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
banker ? banker->GetName() : "UNKNOWN NPC", distance); banker ? banker->GetName() : "UNKNOWN NPC", distance);
database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName()); database.SetMQDetectionFlag(AccountName(), GetName(), hacked_string, zone->GetShortName());
safe_delete_array(hacked_string); safe_delete_array(hacked_string);
Kick(); // Kicking player to avoid item loss do to client and server inventories not being sync'd Kick("Inventory desync"); // Kicking player to avoid item loss do to client and server inventories not being sync'd
return false; return false;
} }
} }
@ -1624,7 +1624,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
//SetTint(dst_slot_id,src_inst->GetColor()); //SetTint(dst_slot_id,src_inst->GetColor());
if (src_inst->GetCharges() > 0 && (src_inst->GetCharges() < (int16)move_in->number_in_stack || move_in->number_in_stack > src_inst->GetItem()->StackSize)) if (src_inst->GetCharges() > 0 && (src_inst->GetCharges() < (int16)move_in->number_in_stack || move_in->number_in_stack > src_inst->GetItem()->StackSize))
{ {
Message(13,"Error: Insufficient number in stack."); Message(Chat::Red,"Error: Insufficient number in stack.");
return false; return false;
} }
} }
@ -1650,7 +1650,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
} }
if (srcitemid==17899 || srcbagid==17899 || dstitemid==17899 || dstbagid==17899){ if (srcitemid==17899 || srcbagid==17899 || dstitemid==17899 || dstbagid==17899){
this->Trader_EndTrader(); this->Trader_EndTrader();
this->Message(13,"You cannot move your Trader Satchels, or items inside them, while Trading."); this->Message(Chat::Red,"You cannot move your Trader Satchels, or items inside them, while Trading.");
} }
} }
@ -1822,14 +1822,14 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
// Step 4: Check for entity trade // Step 4: Check for entity trade
if (dst_slot_id >= EQEmu::invslot::TRADE_BEGIN && dst_slot_id <= EQEmu::invslot::TRADE_END) { if (dst_slot_id >= EQEmu::invslot::TRADE_BEGIN && dst_slot_id <= EQEmu::invslot::TRADE_END) {
if (src_slot_id != EQEmu::invslot::slotCursor) { if (src_slot_id != EQEmu::invslot::slotCursor) {
Kick(); Kick("Trade with non-cursor item");
return false; return false;
} }
if (with) { if (with) {
Log(Logs::Detail, Logs::Inventory, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName()); Log(Logs::Detail, Logs::Inventory, "Trade item move from slot %d to slot %d (trade with %s)", src_slot_id, dst_slot_id, with->GetName());
// Fill Trade list with items from cursor // Fill Trade list with items from cursor
if (!m_inv[EQEmu::invslot::slotCursor]) { if (!m_inv[EQEmu::invslot::slotCursor]) {
Message(13, "Error: Cursor item not located on server!"); Message(Chat::Red, "Error: Cursor item not located on server!");
return false; return false;
} }
@ -1939,7 +1939,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) {
fail_message = "You are not sufficient level to use this item."; fail_message = "You are not sufficient level to use this item.";
if (fail_message) if (fail_message)
Message(CC_Red, "%s", fail_message); Message(Chat::Red, "%s", fail_message);
return false; return false;
} }
@ -2008,7 +2008,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
// resync the 'from' and 'to' slots on an as-needed basis // resync the 'from' and 'to' slots on an as-needed basis
// Not as effective as the full process, but less intrusive to gameplay // Not as effective as the full process, but less intrusive to gameplay
Log(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot); Log(Logs::Detail, Logs::Inventory, "Inventory desyncronization. (charname: %s, source: %i, destination: %i)", GetName(), move_slots->from_slot, move_slots->to_slot);
Message(15, "Inventory Desyncronization detected: Resending slot data..."); Message(Chat::Yellow, "Inventory Desyncronization detected: Resending slot data...");
if (move_slots->from_slot >= EQEmu::invslot::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::invbag::CURSOR_BAG_END) { if (move_slots->from_slot >= EQEmu::invslot::EQUIPMENT_BEGIN && move_slots->from_slot <= EQEmu::invbag::CURSOR_BAG_END) {
int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot); int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot);
@ -2031,9 +2031,9 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
safe_delete(outapp); safe_delete(outapp);
} }
safe_delete(token_inst); safe_delete(token_inst);
Message(14, "Source slot %i resyncronized.", move_slots->from_slot); Message(Chat::Lime, "Source slot %i resyncronized.", move_slots->from_slot);
} }
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } else { Message(Chat::Red, "Could not resyncronize source slot %i.", move_slots->from_slot); }
} }
else { else {
int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot); int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot) == INVALID_INDEX) ? move_slots->from_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->from_slot);
@ -2046,11 +2046,11 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade);
safe_delete(token_inst); safe_delete(token_inst);
Message(14, "Source slot %i resyncronized.", move_slots->from_slot); Message(Chat::Lime, "Source slot %i resyncronized.", move_slots->from_slot);
} }
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } else { Message(Chat::Red, "Could not resyncronize source slot %i.", move_slots->from_slot); }
} }
else { Message(13, "Could not resyncronize source slot %i.", move_slots->from_slot); } else { Message(Chat::Red, "Could not resyncronize source slot %i.", move_slots->from_slot); }
} }
if (move_slots->to_slot >= EQEmu::invslot::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::invbag::CURSOR_BAG_END) { if (move_slots->to_slot >= EQEmu::invslot::EQUIPMENT_BEGIN && move_slots->to_slot <= EQEmu::invbag::CURSOR_BAG_END) {
@ -2073,9 +2073,9 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
safe_delete(outapp); safe_delete(outapp);
} }
safe_delete(token_inst); safe_delete(token_inst);
Message(14, "Destination slot %i resyncronized.", move_slots->to_slot); Message(Chat::Lime, "Destination slot %i resyncronized.", move_slots->to_slot);
} }
else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); } else { Message(Chat::Red, "Could not resyncronize destination slot %i.", move_slots->to_slot); }
} }
else { else {
int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot); int16 resync_slot = (EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot) == INVALID_INDEX) ? move_slots->to_slot : EQEmu::InventoryProfile::CalcSlotId(move_slots->to_slot);
@ -2088,11 +2088,11 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) {
SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade); SendItemPacket(resync_slot, m_inv[resync_slot], ItemPacketTrade);
safe_delete(token_inst); safe_delete(token_inst);
Message(14, "Destination slot %i resyncronized.", move_slots->to_slot); Message(Chat::Lime, "Destination slot %i resyncronized.", move_slots->to_slot);
} }
else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); } else { Message(Chat::Red, "Could not resyncronize destination slot %i.", move_slots->to_slot); }
} }
else { Message(13, "Could not resyncronize destination slot %i.", move_slots->to_slot); } else { Message(Chat::Red, "Could not resyncronize destination slot %i.", move_slots->to_slot); }
} }
} }
@ -2219,7 +2219,7 @@ void Client::DyeArmor(EQEmu::TintProfile* dye){
SendWearChange(i); SendWearChange(i);
} }
else{ else{
Message(13,"Could not locate A Vial of Prismatic Dye."); Message(Chat::Red,"Could not locate A Vial of Prismatic Dye.");
return; return;
} }
} }
@ -3397,7 +3397,7 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
Log(Logs::General, Logs::Error, "Client::InterrogateInventory() called for %s by %s with an error state of %s", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE")); Log(Logs::General, Logs::Error, "Client::InterrogateInventory() called for %s by %s with an error state of %s", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
} }
if (!silent) { if (!silent) {
requester->Message(1, "--- Inventory Interrogation Report for %s (requested by: %s, error state: %s) ---", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE")); requester->Message(Chat::Default, "--- Inventory Interrogation Report for %s (requested by: %s, error state: %s) ---", GetName(), requester->GetName(), (error ? "TRUE" : "FALSE"));
} }
// call InterrogateInventory_ for report // call InterrogateInventory_ for report
@ -3406,9 +3406,9 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
} }
if (error) { if (error) {
Message(13, "An error has been discovered in your inventory!"); Message(Chat::Red, "An error has been discovered in your inventory!");
Message(13, "Do not log out, zone or re-arrange items until this"); Message(Chat::Red, "Do not log out, zone or re-arrange items until this");
Message(13, "issue has been resolved or item loss may occur!"); Message(Chat::Red, "issue has been resolved or item loss may occur!");
if (allowtrip) if (allowtrip)
TripInterrogateInvState(); TripInterrogateInvState();
@ -3419,8 +3419,8 @@ bool Client::InterrogateInventory(Client* requester, bool log, bool silent, bool
Log(Logs::Detail, Logs::None, "[CLIENT] Client::InterrogateInventory() -- End"); Log(Logs::Detail, Logs::None, "[CLIENT] Client::InterrogateInventory() -- End");
} }
if (!silent) { if (!silent) {
requester->Message(1, "Target interrogation flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE")); requester->Message(Chat::Default, "Target interrogation flag: %s", (GetInterrogateInvState() ? "TRUE" : "FALSE"));
requester->Message(1, "--- End of Interrogation Report ---"); requester->Message(Chat::Default, "--- End of Interrogation Report ---");
} }
instmap.clear(); instmap.clear();
@ -3466,7 +3466,7 @@ void Client::InterrogateInventory_(bool errorcheck, Client* requester, int16 hea
head, depth, i.c_str(), p.c_str(), e.c_str()); head, depth, i.c_str(), p.c_str(), e.c_str());
} }
if (!silent) { if (!silent) {
requester->Message(6, "%i:%i - inst: %s - parent: %s%s", requester->Message(Chat::Gray, "%i:%i - inst: %s - parent: %s%s",
head, depth, i.c_str(), p.c_str(), e.c_str()); head, depth, i.c_str(), p.c_str(), e.c_str());
} }

View File

@ -47,7 +47,7 @@ bool Lua_Client::InZone() {
void Lua_Client::Kick() { void Lua_Client::Kick() {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->Kick(); self->Kick("Lua Quest");
} }
void Lua_Client::Disconnect() { void Lua_Client::Disconnect() {
@ -1210,6 +1210,16 @@ void Lua_Client::AddAlternateCurrencyValue(uint32 currency, int amount) {
self->AddAlternateCurrencyValue(currency, amount, 1); self->AddAlternateCurrencyValue(currency, amount, 1);
} }
void Lua_Client::SetAlternateCurrencyValue(uint32 currency, int amount) {
Lua_Safe_Call_Void();
self->SetAlternateCurrencyValue(currency, amount);
}
int Lua_Client::GetAlternateCurrencyValue(uint32 currency) {
Lua_Safe_Call_Int();
return self->GetAlternateCurrencyValue(currency);
}
void Lua_Client::SendWebLink(const char *site) { void Lua_Client::SendWebLink(const char *site) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SendWebLink(site); self->SendWebLink(site);
@ -1760,6 +1770,8 @@ luabind::scope lua_register_client() {
.def("OpenLFGuildWindow", (void(Lua_Client::*)(void))&Lua_Client::OpenLFGuildWindow) .def("OpenLFGuildWindow", (void(Lua_Client::*)(void))&Lua_Client::OpenLFGuildWindow)
.def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal) .def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal)
.def("AddAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddAlternateCurrencyValue) .def("AddAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddAlternateCurrencyValue)
.def("SetAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::SetAlternateCurrencyValue)
.def("GetAlternateCurrencyValue", (int(Lua_Client::*)(uint32))&Lua_Client::GetAlternateCurrencyValue)
.def("SendWebLink", (void(Lua_Client::*)(const char *))&Lua_Client::SendWebLink) .def("SendWebLink", (void(Lua_Client::*)(const char *))&Lua_Client::SendWebLink)
.def("HasSpellScribed", (bool(Lua_Client::*)(int))&Lua_Client::HasSpellScribed) .def("HasSpellScribed", (bool(Lua_Client::*)(int))&Lua_Client::HasSpellScribed)
.def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag) .def("SetAccountFlag", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountFlag)

View File

@ -269,6 +269,8 @@ public:
void OpenLFGuildWindow(); void OpenLFGuildWindow();
void Signal(uint32 id); void Signal(uint32 id);
void AddAlternateCurrencyValue(uint32 currency, int amount); void AddAlternateCurrencyValue(uint32 currency, int amount);
void SetAlternateCurrencyValue(uint32 currency, int amount);
int GetAlternateCurrencyValue(uint32 currency);
void SendWebLink(const char *site); void SendWebLink(const char *site);
bool HasSpellScribed(int spell_id); bool HasSpellScribed(int spell_id);
void SetAccountFlag(std::string flag, std::string val); void SetAccountFlag(std::string flag, std::string val);

View File

@ -36,6 +36,8 @@ struct BodyTypes { };
struct Filters { }; struct Filters { };
struct MessageTypes { }; struct MessageTypes { };
struct Rule { }; struct Rule { };
struct Journal_SpeakMode { };
struct Journal_Mode { };
struct lua_registered_event { struct lua_registered_event {
std::string encounter_name; std::string encounter_name;
@ -2232,91 +2234,92 @@ luabind::scope lua_register_message_types() {
return luabind::class_<MessageTypes>("MT") return luabind::class_<MessageTypes>("MT")
.enum_("constants") .enum_("constants")
[ [
luabind::value("Say", MT_Say), luabind::value("NPCQuestSay", Chat::NPCQuestSay),
luabind::value("Tell", MT_Tell), luabind::value("Say", Chat::Say),
luabind::value("Group", MT_Group), luabind::value("Tell", Chat::Tell),
luabind::value("Guild", MT_Guild), luabind::value("Group", Chat::Group),
luabind::value("OOC", MT_OOC), luabind::value("Guild", Chat::Guild),
luabind::value("Auction", MT_Auction), luabind::value("OOC", Chat::OOC),
luabind::value("Shout", MT_Shout), luabind::value("Auction", Chat::Auction),
luabind::value("Emote", MT_Emote), luabind::value("Shout", Chat::Shout),
luabind::value("Spells", MT_Spells), luabind::value("Emote", Chat::Emote),
luabind::value("YouHitOther", MT_YouHitOther), luabind::value("Spells", Chat::Spells),
luabind::value("OtherHitsYou", MT_OtherHitsYou), luabind::value("YouHitOther", Chat::YouHitOther),
luabind::value("YouMissOther", MT_YouMissOther), luabind::value("OtherHitsYou", Chat::OtherHitYou),
luabind::value("OtherMissesYou", MT_OtherMissesYou), luabind::value("YouMissOther", Chat::YouMissOther),
luabind::value("Broadcasts", MT_Broadcasts), luabind::value("OtherMissesYou", Chat::OtherMissYou),
luabind::value("Skills", MT_Skills), luabind::value("Broadcasts", Chat::Broadcasts),
luabind::value("Disciplines", MT_Disciplines), luabind::value("Skills", Chat::Skills),
luabind::value("Unused1", MT_Unused1), luabind::value("Disciplines", Chat::Disciplines),
luabind::value("DefaultText", MT_DefaultText), luabind::value("Unused1", Chat::Unused1),
luabind::value("Unused2", MT_Unused2), luabind::value("DefaultText", Chat::DefaultText),
luabind::value("MerchantOffer", MT_MerchantOffer), luabind::value("Unused2", Chat::Unused2),
luabind::value("MerchantBuySell", MT_MerchantBuySell), luabind::value("MerchantOffer", Chat::MerchantOffer),
luabind::value("YourDeath", MT_YourDeath), luabind::value("MerchantBuySell", Chat::MerchantExchange),
luabind::value("OtherDeath", MT_OtherDeath), luabind::value("YourDeath", Chat::YourDeath),
luabind::value("OtherHits", MT_OtherHits), luabind::value("OtherDeath", Chat::OtherDeath),
luabind::value("OtherMisses", MT_OtherMisses), luabind::value("OtherHits", Chat::OtherHitOther),
luabind::value("Who", MT_Who), luabind::value("OtherMisses", Chat::OtherMissOther),
luabind::value("YellForHelp", MT_YellForHelp), luabind::value("Who", Chat::Who),
luabind::value("NonMelee", MT_NonMelee), luabind::value("YellForHelp", Chat::YellForHelp),
luabind::value("WornOff", MT_WornOff), luabind::value("NonMelee", Chat::NonMelee),
luabind::value("MoneySplit", MT_MoneySplit), luabind::value("WornOff", Chat::SpellWornOff),
luabind::value("LootMessages", MT_LootMessages), luabind::value("MoneySplit", Chat::MoneySplit),
luabind::value("DiceRoll", MT_DiceRoll), luabind::value("LootMessages", Chat::Loot),
luabind::value("OtherSpells", MT_OtherSpells), luabind::value("DiceRoll", Chat::DiceRoll),
luabind::value("SpellFailure", MT_SpellFailure), luabind::value("OtherSpells", Chat::OtherSpells),
luabind::value("Chat", MT_Chat), luabind::value("SpellFailure", Chat::SpellFailure),
luabind::value("Channel1", MT_Channel1), luabind::value("Chat", Chat::ChatChannel),
luabind::value("Channel2", MT_Channel2), luabind::value("Channel1", Chat::Chat1),
luabind::value("Channel3", MT_Channel3), luabind::value("Channel2", Chat::Chat2),
luabind::value("Channel4", MT_Channel4), luabind::value("Channel3", Chat::Chat3),
luabind::value("Channel5", MT_Channel5), luabind::value("Channel4", Chat::Chat4),
luabind::value("Channel6", MT_Channel6), luabind::value("Channel5", Chat::Chat5),
luabind::value("Channel7", MT_Channel7), luabind::value("Channel6", Chat::Chat6),
luabind::value("Channel8", MT_Channel8), luabind::value("Channel7", Chat::Chat7),
luabind::value("Channel9", MT_Channel9), luabind::value("Channel8", Chat::Chat8),
luabind::value("Channel10", MT_Channel10), luabind::value("Channel9", Chat::Chat9),
luabind::value("CritMelee", MT_CritMelee), luabind::value("Channel10", Chat::Chat10),
luabind::value("SpellCrits", MT_SpellCrits), luabind::value("CritMelee", Chat::MeleeCrit),
luabind::value("TooFarAway", MT_TooFarAway), luabind::value("SpellCrits", Chat::SpellCrit),
luabind::value("NPCRampage", MT_NPCRampage), luabind::value("TooFarAway", Chat::TooFarAway),
luabind::value("NPCFlurry", MT_NPCFlurry), luabind::value("NPCRampage", Chat::NPCRampage),
luabind::value("NPCEnrage", MT_NPCEnrage), luabind::value("NPCFlurry", Chat::NPCFlurry),
luabind::value("SayEcho", MT_SayEcho), luabind::value("NPCEnrage", Chat::NPCEnrage),
luabind::value("TellEcho", MT_TellEcho), luabind::value("SayEcho", Chat::EchoSay),
luabind::value("GroupEcho", MT_GroupEcho), luabind::value("TellEcho", Chat::EchoTell),
luabind::value("GuildEcho", MT_GuildEcho), luabind::value("GroupEcho", Chat::EchoGroup),
luabind::value("OOCEcho", MT_OOCEcho), luabind::value("GuildEcho", Chat::EchoGuild),
luabind::value("AuctionEcho", MT_AuctionEcho), luabind::value("OOCEcho", Chat::EchoOOC),
luabind::value("ShoutECho", MT_ShoutECho), luabind::value("AuctionEcho", Chat::EchoAuction),
luabind::value("EmoteEcho", MT_EmoteEcho), luabind::value("ShoutECho", Chat::EchoShout),
luabind::value("Chat1Echo", MT_Chat1Echo), luabind::value("EmoteEcho", Chat::EchoEmote),
luabind::value("Chat2Echo", MT_Chat2Echo), luabind::value("Chat1Echo", Chat::EchoChat1),
luabind::value("Chat3Echo", MT_Chat3Echo), luabind::value("Chat2Echo", Chat::EchoChat2),
luabind::value("Chat4Echo", MT_Chat4Echo), luabind::value("Chat3Echo", Chat::EchoChat3),
luabind::value("Chat5Echo", MT_Chat5Echo), luabind::value("Chat4Echo", Chat::EchoChat4),
luabind::value("Chat6Echo", MT_Chat6Echo), luabind::value("Chat5Echo", Chat::EchoChat5),
luabind::value("Chat7Echo", MT_Chat7Echo), luabind::value("Chat6Echo", Chat::EchoChat6),
luabind::value("Chat8Echo", MT_Chat8Echo), luabind::value("Chat7Echo", Chat::EchoChat7),
luabind::value("Chat9Echo", MT_Chat9Echo), luabind::value("Chat8Echo", Chat::EchoChat8),
luabind::value("Chat10Echo", MT_Chat10Echo), luabind::value("Chat9Echo", Chat::EchoChat9),
luabind::value("DoTDamage", MT_DoTDamage), luabind::value("Chat10Echo", Chat::EchoChat10),
luabind::value("ItemLink", MT_ItemLink), luabind::value("DoTDamage", Chat::DotDamage),
luabind::value("RaidSay", MT_RaidSay), luabind::value("ItemLink", Chat::ItemLink),
luabind::value("MyPet", MT_MyPet), luabind::value("RaidSay", Chat::RaidSay),
luabind::value("DS", MT_DS), luabind::value("MyPet", Chat::MyPet),
luabind::value("Leadership", MT_Leadership), luabind::value("DS", Chat::DamageShield),
luabind::value("PetFlurry", MT_PetFlurry), luabind::value("Leadership", Chat::LeaderShip),
luabind::value("PetCrit", MT_PetCrit), luabind::value("PetFlurry", Chat::PetFlurry),
luabind::value("FocusEffect", MT_FocusEffect), luabind::value("PetCrit", Chat::PetCritical),
luabind::value("Experience", MT_Experience), luabind::value("FocusEffect", Chat::FocusEffect),
luabind::value("System", MT_System), luabind::value("Experience", Chat::Experience),
luabind::value("PetSpell", MT_PetSpell), luabind::value("System", Chat::System),
luabind::value("PetResponse", MT_PetResponse), luabind::value("PetSpell", Chat::PetSpell),
luabind::value("ItemSpeech", MT_ItemSpeech), luabind::value("PetResponse", Chat::PetResponse),
luabind::value("StrikeThrough", MT_StrikeThrough), luabind::value("ItemSpeech", Chat::ItemSpeech),
luabind::value("Stun", MT_Stun) luabind::value("StrikeThrough", Chat::StrikeThrough),
luabind::value("Stun", Chat::Stun)
]; ];
} }
@ -2362,4 +2365,27 @@ luabind::scope lua_register_ruleb() {
]; ];
} }
luabind::scope lua_register_journal_speakmode() {
return luabind::class_<Journal_SpeakMode>("SpeakMode")
.enum_("constants")
[
luabind::value("Raw", static_cast<int>(Journal::SpeakMode::Raw)),
luabind::value("Say", static_cast<int>(Journal::SpeakMode::Say)),
luabind::value("Shout", static_cast<int>(Journal::SpeakMode::Shout)),
luabind::value("EmoteAlt", static_cast<int>(Journal::SpeakMode::EmoteAlt)),
luabind::value("Emote", static_cast<int>(Journal::SpeakMode::Emote)),
luabind::value("Group", static_cast<int>(Journal::SpeakMode::Group))
];
}
luabind::scope lua_register_journal_mode() {
return luabind::class_<Journal_Mode>("JournalMode")
.enum_("constants")
[
luabind::value("None", static_cast<int>(Journal::Mode::None)),
luabind::value("Log1", static_cast<int>(Journal::Mode::Log1)),
luabind::value("Log2", static_cast<int>(Journal::Mode::Log2))
];
}
#endif #endif

View File

@ -19,6 +19,8 @@ luabind::scope lua_register_rules_const();
luabind::scope lua_register_rulei(); luabind::scope lua_register_rulei();
luabind::scope lua_register_ruler(); luabind::scope lua_register_ruler();
luabind::scope lua_register_ruleb(); luabind::scope lua_register_ruleb();
luabind::scope lua_register_journal_speakmode();
luabind::scope lua_register_journal_mode();
#endif #endif
#endif #endif

View File

@ -743,9 +743,9 @@ void Lua_Mob::Message(int type, const char *message) {
self->Message(type, message); self->Message(type, message);
} }
void Lua_Mob::Message_StringID(int type, int string_id, uint32 distance) { void Lua_Mob::MessageString(int type, int string_id, uint32 distance) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->Message_StringID(type, string_id, distance); self->MessageString(type, string_id, distance);
} }
void Lua_Mob::Say(const char *message) { void Lua_Mob::Say(const char *message) {
@ -753,9 +753,72 @@ void Lua_Mob::Say(const char *message) {
self->Say(message); self->Say(message);
} }
void Lua_Mob::Say(const char* message, int language) {
Lua_Safe_Call_Void();
entity_list.ChannelMessage(self, ChatChannel_Say, language, message); // these run through the client channels and probably shouldn't for NPCs, but oh well
}
void Lua_Mob::QuestSay(Lua_Client client, const char *message) { void Lua_Mob::QuestSay(Lua_Client client, const char *message) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->QuestJournalledSay(client, message); Journal::Options journal_opts;
journal_opts.speak_mode = Journal::SpeakMode::Say;
journal_opts.journal_mode = RuleB(NPC, EnableNPCQuestJournal) ? Journal::Mode::Log2 : Journal::Mode::None;
journal_opts.language = 0;
journal_opts.message_type = Chat::NPCQuestSay;
journal_opts.target_spawn_id = 0;
self->QuestJournalledSay(client, message, journal_opts);
}
void Lua_Mob::QuestSay(Lua_Client client, const char *message, luabind::adl::object opts) {
Lua_Safe_Call_Void();
Journal::Options journal_opts;
// defaults
journal_opts.speak_mode = Journal::SpeakMode::Say;
journal_opts.journal_mode = Journal::Mode::Log2;
journal_opts.language = 0;
journal_opts.message_type = Chat::NPCQuestSay;
journal_opts.target_spawn_id = 0;
if (luabind::type(opts) == LUA_TTABLE) {
auto cur = opts["speak_mode"];
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.speak_mode = static_cast<Journal::SpeakMode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
}
}
cur = opts["journal_mode"];
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.journal_mode = static_cast<Journal::Mode>(luabind::object_cast<int>(cur));
} catch (luabind::cast_failed) {
}
}
cur = opts["language"];
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.language = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
}
}
cur = opts["message_type"];
if (luabind::type(cur) != LUA_TNIL) {
try {
journal_opts.message_type = luabind::object_cast<int>(cur);
} catch (luabind::cast_failed) {
}
}
}
// if rule disables it, we override provided
if (!RuleB(NPC, EnableNPCQuestJournal))
journal_opts.journal_mode = Journal::Mode::None;
self->QuestJournalledSay(client, message, journal_opts);
} }
void Lua_Mob::Shout(const char *message) { void Lua_Mob::Shout(const char *message) {
@ -763,6 +826,11 @@ void Lua_Mob::Shout(const char *message) {
self->Shout(message); self->Shout(message);
} }
void Lua_Mob::Shout(const char* message, int language) {
Lua_Safe_Call_Void();
entity_list.ChannelMessage(self, ChatChannel_Shout, language, message);
}
void Lua_Mob::Emote(const char *message) { void Lua_Mob::Emote(const char *message) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->Emote(message); self->Emote(message);
@ -2318,10 +2386,14 @@ luabind::scope lua_register_mob() {
.def("SetCurrentWP", &Lua_Mob::SetCurrentWP) .def("SetCurrentWP", &Lua_Mob::SetCurrentWP)
.def("GetSize", &Lua_Mob::GetSize) .def("GetSize", &Lua_Mob::GetSize)
.def("Message", &Lua_Mob::Message) .def("Message", &Lua_Mob::Message)
.def("Message_StringID", &Lua_Mob::Message_StringID) .def("MessageString", &Lua_Mob::MessageString)
.def("Say", &Lua_Mob::Say) .def("Message_StringID", &Lua_Mob::MessageString)
.def("QuestSay", &Lua_Mob::QuestSay) .def("Say", (void(Lua_Mob::*)(const char*))& Lua_Mob::Say)
.def("Shout", &Lua_Mob::Shout) .def("Say", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Say)
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *))&Lua_Mob::QuestSay)
.def("QuestSay", (void(Lua_Mob::*)(Lua_Client,const char *,luabind::adl::object))&Lua_Mob::QuestSay)
.def("Shout", (void(Lua_Mob::*)(const char*))& Lua_Mob::Shout)
.def("Shout", (void(Lua_Mob::*)(const char*, int))& Lua_Mob::Shout)
.def("Emote", &Lua_Mob::Emote) .def("Emote", &Lua_Mob::Emote)
.def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell) .def("InterruptSpell", (void(Lua_Mob::*)(void))&Lua_Mob::InterruptSpell)
.def("InterruptSpell", (void(Lua_Mob::*)(int))&Lua_Mob::InterruptSpell) .def("InterruptSpell", (void(Lua_Mob::*)(int))&Lua_Mob::InterruptSpell)

View File

@ -166,10 +166,13 @@ public:
void SetCurrentWP(int wp); void SetCurrentWP(int wp);
double GetSize(); double GetSize();
void Message(int type, const char *message); void Message(int type, const char *message);
void Message_StringID(int type, int string_id, uint32 distance); void MessageString(int type, int string_id, uint32 distance);
void Say(const char *message); void Say(const char *message);
void Say(const char* message, int language);
void QuestSay(Lua_Client client, const char *message); void QuestSay(Lua_Client client, const char *message);
void QuestSay(Lua_Client client, const char *message, luabind::adl::object opts);
void Shout(const char *message); void Shout(const char *message);
void Shout(const char* message, int language);
void Emote(const char *message); void Emote(const char *message);
void InterruptSpell(); void InterruptSpell();
void InterruptSpell(int spell_id); void InterruptSpell(int spell_id);

View File

@ -1,3 +1,5 @@
#ifdef LUA_EQEMU
#include "lua.hpp" #include "lua.hpp"
#include <luabind/luabind.hpp> #include <luabind/luabind.hpp>
#include <luabind/object.hpp> #include <luabind/object.hpp>
@ -629,3 +631,5 @@ void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValu
lua_pop(L, n); lua_pop(L, n);
} }
} }
#endif

View File

@ -159,7 +159,7 @@ void Lua_NPC::SetSaveWaypoint(int wp) {
void Lua_NPC::SetSp2(int sg2) { void Lua_NPC::SetSp2(int sg2) {
Lua_Safe_Call_Void(); Lua_Safe_Call_Void();
self->SetSp2(sg2); self->SetSpawnGroupId(sg2);
} }
int Lua_NPC::GetWaypointMax() { int Lua_NPC::GetWaypointMax() {
@ -174,7 +174,7 @@ int Lua_NPC::GetGrid() {
uint32 Lua_NPC::GetSp2() { uint32 Lua_NPC::GetSp2() {
Lua_Safe_Call_Int(); Lua_Safe_Call_Int();
return self->GetSp2(); return self->GetSpawnGroupId();
} }
int Lua_NPC::GetNPCFactionID() { int Lua_NPC::GetNPCFactionID() {
@ -529,6 +529,24 @@ int Lua_NPC::GetAvoidanceRating()
return self->GetAvoidanceRating(); return self->GetAvoidanceRating();
} }
void Lua_NPC::SetSimpleRoamBox(float box_size)
{
Lua_Safe_Call_Void();
self->SetSimpleRoamBox(box_size);
}
void Lua_NPC::SetSimpleRoamBox(float box_size, float move_distance)
{
Lua_Safe_Call_Void();
self->SetSimpleRoamBox(box_size, move_distance);
}
void Lua_NPC::SetSimpleRoamBox(float box_size, float move_distance, int move_delay)
{
Lua_Safe_Call_Void();
self->SetSimpleRoamBox(box_size, move_distance, move_delay);
}
luabind::scope lua_register_npc() { luabind::scope lua_register_npc() {
return luabind::class_<Lua_NPC, Lua_Mob>("NPC") return luabind::class_<Lua_NPC, Lua_Mob>("NPC")
.def(luabind::constructor<>()) .def(luabind::constructor<>())
@ -614,6 +632,9 @@ luabind::scope lua_register_npc() {
.def("GetGuardPointZ", (float(Lua_NPC::*)(void))&Lua_NPC::GetGuardPointZ) .def("GetGuardPointZ", (float(Lua_NPC::*)(void))&Lua_NPC::GetGuardPointZ)
.def("SetPrimSkill", (void(Lua_NPC::*)(int))&Lua_NPC::SetPrimSkill) .def("SetPrimSkill", (void(Lua_NPC::*)(int))&Lua_NPC::SetPrimSkill)
.def("SetSecSkill", (void(Lua_NPC::*)(int))&Lua_NPC::SetSecSkill) .def("SetSecSkill", (void(Lua_NPC::*)(int))&Lua_NPC::SetSecSkill)
.def("SetSimpleRoamBox", (void(Lua_NPC::*)(float))&Lua_NPC::SetSimpleRoamBox)
.def("SetSimpleRoamBox", (void(Lua_NPC::*)(float, float))&Lua_NPC::SetSimpleRoamBox)
.def("SetSimpleRoamBox", (void(Lua_NPC::*)(float, float, int))&Lua_NPC::SetSimpleRoamBox)
.def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill) .def("GetPrimSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetPrimSkill)
.def("GetSecSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetSecSkill) .def("GetSecSkill", (int(Lua_NPC::*)(void))&Lua_NPC::GetSecSkill)
.def("GetSwarmOwner", (int(Lua_NPC::*)(void))&Lua_NPC::GetSwarmOwner) .def("GetSwarmOwner", (int(Lua_NPC::*)(void))&Lua_NPC::GetSwarmOwner)

View File

@ -131,6 +131,9 @@ public:
void MerchantCloseShop(); void MerchantCloseShop();
int GetRawAC(); int GetRawAC();
int GetAvoidanceRating(); int GetAvoidanceRating();
void SetSimpleRoamBox(float box_size);
void SetSimpleRoamBox(float box_size, float move_distance);
void SetSimpleRoamBox(float box_size, float move_distance, int move_delay);
}; };
#endif #endif

View File

@ -1102,7 +1102,9 @@ void LuaParser::MapFunctions(lua_State *L) {
lua_register_rules_const(), lua_register_rules_const(),
lua_register_rulei(), lua_register_rulei(),
lua_register_ruler(), lua_register_ruler(),
lua_register_ruleb() lua_register_ruleb(),
lua_register_journal_speakmode(),
lua_register_journal_mode()
]; ];
} catch(std::exception &ex) { } catch(std::exception &ex) {
@ -1298,8 +1300,6 @@ QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) {
} }
} }
#endif
void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault)
{ {
for (auto &mod : mods_) { for (auto &mod : mods_) {
@ -1372,3 +1372,5 @@ uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreD
} }
return retval; return retval;
} }
#endif

View File

@ -1,3 +1,5 @@
#ifdef LUA_EQEMU
#include "lua.hpp" #include "lua.hpp"
#include <luabind/luabind.hpp> #include <luabind/luabind.hpp>
@ -1537,3 +1539,5 @@ luabind::scope lua_register_stat_bonuses() {
.def("AssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel) .def("AssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel)
.def("ReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail); .def("ReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail);
} }
#endif

View File

@ -1618,7 +1618,7 @@ void Merc::AI_Process() {
{ {
if(zone->random.Roll(flurrychance)) if(zone->random.Roll(flurrychance))
{ {
Message_StringID(MT_NPCFlurry, YOU_FLURRY); MessageString(Chat::NPCFlurry, YOU_FLURRY);
Attack(GetTarget(), EQEmu::invslot::slotPrimary, false); Attack(GetTarget(), EQEmu::invslot::slotPrimary, false);
Attack(GetTarget(), EQEmu::invslot::slotPrimary, false); Attack(GetTarget(), EQEmu::invslot::slotPrimary, false);
} }
@ -1637,11 +1637,11 @@ void Merc::AI_Process() {
// TODO: Do mercs berserk? Find this out on live... // TODO: Do mercs berserk? Find this out on live...
//if (GetClass() == WARRIOR || GetClass() == BERSERKER) { //if (GetClass() == WARRIOR || GetClass() == BERSERKER) {
// if(GetHP() > 0 && !berserk && this->GetHPRatio() < 30) { // if(GetHP() > 0 && !berserk && this->GetHPRatio() < 30) {
// entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_START, GetName()); // entity_list.MessageCloseString(this, false, 200, 0, BERSERK_START, GetName());
// this->berserk = true; // this->berserk = true;
// } // }
// if (berserk && this->GetHPRatio() > 30) { // if (berserk && this->GetHPRatio() > 30) {
// entity_list.MessageClose_StringID(this, false, 200, 0, BERSERK_END, GetName()); // entity_list.MessageCloseString(this, false, 200, 0, BERSERK_END, GetName());
// this->berserk = false; // this->berserk = false;
// } // }
//} //}
@ -2623,7 +2623,7 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) {
realTotal = CalcFocusEffect(type, UsedFocusID, spell_id); realTotal = CalcFocusEffect(type, UsedFocusID, spell_id);
if (realTotal != 0 && UsedItem) if (realTotal != 0 && UsedItem)
Message_StringID(MT_Spells, BEGINS_TO_GLOW, UsedItem->Name); MessageString(Chat::Spells, BEGINS_TO_GLOW, UsedItem->Name);
} }
//Check if spell focus effect exists for the client. //Check if spell focus effect exists for the client.
@ -5321,10 +5321,10 @@ void Client::UpdateMercTimer()
Log(Logs::General, Logs::Mercenaries, "UpdateMercTimer Complete for %s.", GetName()); Log(Logs::General, Logs::Mercenaries, "UpdateMercTimer Complete for %s.", GetName());
// Normal upkeep charge message // Normal upkeep charge message
//Message(7, "You have been charged a mercenary upkeep cost of %i plat, and %i gold and your mercenary upkeep cost timer has been reset to 15 minutes.", upkeep_plat, upkeep_gold, (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60)); //Message(Chat::LightGray, "You have been charged a mercenary upkeep cost of %i plat, and %i gold and your mercenary upkeep cost timer has been reset to 15 minutes.", upkeep_plat, upkeep_gold, (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60));
// Message below given when too low level to be charged // Message below given when too low level to be charged
//Message(7, "Your mercenary waived an upkeep cost of %i plat, and %i gold or %i %s and your mercenary upkeep cost timer has been reset to %i minutes", upkeep_plat, upkeep_gold, 1, "Bayle Marks", (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60)); //Message(Chat::LightGray, "Your mercenary waived an upkeep cost of %i plat, and %i gold or %i %s and your mercenary upkeep cost timer has been reset to %i minutes", upkeep_plat, upkeep_gold, 1, "Bayle Marks", (int)(RuleI(Mercs, UpkeepIntervalMS) / 1000 / 60));
} }
} }
} }

View File

@ -1128,7 +1128,10 @@ void Mob::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho)
UpdateActiveLight(); UpdateActiveLight();
ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive];
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0; if (IsNPC() && race == ERUDITE)
ns->spawn.showhelm = 1;
else
ns->spawn.showhelm = (helmtexture && helmtexture != 0xFF) ? 1 : 0;
ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players ns->spawn.invis = (invisible || hidden) ? 1 : 0; // TODO: load this before spawning players
ns->spawn.NPC = IsClient() ? 0 : 1; ns->spawn.NPC = IsClient() ? 0 : 1;
@ -1548,39 +1551,39 @@ void Mob::ShowStats(Client* client)
} }
else if (IsCorpse()) { else if (IsCorpse()) {
if (IsPlayerCorpse()) { if (IsPlayerCorpse()) {
client->Message(0, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetCorpseDBID()); client->Message(Chat::White, " CharID: %i PlayerCorpse: %i", CastToCorpse()->GetCharID(), CastToCorpse()->GetCorpseDBID());
} }
else { else {
client->Message(0, " NPCCorpse", GetID()); client->Message(Chat::White, " NPCCorpse", GetID());
} }
} }
else { else {
client->Message(0, " Level: %i AC: %i Class: %i Size: %1.1f Haste: %i", GetLevel(), ACSum(), GetClass(), GetSize(), GetHaste()); client->Message(Chat::White, " Level: %i AC: %i Class: %i Size: %1.1f Haste: %i", GetLevel(), ACSum(), GetClass(), GetSize(), GetHaste());
client->Message(0, " HP: %i Max HP: %i",GetHP(), GetMaxHP()); client->Message(Chat::White, " HP: %i Max HP: %i",GetHP(), GetMaxHP());
client->Message(0, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana()); client->Message(Chat::White, " Mana: %i Max Mana: %i", GetMana(), GetMaxMana());
client->Message(0, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus()); client->Message(Chat::White, " Total ATK: %i Worn/Spell ATK (Cap %i): %i", GetATK(), RuleI(Character, ItemATKCap), GetATKBonus());
client->Message(0, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA()); client->Message(Chat::White, " STR: %i STA: %i DEX: %i AGI: %i INT: %i WIS: %i CHA: %i", GetSTR(), GetSTA(), GetDEX(), GetAGI(), GetINT(), GetWIS(), GetCHA());
client->Message(0, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR()); client->Message(Chat::White, " MR: %i PR: %i FR: %i CR: %i DR: %i Corruption: %i PhR: %i", GetMR(), GetPR(), GetFR(), GetCR(), GetDR(), GetCorrup(), GetPhR());
client->Message(0, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender()); client->Message(Chat::White, " Race: %i BaseRace: %i Texture: %i HelmTexture: %i Gender: %i BaseGender: %i", GetRace(), GetBaseRace(), GetTexture(), GetHelmTexture(), GetGender(), GetBaseGender());
if (client->Admin() >= 100) if (client->Admin() >= 100)
client->Message(0, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted); client->Message(Chat::White, " EntityID: %i PetID: %i OwnerID: %i AIControlled: %i Targetted: %i", GetID(), GetPetID(), GetOwnerID(), IsAIControlled(), targeted);
if (IsNPC()) { if (IsNPC()) {
NPC *n = CastToNPC(); NPC *n = CastToNPC();
uint32 spawngroupid = 0; uint32 spawngroupid = 0;
if(n->respawn2 != 0) if(n->respawn2 != 0)
spawngroupid = n->respawn2->SpawnGroupID(); spawngroupid = n->respawn2->SpawnGroupID();
client->Message(0, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID()); client->Message(Chat::White, " NPCID: %u SpawnGroupID: %u Grid: %i LootTable: %u FactionID: %i SpellsID: %u ", GetNPCTypeID(),spawngroupid, n->GetGrid(), n->GetLoottableID(), n->GetNPCFactionID(), n->GetNPCSpellsID());
client->Message(0, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %.3f Walkspeed: %.3f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), static_cast<float>(0.025f * n->GetRunspeed()), static_cast<float>(0.025f * n->GetWalkspeed())); client->Message(Chat::White, " Accuracy: %i MerchantID: %i EmoteID: %i Runspeed: %.3f Walkspeed: %.3f", n->GetAccuracyRating(), n->MerchantType, n->GetEmoteID(), static_cast<float>(0.025f * n->GetRunspeed()), static_cast<float>(0.025f * n->GetWalkspeed()));
n->QueryLoot(client); n->QueryLoot(client);
} }
if (IsAIControlled()) { if (IsAIControlled()) {
client->Message(0, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange()); client->Message(Chat::White, " AggroRange: %1.0f AssistRange: %1.0f", GetAggroRange(), GetAssistRange());
} }
client->Message(0, " compute_tohit: %i TotalToHit: %i", compute_tohit(EQEmu::skills::SkillHandtoHand), GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0)); client->Message(Chat::White, " compute_tohit: %i TotalToHit: %i", compute_tohit(EQEmu::skills::SkillHandtoHand), GetTotalToHit(EQEmu::skills::SkillHandtoHand, 0));
client->Message(0, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense()); client->Message(Chat::White, " compute_defense: %i TotalDefense: %i", compute_defense(), GetTotalDefense());
client->Message(0, " offense: %i mitigation ac: %i", offense(EQEmu::skills::SkillHandtoHand), GetMitigationAC()); client->Message(Chat::White, " offense: %i mitigation ac: %i", offense(EQEmu::skills::SkillHandtoHand), GetMitigationAC());
} }
} }
@ -1617,33 +1620,33 @@ void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter)
void Mob::ShowBuffs(Client* client) { void Mob::ShowBuffs(Client* client) {
if(SPDAT_RECORDS <= 0) if(SPDAT_RECORDS <= 0)
return; return;
client->Message(0, "Buffs on: %s", this->GetName()); client->Message(Chat::White, "Buffs on: %s", this->GetName());
uint32 i; uint32 i;
uint32 buff_count = GetMaxTotalSlots(); uint32 buff_count = GetMaxTotalSlots();
for (i=0; i < buff_count; i++) { for (i=0; i < buff_count; i++) {
if (buffs[i].spellid != SPELL_UNKNOWN) { if (buffs[i].spellid != SPELL_UNKNOWN) {
if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent)
client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); client->Message(Chat::White, " %i: %s: Permanent", i, spells[buffs[i].spellid].name);
else else
client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); client->Message(Chat::White, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining);
} }
} }
if (IsClient()){ if (IsClient()){
client->Message(0, "itembonuses:"); client->Message(Chat::White, "itembonuses:");
client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", itembonuses.ATK, itembonuses.AC, itembonuses.HPRegen, itembonuses.HP, itembonuses.Mana); client->Message(Chat::White, "Atk:%i Ac:%i HP(%i):%i Mana:%i", itembonuses.ATK, itembonuses.AC, itembonuses.HPRegen, itembonuses.HP, itembonuses.Mana);
client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", client->Message(Chat::White, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i",
itembonuses.STR,itembonuses.STA,itembonuses.DEX,itembonuses.AGI,itembonuses.INT,itembonuses.WIS,itembonuses.CHA); itembonuses.STR,itembonuses.STA,itembonuses.DEX,itembonuses.AGI,itembonuses.INT,itembonuses.WIS,itembonuses.CHA);
client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", client->Message(Chat::White, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i",
itembonuses.MR,itembonuses.FR,itembonuses.CR,itembonuses.PR,itembonuses.DR); itembonuses.MR,itembonuses.FR,itembonuses.CR,itembonuses.PR,itembonuses.DR);
client->Message(0, "DmgShield:%i Haste:%i", itembonuses.DamageShield, itembonuses.haste ); client->Message(Chat::White, "DmgShield:%i Haste:%i", itembonuses.DamageShield, itembonuses.haste );
client->Message(0, "spellbonuses:"); client->Message(Chat::White, "spellbonuses:");
client->Message(0, "Atk:%i Ac:%i HP(%i):%i Mana:%i", spellbonuses.ATK, spellbonuses.AC, spellbonuses.HPRegen, spellbonuses.HP, spellbonuses.Mana); client->Message(Chat::White, "Atk:%i Ac:%i HP(%i):%i Mana:%i", spellbonuses.ATK, spellbonuses.AC, spellbonuses.HPRegen, spellbonuses.HP, spellbonuses.Mana);
client->Message(0, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i", client->Message(Chat::White, "Str:%i Sta:%i Dex:%i Agi:%i Int:%i Wis:%i Cha:%i",
spellbonuses.STR,spellbonuses.STA,spellbonuses.DEX,spellbonuses.AGI,spellbonuses.INT,spellbonuses.WIS,spellbonuses.CHA); spellbonuses.STR,spellbonuses.STA,spellbonuses.DEX,spellbonuses.AGI,spellbonuses.INT,spellbonuses.WIS,spellbonuses.CHA);
client->Message(0, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i", client->Message(Chat::White, "SvMagic:%i SvFire:%i SvCold:%i SvPoison:%i SvDisease:%i",
spellbonuses.MR,spellbonuses.FR,spellbonuses.CR,spellbonuses.PR,spellbonuses.DR); spellbonuses.MR,spellbonuses.FR,spellbonuses.CR,spellbonuses.PR,spellbonuses.DR);
client->Message(0, "DmgShield:%i Haste:%i", spellbonuses.DamageShield, spellbonuses.haste ); client->Message(Chat::White, "DmgShield:%i Haste:%i", spellbonuses.DamageShield, spellbonuses.haste );
} }
} }
@ -1651,15 +1654,15 @@ void Mob::ShowBuffList(Client* client) {
if(SPDAT_RECORDS <= 0) if(SPDAT_RECORDS <= 0)
return; return;
client->Message(0, "Buffs on: %s", this->GetCleanName()); client->Message(Chat::White, "Buffs on: %s", this->GetCleanName());
uint32 i; uint32 i;
uint32 buff_count = GetMaxTotalSlots(); uint32 buff_count = GetMaxTotalSlots();
for (i = 0; i < buff_count; i++) { for (i = 0; i < buff_count; i++) {
if (buffs[i].spellid != SPELL_UNKNOWN) { if (buffs[i].spellid != SPELL_UNKNOWN) {
if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent) if (spells[buffs[i].spellid].buffdurationformula == DF_Permanent)
client->Message(0, " %i: %s: Permanent", i, spells[buffs[i].spellid].name); client->Message(Chat::White, " %i: %s: Permanent", i, spells[buffs[i].spellid].name);
else else
client->Message(0, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining); client->Message(Chat::White, " %i: %s: %i tics left", i, spells[buffs[i].spellid].name, buffs[i].ticsremaining);
} }
} }
} }
@ -2706,7 +2709,7 @@ bool Mob::HateSummon() {
if(target) if(target)
{ {
if(summon_level == 1) { if(summon_level == 1) {
entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() ); entity_list.MessageClose(this, true, 500, Chat::Say, "%s says 'You will not evade me, %s!' ", GetCleanName(), target->GetCleanName() );
if (target->IsClient()) if (target->IsClient())
target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC); target->CastToClient()->MovePC(zone->GetZoneID(), zone->GetInstanceID(), m_Position.x, m_Position.y, m_Position.z, target->GetHeading(), 0, SummonPC);
@ -2715,7 +2718,7 @@ bool Mob::HateSummon() {
return true; return true;
} else if(summon_level == 2) { } else if(summon_level == 2) {
entity_list.MessageClose(this, true, 500, MT_Say, "%s says,'You will not evade me, %s!'", GetCleanName(), target->GetCleanName()); entity_list.MessageClose(this, true, 500, Chat::Say, "%s says 'You will not evade me, %s!'", GetCleanName(), target->GetCleanName());
GMMove(target->GetX(), target->GetY(), target->GetZ()); GMMove(target->GetX(), target->GetY(), target->GetZ());
} }
} }
@ -2786,10 +2789,10 @@ void Mob::WipeHateList()
} }
} }
uint32 Mob::RandomTimer(int min,int max) { uint32 Mob::RandomTimer(int min, int max)
{
int r = 14000; int r = 14000;
if(min != 0 && max != 0 && min < max) if (min != 0 && max != 0 && min < max) {
{
r = zone->random.Int(min, max); r = zone->random.Int(min, max);
} }
return r; return r;
@ -2832,7 +2835,7 @@ void Mob::Say(const char *format, ...)
talker = this; talker = this;
} }
entity_list.MessageClose_StringID( entity_list.MessageCloseString(
talker, false, 200, 10, talker, false, 200, 10,
GENERIC_SAY, GetCleanName(), buf GENERIC_SAY, GetCleanName(), buf
); );
@ -2841,48 +2844,50 @@ void Mob::Say(const char *format, ...)
// //
// this is like the above, but the first parameter is a string id // this is like the above, but the first parameter is a string id
// //
void Mob::Say_StringID(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) void Mob::SayString(uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{ {
char string_id_str[10]; char string_id_str[10];
snprintf(string_id_str, 10, "%d", string_id); snprintf(string_id_str, 10, "%d", string_id);
entity_list.MessageClose_StringID(this, false, 200, 10, entity_list.MessageCloseString(
this, false, 200, 10,
GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5,
message6, message7, message8, message9 message6, message7, message8, message9
); );
} }
void Mob::Say_StringID(uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) void Mob::SayString(uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{ {
char string_id_str[10]; char string_id_str[10];
snprintf(string_id_str, 10, "%d", string_id); snprintf(string_id_str, 10, "%d", string_id);
entity_list.MessageClose_StringID(this, false, 200, type, entity_list.MessageCloseString(
this, false, 200, type,
GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str, message3, message4, message5,
message6, message7, message8, message9 message6, message7, message8, message9
); );
} }
void Mob::SayTo_StringID(Client *to, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) void Mob::SayString(Client *to, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{ {
if (!to) if (!to)
return; return;
auto string_id_str = std::to_string(string_id); auto string_id_str = std::to_string(string_id);
to->Message_StringID(10, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9); to->MessageString(Chat::NPCQuestSay, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9);
} }
void Mob::SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) void Mob::SayString(Client *to, uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9)
{ {
if (!to) if (!to)
return; return;
auto string_id_str = std::to_string(string_id); auto string_id_str = std::to_string(string_id);
to->Message_StringID(type, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9); to->MessageString(type, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9);
} }
void Mob::Shout(const char *format, ...) void Mob::Shout(const char *format, ...)
@ -2894,7 +2899,7 @@ void Mob::Shout(const char *format, ...)
vsnprintf(buf, 1000, format, ap); vsnprintf(buf, 1000, format, ap);
va_end(ap); va_end(ap);
entity_list.Message_StringID(this, false, MT_Shout, entity_list.MessageString(this, false, Chat::Shout,
GENERIC_SHOUT, GetCleanName(), buf); GENERIC_SHOUT, GetCleanName(), buf);
} }
@ -2907,13 +2912,19 @@ void Mob::Emote(const char *format, ...)
vsnprintf(buf, 1000, format, ap); vsnprintf(buf, 1000, format, ap);
va_end(ap); va_end(ap);
entity_list.MessageClose_StringID(this, false, 200, 10, entity_list.MessageCloseString(
GENERIC_EMOTE, GetCleanName(), buf); this, false, 200, 10,
GENERIC_EMOTE, GetCleanName(), buf
);
} }
void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str) void Mob::QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts)
{ {
entity_list.QuestJournalledSayClose(this, QuestInitiator, 200, GetCleanName(), str); // just in case
if (opts.target_spawn_id == 0 && QuestInitiator)
opts.target_spawn_id = QuestInitiator->GetID();
entity_list.QuestJournalledSayClose(this, 200, GetCleanName(), str, opts);
} }
const char *Mob::GetCleanName() const char *Mob::GetCleanName()
@ -3562,7 +3573,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id)
{ {
if(zone->random.Roll(focus)) if(zone->random.Roll(focus))
{ {
Message(MT_Spells,"You twincast %s!",spells[spell_id].name); Message(Chat::Spells,"You twincast %s!", spells[spell_id].name);
SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff);
} }
} }
@ -4880,16 +4891,16 @@ void Mob::SlowMitigation(Mob* caster)
if (GetSlowMitigation() && caster && caster->IsClient()) if (GetSlowMitigation() && caster && caster->IsClient())
{ {
if ((GetSlowMitigation() > 0) && (GetSlowMitigation() < 26)) if ((GetSlowMitigation() > 0) && (GetSlowMitigation() < 26))
caster->Message_StringID(MT_SpellFailure, SLOW_MOSTLY_SUCCESSFUL); caster->MessageString(Chat::SpellFailure, SLOW_MOSTLY_SUCCESSFUL);
else if ((GetSlowMitigation() >= 26) && (GetSlowMitigation() < 74)) else if ((GetSlowMitigation() >= 26) && (GetSlowMitigation() < 74))
caster->Message_StringID(MT_SpellFailure, SLOW_PARTIALLY_SUCCESSFUL); caster->MessageString(Chat::SpellFailure, SLOW_PARTIALLY_SUCCESSFUL);
else if ((GetSlowMitigation() >= 74) && (GetSlowMitigation() < 101)) else if ((GetSlowMitigation() >= 74) && (GetSlowMitigation() < 101))
caster->Message_StringID(MT_SpellFailure, SLOW_SLIGHTLY_SUCCESSFUL); caster->MessageString(Chat::SpellFailure, SLOW_SLIGHTLY_SUCCESSFUL);
else if (GetSlowMitigation() > 100) else if (GetSlowMitigation() > 100)
caster->Message_StringID(MT_SpellFailure, SPELL_OPPOSITE_EFFECT); caster->MessageString(Chat::SpellFailure, SPELL_OPPOSITE_EFFECT);
} }
} }

View File

@ -722,29 +722,29 @@ public:
inline void SetRareSpawn(bool in) { rare_spawn = in; } inline void SetRareSpawn(bool in) { rare_spawn = in; }
virtual void Message(uint32 type, const char* message, ...) { } virtual void Message(uint32 type, const char* message, ...) { }
virtual void Message_StringID(uint32 type, uint32 string_id, uint32 distance = 0) { } virtual void MessageString(uint32 type, uint32 string_id, uint32 distance = 0) { }
virtual void Message_StringID(uint32 type, uint32 string_id, const char* message, const char* message2 = 0, virtual void MessageString(uint32 type, uint32 string_id, const char* message, const char* message2 = 0,
const char* message3 = 0, const char* message4 = 0, const char* message5 = 0, const char* message6 = 0, const char* message3 = 0, const char* message4 = 0, const char* message5 = 0, const char* message6 = 0,
const char* message7 = 0, const char* message8 = 0, const char* message9 = 0, uint32 distance = 0) { } const char* message7 = 0, const char* message8 = 0, const char* message9 = 0, uint32 distance = 0) { }
virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id) { } virtual void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter, uint32 string_id) { }
virtual void FilteredMessage_StringID(Mob *sender, uint32 type, eqFilterType filter, virtual void FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter,
uint32 string_id, const char *message1, const char *message2 = nullptr, uint32 string_id, const char *message1, const char *message2 = nullptr,
const char *message3 = nullptr, const char *message4 = nullptr, const char *message3 = nullptr, const char *message4 = nullptr,
const char *message5 = nullptr, const char *message6 = nullptr, const char *message5 = nullptr, const char *message6 = nullptr,
const char *message7 = nullptr, const char *message8 = nullptr, const char *message7 = nullptr, const char *message8 = nullptr,
const char *message9 = nullptr) { } const char *message9 = nullptr) { }
void Say(const char *format, ...); void Say(const char *format, ...);
void Say_StringID(uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, void SayString(uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void Say_StringID(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, void SayString(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void SayTo_StringID(Client *to, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, void SayString(Client *to, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, void SayString(Client *to, uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0,
const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0);
void Shout(const char *format, ...); void Shout(const char *format, ...);
void Emote(const char *format, ...); void Emote(const char *format, ...);
void QuestJournalledSay(Client *QuestInitiator, const char *str); void QuestJournalledSay(Client *QuestInitiator, const char *str, Journal::Options &opts);
int32 GetItemStat(uint32 itemid, const char *identifier); int32 GetItemStat(uint32 itemid, const char *identifier);
int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false); int16 CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, bool best_focus=false);

View File

@ -578,7 +578,7 @@ void NPC::AI_Stop() {
void Client::AI_Stop() { void Client::AI_Stop() {
Mob::AI_Stop(); Mob::AI_Stop();
this->Message_StringID(13,PLAYER_REGAIN); this->MessageString(Chat::Red,PLAYER_REGAIN);
auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct)); auto app = new EQApplicationPacket(OP_Charm, sizeof(Charm_Struct));
Charm_Struct *ps = (Charm_Struct*)app->pBuffer; Charm_Struct *ps = (Charm_Struct*)app->pBuffer;
@ -1579,7 +1579,25 @@ void NPC::AI_DoMovement() {
if (GetCWP() == EQEmu::WaypointStatus::RoamBoxPauseInProgress && !IsMoving()) { if (GetCWP() == EQEmu::WaypointStatus::RoamBoxPauseInProgress && !IsMoving()) {
// We have arrived // We have arrived
time_until_can_move = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay);
int roambox_move_delay = EQEmu::ClampLower(GetRoamboxDelay(), GetRoamboxMinDelay());
int move_delay_max = (roambox_move_delay > 0 ? roambox_move_delay : (int) GetRoamboxMinDelay() * 4);
int random_timer = RandomTimer(
GetRoamboxMinDelay(),
move_delay_max
);
Log(
Logs::Detail,
Logs::NPCRoamBox, "(%s) Timer calc | random_timer [%i] roambox_move_delay [%i] move_min [%i] move_max [%i]",
this->GetCleanName(),
random_timer,
roambox_move_delay,
(int) GetRoamboxMinDelay(),
move_delay_max
);
time_until_can_move = Timer::GetCurrentTime() + random_timer;
SetCurrentWP(0); SetCurrentWP(0);
return; return;
} }
@ -1636,25 +1654,51 @@ void NPC::AI_DoMovement() {
} }
} }
roambox_destination_z = 0; PathfinderOptions opts;
/* opts.smooth_path = true;
if (zone->zonemap) { opts.step_size = RuleR(Pathing, NavmeshStepSize);
roambox_destination_z = FindGroundZ(roambox_destination_x, roambox_destination_y, this->GetZOffset()); opts.offset = GetZOffset();
} opts.flags = PathingNotDisabled ^ PathingZoneLine;
*/
Log(Logs::Detail, auto partial = false;
auto stuck = false;
auto route = zone->pathing->FindPath(
glm::vec3(GetX(), GetY(), GetZ()),
glm::vec3(
roambox_destination_x,
roambox_destination_y,
GetGroundZ(roambox_destination_x, roambox_destination_y)
),
partial,
stuck,
opts
);
if (route.empty()) {
Log(
Logs::Detail,
Logs::NPCRoamBox, "(%s) We don't have a path route... exiting...",
this->GetCleanName()
);
return;
}
roambox_destination_z = 0;
Log(
Logs::General,
Logs::NPCRoamBox, Logs::NPCRoamBox,
"Calculate | NPC: %s distance %.3f | min_x %.3f | max_x %.3f | final_x %.3f | min_y %.3f | max_y %.3f | final_y %.3f", "NPC (%s) distance [%.0f] X (min/max) [%.0f / %.0f] Y (min/max) [%.0f / %.0f] | Dest x/y/z [%.0f / %.0f / %.0f]",
this->GetCleanName(), this->GetCleanName(),
roambox_distance, roambox_distance,
roambox_min_x, roambox_min_x,
roambox_max_x, roambox_max_x,
roambox_destination_x,
roambox_min_y, roambox_min_y,
roambox_max_y, roambox_max_y,
roambox_destination_y); roambox_destination_x,
Log(Logs::Detail, Logs::NPCRoamBox, "Dest Z is (%f)", roambox_destination_z); roambox_destination_y,
roambox_destination_z
);
SetCurrentWP(EQEmu::WaypointStatus::RoamBoxPauseInProgress); SetCurrentWP(EQEmu::WaypointStatus::RoamBoxPauseInProgress);
NavigateTo(roambox_destination_x, roambox_destination_y, roambox_destination_z); NavigateTo(roambox_destination_x, roambox_destination_y, roambox_destination_z);
@ -2029,14 +2073,14 @@ void Mob::StartEnrage()
// start the timer. need to call IsEnraged frequently since we dont have callback timers :-/ // start the timer. need to call IsEnraged frequently since we dont have callback timers :-/
bEnraged = true; bEnraged = true;
entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_START, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::NPCEnrage, NPC_ENRAGE_START, GetCleanName());
} }
void Mob::ProcessEnrage(){ void Mob::ProcessEnrage(){
if(IsEnraged()){ if(IsEnraged()){
Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE); Timer *timer = GetSpecialAbilityTimer(SPECATK_ENRAGE);
if(timer && timer->Check()){ if(timer && timer->Check()){
entity_list.MessageClose_StringID(this, true, 200, MT_NPCEnrage, NPC_ENRAGE_END, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::NPCEnrage, NPC_ENRAGE_END, GetCleanName());
int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2); int enraged_cooldown = GetSpecialAbilityParam(SPECATK_ENRAGE, 2);
enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer; enraged_cooldown = enraged_cooldown > 0 ? enraged_cooldown : EnragedTimer;
@ -2057,9 +2101,23 @@ bool Mob::Flurry(ExtraAttackOptions *opts)
Mob *target = GetTarget(); Mob *target = GetTarget();
if (target) { if (target) {
if (!IsPet()) { if (!IsPet()) {
entity_list.MessageClose_StringID(this, true, 200, MT_NPCFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); entity_list.MessageCloseString(
this,
true,
200,
Chat::NPCFlurry,
NPC_FLURRY,
GetCleanName(),
target->GetCleanName());
} else { } else {
entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_FLURRY, GetCleanName(), target->GetCleanName()); entity_list.MessageCloseString(
this,
true,
200,
Chat::PetFlurry,
NPC_FLURRY,
GetCleanName(),
target->GetCleanName());
} }
int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1); int num_attacks = GetSpecialAbilityParam(SPECATK_FLURRY, 1);
@ -2096,9 +2154,9 @@ bool Mob::Rampage(ExtraAttackOptions *opts)
{ {
int index_hit = 0; int index_hit = 0;
if (!IsPet()) if (!IsPet())
entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, NPC_RAMPAGE, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, NPC_RAMPAGE, GetCleanName());
else else
entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, NPC_RAMPAGE, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::PetFlurry, NPC_RAMPAGE, GetCleanName());
int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1); int rampage_targets = GetSpecialAbilityParam(SPECATK_RAMPAGE, 1);
if (rampage_targets == 0) // if set to 0 or not set in the DB if (rampage_targets == 0) // if set to 0 or not set in the DB
@ -2153,9 +2211,9 @@ void Mob::AreaRampage(ExtraAttackOptions *opts)
{ {
int index_hit = 0; int index_hit = 0;
if (!IsPet()) { // do not know every pet AA so thought it safer to add this if (!IsPet()) { // do not know every pet AA so thought it safer to add this
entity_list.MessageClose_StringID(this, true, 200, MT_NPCRampage, AE_RAMPAGE, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::NPCRampage, AE_RAMPAGE, GetCleanName());
} else { } else {
entity_list.MessageClose_StringID(this, true, 200, MT_PetFlurry, AE_RAMPAGE, GetCleanName()); entity_list.MessageCloseString(this, true, 200, Chat::PetFlurry, AE_RAMPAGE, GetCleanName());
} }
int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1); int rampage_targets = GetSpecialAbilityParam(SPECATK_AREA_RAMPAGE, 1);
@ -2744,7 +2802,7 @@ void NPC::AISpellsList(Client *c)
return; return;
for (auto it = AIspells.begin(); it != AIspells.end(); ++it) for (auto it = AIspells.begin(); it != AIspells.end(); ++it)
c->Message(0, "%s (%d): Type %d, Priority %d, Recast Delay %d, Resist Adjust %d, Min HP %d, Max HP %d", c->Message(Chat::White, "%s (%d): Type %d, Priority %d, Recast Delay %d, Resist Adjust %d, Min HP %d, Max HP %d",
spells[it->spellid].name, it->spellid, it->type, it->priority, it->recast_delay, it->resist_adjust, it->min_hp, it->max_hp); spells[it->spellid].name, it->spellid, it->type, it->priority, it->recast_delay, it->resist_adjust, it->min_hp, it->max_hp);
return; return;

View File

@ -278,7 +278,7 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut
return std::to_string((int)npc->GetWalkspeed()); return std::to_string((int)npc->GetWalkspeed());
} }
if (attribute == "spawngroup") { if (attribute == "spawngroup") {
return std::to_string(npc->GetSp2()); return std::to_string(npc->GetSpawnGroupId());
} }
if (attribute == "grid") { if (attribute == "grid") {
return std::to_string(npc->GetGrid()); return std::to_string(npc->GetGrid());
@ -624,7 +624,7 @@ inline void NPCCommandsMenu(Client* client, NPC* npc)
if (menu_commands.length() > 0) { if (menu_commands.length() > 0) {
std::string dev_menu = "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools", false, "DevTools") + "] ";; std::string dev_menu = "[" + EQEmu::SayLinkEngine::GenerateQuestSaylink("#devtools", false, "DevTools") + "] ";;
client->Message(0, "| %s [Show Commands] %s", dev_menu.c_str(), menu_commands.c_str()); client->Message(Chat::White, "| %s [Show Commands] %s", dev_menu.c_str(), menu_commands.c_str());
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -41,18 +41,29 @@ class MobMovementManager
public: public:
~MobMovementManager(); ~MobMovementManager();
void Process(); void Process();
void AddMob(Mob *m); void AddMob(Mob *mob);
void RemoveMob(Mob *m); void RemoveMob(Mob *mob);
void AddClient(Client *c); void AddClient(Client *client);
void RemoveClient(Client *c); void RemoveClient(Client *client);
void RotateTo(Mob *who, float to, MobMovementMode mode = MovementRunning); void RotateTo(Mob *who, float to, MobMovementMode mob_movement_mode = MovementRunning);
void Teleport(Mob *who, float x, float y, float z, float heading); void Teleport(Mob *who, float x, float y, float z, float heading);
void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning); void NavigateTo(Mob *who, float x, float y, float z, MobMovementMode mode = MovementRunning);
void StopNavigation(Mob *who); void StopNavigation(Mob *who);
void SendCommandToClients(Mob *m, float dx, float dy, float dz, float dh, int anim, ClientRange range);
void SendCommandToClients(
Mob *mob,
float delta_x,
float delta_y,
float delta_z,
float delta_heading,
int anim,
ClientRange range,
Client* single_client = nullptr
);
float FixHeading(float in); float FixHeading(float in);
void DumpStats(Client *to); void DumpStats(Client *client);
void ClearStats(); void ClearStats();
static MobMovementManager &Get() { static MobMovementManager &Get() {
@ -65,18 +76,18 @@ private:
MobMovementManager(const MobMovementManager&); MobMovementManager(const MobMovementManager&);
MobMovementManager& operator=(const MobMovementManager&); MobMovementManager& operator=(const MobMovementManager&);
void FillCommandStruct(PlayerPositionUpdateServer_Struct *spu, Mob *m, float dx, float dy, float dz, float dh, int anim); void FillCommandStruct(PlayerPositionUpdateServer_Struct *position_update, Mob *mob, float delta_x, float delta_y, float delta_z, float delta_heading, int anim);
void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode); void UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode); void UpdatePathGround(Mob *who, float x, float y, float z, MobMovementMode mode);
void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode mode); void UpdatePathUnderwater(Mob *who, float x, float y, float z, MobMovementMode movement_mode);
void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode); void UpdatePathBoat(Mob *who, float x, float y, float z, MobMovementMode mode);
void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading); void PushTeleportTo(MobMovementEntry &ent, float x, float y, float z, float heading);
void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); void PushMoveTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mode); void PushSwimTo(MobMovementEntry &ent, float x, float y, float z, MobMovementMode mob_movement_mode);
void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mode); void PushRotateTo(MobMovementEntry &ent, Mob *who, float to, MobMovementMode mob_movement_mode);
void PushStopMoving(MobMovementEntry &ent); void PushStopMoving(MobMovementEntry &mob_movement_entry);
void PushEvadeCombat(MobMovementEntry &ent); void PushEvadeCombat(MobMovementEntry &mob_movement_entry);
void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mode); void HandleStuckBehavior(Mob *who, float x, float y, float z, MobMovementMode mob_movement_mode);
struct Implementation; struct Implementation;
std::unique_ptr<Implementation> _impl; std::unique_ptr<Implementation> _impl;

View File

@ -514,7 +514,7 @@ int main(int argc, char** argv) {
} }
else { else {
if (worldwasconnected && is_zone_loaded) { if (worldwasconnected && is_zone_loaded) {
entity_list.ChannelMessageFromWorld(0, 0, 6, 0, 0, "WARNING: World server connection lost"); entity_list.ChannelMessageFromWorld(0, 0, ChatChannel_Broadcast, 0, 0, 100, "WARNING: World server connection lost");
worldwasconnected = false; worldwasconnected = false;
} }
} }

View File

@ -146,33 +146,33 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi
size = GetRaceGenderDefaultHeight(race, gender); size = GetRaceGenderDefaultHeight(race, gender);
} }
taunting = false; taunting = false;
proximity = nullptr; proximity = nullptr;
copper = 0; copper = 0;
silver = 0; silver = 0;
gold = 0; gold = 0;
platinum = 0; platinum = 0;
max_dmg = npc_type_data->max_dmg; max_dmg = npc_type_data->max_dmg;
min_dmg = npc_type_data->min_dmg; min_dmg = npc_type_data->min_dmg;
attack_count = npc_type_data->attack_count; attack_count = npc_type_data->attack_count;
grid = 0; grid = 0;
wp_m = 0; wp_m = 0;
max_wp = 0; max_wp = 0;
save_wp = 0; save_wp = 0;
spawn_group = 0; spawn_group_id = 0;
swarmInfoPtr = nullptr; swarmInfoPtr = nullptr;
spellscale = npc_type_data->spellscale; spellscale = npc_type_data->spellscale;
healscale = npc_type_data->healscale; healscale = npc_type_data->healscale;
pAggroRange = npc_type_data->aggroradius; pAggroRange = npc_type_data->aggroradius;
pAssistRange = npc_type_data->assistradius; pAssistRange = npc_type_data->assistradius;
findable = npc_type_data->findable; findable = npc_type_data->findable;
trackable = npc_type_data->trackable; trackable = npc_type_data->trackable;
MR = npc_type_data->MR; MR = npc_type_data->MR;
CR = npc_type_data->CR; CR = npc_type_data->CR;
DR = npc_type_data->DR; DR = npc_type_data->DR;
FR = npc_type_data->FR; FR = npc_type_data->FR;
PR = npc_type_data->PR; PR = npc_type_data->PR;
Corrup = npc_type_data->Corrup; Corrup = npc_type_data->Corrup;
PhR = npc_type_data->PhR; PhR = npc_type_data->PhR;
STR = npc_type_data->STR; STR = npc_type_data->STR;
STA = npc_type_data->STA; STA = npc_type_data->STA;
@ -611,7 +611,7 @@ void NPC::ClearItemList() {
void NPC::QueryLoot(Client* to) void NPC::QueryLoot(Client* to)
{ {
to->Message(0, "| # Current Loot (%s) LootTableID: %i", GetName(), GetLoottableID()); to->Message(Chat::White, "| # Current Loot (%s) LootTableID: %i", GetName(), GetLoottableID());
int item_count = 0; int item_count = 0;
for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++item_count) { for (auto cur = itemlist.begin(); cur != itemlist.end(); ++cur, ++item_count) {
@ -639,7 +639,7 @@ void NPC::QueryLoot(Client* to)
); );
} }
to->Message(0, "| %i Platinum %i Gold %i Silver %i Copper", platinum, gold, silver, copper); to->Message(Chat::White, "| %i Platinum %i Gold %i Silver %i Copper", platinum, gold, silver, copper);
} }
void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) { void NPC::AddCash(uint16 in_copper, uint16 in_silver, uint16 in_gold, uint16 in_platinum) {
@ -1190,17 +1190,17 @@ NPC* NPC::SpawnNPC(const char* spawncommand, const glm::vec4& position, Client*
if (client) { if (client) {
// Notify client of spawn data // Notify client of spawn data
client->Message(0, "New spawn:"); client->Message(Chat::White, "New spawn:");
client->Message(0, "Name: %s", npc->name); client->Message(Chat::White, "Name: %s", npc->name);
client->Message(0, "Race: %u", npc->race); client->Message(Chat::White, "Race: %u", npc->race);
client->Message(0, "Level: %u", npc->level); client->Message(Chat::White, "Level: %u", npc->level);
client->Message(0, "Material: %u", npc->texture); client->Message(Chat::White, "Material: %u", npc->texture);
client->Message(0, "Current/Max HP: %i", npc->max_hp); client->Message(Chat::White, "Current/Max HP: %i", npc->max_hp);
client->Message(0, "Gender: %u", npc->gender); client->Message(Chat::White, "Gender: %u", npc->gender);
client->Message(0, "Class: %u", npc->class_); client->Message(Chat::White, "Class: %u", npc->class_);
client->Message(0, "Weapon Item Number: %u/%u", npc->d_melee_texture1, npc->d_melee_texture2); client->Message(Chat::White, "Weapon Item Number: %u/%u", npc->d_melee_texture1, npc->d_melee_texture2);
client->Message(0, "MerchantID: %u", npc->MerchantType); client->Message(Chat::White, "MerchantID: %u", npc->MerchantType);
client->Message(0, "Bodytype: %u", npc->bodytype); client->Message(Chat::White, "Bodytype: %u", npc->bodytype);
} }
return npc; return npc;
@ -1270,7 +1270,7 @@ uint32 ZoneDatabase::CreateNewNPCCommand(const char *zone, uint32 zone_version,
} }
uint32 spawngroupid = results.LastInsertedID(); uint32 spawngroupid = results.LastInsertedID();
spawn->SetSp2(spawngroupid); spawn->SetSpawnGroupId(spawngroupid);
spawn->SetNPCTypeID(npc_type_id); spawn->SetNPCTypeID(npc_type_id);
query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) " query = StringFormat("INSERT INTO spawn2 (zone, version, x, y, z, respawntime, heading, spawngroupID) "
@ -1355,7 +1355,7 @@ uint32 ZoneDatabase::DeleteSpawnLeaveInNPCTypeTable(const char *zone, Client *cl
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE " std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE "
"zone='%s' AND spawngroupID=%i", "zone='%s' AND spawngroupID=%i",
zone, spawn->GetSp2()); zone, spawn->GetSpawnGroupId());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
return 0; return 0;
@ -1396,7 +1396,7 @@ uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32
std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' " std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' "
"AND (version = %u OR version = -1) AND spawngroupID = %i", "AND (version = %u OR version = -1) AND spawngroupID = %i",
zone, zone_version, spawn->GetSp2()); zone, zone_version, spawn->GetSpawnGroupId());
auto results = QueryDatabase(query); auto results = QueryDatabase(query);
if (!results.Success()) if (!results.Success())
return 0; return 0;
@ -1471,7 +1471,7 @@ uint32 ZoneDatabase::AddNPCTypes(const char *zone, uint32 zone_version, Client *
npc_type_id = results.LastInsertedID(); npc_type_id = results.LastInsertedID();
if (client) if (client)
client->Message(0, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id); client->Message(Chat::White, "%s npc_type ID %i created successfully!", numberlessName, npc_type_id);
return 1; return 1;
} }
@ -1577,7 +1577,7 @@ void NPC::PickPocket(Client* thief)
//make sure were allowed to target them: //make sure were allowed to target them:
int over_level = GetLevel(); int over_level = GetLevel();
if(over_level > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) { if(over_level > (thief->GetLevel() + THIEF_PICKPOCKET_OVER)) {
thief->Message(13, "You are too inexperienced to pick pocket this target"); thief->Message(Chat::Red, "You are too inexperienced to pick pocket this target");
thief->SendPickPocketResponse(this, 0, PickPocketFailed); thief->SendPickPocketResponse(this, 0, PickPocketFailed);
//should we check aggro //should we check aggro
return; return;
@ -1587,7 +1587,7 @@ void NPC::PickPocket(Client* thief)
if (zone->CanDoCombat()) if (zone->CanDoCombat())
AddToHateList(thief, 50); AddToHateList(thief, 50);
Say("Stop thief!"); Say("Stop thief!");
thief->Message(13, "You are noticed trying to steal!"); thief->Message(Chat::Red, "You are noticed trying to steal!");
thief->SendPickPocketResponse(this, 0, PickPocketFailed); thief->SendPickPocketResponse(this, 0, PickPocketFailed);
return; return;
} }
@ -1694,7 +1694,7 @@ void NPC::PickPocket(Client* thief)
return; return;
} }
thief->Message(0, "This target's pockets are empty"); thief->Message(Chat::White, "This target's pockets are empty");
thief->SendPickPocketResponse(this, 0, PickPocketFailed); thief->SendPickPocketResponse(this, 0, PickPocketFailed);
} }
@ -1744,17 +1744,17 @@ void NPC::Disarm(Client* client, int chance) {
SendWearChange(matslot); SendWearChange(matslot);
if ((CastToMob()->GetBodyType() == BT_Humanoid || CastToMob()->GetBodyType() == BT_Summoned) && eslot == EQEmu::invslot::slotPrimary) if ((CastToMob()->GetBodyType() == BT_Humanoid || CastToMob()->GetBodyType() == BT_Summoned) && eslot == EQEmu::invslot::slotPrimary)
Say("Ahh! My weapon!"); Say("Ahh! My weapon!");
client->Message_StringID(MT_Skills, DISARM_SUCCESS, this->GetCleanName()); client->MessageString(Chat::Skills, DISARM_SUCCESS, this->GetCleanName());
if (chance != 1000) if (chance != 1000)
client->CheckIncreaseSkill(EQEmu::skills::SkillDisarm, nullptr, 4); client->CheckIncreaseSkill(EQEmu::skills::SkillDisarm, nullptr, 4);
return; return;
} }
client->Message_StringID(MT_Skills, DISARM_FAILED); client->MessageString(Chat::Skills, DISARM_FAILED);
if (chance != 1000) if (chance != 1000)
client->CheckIncreaseSkill(EQEmu::skills::SkillDisarm, nullptr, 2); client->CheckIncreaseSkill(EQEmu::skills::SkillDisarm, nullptr, 2);
return; return;
} }
client->Message_StringID(MT_Skills, DISARM_FAILED); client->MessageString(Chat::Skills, DISARM_FAILED);
} }
void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) { void Mob::NPCSpecialAttacks(const char* parse, int permtag, bool reset, bool remove) {
@ -2592,7 +2592,7 @@ void NPC::DoNPCEmote(uint8 event_, uint16 emoteid)
else if(nes->type == 2) else if(nes->type == 2)
this->Shout("%s",nes->text); this->Shout("%s",nes->text);
else if(nes->type == 3) else if(nes->type == 3)
entity_list.MessageClose_StringID(this, true, 200, 10, GENERIC_STRING, nes->text); entity_list.MessageCloseString(this, true, 200, 10, GENERIC_STRING, nes->text);
else else
this->Say("%s",nes->text); this->Say("%s",nes->text);
} }
@ -2924,3 +2924,15 @@ bool NPC::IsProximitySet()
return false; return false;
} }
void NPC::SetSimpleRoamBox(float box_size, float move_distance, int move_delay)
{
AI_SetRoambox(
(move_distance != 0 ? move_distance : box_size / 2),
GetX() + box_size,
GetX() - box_size,
GetY() + box_size,
GetY() - box_size,
move_delay
);
}

View File

@ -214,13 +214,13 @@ public:
virtual int32 CalcMaxMana(); virtual int32 CalcMaxMana();
void SetGrid(int32 grid_){ grid=grid_; } void SetGrid(int32 grid_){ grid=grid_; }
void SetSp2(uint32 sg2){ spawn_group=sg2; } void SetSpawnGroupId(uint32 sg2){ spawn_group_id =sg2; }
void SetWaypointMax(uint16 wp_){ wp_m=wp_; } void SetWaypointMax(uint16 wp_){ wp_m=wp_; }
void SetSaveWaypoint(uint16 wp_){ save_wp=wp_; } void SetSaveWaypoint(uint16 wp_){ save_wp=wp_; }
uint16 GetWaypointMax() const { return wp_m; } uint16 GetWaypointMax() const { return wp_m; }
int32 GetGrid() const { return grid; } int32 GetGrid() const { return grid; }
uint32 GetSp2() const { return spawn_group; } uint32 GetSpawnGroupId() const { return spawn_group_id; }
uint32 GetSpawnPointID() const; uint32 GetSpawnPointID() const;
glm::vec4 const GetSpawnPoint() const { return m_SpawnPoint; } glm::vec4 const GetSpawnPoint() const { return m_SpawnPoint; }
@ -453,6 +453,8 @@ public:
bool IgnoreDespawn() { return ignore_despawn; } bool IgnoreDespawn() { return ignore_despawn; }
void SetSimpleRoamBox(float box_size, float move_distance = 0, int move_delay = 0);
float GetRoamboxMaxX() const; float GetRoamboxMaxX() const;
float GetRoamboxMaxY() const; float GetRoamboxMaxY() const;
float GetRoamboxMinX() const; float GetRoamboxMinX() const;
@ -478,13 +480,13 @@ protected:
friend class EntityList; friend class EntityList;
friend class Aura; friend class Aura;
std::list<struct NPCFaction*> faction_list; std::list<struct NPCFaction*> faction_list;
uint32 copper; uint32 copper;
uint32 silver; uint32 silver;
uint32 gold; uint32 gold;
uint32 platinum; uint32 platinum;
int32 grid; int32 grid;
uint32 spawn_group; uint32 spawn_group_id;
uint16 wp_m; uint16 wp_m;
int32 npc_faction_id; int32 npc_faction_id;
int32 primary_faction; int32 primary_faction;

View File

@ -572,7 +572,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
if (sender->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) { if (sender->ClientVersion() >= EQEmu::versions::ClientVersion::RoF) {
coa->drop_id = 0xFFFFFFFF; coa->drop_id = 0xFFFFFFFF;
sender->Message(0, "Someone else is using that. Try again later."); sender->Message(Chat::White, "Someone else is using that. Try again later.");
} }
} }

Some files were not shown because too many files have changed in this diff Show More