diff --git a/.gitignore b/.gitignore index 52dbcb224..805c783a4 100644 --- a/.gitignore +++ b/.gitignore @@ -33,5 +33,7 @@ Build_32/ build_32/ Build_64/ build_64/ +x64/ +x86/ log/ logs/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 53969c7ee..ce1a3bc9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,12 +13,6 @@ #EQEMU_LOG_LEVEL_QUEST #EQEMU_LOG_LEVEL_COMMANDS #EQEMU_LOG_LEVEL_CRASH -#EQEMU_STREAM_SEND_RATE -#EQEMU_STREAM_DECAY_RATE -#EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL -#EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX -#EQEMU_STREAM_AVERAGE_DELTA_MAX -#EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS #EQEMU_DEPOP_INVALIDATES_CACHE #EQEMU_ENABLE_BOTS #EQEMU_DISABLE_LOGSYS @@ -237,14 +231,6 @@ SET(EQEMU_LOG_LEVEL_CRASH 3 CACHE STRING "EQEmu logging level for [Crash]: MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_STATUS EQEMU_LOG_LEVEL_NORMAL EQEMU_LOG_LEVEL_ERROR EQEMU_LOG_LEVEL_DEBUG EQEMU_LOG_LEVEL_QUEST EQEMU_LOG_LEVEL_COMMANDS EQEMU_LOG_LEVEL_CRASH) -SET(EQEMU_STREAM_SEND_RATE 1048576 CACHE STRING "Advanced: Base amount of data stream can send before throttle.") -SET(EQEMU_STREAM_DECAY_RATE 78642 CACHE STRING "Advanced: Base amount of data stream recovers per tic.") -SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL 3.0 CACHE STRING "Advanced: Multiplier on retransmit timeout.") -SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX 5000 CACHE STRING "Advanced: Max in ms for retransmit timeout timer.") -SET(EQEMU_STREAM_AVERAGE_DELTA_MAX 2500 CACHE STRING "Advanced: The maximum average delta in ms allowed.") -SET(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS TRUE CACHE BOOL "Advanced: Whether or not acked packets can be retransmitted") -MARK_AS_ADVANCED(EQEMU_STREAM_SEND_RATE EQEMU_STREAM_DECAY_RATE EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX EQEMU_STREAM_AVERAGE_DELTA_MAX EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - #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) @@ -306,11 +292,6 @@ ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL}) ADD_DEFINITIONS(-DINVERSEXY) ADD_DEFINITIONS(-DFIELD_ITEMS) ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}") -ADD_DEFINITIONS(-DRATEBASE=${EQEMU_STREAM_SEND_RATE}) -ADD_DEFINITIONS(-DDECAYBASE=${EQEMU_STREAM_DECAY_RATE}) -ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MULT=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL}) -ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MAX=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX}) -ADD_DEFINITIONS(-DAVERAGE_DELTA_MAX=${EQEMU_STREAM_AVERAGE_DELTA_MAX}) ADD_DEFINITIONS(-DLOG_LEVEL_STATUS=${EQEMU_LOG_LEVEL_STATUS}) ADD_DEFINITIONS(-DLOG_LEVEL_NORMAL=${EQEMU_LOG_LEVEL_NORMAL}) ADD_DEFINITIONS(-DLOG_LEVEL_ERROR=${EQEMU_LOG_LEVEL_ERROR}) @@ -320,12 +301,6 @@ ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS}) ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH}) ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) -IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true) -ELSE(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=false) -ENDIF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - #Find everything we need FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(MySQL REQUIRED) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 06486d2db..d65efd183 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -103,6 +103,7 @@ SET(common_sources tinyxml/tinyxml.cpp tinyxml/tinyxmlerror.cpp tinyxml/tinyxmlparser.cpp + util/directory.cpp util/uuid.cpp ) @@ -257,6 +258,7 @@ SET(common_headers tinyxml/tinystr.h tinyxml/tinyxml.h util/memory_stream.h + util/directory.h util/uuid.h ) @@ -366,6 +368,8 @@ SOURCE_GROUP(TinyXML FILES SOURCE_GROUP(Util FILES util/memory_stream.h + util/directory.cpp + util/directory.h util/uuid.cpp util/uuid.h ) diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index d8f08b05d..ab420bd42 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -25,6 +25,23 @@ void EQ::Net::ConsoleServer::RegisterLogin(ConsoleServerLoginCallback fn) m_login = fn; } +EQ::Net::ConsoleServerConnection *EQ::Net::ConsoleServer::FindByAccountName(const std::string &acct_name) { + for (auto &iter : m_connections) { + if (iter.second->UserName().compare(acct_name) == 0) { + return iter.second.get(); + } + } + + return nullptr; +} + + +void EQ::Net::ConsoleServer::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell) { + for (auto &iter : m_connections) { + iter.second->SendChannelMessage(scm, onTell); + } +} + void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c) { auto iter = m_connections.find(c->GetUUID()); diff --git a/common/net/console_server.h b/common/net/console_server.h index 5a0c48f8e..d28f43844 100644 --- a/common/net/console_server.h +++ b/common/net/console_server.h @@ -25,7 +25,8 @@ namespace EQ void RegisterCall(const std::string& command, int status_required, const std::string& help_definition, ConsoleServerCallback fn); void RegisterLogin(ConsoleServerLoginCallback fn); - + ConsoleServerConnection *FindByAccountName(const std::string &acct_name); + void SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell); private: void ConnectionDisconnected(ConsoleServerConnection *c); void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd); diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index 8764f09b6..249817818 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -2,6 +2,8 @@ #include "../common/util/uuid.h" #include "../common/net/packet.h" #include "../common/eqemu_logsys.h" +#include "../common/servertalk.h" +#include "../common/rulesys.h" EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr connection) { @@ -107,6 +109,53 @@ void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg) } } +bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell) { + if (!m_accept_messages) { + return false; + } + + switch (scm->chan_num) { + if (RuleB(Chat, ServerWideAuction)) { + case 4: { + QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message)); + break; + } + } + + if (RuleB(Chat, ServerWideOOC)) { + case 5: { + QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message)); + break; + } + } + + case 6: { + QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message)); + break; + } + + case 7: { + QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message)); + if (onTell) { + onTell(); + } + + break; + } + + case 11: { + QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message)); + break; + } + + default: { + return false; + } + } + + return true; +} + void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz) { for (size_t i = 0; i < sz; ++i) { diff --git a/common/net/console_server_connection.h b/common/net/console_server_connection.h index d826ba07b..a49700841 100644 --- a/common/net/console_server_connection.h +++ b/common/net/console_server_connection.h @@ -4,6 +4,8 @@ #include #include +struct ServerChannelMessage_Struct; + namespace EQ { namespace Net @@ -42,6 +44,7 @@ namespace EQ bool AcceptMessages() const { return m_accept_messages; } void SetAcceptMessages(bool v) { m_accept_messages = v; } void QueueMessage(const std::string &msg); + bool SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell); private: void OnRead(TCPConnection* c, const unsigned char* data, size_t sz); void OnDisconnect(TCPConnection* c); diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 68fc24ad2..19b5ee5d1 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -277,7 +277,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_encode_passes[1] = owner->m_options.encode_passes[1]; m_hold_time = Clock::now(); m_buffered_packets_length = 0; - m_rolling_ping = 500; + m_rolling_ping = 900; m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms; m_combined.reset(new char[512]); m_combined[0] = 0; @@ -300,7 +300,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_crc_bytes = 0; m_hold_time = Clock::now(); m_buffered_packets_length = 0; - m_rolling_ping = 500; + m_rolling_ping = 900; m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms; m_combined.reset(new char[512]); m_combined[0] = 0; @@ -1026,7 +1026,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + m_rolling_ping += 300; } } else { @@ -1040,7 +1040,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + m_rolling_ping += 300; } } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 409471589..2d99153e9 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -155,13 +156,13 @@ namespace EQ uint16_t sequence_in; uint16_t sequence_out; - std::map packet_queue; + std::unordered_map packet_queue; DynamicPacket fragment_packet; uint32_t fragment_current_bytes; uint32_t fragment_total_bytes; - std::map sent_packets; + std::unordered_map sent_packets; }; DaybreakStream m_streams[4]; @@ -205,10 +206,10 @@ namespace EQ DaybreakConnectionManagerOptions() { max_connection_count = 0; keepalive_delay_ms = 9000; - resend_delay_ms = 150; + resend_delay_ms = 300; resend_delay_factor = 1.5; - resend_delay_min = 150; - resend_delay_max = 1000; + resend_delay_min = 350; + resend_delay_max = 8000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -282,4 +283,4 @@ namespace EQ friend class DaybreakConnection; }; } -} \ No newline at end of file +} diff --git a/common/util/directory.cpp b/common/util/directory.cpp new file mode 100644 index 000000000..9bc075bbe --- /dev/null +++ b/common/util/directory.cpp @@ -0,0 +1,49 @@ +#include "directory.h" + +#ifdef _WIN32 +#include "win_dirent.h" +#else +#include +#endif + +struct EQ::Directory::impl { + DIR *m_dir; +}; + +EQ::Directory::Directory(const std::string &path) +{ + m_impl = new impl; + m_impl->m_dir = opendir(path.c_str()); +} + +EQ::Directory::~Directory() +{ + if (m_impl->m_dir) { + closedir(m_impl->m_dir); + } + + delete m_impl; +} + +bool EQ::Directory::Exists() +{ + return m_impl->m_dir != nullptr; +} + +void EQ::Directory::GetFiles(std::vector& files) +{ + if (m_impl->m_dir) { + struct dirent *ent; + while ((ent = readdir(m_impl->m_dir)) != nullptr) { + switch (ent->d_type) { + case DT_REG: + files.push_back(ent->d_name); + break; + default: + break; + } + } + + rewinddir(m_impl->m_dir); + } +} diff --git a/common/util/directory.h b/common/util/directory.h new file mode 100644 index 000000000..d5f7441b2 --- /dev/null +++ b/common/util/directory.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include + +namespace EQ { + class Directory + { + public: + Directory(const std::string &path); + ~Directory(); + + bool Exists(); + void GetFiles(std::vector &files); + private: + struct impl; + impl *m_impl; + }; +} diff --git a/common/util/win_dirent.h b/common/util/win_dirent.h new file mode 100644 index 000000000..89f4df49f --- /dev/null +++ b/common/util/win_dirent.h @@ -0,0 +1,928 @@ +/* + * Dirent interface for Microsoft Visual Studio + * Version 1.21 + * + * Copyright (C) 2006-2012 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of d_namlen without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return number of bytes needed to store d_namlen */ +#define _D_ALLOC_NAMLEN(p) (PATH_MAX) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +static _WDIR *_wopendir (const wchar_t *dirname); +static struct _wdirent *_wreaddir (_WDIR *dirp); +static int _wclosedir (_WDIR *dirp); +static void _wrewinddir (_WDIR* dirp); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Multi-byte character versions */ +struct dirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + +static DIR *opendir (const char *dirname); +static struct dirent *readdir (DIR *dirp); +static int closedir (DIR *dirp); +static void rewinddir (DIR* dirp); + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); +# else + n = GetFullPathNameW (dirname, 0, NULL, NULL); +# endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n+1, dirname, n); +# else + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); +# endif + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first (dirp)) { + /* Directory stream opened successfully */ + error = 0; + } else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno (ENOENT); + } + + } else { + /* Cannot retrieve full path name */ + dirent_set_errno (ENOENT); + error = 1; + } + + } else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct _wdirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct _wdirent); + + } else { + + /* Last directory entry read */ + entp = NULL; + + } + + return entp; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free (dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; +} + +/* Get next directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occured */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } else { + /* Failed to open directory stream */ + error = 1; + } + + } else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + + } else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correcly. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct dirent); + + } else { + /* + * Cannot convert file name to multi-byte string so construct + * an errornous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } else { + /* No more directory entries */ + entp = NULL; + } + + return entp; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ diff --git a/utils/mods/classic_wow_experience.lua b/utils/mods/classic_wow_experience.lua new file mode 100644 index 000000000..cde740ff6 --- /dev/null +++ b/utils/mods/classic_wow_experience.lua @@ -0,0 +1,159 @@ +--Mod file to demo changing the experience tables +--In this case I used some old wow tables (roughly it's not 100%) + +function GetRequiredAAExperience(e) + e.level = 51; + return GetEXPForLevel(e); +end + +function GetExperienceForKill(e) + local ML = e.other:GetLevel(); + local CL = e.self:GetLevel(); + + if(ML > CL) then + local lmod = (ML - CL) * 0.05; + if(lmod > 1.0) then + lmod = 1.0; + end + e.ReturnValue = BaseXP(ML) * (1 + lmod); + elseif(ML < CL) then + local lmod = (CL - ML) * 0.05; + if(lmod > 1.0) then + lmod = 1.0; + end + e.ReturnValue = BaseXP(ML) * (1 - lmod); + else + e.ReturnValue = BaseXP(ML); + end + + e.IgnoreDefault = true; + return e; +end + +function BaseXP(L) + local base = L * 5; + + if(L < 60) then + base = base + 45; + elseif(L < 70) then + base = base + 235; + elseif(L < 80) then + base = base + 580; + else + base = base + 1875; + end + + return base; +end + +function GetEXPForLevel(e) + local exp_table = { + 0, + 400, + 900, + 1400, + 2100, + 2800, + 3600, + 4500, + 5400, + 6500, + 7600, + 8700, + 9800, + 11000, + 12300, + 13600, + 15000, + 16400, + 17800, + 19300, + 20800, + 22400, + 24000, + 25500, + 27200, + 28900, + 30500, + 32200, + 33900, + 36300, + 38800, + 41600, + 44600, + 48000, + 51400, + 55000, + 58700, + 62400, + 66200, + 70200, + 74300, + 78500, + 82800, + 87100, + 91600, + 96300, + 101000, + 105800, + 110700, + 115700, + 120900, + 126100, + 131500, + 137000, + 142500, + 148200, + 154000, + 159900, + 165800, + 172000, + 290000, + 317000, + 349000, + 386000, + 428000, + 475000, + 527000, + 585000, + 648000, + 717000, + 1523800, + 1539000, + 1555700, + 1571800, + 1587900, + 1604200, + 1620700, + 1637400, + 1653900, + 1670800, + 1670800, + 1670800, + 2121500, + 2669000, + 3469000, + 4583000, + 13000000, + 15080000, + 22600000, + 27300000, + 32800000 + }; + + if(e.level < 1) then + e.ReturnValue = 0; + e.IgnoreDefault = true; + return e; + end + + if(e.level > 91) then + e.ReturnValue = exp_table[91]; + e.IgnoreDefault = true; + return e; + end + + e.ReturnValue = exp_table[e.level]; + e.IgnoreDefault = true; + return e; +end diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua new file mode 100644 index 000000000..297b81b98 --- /dev/null +++ b/utils/mods/legacy_combat.lua @@ -0,0 +1,752 @@ +MonkACBonusWeight = RuleI.Get(Rule.MonkACBonusWeight); +NPCACFactor = RuleR.Get(Rule.NPCACFactor); +OldACSoftcapRules = RuleB.Get(Rule.OldACSoftcapRules); +ClothACSoftcap = RuleI.Get(Rule.ClothACSoftcap); +LeatherACSoftcap = RuleI.Get(Rule.LeatherACSoftcap); +MonkACSoftcap = RuleI.Get(Rule.MonkACSoftcap); +ChainACSoftcap = RuleI.Get(Rule.ChainACSoftcap); +PlateACSoftcap = RuleI.Get(Rule.PlateACSoftcap); + +AAMitigationACFactor = RuleR.Get(Rule.AAMitigationACFactor); +WarriorACSoftcapReturn = RuleR.Get(Rule.WarriorACSoftcapReturn); +KnightACSoftcapReturn = RuleR.Get(Rule.KnightACSoftcapReturn); +LowPlateChainACSoftcapReturn = RuleR.Get(Rule.LowPlateChainACSoftcapReturn); +LowChainLeatherACSoftcapReturn = RuleR.Get(Rule.LowChainLeatherACSoftcapReturn); +CasterACSoftcapReturn = RuleR.Get(Rule.CasterACSoftcapReturn); +MiscACSoftcapReturn = RuleR.Get(Rule.MiscACSoftcapReturn); +WarACSoftcapReturn = RuleR.Get(Rule.WarACSoftcapReturn); +ClrRngMnkBrdACSoftcapReturn = RuleR.Get(Rule.ClrRngMnkBrdACSoftcapReturn); +PalShdACSoftcapReturn = RuleR.Get(Rule.PalShdACSoftcapReturn); +DruNecWizEncMagACSoftcapReturn = RuleR.Get(Rule.DruNecWizEncMagACSoftcapReturn); +RogShmBstBerACSoftcapReturn = RuleR.Get(Rule.RogShmBstBerACSoftcapReturn); +SoftcapFactor = RuleR.Get(Rule.SoftcapFactor); +ACthac0Factor = RuleR.Get(Rule.ACthac0Factor); +ACthac20Factor = RuleR.Get(Rule.ACthac20Factor); + +MeleeBaseCritChance = 0.0; +ClientBaseCritChance = 0.0; +BerserkBaseCritChance = 6.0; +WarBerBaseCritChance = 3.0; +RogueCritThrowingChance = 25; +RogueDeadlyStrikeChance = 80; +RogueDeadlyStrikeMod = 2; + +BaseHitChance = RuleR.Get(Rule.BaseHitChance); +NPCBonusHitChance = RuleR.Get(Rule.NPCBonusHitChance); +HitFalloffMinor = RuleR.Get(Rule.HitFalloffMinor); +HitFalloffModerate = RuleR.Get(Rule.HitFalloffModerate); +HitFalloffMajor = RuleR.Get(Rule.HitFalloffMajor); +HitBonusPerLevel = RuleR.Get(Rule.HitBonusPerLevel); +AgiHitFactor = RuleR.Get(Rule.AgiHitFactor); +WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff); +ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty); +UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules); + +function MeleeMitigation(e) + e.IgnoreDefault = true; + + if e.hit.damage_done < 0 or e.hit.base_damage == 0 then + return e; + end + + e.hit.damage_done = 2 * e.hit.base_damage * GetDamageTable(e.other, e.hit.skill) / 100; + e.hit = DoMeleeMitigation(e.self, e.other, e.hit, e.opts); + return e; +end + +function CheckHitChance(e) + e.IgnoreDefault = true; + + local other = e.other; + local attacker = other; + local self = e.self; + local defender = self; + local chancetohit = BaseHitChance; + local chance_mod = 0; + + if(e.opts ~= nil) then + chance_mod = e.opts.hit_chance; + end + + if(attacker:IsNPC() and not attacker:IsPet()) then + chancetohit = chancetohit + NPCBonusHitChance; + end + + local pvpmode = false; + if(self:IsClient() and other:IsClient()) then + pvpmode = true; + end + + if (chance_mod >= 10000) then + e.ReturnValue = true; + return e; + end + + local avoidanceBonus = 0; + local hitBonus = 0; + + local attacker_level = attacker:GetLevel(); + if(attacker_level < 1) then + attacker_level = 1; + end + + local defender_level = defender:GetLevel(); + if(defender_level < 1) then + defender_level = 1; + end + + local level_difference = attacker_level - defender_level; + local range = defender_level; + range = ((range / 4) + 3); + + if(level_difference < 0) then + if(level_difference >= -range) then + chancetohit = chancetohit + ((level_difference / range) * HitFalloffMinor); + elseif (level_difference >= -(range+3.0)) then + chancetohit = chancetohit - HitFalloffMinor; + chancetohit = chancetohit + (((level_difference + range) / 3.0) * HitFalloffModerate); + else + chancetohit = chancetohit - (HitFalloffMinor + HitFalloffModerate); + chancetohit = chancetohit + (((level_difference + range + 3.0) / 12.0) * HitFalloffMajor); + end + else + chancetohit = chancetohit + (HitBonusPerLevel * level_difference); + end + + chancetohit = chancetohit - (defender:GetAGI() * AgiHitFactor); + + if(attacker:IsClient()) then + chancetohit = chancetohit - (WeaponSkillFalloff * (attacker:CastToClient():MaxSkill(e.hit.skill) - attacker:GetSkill(e.hit.skill))); + end + + if(defender:IsClient()) then + chancetohit = chancetohit + (WeaponSkillFalloff * (defender:CastToClient():MaxSkill(Skill.Defense) - defender:GetSkill(Skill.Defense))); + end + + local attacker_spellbonuses = attacker:GetSpellBonuses(); + local attacker_itembonuses = attacker:GetItemBonuses(); + local attacker_aabonuses = attacker:GetAABonuses(); + local defender_spellbonuses = defender:GetSpellBonuses(); + local defender_itembonuses = defender:GetItemBonuses(); + local defender_aabonuses = defender:GetAABonuses(); + + if(attacker_spellbonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_spellbonuses:MeleeSkillCheckSkill() == 255) then + chancetohit = chancetohit + attacker_spellbonuses:MeleeSkillCheck(); + end + + if(attacker_itembonuses:MeleeSkillCheckSkill() == e.hit.skill or attacker_itembonuses:MeleeSkillCheckSkill() == 255) then + chancetohit = chancetohit + attacker_itembonuses:MeleeSkillCheck(); + end + + avoidanceBonus = defender_spellbonuses:AvoidMeleeChanceEffect() + + defender_itembonuses:AvoidMeleeChanceEffect() + + defender_aabonuses:AvoidMeleeChanceEffect() + + (defender_itembonuses:AvoidMeleeChance() / 10.0); + + local owner = Mob(); + if (defender:IsPet()) then + owner = defender:GetOwner(); + elseif (defender:IsNPC() and defender:CastToNPC():GetSwarmOwner()) then + local entity_list = eq.get_entity_list(); + owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner()); + end + + if (owner.valid) then + avoidanceBonus = avoidanceBonus + owner:GetAABonuses():PetAvoidance() + owner:GetSpellBonuses():PetAvoidance() + owner:GetItemBonuses():PetAvoidance(); + end + + if(defender:IsNPC()) then + avoidanceBonus = avoidanceBonus + (defender:CastToNPC():GetAvoidanceRating() / 10.0); + end + + hitBonus = hitBonus + attacker_itembonuses:HitChanceEffect(e.hit.skill) + + attacker_spellbonuses:HitChanceEffect(e.hit.skill) + + attacker_aabonuses:HitChanceEffect(e.hit.skill) + + attacker_itembonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) + + attacker_spellbonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1) + + attacker_aabonuses:HitChanceEffect(Skill.HIGHEST_SKILL + 1); + + hitBonus = hitBonus + (attacker_itembonuses:Accuracy(Skill.HIGHEST_SKILL + 1) + + attacker_spellbonuses:Accuracy(Skill.HIGHEST_SKILL + 1) + + attacker_aabonuses:Accuracy(Skill.HIGHEST_SKILL + 1) + + attacker_aabonuses:Accuracy(e.hit.skill) + + attacker_itembonuses:HitChance()) / 15.0; + + hitBonus = hitBonus + chance_mod; + + if(attacker:IsNPC()) then + hitBonus = hitBonus + (attacker:CastToNPC():GetAccuracyRating() / 10.0); + end + + if (e.hit.skill == Skill.Archery) then + hitBonus = hitBonus - (hitBonus * ArcheryHitPenalty); + end + + chancetohit = chancetohit + ((chancetohit * (hitBonus - avoidanceBonus)) / 100.0); + + if(chancetohit > 1000 or chancetohit < -1000) then + elseif(chancetohit > 95) then + chancetohit = 95; + elseif(chancetohit < 5) then + chancetohit = 5; + end + + local tohit_roll = Random.Real(0, 100); + if(tohit_roll <= chancetohit) then + e.ReturnValue = true; + else + e.ReturnValue = false; + end + + return e; +end + +function TryCriticalHit(e) + e.IgnoreDefault = true; + + local self = e.self; + local defender = e.other; + + if(e.hit.damage_done < 1 or defender.null) then + return e; + end + + if ((self:IsPet() and self:GetOwner():IsClient()) or (self:IsNPC() and self:CastToNPC():GetSwarmOwner() ~= 0)) then + e.hit = TryPetCriticalHit(self, defender, e.hit); + return e; + end + + if (self:IsPet() and self:GetOwner().valid and self:GetOwner():IsBot()) then + e.hit = TryPetCriticalHit(self, defender, e.hit); + return e; + end + + local critChance = 0.0; + local IsBerskerSPA = false; + local aabonuses = self:GetAABonuses(); + local itembonuses = self:GetItemBonuses(); + local spellbonuses = self:GetSpellBonuses(); + local entity_list = eq.get_entity_list(); + + if (defender:GetBodyType() == BT.Undead or defender:GetBodyType() == BT.SummonedUndead or defender:GetBodyType() == BT.Vampire) then + local SlayRateBonus = aabonuses:SlayUndead(0) + itembonuses:SlayUndead(0) + spellbonuses:SlayUndead(0); + if (SlayRateBonus > 0) then + local slayChance = SlayRateBonus / 10000.0; + if (Random.RollReal(slayChance)) then + local SlayDmgBonus = aabonuses:SlayUndead(1) + itembonuses:SlayUndead(1) + spellbonuses:SlayUndead(1); + e.hit.damage_done = (e.hit.damage_done * SlayDmgBonus * 2.25) / 100; + + if (self:GetGender() == 1) then + entity_list:FilteredMessageClose(self, false, 200, MT.CritMelee, Filter.MeleeCrits, string.format('%s\'s holy blade cleanses her target! (%d)', self:GetCleanName(), e.hit.damage_done)); + else + entity_list:FilteredMessageClose(self, false, 200, MT.CritMelee, Filter.MeleeCrits, string.format('%s\'s holy blade cleanses his target! (%d)', self:GetCleanName(), e.hit.damage_done)); + end + + return e; + end + end + end + + critChance = critChance + MeleeBaseCritChance; + + if (self:IsClient()) then + critChance = critChance + ClientBaseCritChance; + + if (spellbonuses:BerserkSPA() or itembonuses:BerserkSPA() or aabonuses:BerserkSPA()) then + IsBerskerSPA = true; + end + + if (((self:GetClass() == Class.WARRIOR or self:GetClass() == Class.BERSERKER) and self:GetLevel() >= 12) or IsBerskerSPA) then + if (self:IsBerserk() or IsBerskerSPA) then + critChance = critChance + BerserkBaseCritChance; + else + critChance = critChance + WarBerBaseCritChance; + end + end + end + + local deadlyChance = 0; + local deadlyMod = 0; + if (e.hit.skill == Skill.Archery and self:GetClass() == Class.RANGER and self:GetSkill(Skill.Archery) >= 65) then + critChance = critChance + 6; + end + + if (e.hit.skill == Skill.Throwing and self:GetClass() == Class.ROGUE and self:GetSkill(Skill.Throwing) >= 65) then + critChance = critChance + RogueCritThrowingChance; + deadlyChance = RogueDeadlyStrikeChance; + deadlyMod = RogueDeadlyStrikeMod; + end + + local CritChanceBonus = GetCriticalChanceBonus(self, e.hit.skill); + + if (CritChanceBonus > 0 or critChance > 0) then + if (self:GetDEX() <= 255) then + critChance = critChance + (self:GetDEX() / 125.0); + elseif (self:GetDEX() > 255) then + critChance = critChance + ((self:GetDEX() - 255) / 500.0) + 2.0; + end + critChance = critChance + (critChance * CritChanceBonus / 100.0); + end + + if(opts ~= nil) then + critChance = critChance * opts.crit_percent; + critChance = critChance + opts.crit_flat; + end + + if(critChance > 0) then + + critChance = critChance / 100; + + if(Random.RollReal(critChance)) then + local critMod = 200; + local crip_success = false; + local CripplingBlowChance = GetCrippBlowChance(self); + + if (CripplingBlowChance > 0 or (self:IsBerserk() or IsBerskerSPA)) then + if (not self:IsBerserk() and not IsBerskerSPA) then + critChance = critChance * (CripplingBlowChance / 100.0); + end + + if ((self:IsBerserk() or IsBerskerSPA) or Random.RollReal(critChance)) then + critMod = 400; + crip_success = true; + end + end + + critMod = critMod + GetCritDmgMod(self, e.hit.skill) * 2; + e.hit.damage_done = e.hit.damage_done * critMod / 100; + + local deadlySuccess = false; + if (deadlyChance > 0 and Random.RollReal(deadlyChance / 100.0)) then + if (self:BehindMob(defender, self:GetX(), self:GetY())) then + e.hit.damage_done = e.hit.damage_done * deadlyMod; + deadlySuccess = true; + end + end + + if (crip_success) then + entity_list:FilteredMessageClose(self, false, 200, MT.CritMelee, Filter.MeleeCrits, string.format('%s lands a Crippling Blow! (%d)', self:GetCleanName(), e.hit.damage_done)); + if (defender:GetLevel() <= 55 and not defender:GetSpecialAbility(SpecialAbility.unstunable)) then + defender:Emote("staggers."); + defender:Stun(0); + end + elseif (deadlySuccess) then + entity_list:FilteredMessageClose(self, false, 200, MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a Deadly Strike! (%d)', self:GetCleanName(), e.hit.damage_done)); + else + entity_list:FilteredMessageClose(self, false, 200, MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a critical hit! (%d)', self:GetCleanName(), e.hit.damage_done)); + end + end + end + + return e; +end + +function TryPetCriticalHit(self, defender, hit) + if(hit.damage_done < 1) then + return hit; + end + + local owner = Mob(); + local critChance = MeleeBaseCritChance; + local critMod = 163; + + if (self:IsPet()) then + owner = self:GetOwner(); + elseif (self:IsNPC() and self:CastToNPC():GetSwarmOwner()) then + local entity_list = eq.get_entity_list(); + owner = entity_list:GetMobID(self:CastToNPC():GetSwarmOwner()); + else + return hit; + end + + if (owner.null) then + return hit; + end + + local CritPetChance = owner:GetAABonuses():PetCriticalHit() + owner:GetItemBonuses():PetCriticalHit() + owner:GetSpellBonuses():PetCriticalHit(); + local CritChanceBonus = GetCriticalChanceBonus(self, hit.skill); + + if (CritPetChance or critChance) then + critChance = critChance + CritPetChance; + critChance = critChance + (critChance * CritChanceBonus / 100.0); + end + + if(critChance > 0) then + critChance = critChance / 100; + + if(Random.RollReal(critChance)) then + local entity_list = eq.get_entity_list(); + critMod = critMod + GetCritDmgMob(self, hit.skill) * 2; + hit.damage_done = (hit.damage_done * critMod) / 100; + entity_list:FilteredMessageClose(this, false, 200, + MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a critical hit! (%d)', + self:GetCleanName(), hit.damage_done)); + end + end + + return hit; +end + +function GetCriticalChanceBonus(self, skill) + + local critical_chance = 0; + + local aabonuses = self:GetAABonuses(); + local itembonuses = self:GetItemBonuses(); + local spellbonuses = self:GetSpellBonuses(); + + critical_chance = critical_chance + itembonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1); + critical_chance = critical_chance + spellbonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1); + critical_chance = critical_chance + aabonuses:CriticalHitChance(Skill.HIGHEST_SKILL + 1); + critical_chance = critical_chance + itembonuses:CriticalHitChance(skill); + critical_chance = critical_chance + spellbonuses:CriticalHitChance(skill); + critical_chance = critical_chance + aabonuses:CriticalHitChance(skill); + + return critical_chance; +end + +function GetCritDmgMod(self, skill) + local critDmg_mod = 0; + + local aabonuses = self:GetAABonuses(); + local itembonuses = self:GetItemBonuses(); + local spellbonuses = self:GetSpellBonuses(); + + critDmg_mod = critDmg_mod + itembonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); + critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); + critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(Skill.HIGHEST_SKILL + 1); + critDmg_mod = critDmg_mod + itembonuses:CritDmgMod(skill); + critDmg_mod = critDmg_mod + spellbonuses:CritDmgMod(skill); + critDmg_mod = critDmg_mod + aabonuses:CritDmgMod(skill); + + return critDmg_mod; +end + +function GetCrippBlowChance(self) + local aabonuses = self:GetAABonuses(); + local itembonuses = self:GetItemBonuses(); + local spellbonuses = self:GetSpellBonuses(); + local crip_chance = itembonuses:CrippBlowChance() + spellbonuses:CrippBlowChance() + aabonuses:CrippBlowChance(); + + if(crip_chance < 0) then + crip_chance = 0; + end + + return crip_chance; +end + +function DoMeleeMitigation(defender, attacker, hit, opts) + if hit.damage_done <= 0 then + return hit; + end + + local aabonuses = defender:GetAABonuses(); + local itembonuses = defender:GetItemBonuses(); + local spellbonuses = defender:GetSpellBonuses(); + + local aa_mit = (aabonuses:CombatStability() + itembonuses:CombatStability() + spellbonuses:CombatStability()) / 100.0; + local softcap = (defender:GetSkill(15) + defender:GetLevel()) * SoftcapFactor * (1.0 + aa_mit); + local mitigation_rating = 0.0; + local attack_rating = 0.0; + local shield_ac = 0; + local armor = 0; + local weight = 0.0; + local monkweight = MonkACBonusWeight; + + if defender:IsClient() then + armor, shield_ac = GetRawACNoShield(defender); + weight = defender:CastToClient():CalcCurrentWeight() / 10; + elseif defender:IsNPC() then + armor = defender:CastToNPC():GetRawAC(); + local PetACBonus = 0; + + if not defender:IsPet() then + armor = armor / NPCACFactor; + end + + local owner = Mob(); + if defender:IsPet() then + owner = defender:GetOwner(); + elseif defender:CastToNPC():GetSwarmOwner() ~= 0 then + local entity_list = eq.get_entity_list(); + owner = entity_list:GetMobID(defender:CastToNPC():GetSwarmOwner()); + end + + if owner.valid then + PetACBonus = owner:GetAABonuses():PetMeleeMitigation() + owner:GetItemBonuses():PetMeleeMitigation() + owner:GetSpellBonuses():PetMeleeMitigation(); + end + + armor = armor + defender:GetSpellBonuses():AC() + defender:GetItemBonuses():AC() + PetACBonus + 1; + end + + if (opts ~= nil) then + armor = armor * (1.0 - opts.armor_pen_percent); + armor = armor - opts.armor_pen_flat; + end + + local defender_class = defender:GetClass(); + if OldACSoftcapRules then + if defender_class == Class.WIZARD or defender_class == Class.MAGICIAN or defender_class == Class.NECROMANCER or defender_class == Class.ENCHANTER then + softcap = ClothACSoftcap; + elseif defender_class == Class.MONK and weight <= monkweight then + softcap = MonkACSoftcap; + elseif defender_class == Class.DRUID or defender_class == Class.BEASTLORD or defender_class == Class.MONK then + softcap = LeatherACSoftcap; + elseif defender_class == Class.SHAMAN or defender_class == Class.ROGUE or defender_class == Class.BERSERKER or defender_class == Class.RANGER then + softcap = ChainACSoftcap; + else + softcap = PlateACSoftcap; + end + end + + softcap = softcap + shield_ac; + armor = armor + shield_ac; + + if OldACSoftcapRules then + softcap = softcap + (softcap * (aa_mit * AAMitigationACFactor)); + end + + if armor > softcap then + local softcap_armor = armor - softcap; + if OldACSoftcapRules then + if defender_class == Class.WARRIOR then + softcap_armor = softcap_armor * WarriorACSoftcapReturn; + elseif defender_class == Class.SHADOWKNIGHT or defender_class == Class.PALADIN or (defender_class == Class.MONK and weight <= monkweight) then + softcap_armor = softcap_armor * KnightACSoftcapReturn; + elseif defender_class == Class.CLERIC or defender_class == Class.BARD or defender_class == Class.BERSERKER or defender_class == Class.ROGUE or defender_class == Class.SHAMAN or defender_class == Class.MONK then + softcap_armor = softcap_armor * LowPlateChainACSoftcapReturn; + elseif defender_class == Class.RANGER or defender_class == Class.BEASTLORD then + softcap_armor = softcap_armor * LowChainLeatherACSoftcapReturn; + elseif defender_class == Class.WIZARD or defender_class == Class.MAGICIAN or defender_class == Class.NECROMANCER or defender_class == Class.ENCHANTER or defender_class == Class.DRUID then + softcap_armor = softcap_armor * CasterACSoftcapReturn; + else + softcap_armor = softcap_armor * MiscACSoftcapReturn; + end + else + if defender_class == Class.WARRIOR then + softcap_armor = softcap_armor * WarACSoftcapReturn; + elseif defender_class == Class.PALADIN or defender_class == Class.SHADOWKNIGHT then + softcap_armor = softcap_armor * PalShdACSoftcapReturn; + elseif defender_class == Class.CLERIC or defender_class == Class.RANGER or defender_class == Class.MONK or defender_class == Class.BARD then + softcap_armor = softcap_armor * ClrRngMnkBrdACSoftcapReturn; + elseif defender_class == Class.DRUID or defender_class == Class.NECROMANCER or defender_class == Class.WIZARD or defender_class == Class.ENCHANTER or defender_class == Class.MAGICIAN then + softcap_armor = softcap_armor * DruNecWizEncMagACSoftcapReturn; + elseif defender_class == Class.ROGUE or defender_class == Class.SHAMAN or defender_class == Class.BEASTLORD or defender_class == Class.BERSERKER then + softcap_armor = softcap_armor * RogShmBstBerACSoftcapReturn; + else + softcap_armor = softcap_armor * MiscACSoftcapReturn; + end + end + + armor = softcap + softcap_armor; + end + + local mitigation_rating; + if defender_class == Class.WIZARD or defender_class == Class.MAGICIAN or defender_class == Class.NECROMANCER or defender_class == Class.ENCHANTER then + mitigation_rating = ((defender:GetSkill(Skill.Defense) + defender:GetItemBonuses():HeroicAGI() / 10) / 4.0) + armor + 1; + else + mitigation_rating = ((defender:GetSkill(Skill.Defense) + defender:GetItemBonuses():HeroicAGI() / 10) / 3.0) + (armor * 1.333333) + 1; + end + + mitigation_rating = mitigation_rating * 0.847; + + local attack_rating; + if attacker:IsClient() then + attack_rating = (attacker:CastToClient():CalcATK() + ((attacker:GetSTR() - 66) * 0.9) + (attacker:GetSkill(Skill.Offense)*1.345)); + else + attack_rating = (attacker:GetATK() + (attacker:GetSkill(Skill.Offense)*1.345) + ((attacker:GetSTR() - 66) * 0.9)); + end + + hit.damage_done = GetMeleeMitDmg(defender, attacker, hit.damage_done, hit.min_damage, mitigation_rating, attack_rating); + + if hit.damage_done < 0 then + hit.damage_done = 0; + end + + return hit; +end + +function GetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) + if defender:IsClient() then + return ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating); + else + return MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating); + end +end + +function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) + if (not attacker:IsNPC() or UseOldDamageIntervalRules) then + return MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating); + end + + local d = 10; + local dmg_interval = (damage - min_damage) / 19.0; + local dmg_bonus = min_damage - dmg_interval; + local spellMeleeMit = (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100.0; + if (defender:GetClass() == Class.WARRIOR) then + spellMeleeMit = spellMeleeMit - 0.05; + end + + dmg_bonus = dmg_bonus - (dmg_bonus * (defender:GetItemBonuses():MeleeMitigation() / 100.0)); + dmg_interval = dmg_interval + (dmg_interval * spellMeleeMit); + + local mit_roll = Random.Real(0, mitigation_rating); + local atk_roll = Random.Real(0, attack_rating); + + if (atk_roll > mit_roll) then + local a_diff = atk_roll - mit_roll; + local thac0 = attack_rating * ACthac0Factor; + local thac0cap = attacker:GetLevel() * 9 + 20; + if (thac0 > thac0cap) then + thac0 = thac0cap; + end + + d = d + (10 * (a_diff / thac0)); + elseif (mit_roll > atk_roll) then + local m_diff = mit_roll - atk_roll; + local thac20 = mitigation_rating * ACthac20Factor; + local thac20cap = defender:GetLevel() * 9 + 20; + if (thac20 > thac20cap) then + thac20 = thac20cap; + end + + d = d - (10 * (m_diff / thac20)); + end + + if (d < 1) then + d = 1; + elseif (d > 20) then + d = 20; + end + + return math.floor(dmg_bonus + dmg_interval * d); +end + +function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) + local d = 10.0; + local mit_roll = Random.Real(0, mitigation_rating); + local atk_roll = Random.Real(0, attack_rating); + + if (atk_roll > mit_roll) then + local a_diff = atk_roll - mit_roll; + local thac0 = attack_rating * ACthac0Factor; + local thac0cap = attacker:GetLevel() * 9 + 20; + if (thac0 > thac0cap) then + thac0 = thac0cap; + end + + d = d - (10.0 * (a_diff / thac0)); + elseif (mit_roll > atk_roll) then + local m_diff = mit_roll - atk_roll; + local thac20 = mitigation_rating * ACthac20Factor; + local thac20cap = defender:GetLevel() * 9 + 20; + if (thac20 > thac20cap) then + thac20 = thac20cap; + end + + d = d + (10.0 * (m_diff / thac20)); + end + + if (d < 0.0) then + d = 0.0; + elseif (d > 20.0) then + d = 20.0; + end + + local interval = (damage - min_damage) / 20.0; + damage = damage - (math.floor(d) * interval); + damage = damage - (min_damage * defender:GetItemBonuses():MeleeMitigation() / 100); + damage = damage + (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100); + + return damage; +end + +function GetRawACNoShield(self) + self = self:CastToClient(); + + local ac = self:GetItemBonuses():AC() + self:GetSpellBonuses():AC() + self:GetAABonuses():AC(); + local shield_ac = 0; + local inst = self:GetInventory():GetItem(Slot.Secondary); + + if inst.valid then + if inst:GetItem():ItemType() == 8 then + shield_ac = inst:GetItem():AC(); + + for i = 1, 6 do + local augment = inst:GetAugment(i - 1); + if augment.valid then + shield_ac = shield_ac + augment:GetItem():AC(); + end + end + end + end + + ac = ac - shield_ac; + return ac, shield_ac; +end + +function GetDamageTable(attacker, skill) + if not attacker:IsClient() then + return 100; + end + + if attacker:GetLevel() <= 51 then + local ret_table = 0; + local str_over_75 = 0; + if attacker:GetSTR() > 75 then + str_over_75 = attacker:GetSTR() - 75; + end + + if str_over_75 > 255 then + ret_table = (attacker:GetSkill(skill) + 255) / 2; + else + ret_table = (attacker:GetSkill(skill) + str_over_75) / 2; + end + + if ret_table < 100 then + return 100; + end + + return ret_table; + elseif attacker:GetLevel() >= 90 then + if attacker:GetClass() == 7 then + return 379; + else + return 345; + end + else + local dmg_table = { 275, 275, 275, 275, 275, 280, 280, 280, 280, 285, 285, 285, 290, 290, 295, 295, 300, 300, 300, 305, 305, 305, 310, 310, 315, 315, 320, 320, 320, 325, 325, 325, 330, 330, 335, 335, 340, 340, 340 }; + + if attacker:GetClass() == 7 then + local monkDamageTableBonus = 20; + return (dmg_table[GetLevel() - 50] * (100 + monkDamageTableBonus) / 100); + else + return dmg_table[attacker:GetLevel() - 50]; + end + end + return 100; +end + +function ApplyDamageTable(e) + e.IgnoreDefault = true; + return e; +end + +function CommonOutgoingHitSuccess(e) + e = ApplyMeleeDamageBonus(e); + e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + (e.self:GetSkillDmgAmt(e.hit.skill) + e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill)); + e = TryCriticalHit(e); + e.self:CheckNumHitsRemaining(5, -1, 65535); + e.IgnoreDefault = true; + return e; +end + +function ApplyMeleeDamageBonus(e) + local dmgbonusmod = e.self:GetMeleeDamageMod_SE(e.hit.skill); + if (opts) then + dmgbonusmod = dmgbonusmod + e.opts.melee_damage_bonus_flat; + end + + e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100); + return e; +end \ No newline at end of file diff --git a/utils/mods/load_order.txt b/utils/mods/load_order.txt new file mode 100644 index 000000000..979674adb --- /dev/null +++ b/utils/mods/load_order.txt @@ -0,0 +1 @@ +legacy_combat.lua diff --git a/world/net.cpp b/world/net.cpp index df3749829..09511c3f2 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -392,12 +392,12 @@ int main(int argc, char** argv) { server_connection->Listen(server_opts); Log(Logs::General, Logs::World_Server, "Server (TCP) listener started."); - server_connection->OnConnectionIdentified("Zone", [](std::shared_ptr connection) { + server_connection->OnConnectionIdentified("Zone", [&console](std::shared_ptr connection) { LogF(Logs::General, Logs::World_Server, "New Zone Server connection from {2} at {0}:{1}", connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); numzones++; - zoneserver_list.Add(new ZoneServer(connection)); + zoneserver_list.Add(new ZoneServer(connection, console.get())); }); server_connection->OnConnectionRemoved("Zone", [](std::shared_ptr connection) { diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index d9c32a15f..4de771701 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -46,7 +46,7 @@ extern UCSConnection UCSLink; extern QueryServConnection QSLink; void CatchSignal(int sig_num); -ZoneServer::ZoneServer(std::shared_ptr connection) +ZoneServer::ZoneServer(std::shared_ptr connection, EQ::Net::ConsoleServer *console) : tcpc(connection), zone_boot_timer(5000) { /* Set Process tracking variable defaults */ @@ -73,6 +73,8 @@ ZoneServer::ZoneServer(std::shared_ptr conn zone_boot_timer.Disable(); } })); + + this->console = console; } ZoneServer::~ZoneServer() { @@ -412,6 +414,27 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { break; } if (scm->chan_num == 7 || scm->chan_num == 14) { + if (scm->deliverto[0] == '*') { + + if (console) { + auto con = console->FindByAccountName(&scm->deliverto[1]); + if (((!con) || (!con->SendChannelMessage(scm, [&scm]() { + auto pack = new ServerPacket(ServerOP_ChannelMessage, + sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); + memcpy(pack->pBuffer, scm, pack->size); + ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer; + strcpy(scm2->deliverto, scm2->from); + scm2->noreply = true; + client_list.SendPacket(scm->from, pack); + safe_delete(pack); + }))) && (!scm->noreply)) + { + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); + } + } + break; + } + ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { @@ -462,6 +485,20 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { cle->Server()->SendPacket(pack); } else { + if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) { + if (console) { + console->SendChannelMessage(scm, [&scm]() { + auto pack = new ServerPacket(ServerOP_ChannelMessage, + sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); + memcpy(pack->pBuffer, scm, pack->size); + ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer; + strcpy(scm2->deliverto, scm2->from); + scm2->noreply = true; + client_list.SendPacket(scm->from, pack); + safe_delete(pack); + }); + } + } zoneserver_list.SendPacket(pack); } break; diff --git a/world/zoneserver.h b/world/zoneserver.h index a6bbc8373..1f9e9516c 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -22,6 +22,7 @@ #include "../net/servertalk_server.h" #include "../event/timer.h" #include "../timer.h" +#include "console.h" #include #include @@ -31,7 +32,7 @@ class ServerPacket; class ZoneServer : public WorldTCPConnection { public: - ZoneServer(std::shared_ptr connection); + ZoneServer(std::shared_ptr connection, EQ::Net::ConsoleServer *console); ~ZoneServer(); virtual inline bool IsZoneServer() { return true; } @@ -97,6 +98,7 @@ private: uint32 zone_os_process_id; std::string launcher_name; //the launcher which started us std::string launched_name; //the name of the zone we launched. + EQ::Net::ConsoleServer *console; }; #endif diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index b267ae11b..0c2c9bd63 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -51,6 +51,7 @@ SET(zone_sources lua_item.cpp lua_iteminst.cpp lua_mob.cpp + lua_mod.cpp lua_npc.cpp lua_object.cpp lua_packet.cpp @@ -59,6 +60,7 @@ SET(zone_sources lua_raid.cpp lua_spawn.cpp lua_spell.cpp + lua_stat_bonuses.cpp embperl.cpp embxs.cpp entity.cpp @@ -173,6 +175,7 @@ SET(zone_headers lua_item.h lua_iteminst.h lua_mob.h + lua_mod.h lua_npc.h lua_object.h lua_packet.h @@ -182,6 +185,7 @@ SET(zone_headers lua_raid.h lua_spawn.h lua_spell.h + lua_stat_bonuses.h map.h masterentity.h maxskill.h diff --git a/zone/aa.cpp b/zone/aa.cpp index 51cb376da..31ad9c162 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -916,7 +916,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { void Client::SendAlternateAdvancementStats() { auto outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); + aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)GetRequiredAAExperience()); aps->unspent = m_pp.aapoints; aps->percentage = m_epp.perAA; QueuePacket(outapp); diff --git a/zone/attack.cpp b/zone/attack.cpp index 144578561..388a959c2 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "water_map.h" #include "worldserver.h" #include "zone.h" +#include "lua_parser.h" #include #include @@ -52,8 +53,9 @@ extern WorldServer worldserver; extern EntityList entity_list; extern Zone* zone; -bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const EQEmu::ItemInstance* weapon) +EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon) { + EQEmu::skills::SkillType skillinuse = EQEmu::skills::Skill1HBlunt; // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { @@ -137,7 +139,7 @@ bool Mob::AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const type = animDualWield; DoAnim(type, 0, false); - return true; + return skillinuse; } int Mob::compute_tohit(EQEmu::skills::SkillType skillinuse) @@ -271,6 +273,16 @@ int Mob::GetTotalDefense() // and does other mitigation checks. 'this' is the mob being attacked. bool Mob::CheckHitChance(Mob* other, DamageHitInfo &hit) { +#ifdef LUA_EQEMU + bool lua_ret = false; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->CheckHitChance(this, other, hit, ignoreDefault); + + if(ignoreDefault) { + return lua_ret; + } +#endif + Mob *attacker = other; Mob *defender = this; Log(Logs::Detail, Logs::Attack, "CheckHitChance(%s) attacked by %s", defender->GetName(), attacker->GetName()); @@ -301,6 +313,16 @@ bool Mob::CheckHitChance(Mob* other, DamageHitInfo &hit) bool Mob::AvoidDamage(Mob *other, DamageHitInfo &hit) { +#ifdef LUA_EQEMU + bool lua_ret = false; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->AvoidDamage(this, other, hit, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + /* called when a mob is attacked, does the checks to see if it's a hit * and does other mitigation checks. 'this' is the mob being attacked. * @@ -871,6 +893,15 @@ double Mob::RollD20(int offense, int mitigation) void Mob::MeleeMitigation(Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->MeleeMitigation(this, attacker, hit, opts, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if (hit.damage_done < 0 || hit.base_damage == 0) return; @@ -1237,6 +1268,7 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) return; Log(Logs::Detail, Logs::Combat, "%s::DoAttack vs %s base %d min %d offense %d tohit %d skill %d", GetName(), other->GetName(), hit.base_damage, hit.min_damage, hit.offense, hit.tohit, hit.skill); + // check to see if we hit.. if (other->AvoidDamage(this, hit)) { int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; @@ -1331,7 +1363,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b DamageHitInfo my_hit; // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients - AttackAnimation(my_hit.skill, Hand, weapon); + my_hit.skill = AttackAnimation(Hand, weapon); Log(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon ? weapon->GetItem()->Name : "Fist", Hand, my_hit.skill); // Now figure out damage @@ -1892,7 +1924,7 @@ bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool //do attack animation regardless of whether or not we can hit below int16 charges = 0; EQEmu::ItemInstance weapon_inst(weapon, charges); - AttackAnimation(my_hit.skill, Hand, &weapon_inst); + my_hit.skill = AttackAnimation(Hand, &weapon_inst); //basically "if not immune" then do the attack if (weapon_damage > 0) { @@ -2190,7 +2222,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil Group *kg = entity_list.GetGroupByClient(give_exp_client); Raid *kr = entity_list.GetRaidByClient(give_exp_client); - int32 finalxp = EXP_FORMULA; + int32 finalxp = give_exp_client->GetExperienceForKill(this); finalxp = give_exp_client->mod_client_xp(finalxp, this); if (kr) { @@ -2801,6 +2833,8 @@ uint8 Mob::GetWeaponDamageBonus(const EQEmu::ItemData *weapon, bool offhand) } return damage_bonus; } + + return 0; } int Mob::GetHandToHandDamage(void) @@ -4064,7 +4098,7 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) if (critChance > 0) { if (zone->random.Roll(critChance)) { - critMod += GetCritDmgMob(hit.skill); + critMod += GetCritDmgMod(hit.skill); hit.damage_done += 5; hit.damage_done = (hit.damage_done * critMod) / 100; @@ -4085,6 +4119,15 @@ void Mob::TryPetCriticalHit(Mob *defender, DamageHitInfo &hit) void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->TryCriticalHit(this, defender, hit, opts, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if (hit.damage_done < 1 || !defender) return; @@ -4193,7 +4236,11 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * // step 2: calculate damage hit.damage_done = std::max(hit.damage_done, hit.base_damage) + 5; int og_damage = hit.damage_done; - int crit_mod = 170 + GetCritDmgMob(hit.skill); + int crit_mod = 170 + GetCritDmgMod(hit.skill); + if (crit_mod < 100) { + crit_mod = 100; + } + hit.damage_done = hit.damage_done * crit_mod / 100; Log(Logs::Detail, Logs::Combat, "Crit success roll %d dex chance %d og dmg %d crit_mod %d new dmg %d", roll, dex_bonus, @@ -4254,7 +4301,7 @@ void Mob::TryCriticalHit(Mob *defender, DamageHitInfo &hit, ExtraAttackOptions * // Crippling blows also have a chance to stun // Kayen: Crippling Blow would cause a chance to interrupt for npcs < 55, with a // staggers message. - if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(IMMUNE_STUN)) { + if (defender->GetLevel() <= 55 && !defender->GetSpecialAbility(UNSTUNABLE)) { defender->Emote("staggers."); defender->Stun(2000); } @@ -4535,6 +4582,15 @@ const DamageTable &Mob::GetDamageTable() const void Mob::ApplyDamageTable(DamageHitInfo &hit) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->ApplyDamageTable(this, hit, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + // someone may want to add this to custom servers, can remove this if that's the case if (!IsClient() #ifdef BOTS @@ -4870,6 +4926,15 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac if (!defender) return; +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->CommonOutgoingHitSuccess(this, defender, hit, opts, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + // BER weren't parsing the halving if (hit.skill == EQEmu::skills::SkillArchery || (hit.skill == EQEmu::skills::SkillThrowing && GetClass() != BERSERKER)) diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 7544ceb5f..232b74b2a 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1084,9 +1084,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; // base1 = effect value, base2 = skill restrictions(-1 for all) if (base2 == ALL_SKILLS) - newbon->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += base1; + newbon->CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else - newbon->CritDmgMob[base2] += base1; + newbon->CritDmgMod[base2] += base1; break; } @@ -2441,9 +2441,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if(base2 == ALL_SKILLS) - new_bonus->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; + new_bonus->CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else - new_bonus->CritDmgMob[base2] += effect_value; + new_bonus->CritDmgMod[base2] += effect_value; break; } @@ -4203,9 +4203,9 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) { for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { - spellbonuses.CritDmgMob[e] = effect_value; - aabonuses.CritDmgMob[e] = effect_value; - itembonuses.CritDmgMob[e] = effect_value; + spellbonuses.CritDmgMod[e] = effect_value; + aabonuses.CritDmgMod[e] = effect_value; + itembonuses.CritDmgMod[e] = effect_value; } break; } diff --git a/zone/bot.cpp b/zone/bot.cpp index d87bd472e..fbed35a06 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -22,6 +22,7 @@ #include "object.h" #include "doors.h" #include "quest_parser_collection.h" +#include "lua_parser.h" #include "../common/string_util.h" #include "../common/say_link.h" @@ -3856,7 +3857,7 @@ void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic, pet_command); } -bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { +bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); @@ -3919,7 +3920,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients DamageHitInfo my_hit; - AttackAnimation(my_hit.skill, Hand, weapon); + my_hit.skill = AttackAnimation(Hand, weapon); Log(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); // Now figure out damage diff --git a/zone/client.cpp b/zone/client.cpp index 741b41e72..cecd22b45 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1255,6 +1255,37 @@ void Client::Message(uint32 type, const char* message, ...) { safe_delete_array(buffer); } +void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...) { + if (!FilteredMessageCheck(sender, filter)) + return; + + va_list argptr; + auto buffer = new char[4096]; + va_start(argptr, message); + vsnprintf(buffer, 4096, message, argptr); + va_end(argptr); + + size_t len = strlen(buffer); + + //client dosent like our packet all the time unless + //we make it really big, then it seems to not care that + //our header is malformed. + //len = 4096 - sizeof(SpecialMesg_Struct); + + uint32 len_packet = sizeof(SpecialMesg_Struct) + len; + auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet); + SpecialMesg_Struct* sm = (SpecialMesg_Struct*)app->pBuffer; + sm->header[0] = 0x00; // Header used for #emote style messages.. + sm->header[1] = 0x00; // Play around with these to see other types + sm->header[2] = 0x00; + sm->msg_type = type; + memcpy(sm->message, buffer, len + 1); + + FastQueuePacket(&app); + + safe_delete_array(buffer); +} + void Client::QuestJournalledMessage(const char *npcname, const char* message) { // npcnames longer than 60 characters crash the client when they log back in diff --git a/zone/client.h b/zone/client.h index 9ff541edc..50f36ba72 100644 --- a/zone/client.h +++ b/zone/client.h @@ -308,6 +308,7 @@ public: 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 Message(uint32 type, 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 SendSound(); @@ -570,6 +571,7 @@ public: void AddCrystals(uint32 Radiant, uint32 Ebon); void SendCrystalCounts(); + uint32 GetExperienceForKill(Mob *against); void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false); uint32 CalcEXP(uint8 conlevel = 0xFF); void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false); @@ -795,12 +797,12 @@ public: void AddAAPoints(uint32 points) { m_pp.aapoints += points; SendAlternateAdvancementStats(); } int GetAAPoints() { return m_pp.aapoints; } int GetSpentAA() { return m_pp.aapoints_spent; } + uint32 GetRequiredAAExperience(); //old AA methods that we still use void ResetAA(); void RefundAA(); void SendClearAA(); - inline uint32 GetMaxAAXP(void) const { return max_AAXP; } inline uint32 GetAAXP() const { return m_pp.expAA; } inline uint32 GetAAPercent() const { return m_epp.perAA; } int16 CalcAAFocus(focusType type, const AA::Rank &rank, uint16 spell_id); @@ -1261,6 +1263,8 @@ public: void CheckRegionTypeChanges(); + int32 CalcATK(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1320,7 +1324,6 @@ private: void HandleTraderPriceUpdate(const EQApplicationPacket *app); - int32 CalcATK(); int32 CalcItemATKCap(); int32 CalcHaste(); @@ -1491,7 +1494,6 @@ private: uint32 tribute_master_id; - uint32 max_AAXP; bool npcflag; uint8 npclevel; bool feigned; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 361c67d40..9249f5266 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1355,8 +1355,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; - /* Set Max AA XP */ - max_AAXP = RuleI(AA, ExpPerPoint); + /* If we can maintain intoxication across zones, check for it */ if (!RuleB(Character, MaintainIntoxicationAcrossZones)) m_pp.intoxication = 0; diff --git a/zone/common.h b/zone/common.h index 7b63174d4..7294c87dc 100644 --- a/zone/common.h +++ b/zone/common.h @@ -408,7 +408,7 @@ struct StatBonuses { uint32 SpellTriggers[MAX_SPELL_TRIGGER]; // Innate/Spell/Item Spells that trigger when you cast uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die - int32 CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 + int32 CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 SkillReuseTime[EQEmu::skills::HIGHEST_SKILL + 1]; // Reduces skill timers int32 SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon diff --git a/zone/entity.cpp b/zone/entity.cpp index 37af35fdb..5a8e9fa5e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2135,6 +2135,25 @@ void EntityList::MessageClose(Mob* sender, bool skipsender, float dist, uint32 t } } +void EntityList::FilteredMessageClose(Mob *sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char *message, ...) +{ + va_list argptr; + char buffer[4096]; + + va_start(argptr, message); + vsnprintf(buffer, 4095, message, argptr); + va_end(argptr); + + float dist2 = dist * dist; + + auto it = client_list.begin(); + while (it != client_list.end()) { + if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || it->second != sender)) + it->second->FilteredMessage(sender, type, filter, buffer); + ++it; + } +} + void EntityList::RemoveAllMobs() { auto it = mob_list.begin(); diff --git a/zone/entity.h b/zone/entity.h index 2f2237283..94078691a 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -79,6 +79,7 @@ public: virtual bool IsTrap() const { return false; } virtual bool IsBeacon() const { return false; } virtual bool IsEncounter() const { return false; } + virtual bool IsBot() const { return false; } virtual bool Process() { return false; } virtual bool Save() { return true; } @@ -113,7 +114,6 @@ public: bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1); #ifdef BOTS - virtual bool IsBot() const { return false; } Bot* CastToBot(); #endif @@ -315,6 +315,7 @@ public: void Message(uint32 to_guilddbid, uint32 type, const char* message, ...); void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...); void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...); + 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 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 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); diff --git a/zone/exp.cpp b/zone/exp.cpp index 044a102e0..7d9a02fa8 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -28,6 +28,7 @@ #include "queryserv.h" #include "quest_parser_collection.h" +#include "lua_parser.h" #include "string_ids.h" #ifdef BOTS @@ -153,6 +154,26 @@ uint32 Client::CalcEXP(uint8 conlevel) { return in_add_exp; } +uint32 Client::GetExperienceForKill(Mob *against) +{ +#ifdef LUA_EQEMU + uint32 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->GetExperienceForKill(this, against, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + + if (against && against->IsNPC()) { + uint32 level = (uint32)against->GetLevel(); + return EXP_FORMULA; + } + + return 0; +} + void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { this->EVENT_ITEM_ScriptStopReturn(); @@ -339,8 +360,8 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { Log(Logs::Detail, Logs::None, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false"); - //max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients - max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2() + + auto max_AAXP = GetRequiredAAExperience(); if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) { Message(13, "Error in Client::SetEXP. EXP not set."); return; // Must be invalid class/race @@ -377,19 +398,23 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { } if (isrezzexp) { - 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()); + 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()); else Message_StringID(MT_Experience, REZ_REGAIN); } else { if (membercount > 1) { - 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()); + 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()); else Message_StringID(MT_Experience, GAIN_GROUPXP); } else if (IsRaidGrouped()) { - 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()); + 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()); else Message_StringID(MT_Experience, GAIN_RAIDEXP); } else { - if (RuleI(Character, ShowExpValues) > 0) Message(MT_Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); + if (RuleI(Character, ShowExpValues) > 0) + Message(MT_Experience, "You have gained %s experience! %s", exp_amount_message.c_str(), exp_percent_message.c_str()); else Message_StringID(MT_Experience, GAIN_XP); } } @@ -460,14 +485,13 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { //add in how many points we had m_pp.aapoints += last_unspentAA; - //set_aaxp = m_pp.expAA % max_AAXP; //figure out how many points were actually gained /*uint32 gained = m_pp.aapoints - last_unspentAA;*/ //unused //Message(15, "You have gained %d skill points!!", m_pp.aapoints - last_unspentAA); 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. + 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. /* QS: PlayerLogAARate */ if (RuleB(QueryServ, PlayerLogAARate)){ @@ -571,8 +595,7 @@ void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { char val1[20]={0}; char val2[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). - //Message(15, "[GM] You now have %d / %d EXP and %d / %d AA exp.", set_exp, GetEXPForLevel(GetLevel()+1), set_aaxp, max_AAXP); + 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). } } @@ -664,6 +687,15 @@ void Client::SetLevel(uint8 set_level, bool command) // Add: You can set the values you want now, client will be always sync :) - Merkur uint32 Client::GetEXPForLevel(uint16 check_level) { +#ifdef LUA_EQEMU + uint32 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->GetEXPForLevel(this, check_level, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif uint16 check_levelm1 = check_level-1; float mod; @@ -933,3 +965,17 @@ uint32 Client::GetCharMaxLevelFromQGlobal() { return false; } + +uint32 Client::GetRequiredAAExperience() { +#ifdef LUA_EQEMU + uint32 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->GetRequiredAAExperience(this, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + + return RuleI(AA, ExpPerPoint); +} diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index dde90988c..64bf2321c 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1172,6 +1172,11 @@ uint64 Lua_Client::GetAllMoney() { return self->GetAllMoney(); } +uint32 Lua_Client::GetMoney(uint8 type, uint8 subtype) { + Lua_Safe_Call_Int(); + return self->GetMoney(type, subtype); +} + void Lua_Client::OpenLFGuildWindow() { Lua_Safe_Call_Void(); self->OpenLFGuildWindow(); @@ -1414,9 +1419,25 @@ void Lua_Client::QuestReward(Lua_Mob target, luabind::adl::object reward) { self->QuestReward(target, copper, silver, gold, platinum, itemid, exp, faction); } -uint32 Lua_Client::GetMoney(uint8 type, uint8 subtype) { +bool Lua_Client::IsDead() { + Lua_Safe_Call_Bool(); + return self->IsDead(); +} + +int Lua_Client::CalcCurrentWeight() { Lua_Safe_Call_Int(); - return self->GetMoney(type, subtype); + return self->CalcCurrentWeight(); +} + +int Lua_Client::CalcATK() { + Lua_Safe_Call_Int(); + return self->CalcATK(); +} + +void Lua_Client::FilteredMessage(Mob *sender, uint32 type, int filter, const char *message) +{ + Lua_Safe_Call_Void(); + self->FilteredMessage(sender, type, (eqFilterType)filter, message); } luabind::scope lua_register_client() { @@ -1653,6 +1674,7 @@ luabind::scope lua_register_client() { .def("GetAggroCount", (int(Lua_Client::*)(void))&Lua_Client::GetAggroCount) .def("GetCarriedMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetCarriedMoney) .def("GetAllMoney", (uint64(Lua_Client::*)(void))&Lua_Client::GetAllMoney) + .def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney) .def("OpenLFGuildWindow", (void(Lua_Client::*)(void))&Lua_Client::OpenLFGuildWindow) .def("Signal", (void(Lua_Client::*)(uint32))&Lua_Client::Signal) .def("AddAlternateCurrencyValue", (void(Lua_Client::*)(uint32,int))&Lua_Client::AddAlternateCurrencyValue) @@ -1687,7 +1709,10 @@ luabind::scope lua_register_client() { .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, uint32, uint32, uint32, uint32, uint32, uint32, bool))&Lua_Client::QuestReward) .def("QuestReward", (void(Lua_Client::*)(Lua_Mob, luabind::adl::object))&Lua_Client::QuestReward) - .def("GetMoney", (uint32(Lua_Client::*)(uint8, uint8))&Lua_Client::GetMoney); + .def("IsDead", &Lua_Client::IsDead) + .def("CalcCurrentWeight", &Lua_Client::CalcCurrentWeight) + .def("CalcATK", &Lua_Client::CalcATK) + .def("FilteredMessage", &Lua_Client::FilteredMessage); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index d7cf4f75f..f29e3b46f 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -297,6 +297,10 @@ public: void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp); void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction); void QuestReward(Lua_Mob target, luabind::adl::object reward); + bool IsDead(); + int CalcCurrentWeight(); + int CalcATK(); + void FilteredMessage(Mob *sender, uint32 type, int filter, const char* message); }; #endif diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index ea233af4b..725e78f5e 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -67,6 +67,16 @@ bool Lua_Entity::IsBeacon() { return self->IsBeacon(); } +bool Lua_Entity::IsEncounter() { + Lua_Safe_Call_Bool(); + return self->IsEncounter(); +} + +bool Lua_Entity::IsBot() { + Lua_Safe_Call_Bool(); + return self->IsBot(); +} + int Lua_Entity::GetID() { Lua_Safe_Call_Bool(); return self->GetID(); @@ -124,6 +134,8 @@ luabind::scope lua_register_entity() { .def("IsDoor", &Lua_Entity::IsDoor) .def("IsTrap", &Lua_Entity::IsTrap) .def("IsBeacon", &Lua_Entity::IsBeacon) + .def("IsEncounter", &Lua_Entity::IsEncounter) + .def("IsBot", &Lua_Entity::IsBot) .def("GetID", &Lua_Entity::GetID) .def("CastToClient", &Lua_Entity::CastToClient) .def("CastToNPC", &Lua_Entity::CastToNPC) diff --git a/zone/lua_entity.h b/zone/lua_entity.h index 7e3254ff3..b45208581 100644 --- a/zone/lua_entity.h +++ b/zone/lua_entity.h @@ -44,6 +44,8 @@ public: bool IsDoor(); bool IsTrap(); bool IsBeacon(); + bool IsEncounter(); + bool IsBot(); int GetID(); Lua_Client CastToClient(); diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index 7626a709b..ef4057ed1 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -210,6 +210,12 @@ void Lua_EntityList::MessageClose(Lua_Mob sender, bool skip_sender, float dist, self->MessageClose(sender, skip_sender, dist, type, message); } +void Lua_EntityList::FilteredMessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, int filter, const char *message) +{ + Lua_Safe_Call_Void(); + self->FilteredMessageClose(sender, skip_sender, dist, type, (eqFilterType)filter, message); +} + void Lua_EntityList::RemoveFromTargets(Lua_Mob mob) { Lua_Safe_Call_Void(); self->RemoveFromTargets(mob); @@ -450,16 +456,17 @@ luabind::scope lua_register_entity_list() { .def("GetSpawnByID", (Lua_Spawn(Lua_EntityList::*)(uint32))&Lua_EntityList::GetSpawnByID) .def("ClearClientPetitionQueue", (void(Lua_EntityList::*)(void))&Lua_EntityList::ClearClientPetitionQueue) .def("CanAddHateForMob", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::CanAddHateForMob) - .def("Message", (void(Lua_EntityList::*)(uint32,uint32,const char*))&Lua_EntityList::Message) - .def("MessageStatus", (void(Lua_EntityList::*)(uint32,uint32,uint32,const char*))&Lua_EntityList::MessageStatus) - .def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob,bool,float,uint32,const char*))&Lua_EntityList::MessageClose) + .def("Message", (void(Lua_EntityList::*)(uint32, uint32, const char*))&Lua_EntityList::Message) + .def("MessageStatus", (void(Lua_EntityList::*)(uint32, uint32, uint32, const char*))&Lua_EntityList::MessageStatus) + .def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob, bool, float, uint32, const char*))&Lua_EntityList::MessageClose) + .def("FilteredMessageClose", &Lua_EntityList::FilteredMessageClose) .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::RemoveFromTargets) - .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob,bool))&Lua_EntityList::RemoveFromTargets) - .def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob,Lua_Mob))&Lua_EntityList::ReplaceWithTarget) + .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromTargets) + .def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob))&Lua_EntityList::ReplaceWithTarget) .def("OpenDoorsNear", (void(Lua_EntityList::*)(Lua_NPC))&Lua_EntityList::OpenDoorsNear) .def("MakeNameUnique", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::MakeNameUnique) .def("RemoveNumbers", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::RemoveNumbers) - .def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32,int))&Lua_EntityList::SignalMobsByNPCID) + .def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalMobsByNPCID) .def("DeleteNPCCorpses", (int(Lua_EntityList::*)(void))&Lua_EntityList::DeleteNPCCorpses) .def("DeletePlayerCorpses", (int(Lua_EntityList::*)(void))&Lua_EntityList::DeletePlayerCorpses) .def("HalveAggro", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::HalveAggro) @@ -467,10 +474,10 @@ luabind::scope lua_register_entity_list() { .def("ClearFeignAggro", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::ClearFeignAggro) .def("Fighting", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::Fighting) .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::RemoveFromHateLists) - .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob,bool))&Lua_EntityList::RemoveFromHateLists) - .def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob,bool,uint32,const char*))&Lua_EntityList::MessageGroup) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomClient) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float,Lua_Client))&Lua_EntityList::GetRandomClient) + .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromHateLists) + .def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob, bool, uint32, const char*))&Lua_EntityList::MessageGroup) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float))&Lua_EntityList::GetRandomClient) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float, Lua_Client))&Lua_EntityList::GetRandomClient) .def("GetMobList", (Lua_Mob_List(Lua_EntityList::*)(void))&Lua_EntityList::GetMobList) .def("GetClientList", (Lua_Client_List(Lua_EntityList::*)(void))&Lua_EntityList::GetClientList) .def("GetNPCList", (Lua_NPC_List(Lua_EntityList::*)(void))&Lua_EntityList::GetNPCList) @@ -479,7 +486,7 @@ luabind::scope lua_register_entity_list() { .def("GetDoorsList", (Lua_Doors_List(Lua_EntityList::*)(void))&Lua_EntityList::GetDoorsList) .def("GetSpawnList", (Lua_Spawn_List(Lua_EntityList::*)(void))&Lua_EntityList::GetSpawnList) .def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients) - .def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob,int,int,const char*))&Lua_EntityList::ChannelMessage); + .def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob, int, int, const char*))&Lua_EntityList::ChannelMessage); } luabind::scope lua_register_mob_list() { diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index 823499f24..17b00579e 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -80,6 +80,7 @@ public: void Message(uint32 guild_dbid, uint32 type, const char *message); void MessageStatus(uint32 guild_dbid, int min_status, uint32 type, const char *message); void MessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, const char *message); + void FilteredMessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, int filter, const char *message); void RemoveFromTargets(Lua_Mob mob); void RemoveFromTargets(Lua_Mob mob, bool RemoveFromXTargets); void ReplaceWithTarget(Lua_Mob target, Lua_Mob new_target); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index c635f8b2a..aad0be464 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -7,6 +7,10 @@ #include #include +#include "../common/timer.h" +#include "../common/eqemu_logsys.h" +#include "../common/classes.h" +#include "../common/rulesys.h" #include "lua_parser.h" #include "lua_item.h" #include "lua_iteminst.h" @@ -16,8 +20,6 @@ #include "quest_parser_collection.h" #include "questmgr.h" #include "qglobals.h" -#include "../common/timer.h" -#include "../common/eqemu_logsys.h" #include "encounter.h" #include "lua_encounter.h" @@ -27,6 +29,12 @@ struct Slots { }; struct Materials { }; struct ClientVersions { }; struct Appearances { }; +struct Classes { }; +struct Skills { }; +struct BodyTypes { }; +struct Filters { }; +struct MessageTypes { }; +struct Rule { }; struct lua_registered_event { std::string encounter_name; @@ -1462,6 +1470,39 @@ void lua_create_npc(luabind::adl::object table, float x, float y, float z, float npc->GiveNPCTypeData(npc_type); entity_list.AddNPC(npc); } + +int random_int(int low, int high) { + return zone->random.Int(low, high); +} + +double random_real(double low, double high) { + return zone->random.Real(low, high); +} + +bool random_roll_int(int required) { + return zone->random.Roll(required); +} + +bool random_roll_real(double required) { + return zone->random.Roll(required); +} + +int random_roll0(int max) { + return zone->random.Roll0(max); +} + +int get_rulei(int rule) { + return RuleManager::Instance()->GetIntRule((RuleManager::IntType)rule); +} + +float get_ruler(int rule) { + return RuleManager::Instance()->GetRealRule((RuleManager::RealType)rule); +} + +bool get_ruleb(int rule) { + return RuleManager::Instance()->GetBoolRule((RuleManager::BoolType)rule); +} + luabind::scope lua_register_general() { return luabind::namespace_("eq") [ @@ -1663,6 +1704,18 @@ luabind::scope lua_register_general() { ]; } +luabind::scope lua_register_random() { + return luabind::namespace_("Random") + [ + luabind::def("Int", &random_int), + luabind::def("Real", &random_real), + luabind::def("Roll", &random_roll_int), + luabind::def("RollReal", &random_roll_real), + luabind::def("Roll0", &random_roll0) + ]; +} + + luabind::scope lua_register_events() { return luabind::class_("Event") .enum_("constants") @@ -1863,4 +1916,355 @@ luabind::scope lua_register_appearance() { ]; } +luabind::scope lua_register_classes() { + return luabind::class_("Class") + .enum_("constants") + [ + luabind::value("WARRIOR", WARRIOR), + luabind::value("CLERIC", CLERIC), + luabind::value("PALADIN", PALADIN), + luabind::value("RANGER", RANGER), + luabind::value("SHADOWKNIGHT", SHADOWKNIGHT), + luabind::value("DRUID", DRUID), + luabind::value("MONK", MONK), + luabind::value("BARD", BARD), + luabind::value("ROGUE", ROGUE), + luabind::value("SHAMAN", SHAMAN), + luabind::value("NECROMANCER", NECROMANCER), + luabind::value("WIZARD", WIZARD), + luabind::value("MAGICIAN", MAGICIAN), + luabind::value("ENCHANTER", ENCHANTER), + luabind::value("BEASTLORD", BEASTLORD), + luabind::value("BERSERKER", BERSERKER), + luabind::value("WARRIORGM", WARRIORGM), + luabind::value("CLERICGM", CLERICGM), + luabind::value("PALADINGM", PALADINGM), + luabind::value("RANGERGM", RANGERGM), + luabind::value("SHADOWKNIGHTGM", SHADOWKNIGHTGM), + luabind::value("DRUIDGM", DRUIDGM), + luabind::value("MONKGM", MONKGM), + luabind::value("BARDGM", BARDGM), + luabind::value("ROGUEGM", ROGUEGM), + luabind::value("SHAMANGM", SHAMANGM), + luabind::value("NECROMANCERGM", NECROMANCERGM), + luabind::value("WIZARDGM", WIZARDGM), + luabind::value("MAGICIANGM", MAGICIANGM), + luabind::value("ENCHANTERGM", ENCHANTERGM), + luabind::value("BEASTLORDGM", BEASTLORDGM), + luabind::value("BERSERKERGM", BERSERKERGM), + luabind::value("BANKER", BANKER), + luabind::value("MERCHANT", MERCHANT), + luabind::value("DISCORD_MERCHANT", DISCORD_MERCHANT), + luabind::value("ADVENTURERECRUITER", ADVENTURERECRUITER), + luabind::value("ADVENTUREMERCHANT", ADVENTUREMERCHANT), + luabind::value("LDON_TREASURE", LDON_TREASURE), + luabind::value("CORPSE_CLASS", CORPSE_CLASS), + luabind::value("TRIBUTE_MASTER", TRIBUTE_MASTER), + luabind::value("GUILD_TRIBUTE_MASTER", GUILD_TRIBUTE_MASTER), + luabind::value("NORRATHS_KEEPERS_MERCHANT", NORRATHS_KEEPERS_MERCHANT), + luabind::value("DARK_REIGN_MERCHANT", DARK_REIGN_MERCHANT), + luabind::value("FELLOWSHIP_MASTER", FELLOWSHIP_MASTER), + luabind::value("ALT_CURRENCY_MERCHANT", ALT_CURRENCY_MERCHANT), + luabind::value("MERCERNARY_MASTER", MERCERNARY_MASTER) + ]; +} + +luabind::scope lua_register_skills() { + return luabind::class_("Skill") + .enum_("constants") + [ + luabind::value("1HBlunt", EQEmu::skills::Skill1HBlunt), + luabind::value("1HSlashing", EQEmu::skills::Skill1HSlashing), + luabind::value("2HBlunt", EQEmu::skills::Skill2HBlunt), + luabind::value("2HSlashing", EQEmu::skills::Skill2HSlashing), + luabind::value("Abjuration", EQEmu::skills::SkillAbjuration), + luabind::value("Alteration", EQEmu::skills::SkillAlteration), + luabind::value("ApplyPoison", EQEmu::skills::SkillApplyPoison), + luabind::value("Archery", EQEmu::skills::SkillArchery), + luabind::value("Backstab", EQEmu::skills::SkillBackstab), + luabind::value("BindWound", EQEmu::skills::SkillBindWound), + luabind::value("Bash", EQEmu::skills::SkillBash), + luabind::value("Block", EQEmu::skills::SkillBlock), + luabind::value("BrassInstruments", EQEmu::skills::SkillBrassInstruments), + luabind::value("Channeling", EQEmu::skills::SkillChanneling), + luabind::value("Conjuration", EQEmu::skills::SkillConjuration), + luabind::value("Defense", EQEmu::skills::SkillDefense), + luabind::value("Disarm", EQEmu::skills::SkillDisarm), + luabind::value("DisarmTraps", EQEmu::skills::SkillDisarmTraps), + luabind::value("Divination", EQEmu::skills::SkillDivination), + luabind::value("Dodge", EQEmu::skills::SkillDodge), + luabind::value("DoubleAttack", EQEmu::skills::SkillDoubleAttack), + luabind::value("DragonPunch", EQEmu::skills::SkillDragonPunch), + luabind::value("TailRake", EQEmu::skills::SkillTailRake), + luabind::value("DualWield", EQEmu::skills::SkillDualWield), + luabind::value("EagleStrike", EQEmu::skills::SkillEagleStrike), + luabind::value("Evocation", EQEmu::skills::SkillEvocation), + luabind::value("FeignDeath", EQEmu::skills::SkillFeignDeath), + luabind::value("FlyingKick", EQEmu::skills::SkillFlyingKick), + luabind::value("Forage", EQEmu::skills::SkillForage), + luabind::value("HandtoHand", EQEmu::skills::SkillHandtoHand), + luabind::value("Hide", EQEmu::skills::SkillHide), + luabind::value("Kick", EQEmu::skills::SkillKick), + luabind::value("Meditate", EQEmu::skills::SkillMeditate), + luabind::value("Mend", EQEmu::skills::SkillMend), + luabind::value("Offense", EQEmu::skills::SkillOffense), + luabind::value("Parry", EQEmu::skills::SkillParry), + luabind::value("PickLock", EQEmu::skills::SkillPickLock), + luabind::value("1HPiercing", EQEmu::skills::Skill1HPiercing), + luabind::value("Riposte", EQEmu::skills::SkillRiposte), + luabind::value("RoundKick", EQEmu::skills::SkillRoundKick), + luabind::value("SafeFall", EQEmu::skills::SkillSafeFall), + luabind::value("SenseHeading", EQEmu::skills::SkillSenseHeading), + luabind::value("Singing", EQEmu::skills::SkillSinging), + luabind::value("Sneak", EQEmu::skills::SkillSneak), + luabind::value("SpecializeAbjure", EQEmu::skills::SkillSpecializeAbjure), + luabind::value("SpecializeAlteration", EQEmu::skills::SkillSpecializeAlteration), + luabind::value("SpecializeConjuration", EQEmu::skills::SkillSpecializeConjuration), + luabind::value("SpecializeDivination", EQEmu::skills::SkillSpecializeDivination), + luabind::value("SpecializeEvocation", EQEmu::skills::SkillSpecializeEvocation), + luabind::value("PickPockets", EQEmu::skills::SkillPickPockets), + luabind::value("StringedInstruments", EQEmu::skills::SkillStringedInstruments), + luabind::value("Swimming", EQEmu::skills::SkillSwimming), + luabind::value("Throwing", EQEmu::skills::SkillThrowing), + luabind::value("TigerClaw", EQEmu::skills::SkillTigerClaw), + luabind::value("Tracking", EQEmu::skills::SkillTracking), + luabind::value("WindInstruments", EQEmu::skills::SkillWindInstruments), + luabind::value("Fishing", EQEmu::skills::SkillFishing), + luabind::value("MakePoison", EQEmu::skills::SkillMakePoison), + luabind::value("Tinkering", EQEmu::skills::SkillTinkering), + luabind::value("Research", EQEmu::skills::SkillResearch), + luabind::value("Alchemy", EQEmu::skills::SkillAlchemy), + luabind::value("Baking", EQEmu::skills::SkillBaking), + luabind::value("Tailoring", EQEmu::skills::SkillTailoring), + luabind::value("SenseTraps", EQEmu::skills::SkillSenseTraps), + luabind::value("Blacksmithing", EQEmu::skills::SkillBlacksmithing), + luabind::value("Fletching", EQEmu::skills::SkillFletching), + luabind::value("Brewing", EQEmu::skills::SkillBrewing), + luabind::value("AlcoholTolerance", EQEmu::skills::SkillAlcoholTolerance), + luabind::value("Begging", EQEmu::skills::SkillBegging), + luabind::value("JewelryMaking", EQEmu::skills::SkillJewelryMaking), + luabind::value("Pottery", EQEmu::skills::SkillPottery), + luabind::value("PercussionInstruments", EQEmu::skills::SkillPercussionInstruments), + luabind::value("Intimidation", EQEmu::skills::SkillIntimidation), + luabind::value("Berserking", EQEmu::skills::SkillBerserking), + luabind::value("Taunt", EQEmu::skills::SkillTaunt), + luabind::value("Frenzy", EQEmu::skills::SkillFrenzy), + luabind::value("RemoveTraps", EQEmu::skills::SkillRemoveTraps), + luabind::value("TripleAttack", EQEmu::skills::SkillTripleAttack), + luabind::value("2HPiercing", EQEmu::skills::Skill2HPiercing), + luabind::value("HIGHEST_SKILL", EQEmu::skills::HIGHEST_SKILL) + ]; +} + +luabind::scope lua_register_bodytypes() { + return luabind::class_("BT") + .enum_("constants") + [ + luabind::value("Humanoid", 1), + luabind::value("Lycanthrope", 2), + luabind::value("Undead", 3), + luabind::value("Giant", 4), + luabind::value("Construct", 5), + luabind::value("Extraplanar", 6), + luabind::value("Magical", 7), + luabind::value("SummonedUndead", 8), + luabind::value("RaidGiant", 9), + luabind::value("NoTarget", 11), + luabind::value("Vampire", 12), + luabind::value("Atenha_Ra", 13), + luabind::value("Greater_Akheva", 14), + luabind::value("Khati_Sha", 15), + luabind::value("Seru", 16), + luabind::value("Draz_Nurakk", 18), + luabind::value("Zek", 19), + luabind::value("Luggald", 20), + luabind::value("Animal", 21), + luabind::value("Insect", 22), + luabind::value("Monster", 23), + luabind::value("Summoned", 24), + luabind::value("Plant", 25), + luabind::value("Dragon", 26), + luabind::value("Summoned2", 27), + luabind::value("Summoned3", 28), + luabind::value("VeliousDragon", 30), + luabind::value("Dragon3", 32), + luabind::value("Boxes", 33), + luabind::value("Muramite", 34), + luabind::value("NoTarget2", 60), + luabind::value("SwarmPet", 63), + luabind::value("InvisMan", 66), + luabind::value("Special", 67) + ]; +} + +luabind::scope lua_register_filters() { + return luabind::class_("Filter") + .enum_("constants") + [ + luabind::value("None", FilterNone), + luabind::value("GuildChat", FilterGuildChat), + luabind::value("Socials", FilterSocials), + luabind::value("GroupChat", FilterGroupChat), + luabind::value("Shouts", FilterShouts), + luabind::value("Auctions", FilterAuctions), + luabind::value("OOC", FilterOOC), + luabind::value("BadWords", FilterBadWords), + luabind::value("PCSpells", FilterPCSpells), + luabind::value("NPCSpells", FilterNPCSpells), + luabind::value("BardSongs", FilterBardSongs), + luabind::value("SpellCrits", FilterSpellCrits), + luabind::value("MeleeCrits", FilterMeleeCrits), + luabind::value("SpellDamage", FilterSpellDamage), + luabind::value("MyMisses", FilterMyMisses), + luabind::value("OthersMiss", FilterOthersMiss), + luabind::value("OthersHit", FilterOthersHit), + luabind::value("MissedMe", FilterMissedMe), + luabind::value("DamageShields", FilterDamageShields), + luabind::value("DOT", FilterDOT), + luabind::value("PetHits", FilterPetHits), + luabind::value("PetMisses", FilterPetMisses), + luabind::value("FocusEffects", FilterFocusEffects), + luabind::value("PetSpells", FilterPetSpells), + luabind::value("HealOverTime", FilterHealOverTime), + luabind::value("Unknown25", FilterUnknown25), + luabind::value("Unknown26", FilterUnknown26), + luabind::value("Unknown27", FilterUnknown27), + luabind::value("Unknown28", FilterUnknown28) + ]; +} + +luabind::scope lua_register_message_types() { + return luabind::class_("MT") + .enum_("constants") + [ + luabind::value("Say", MT_Say), + luabind::value("Tell", MT_Tell), + luabind::value("Group", MT_Group), + luabind::value("Guild", MT_Guild), + luabind::value("OOC", MT_OOC), + luabind::value("Auction", MT_Auction), + luabind::value("Shout", MT_Shout), + luabind::value("Emote", MT_Emote), + luabind::value("Spells", MT_Spells), + luabind::value("YouHitOther", MT_YouHitOther), + luabind::value("OtherHitsYou", MT_OtherHitsYou), + luabind::value("YouMissOther", MT_YouMissOther), + luabind::value("OtherMissesYou", MT_OtherMissesYou), + luabind::value("Broadcasts", MT_Broadcasts), + luabind::value("Skills", MT_Skills), + luabind::value("Disciplines", MT_Disciplines), + luabind::value("Unused1", MT_Unused1), + luabind::value("DefaultText", MT_DefaultText), + luabind::value("Unused2", MT_Unused2), + luabind::value("MerchantOffer", MT_MerchantOffer), + luabind::value("MerchantBuySell", MT_MerchantBuySell), + luabind::value("YourDeath", MT_YourDeath), + luabind::value("OtherDeath", MT_OtherDeath), + luabind::value("OtherHits", MT_OtherHits), + luabind::value("OtherMisses", MT_OtherMisses), + luabind::value("Who", MT_Who), + luabind::value("YellForHelp", MT_YellForHelp), + luabind::value("NonMelee", MT_NonMelee), + luabind::value("WornOff", MT_WornOff), + luabind::value("MoneySplit", MT_MoneySplit), + luabind::value("LootMessages", MT_LootMessages), + luabind::value("DiceRoll", MT_DiceRoll), + luabind::value("OtherSpells", MT_OtherSpells), + luabind::value("SpellFailure", MT_SpellFailure), + luabind::value("Chat", MT_Chat), + luabind::value("Channel1", MT_Channel1), + luabind::value("Channel2", MT_Channel2), + luabind::value("Channel3", MT_Channel3), + luabind::value("Channel4", MT_Channel4), + luabind::value("Channel5", MT_Channel5), + luabind::value("Channel6", MT_Channel6), + luabind::value("Channel7", MT_Channel7), + luabind::value("Channel8", MT_Channel8), + luabind::value("Channel9", MT_Channel9), + luabind::value("Channel10", MT_Channel10), + luabind::value("CritMelee", MT_CritMelee), + luabind::value("SpellCrits", MT_SpellCrits), + luabind::value("TooFarAway", MT_TooFarAway), + luabind::value("NPCRampage", MT_NPCRampage), + luabind::value("NPCFlurry", MT_NPCFlurry), + luabind::value("NPCEnrage", MT_NPCEnrage), + luabind::value("SayEcho", MT_SayEcho), + luabind::value("TellEcho", MT_TellEcho), + luabind::value("GroupEcho", MT_GroupEcho), + luabind::value("GuildEcho", MT_GuildEcho), + luabind::value("OOCEcho", MT_OOCEcho), + luabind::value("AuctionEcho", MT_AuctionEcho), + luabind::value("ShoutECho", MT_ShoutECho), + luabind::value("EmoteEcho", MT_EmoteEcho), + luabind::value("Chat1Echo", MT_Chat1Echo), + luabind::value("Chat2Echo", MT_Chat2Echo), + luabind::value("Chat3Echo", MT_Chat3Echo), + luabind::value("Chat4Echo", MT_Chat4Echo), + luabind::value("Chat5Echo", MT_Chat5Echo), + luabind::value("Chat6Echo", MT_Chat6Echo), + luabind::value("Chat7Echo", MT_Chat7Echo), + luabind::value("Chat8Echo", MT_Chat8Echo), + luabind::value("Chat9Echo", MT_Chat9Echo), + luabind::value("Chat10Echo", MT_Chat10Echo), + luabind::value("DoTDamage", MT_DoTDamage), + luabind::value("ItemLink", MT_ItemLink), + luabind::value("RaidSay", MT_RaidSay), + luabind::value("MyPet", MT_MyPet), + luabind::value("DS", MT_DS), + luabind::value("Leadership", MT_Leadership), + luabind::value("PetFlurry", MT_PetFlurry), + luabind::value("PetCrit", MT_PetCrit), + luabind::value("FocusEffect", MT_FocusEffect), + luabind::value("Experience", MT_Experience), + luabind::value("System", MT_System), + luabind::value("PetSpell", MT_PetSpell), + luabind::value("PetResponse", MT_PetResponse), + luabind::value("ItemSpeech", MT_ItemSpeech), + luabind::value("StrikeThrough", MT_StrikeThrough), + luabind::value("Stun", MT_Stun) + ]; +} + +luabind::scope lua_register_rules_const() { + return luabind::class_("Rule") + .enum_("constants") + [ +#define RULE_INT(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Int__##rule), +#include "../common/ruletypes.h" + luabind::value("_IntRuleCount", RuleManager::_IntRuleCount), +#undef RULE_INT +#define RULE_REAL(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Real__##rule), +#include "../common/ruletypes.h" + luabind::value("_RealRuleCount", RuleManager::_RealRuleCount), +#undef RULE_REAL +#define RULE_BOOL(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Bool__##rule), +#include "../common/ruletypes.h" + luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount) + ]; +} + +luabind::scope lua_register_rulei() { + return luabind::namespace_("RuleI") + [ + luabind::def("Get", &get_rulei) + ]; +} + +luabind::scope lua_register_ruler() { + return luabind::namespace_("RuleR") + [ + luabind::def("Get", &get_ruler) + ]; +} + +luabind::scope lua_register_ruleb() { + return luabind::namespace_("RuleB") + [ + luabind::def("Get", &get_ruleb) + ]; +} + #endif diff --git a/zone/lua_general.h b/zone/lua_general.h index eb117cfc6..4c8b7f8d2 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -3,12 +3,22 @@ #ifdef LUA_EQEMU luabind::scope lua_register_general(); +luabind::scope lua_register_random(); luabind::scope lua_register_events(); luabind::scope lua_register_faction(); luabind::scope lua_register_slot(); luabind::scope lua_register_material(); luabind::scope lua_register_client_version(); luabind::scope lua_register_appearance(); +luabind::scope lua_register_classes(); +luabind::scope lua_register_skills(); +luabind::scope lua_register_bodytypes(); +luabind::scope lua_register_filters(); +luabind::scope lua_register_message_types(); +luabind::scope lua_register_rules_const(); +luabind::scope lua_register_rulei(); +luabind::scope lua_register_ruler(); +luabind::scope lua_register_ruleb(); #endif -#endif \ No newline at end of file +#endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 190db1f18..18651edea 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -10,6 +10,7 @@ #include "lua_mob.h" #include "lua_hate_list.h" #include "lua_client.h" +#include "lua_stat_bonuses.h" struct SpecialAbilities { }; @@ -1725,6 +1726,18 @@ int Lua_Mob::GetSkillDmgTaken(int skill) { return self->GetSkillDmgTaken(static_cast(skill)); } +int Lua_Mob::GetFcDamageAmtIncoming(Lua_Mob caster, uint32 spell_id, bool use_skill, uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetFcDamageAmtIncoming(caster, spell_id, use_skill, skill); +} + +int Lua_Mob::GetSkillDmgAmt(uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetSkillDmgAmt(skill); +} + void Lua_Mob::SetAllowBeneficial(bool value) { Lua_Safe_Call_Void(); self->SetAllowBeneficial(value); @@ -1985,6 +1998,89 @@ int32 Lua_Mob::GetMeleeMitigation() { return self->GetMeleeMitigation(); } +int Lua_Mob::GetWeaponDamageBonus(Lua_Item weapon, bool offhand) { + Lua_Safe_Call_Int(); + return self->GetWeaponDamageBonus(weapon, offhand); +} + +Lua_StatBonuses Lua_Mob::GetItemBonuses() +{ + Lua_Safe_Call_Class(Lua_StatBonuses); + return self->GetItemBonusesPtr(); +} + +Lua_StatBonuses Lua_Mob::GetSpellBonuses() +{ + Lua_Safe_Call_Class(Lua_StatBonuses); + return self->GetSpellBonusesPtr(); +} + +Lua_StatBonuses Lua_Mob::GetAABonuses() +{ + Lua_Safe_Call_Class(Lua_StatBonuses); + return self->GetAABonusesPtr(); +} + +int16 Lua_Mob::GetMeleeDamageMod_SE(uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetMeleeDamageMod_SE(skill); +} + +int16 Lua_Mob::GetMeleeMinDamageMod_SE(uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetMeleeMinDamageMod_SE(skill); +} + +bool Lua_Mob::IsAttackAllowed(Lua_Mob target, bool isSpellAttack) { + Lua_Safe_Call_Bool(); + return self->IsAttackAllowed(target, isSpellAttack); +} + +bool Lua_Mob::IsCasting() { + Lua_Safe_Call_Bool(); + return self->IsCasting(); +} + +int Lua_Mob::AttackAnimation(int Hand, Lua_ItemInst weapon) { + Lua_Safe_Call_Int(); + return (int)self->AttackAnimation(Hand, weapon); +} + +int Lua_Mob::GetWeaponDamage(Lua_Mob against, Lua_ItemInst weapon) { + Lua_Safe_Call_Int(); + return self->GetWeaponDamage(against, weapon); +} + +bool Lua_Mob::IsBerserk() { + Lua_Safe_Call_Bool(); + return self->IsBerserk(); +} + +bool Lua_Mob::TryFinishingBlow(Lua_Mob defender, int &damage) { + Lua_Safe_Call_Bool(); + return self->TryFinishingBlow(defender, damage); +} + +int Lua_Mob::GetBodyType() +{ + Lua_Safe_Call_Int(); + return (int)self->GetBodyType(); +} + +int Lua_Mob::GetOrigBodyType() +{ + Lua_Safe_Call_Int(); + return (int)self->GetOrigBodyType(); +} + +void Lua_Mob::CheckNumHitsRemaining(int type, int32 buff_slot, uint16 spell_id) +{ + Lua_Safe_Call_Void(); + self->CheckNumHitsRemaining((NumHit)type, buff_slot, spell_id); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2281,6 +2377,8 @@ luabind::scope lua_register_mob() { .def("ModSkillDmgTaken", (void(Lua_Mob::*)(int,int))&Lua_Mob::ModSkillDmgTaken) .def("GetModSkillDmgTaken", (int(Lua_Mob::*)(int))&Lua_Mob::GetModSkillDmgTaken) .def("GetSkillDmgTaken", (int(Lua_Mob::*)(int))&Lua_Mob::GetSkillDmgTaken) + .def("GetFcDamageAmtIncoming", &Lua_Mob::GetFcDamageAmtIncoming) + .def("GetSkillDmgAmt", (int(Lua_Mob::*)(int))&Lua_Mob::GetSkillDmgAmt) .def("SetAllowBeneficial", (void(Lua_Mob::*)(bool))&Lua_Mob::SetAllowBeneficial) .def("GetAllowBeneficial", (bool(Lua_Mob::*)(void))&Lua_Mob::GetAllowBeneficial) .def("IsBeneficialAllowed", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsBeneficialAllowed) @@ -2330,7 +2428,22 @@ luabind::scope lua_register_mob() { .def("HasPet", (bool(Lua_Mob::*)(void))&Lua_Mob::HasPet) .def("IsSilenced", (bool(Lua_Mob::*)(void))&Lua_Mob::IsSilenced) .def("IsAmnesiad", (bool(Lua_Mob::*)(void))&Lua_Mob::IsAmnesiad) - .def("GetMeleeMitigation", (int32(Lua_Mob::*)(void))&Lua_Mob::GetMeleeMitigation); + .def("GetMeleeMitigation", (int32(Lua_Mob::*)(void))&Lua_Mob::GetMeleeMitigation) + .def("GetWeaponDamageBonus", &Lua_Mob::GetWeaponDamageBonus) + .def("GetItemBonuses", &Lua_Mob::GetItemBonuses) + .def("GetSpellBonuses", &Lua_Mob::GetSpellBonuses) + .def("GetAABonuses", &Lua_Mob::GetAABonuses) + .def("GetMeleeDamageMod_SE", &Lua_Mob::GetMeleeDamageMod_SE) + .def("GetMeleeMinDamageMod_SE", &Lua_Mob::GetMeleeMinDamageMod_SE) + .def("IsAttackAllowed", &Lua_Mob::IsAttackAllowed) + .def("IsCasting", &Lua_Mob::IsCasting) + .def("AttackAnimation", &Lua_Mob::AttackAnimation) + .def("GetWeaponDamage", &Lua_Mob::GetWeaponDamage) + .def("IsBerserk", &Lua_Mob::IsBerserk) + .def("TryFinishingBlow", &Lua_Mob::TryFinishingBlow) + .def("GetBodyType", &Lua_Mob::GetBodyType) + .def("GetOrigBodyType", &Lua_Mob::GetOrigBodyType) + .def("CheckNumHitsRemaining", &Lua_Mob::CheckNumHitsRemaining); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 08502b1a9..c54deb6bc 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -8,6 +8,7 @@ class Mob; struct Lua_HateList; class Lua_Item; class Lua_ItemInst; +class Lua_StatBonuses; namespace luabind { struct scope; @@ -330,6 +331,8 @@ public: void ModSkillDmgTaken(int skill, int value); int GetModSkillDmgTaken(int skill); int GetSkillDmgTaken(int skill); + int GetFcDamageAmtIncoming(Lua_Mob caster, uint32 spell_id, bool use_skill, uint16 skill); + int GetSkillDmgAmt(uint16 skill); void SetAllowBeneficial(bool value); bool GetAllowBeneficial(); bool IsBeneficialAllowed(Lua_Mob target); @@ -340,7 +343,6 @@ public: void SetFlurryChance(int value); int GetFlurryChance(); int GetSkill(int skill_id); - void CalcBonuses(); int GetSpecialAbility(int ability); int GetSpecialAbilityParam(int ability, int param); void SetSpecialAbility(int ability, int level); @@ -381,6 +383,21 @@ public: bool IsSilenced(); bool IsAmnesiad(); int32 GetMeleeMitigation(); + int GetWeaponDamageBonus(Lua_Item weapon, bool offhand); + Lua_StatBonuses GetItemBonuses(); + Lua_StatBonuses GetSpellBonuses(); + Lua_StatBonuses GetAABonuses(); + int16 GetMeleeDamageMod_SE(uint16 skill); + int16 GetMeleeMinDamageMod_SE(uint16 skill); + bool IsAttackAllowed(Lua_Mob target, bool isSpellAttack); + bool IsCasting(); + int AttackAnimation(int Hand, Lua_ItemInst weapon); + int GetWeaponDamage(Lua_Mob against, Lua_ItemInst weapon); + bool IsBerserk(); + bool TryFinishingBlow(Lua_Mob defender, int &damage); + int GetBodyType(); + int GetOrigBodyType(); + void CheckNumHitsRemaining(int type, int32 buff_slot, uint16 spell_id); }; #endif diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp new file mode 100644 index 000000000..a891fb064 --- /dev/null +++ b/zone/lua_mod.cpp @@ -0,0 +1,631 @@ +#include "lua.hpp" +#include +#include + +#include "../common/spdat.h" +#include "masterentity.h" +#include "questmgr.h" +#include "zone.h" +#include "zone_config.h" + +#include "lua_parser.h" +#include "lua_mod.h" +#include "lua_bit.h" +#include "lua_entity.h" +#include "lua_item.h" +#include "lua_iteminst.h" +#include "lua_mob.h" +#include "lua_hate_list.h" +#include "lua_client.h" +#include "lua_inventory.h" +#include "lua_npc.h" +#include "lua_spell.h" +#include "lua_entity_list.h" +#include "lua_group.h" +#include "lua_raid.h" +#include "lua_corpse.h" +#include "lua_object.h" +#include "lua_door.h" +#include "lua_spawn.h" +#include "lua_packet.h" +#include "lua_general.h" +#include "lua_encounter.h" +#include "lua_stat_bonuses.h" + +void LuaMod::Init() +{ + m_has_melee_mitigation = parser_->HasFunction("MeleeMitigation", package_name_); + m_has_apply_damage_table = parser_->HasFunction("ApplyDamageTable", package_name_); + m_has_avoid_damage = parser_->HasFunction("AvoidDamage", package_name_); + m_has_check_hit_chance = parser_->HasFunction("CheckHitChance", package_name_); + m_has_try_critical_hit = parser_->HasFunction("TryCriticalHit", package_name_); + m_has_get_required_aa_experience = parser_->HasFunction("GetRequiredAAExperience", package_name_); + m_has_get_exp_for_level = parser_->HasFunction("GetEXPForLevel", package_name_); + m_has_get_experience_for_kill = parser_->HasFunction("GetExperienceForKill", package_name_); + m_has_common_outgoing_hit_success = parser_->HasFunction("CommonOutgoingHitSuccess", package_name_); +} + +void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) { + luabind::adl::object lua_hit = luabind::newtable(L); + lua_hit["base_damage"] = hit.base_damage; + lua_hit["min_damage"] = hit.min_damage; + lua_hit["damage_done"] = hit.damage_done; + lua_hit["offense"] = hit.offense; + lua_hit["tohit"] = hit.tohit; + lua_hit["hand"] = hit.hand; + lua_hit["skill"] = (int)hit.skill; + e["hit"] = lua_hit; +} + +void GetDamageHitInfo(luabind::adl::object &ret, DamageHitInfo &hit) { + auto luaHitTable = ret["hit"]; + if (luabind::type(luaHitTable) == LUA_TTABLE) { + auto base_damage = luaHitTable["base_damage"]; + auto min_damage = luaHitTable["min_damage"]; + auto damage_done = luaHitTable["damage_done"]; + auto offense = luaHitTable["offense"]; + auto tohit = luaHitTable["tohit"]; + auto hand = luaHitTable["hand"]; + auto skill = luaHitTable["skill"]; + + if (luabind::type(base_damage) == LUA_TNUMBER) { + hit.base_damage = luabind::object_cast(base_damage); + } + + if (luabind::type(min_damage) == LUA_TNUMBER) { + hit.min_damage = luabind::object_cast(min_damage); + } + + if (luabind::type(damage_done) == LUA_TNUMBER) { + hit.damage_done = luabind::object_cast(damage_done); + } + + if (luabind::type(offense) == LUA_TNUMBER) { + hit.offense = luabind::object_cast(offense); + } + + if (luabind::type(tohit) == LUA_TNUMBER) { + hit.tohit = luabind::object_cast(tohit); + } + + if (luabind::type(hand) == LUA_TNUMBER) { + hit.hand = luabind::object_cast(hand); + } + + if (luabind::type(skill) == LUA_TNUMBER) { + hit.skill = (EQEmu::skills::SkillType)luabind::object_cast(skill); + } + } +} + +void PutExtraAttackOptions(lua_State *L, luabind::adl::object &e, ExtraAttackOptions *opts) { + if (opts) { + luabind::adl::object lua_opts = luabind::newtable(L); + lua_opts["damage_percent"] = opts->damage_percent; + lua_opts["damage_flat"] = opts->damage_flat; + lua_opts["armor_pen_percent"] = opts->armor_pen_percent; + lua_opts["armor_pen_flat"] = opts->armor_pen_flat; + lua_opts["crit_percent"] = opts->crit_percent; + lua_opts["crit_flat"] = opts->crit_flat; + lua_opts["hate_percent"] = opts->hate_percent; + lua_opts["hate_flat"] = opts->hate_flat; + lua_opts["hit_chance"] = opts->hit_chance; + lua_opts["melee_damage_bonus_flat"] = opts->melee_damage_bonus_flat; + lua_opts["skilldmgtaken_bonus_flat"] = opts->skilldmgtaken_bonus_flat; + e["opts"] = lua_opts; + } +} + +void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) { + if (opts) { + auto luaOptsTable = ret["opts"]; + if (luabind::type(luaOptsTable) == LUA_TTABLE) { + auto damage_percent = luaOptsTable["damage_percent"]; + auto damage_flat = luaOptsTable["damage_flat"]; + auto armor_pen_percent = luaOptsTable["armor_pen_percent"]; + auto armor_pen_flat = luaOptsTable["armor_pen_flat"]; + auto crit_percent = luaOptsTable["crit_percent"]; + auto crit_flat = luaOptsTable["crit_flat"]; + auto hate_percent = luaOptsTable["hate_percent"]; + auto hate_flat = luaOptsTable["hate_flat"]; + auto hit_chance = luaOptsTable["hit_chance"]; + auto melee_damage_bonus_flat = luaOptsTable["melee_damage_bonus_flat"]; + auto skilldmgtaken_bonus_flat = luaOptsTable["skilldmgtaken_bonus_flat"]; + + if (luabind::type(damage_percent) == LUA_TNUMBER) { + opts->damage_percent = luabind::object_cast(damage_percent); + } + + if (luabind::type(damage_flat) == LUA_TNUMBER) { + opts->damage_flat = luabind::object_cast(damage_flat); + } + + if (luabind::type(armor_pen_percent) == LUA_TNUMBER) { + opts->armor_pen_percent = luabind::object_cast(armor_pen_percent); + } + + if (luabind::type(armor_pen_flat) == LUA_TNUMBER) { + opts->armor_pen_flat = luabind::object_cast(armor_pen_flat); + } + + if (luabind::type(crit_percent) == LUA_TNUMBER) { + opts->crit_percent = luabind::object_cast(crit_percent); + } + + if (luabind::type(crit_flat) == LUA_TNUMBER) { + opts->crit_flat = luabind::object_cast(crit_flat); + } + + if (luabind::type(hate_percent) == LUA_TNUMBER) { + opts->hate_percent = luabind::object_cast(hate_percent); + } + + if (luabind::type(hate_flat) == LUA_TNUMBER) { + opts->hate_flat = luabind::object_cast(hate_flat); + } + + if (luabind::type(hit_chance) == LUA_TNUMBER) { + opts->hit_chance = luabind::object_cast(hit_chance); + } + + if (luabind::type(melee_damage_bonus_flat) == LUA_TNUMBER) { + opts->melee_damage_bonus_flat = luabind::object_cast(melee_damage_bonus_flat); + } + + if (luabind::type(skilldmgtaken_bonus_flat) == LUA_TNUMBER) { + opts->skilldmgtaken_bonus_flat = luabind::object_cast(skilldmgtaken_bonus_flat); + } + } + } +} + +void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_melee_mitigation) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "MeleeMitigation"); + + Lua_Mob l_self(self); + Lua_Mob l_other(attacker); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_apply_damage_table) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "ApplyDamageTable"); + + Lua_Mob l_self(self); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + + PutDamageHitInfo(L, e, hit); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_avoid_damage) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "AvoidDamage"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + returnValue = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_check_hit_chance) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "CheckHitChance"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + returnValue = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + int start = lua_gettop(L); + + try { + if (!m_has_common_outgoing_hit_success) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "CommonOutgoingHitSuccess"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_try_critical_hit) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "TryCriticalHit"); + + Lua_Mob l_self(self); + Lua_Mob l_other(defender); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ignoreDefault) +{ + int start = lua_gettop(L); + + try { + if (!m_has_get_required_aa_experience) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "GetRequiredAAExperience"); + + Lua_Client l_self(self); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + returnValue = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, bool &ignoreDefault) { + int start = lua_gettop(L); + + try { + if (!m_has_get_exp_for_level) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "GetEXPForLevel"); + + Lua_Client l_self(self); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["level"] = level; + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + returnValue = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValue, bool &ignoreDefault) +{ + int start = lua_gettop(L); + uint32 retval = 0; + + try { + if (!m_has_get_experience_for_kill) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "GetExperienceForKill"); + + Lua_Client l_self(self); + Lua_Mob l_other(against); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + returnValue = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} diff --git a/zone/lua_mod.h b/zone/lua_mod.h new file mode 100644 index 000000000..defc5edab --- /dev/null +++ b/zone/lua_mod.h @@ -0,0 +1,43 @@ +#pragma once + +#include + +struct lua_State; + +class LuaParser; +class LuaMod +{ +public: + LuaMod(lua_State *ls, LuaParser *lp, const std::string &package_name) { + L = ls; + parser_ = lp; + package_name_ = package_name; + Init(); + } + ~LuaMod() { } + void Init(); + + void MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + void ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault); + void AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault); + void CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault); + void CommonOutgoingHitSuccess(Mob *self, Mob* other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + void GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ignoreDefault); + void GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, bool &ignoreDefault); + void GetExperienceForKill(Client *self, Mob *against, uint32 &returnValue, bool &ignoreDefault); +private: + LuaParser *parser_; + lua_State *L; + std::string package_name_; + + bool m_has_melee_mitigation; + bool m_has_apply_damage_table; + bool m_has_avoid_damage; + bool m_has_check_hit_chance; + bool m_has_common_outgoing_hit_success; + bool m_has_try_critical_hit; + bool m_has_get_required_aa_experience; + bool m_has_get_exp_for_level; + bool m_has_get_experience_for_kill; +}; diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 9ed705496..50ff597f6 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -498,6 +498,17 @@ uint8 Lua_NPC::GetMerchantProbability() { return self->GetMerchantProbability(); } +int Lua_NPC::GetRawAC() { + Lua_Safe_Call_Int(); + return self->GetRawAC(); +} + +int Lua_NPC::GetAvoidanceRating() +{ + Lua_Safe_Call_Int(); + return self->GetAvoidanceRating(); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -598,7 +609,9 @@ luabind::scope lua_register_npc() { .def("MerchantOpenShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantOpenShop) .def("MerchantCloseShop", (void(Lua_NPC::*)(void))&Lua_NPC::MerchantCloseShop) .def("SetMerchantProbability", (void(Lua_NPC::*)(void))&Lua_NPC::SetMerchantProbability) - .def("GetMerchantProbability", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetMerchantProbability); + .def("GetMerchantProbability", (uint8(Lua_NPC::*)(void))&Lua_NPC::GetMerchantProbability) + .def("GetRawAC", (int(Lua_NPC::*)(void))&Lua_NPC::GetRawAC) + .def("GetAvoidanceRating", &Lua_NPC::GetAvoidanceRating); } #endif diff --git a/zone/lua_npc.h b/zone/lua_npc.h index e355c3e4d..d3d673641 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -125,6 +125,8 @@ public: void MerchantCloseShop(); void SetMerchantProbability(uint8 amt); uint8 GetMerchantProbability(); + int GetRawAC(); + int GetAvoidanceRating(); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index edd4d71db..dda4b2d23 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -10,8 +10,13 @@ #include #include -#include "masterentity.h" #include "../common/spdat.h" +#include "masterentity.h" +#include "questmgr.h" +#include "zone.h" +#include "zone_config.h" + +#include "lua_parser.h" #include "lua_bit.h" #include "lua_entity.h" #include "lua_item.h" @@ -31,11 +36,8 @@ #include "lua_spawn.h" #include "lua_packet.h" #include "lua_general.h" -#include "questmgr.h" -#include "zone.h" -#include "zone_config.h" -#include "lua_parser.h" #include "lua_encounter.h" +#include "lua_stat_bonuses.h" const char *LuaEvents[_LargestEventID] = { "event_say", @@ -799,12 +801,14 @@ void LuaParser::Init() { void LuaParser::ReloadQuests() { loaded_.clear(); errors_.clear(); + mods_.clear(); lua_encounter_events_registered.clear(); lua_encounters_loaded.clear(); for (auto encounter : lua_encounters) { encounter.second->Depop(); } + lua_encounters.clear(); // so the Depop function above depends on the Process being called again so ... // And there is situations where it wouldn't be :P @@ -817,6 +821,8 @@ void LuaParser::ReloadQuests() { L = luaL_newstate(); luaL_openlibs(L); + auto top = lua_gettop(L); + if(luaopen_bit(L) != 1) { std::string error = lua_tostring(L, -1); AddError(error); @@ -830,7 +836,7 @@ void LuaParser::ReloadQuests() { #ifdef SANITIZE_LUA_LIBS //io lua_pushnil(L); - lua_setglobal(L, "io"); + //lua_setglobal(L, "io"); //some os/debug are okay some are not lua_getglobal(L, "os"); @@ -933,24 +939,48 @@ void LuaParser::ReloadQuests() { std::string error = lua_tostring(L, -1); AddError(error); } - - return; } + else { + zone_script = Config->QuestDir; + zone_script += "/"; + zone_script += zone->GetShortName(); + zone_script += "/script_init.lua"; + f = fopen(zone_script.c_str(), "r"); + if (f) { + fclose(f); - zone_script = Config->QuestDir; - zone_script += "/"; - zone_script += zone->GetShortName(); - zone_script += "/script_init.lua"; - f = fopen(zone_script.c_str(), "r"); - if(f) { - fclose(f); - - if(luaL_dofile(L, zone_script.c_str())) { - std::string error = lua_tostring(L, -1); - AddError(error); + if (luaL_dofile(L, zone_script.c_str())) { + std::string error = lua_tostring(L, -1); + AddError(error); + } } } } + + FILE *load_order = fopen("mods/load_order.txt", "r"); + if (load_order) { + char file_name[256] = { 0 }; + while (fgets(file_name, 256, load_order) != nullptr) { + for (int i = 0; i < 256; ++i) { + auto c = file_name[i]; + if (c == '\n' || c == '\r' || c == ' ') { + file_name[i] = 0; + break; + } + } + + LoadScript("mods/" + std::string(file_name), file_name); + mods_.push_back(LuaMod(L, this, file_name)); + } + + fclose(load_order); + } + + auto end = lua_gettop(L); + int n = end - top; + if (n > 0) { + lua_pop(L, n); + } } void LuaParser::LoadScript(std::string filename, std::string package_name) { @@ -959,6 +989,7 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) { return; } + auto top = lua_gettop(L); if(luaL_loadfile(L, filename.c_str())) { std::string error = lua_tostring(L, -1); AddError(error); @@ -986,14 +1017,20 @@ void LuaParser::LoadScript(std::string filename, std::string package_name) { std::string error = lua_tostring(L, -1); AddError(error); lua_pop(L, 1); - return; + } + else { + loaded_[package_name] = true; } - loaded_[package_name] = true; + auto end = lua_gettop(L); + int n = end - top; + if (n > 0) { + lua_pop(L, n); + } } bool LuaParser::HasFunction(std::string subname, std::string package_name) { - std::transform(subname.begin(), subname.end(), subname.begin(), ::tolower); + //std::transform(subname.begin(), subname.end(), subname.begin(), ::tolower); auto iter = loaded_.find(package_name); if(iter == loaded_.end()) { @@ -1020,12 +1057,18 @@ void LuaParser::MapFunctions(lua_State *L) { luabind::module(L) [ lua_register_general(), + lua_register_random(), lua_register_events(), lua_register_faction(), lua_register_slot(), lua_register_material(), lua_register_client_version(), lua_register_appearance(), + lua_register_classes(), + lua_register_skills(), + lua_register_bodytypes(), + lua_register_filters(), + lua_register_message_types(), lua_register_entity(), lua_register_encounter(), lua_register_mob(), @@ -1054,7 +1097,12 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_door(), lua_register_object(), lua_register_packet(), - lua_register_packet_opcodes() + lua_register_packet_opcodes(), + lua_register_stat_bonuses(), + lua_register_rules_const(), + lua_register_rulei(), + lua_register_ruler(), + lua_register_ruleb() ]; } catch(std::exception &ex) { @@ -1251,3 +1299,76 @@ QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { } #endif + +void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.MeleeMitigation(self, attacker, hit, opts, ignoreDefault); + } +} + +void LuaParser::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.ApplyDamageTable(self, hit, ignoreDefault); + } +} + +bool LuaParser::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool & ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + mod.AvoidDamage(self, other, hit, retval, ignoreDefault); + } + return retval; +} + +bool LuaParser::CheckHitChance(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + mod.CheckHitChance(self, other, hit, retval, ignoreDefault); + } + return retval; +} + +void LuaParser::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.TryCriticalHit(self, defender, hit, opts, ignoreDefault); + } +} + +void LuaParser::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.CommonOutgoingHitSuccess(self, other, hit, opts, ignoreDefault); + } +} + +uint32 LuaParser::GetRequiredAAExperience(Client *self, bool &ignoreDefault) +{ + uint32 retval = 0; + for (auto &mod : mods_) { + mod.GetRequiredAAExperience(self, retval, ignoreDefault); + } + return retval; +} + +uint32 LuaParser::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) +{ + uint32 retval = 0; + for (auto &mod : mods_) { + mod.GetEXPForLevel(self, level, retval, ignoreDefault); + } + return retval; +} + +uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) +{ + uint32 retval = 0; + for (auto &mod : mods_) { + mod.GetExperienceForKill(self, against, retval, ignoreDefault); + } + return retval; +} diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 003c936ce..eb57faa96 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -7,8 +7,10 @@ #include #include #include +#include #include "zone_config.h" +#include "lua_mod.h" extern const ZoneConfig *Config; @@ -32,7 +34,6 @@ namespace luabind { class LuaParser : public QuestInterface { public: - LuaParser(); ~LuaParser(); virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, @@ -81,7 +82,29 @@ public: virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); + static LuaParser* Instance() { + static LuaParser inst; + return &inst; + } + + bool HasFunction(std::string function, std::string package_name); + + //Mod Extensions + void MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + void ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault); + bool AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault); + bool CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault); + void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + void CommonOutgoingHitSuccess(Mob *self, Mob* other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); + uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); + uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault); + private: + LuaParser(); + LuaParser(const LuaParser&); + LuaParser& operator=(const LuaParser&); + int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, @@ -94,13 +117,12 @@ private: std::vector *extra_pointers); void LoadScript(std::string filename, std::string package_name); - bool HasFunction(std::string function, std::string package_name); - void ClearStates(); void MapFunctions(lua_State *L); QuestEventID ConvertLuaEvent(QuestEventID evt); std::map vars_; std::map loaded_; + std::vector mods_; lua_State *L; NPCArgumentHandler NPCArgumentDispatch[_LargestEventID]; diff --git a/zone/lua_ptr.h b/zone/lua_ptr.h index 11478f093..d337059ae 100644 --- a/zone/lua_ptr.h +++ b/zone/lua_ptr.h @@ -2,13 +2,21 @@ #define EQEMU_LUA_PTR_H #ifdef LUA_EQEMU -//TODO: Remove the error checking by a flag since this adds significant overhead to each c call +#ifndef EQEMU_UNSAFE_LUA #define Lua_Safe_Call_Void() if(!d_) { return; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Int() if(!d_) { return 0; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Real() if(!d_) { return 0.0; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_String() if(!d_) { return ""; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Class(type) if(!d_) { return type(); } NativeType *self = reinterpret_cast(d_) +#else +#define Lua_Safe_Call_Void() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Bool() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Int() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Real() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_String() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Class(type) NativeType *self = reinterpret_cast(d_) +#endif template class Lua_Ptr diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp new file mode 100644 index 000000000..e1fb329cc --- /dev/null +++ b/zone/lua_stat_bonuses.cpp @@ -0,0 +1,1539 @@ +#include "lua.hpp" +#include + +#include "lua_stat_bonuses.h" + +int32 Lua_StatBonuses::GetAC() const { + Lua_Safe_Call_Int(); + return self->AC; +} + +int32 Lua_StatBonuses::GetHP() const { + Lua_Safe_Call_Int(); + return self->HP; +} + +int32 Lua_StatBonuses::GetHPRegen() const { + Lua_Safe_Call_Int(); + return self->HPRegen; +} + +int32 Lua_StatBonuses::GetMaxHP() const { + Lua_Safe_Call_Int(); + return self->MaxHP; +} + +int32 Lua_StatBonuses::GetManaRegen() const { + Lua_Safe_Call_Int(); + return self->ManaRegen; +} + +int32 Lua_StatBonuses::GetEnduranceRegen() const { + Lua_Safe_Call_Int(); + return self->EnduranceRegen; +} + +int32 Lua_StatBonuses::GetMana() const { + Lua_Safe_Call_Int(); + return self->Mana; +} + +int32 Lua_StatBonuses::GetEndurance() const { + Lua_Safe_Call_Int(); + return self->Endurance; +} + +int32 Lua_StatBonuses::GetATK() const { + Lua_Safe_Call_Int(); + return self->ATK; +} + +int32 Lua_StatBonuses::GetSTR() const { + Lua_Safe_Call_Int(); + return self->STR; +} + +int32 Lua_StatBonuses::GetSTRCapMod() const { + Lua_Safe_Call_Int(); + return self->STRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicSTR() const { + Lua_Safe_Call_Int(); + return self->HeroicSTR; +} + +int32 Lua_StatBonuses::GetSTA() const { + Lua_Safe_Call_Int(); + return self->STA; +} + +int32 Lua_StatBonuses::GetSTACapMod() const { + Lua_Safe_Call_Int(); + return self->STACapMod; +} + +int32 Lua_StatBonuses::GetHeroicSTA() const { + Lua_Safe_Call_Int(); + return self->HeroicSTA; +} + +int32 Lua_StatBonuses::GetDEX() const { + Lua_Safe_Call_Int(); + return self->DEX; +} + +int32 Lua_StatBonuses::GetDEXCapMod() const { + Lua_Safe_Call_Int(); + return self->DEXCapMod; +} + +int32 Lua_StatBonuses::GetHeroicDEX() const { + Lua_Safe_Call_Int(); + return self->HeroicDEX; +} + +int32 Lua_StatBonuses::GetAGI() const { + Lua_Safe_Call_Int(); + return self->AGI; +} + +int32 Lua_StatBonuses::GetAGICapMod() const { + Lua_Safe_Call_Int(); + return self->AGICapMod; +} + +int32 Lua_StatBonuses::GetHeroicAGI() const { + Lua_Safe_Call_Int(); + return self->HeroicAGI; +} + +int32 Lua_StatBonuses::GetINT() const { + Lua_Safe_Call_Int(); + return self->INT; +} + +int32 Lua_StatBonuses::GetINTCapMod() const { + Lua_Safe_Call_Int(); + return self->INTCapMod; +} + +int32 Lua_StatBonuses::GetHeroicINT() const { + Lua_Safe_Call_Int(); + return self->HeroicINT; +} + +int32 Lua_StatBonuses::GetWIS() const { + Lua_Safe_Call_Int(); + return self->WIS; +} + +int32 Lua_StatBonuses::GetWISCapMod() const { + Lua_Safe_Call_Int(); + return self->WISCapMod; +} + +int32 Lua_StatBonuses::GetHeroicWIS() const { + Lua_Safe_Call_Int(); + return self->HeroicWIS; +} + +int32 Lua_StatBonuses::GetCHA() const { + Lua_Safe_Call_Int(); + return self->CHA; +} + +int32 Lua_StatBonuses::GetCHACapMod() const { + Lua_Safe_Call_Int(); + return self->CHACapMod; +} + +int32 Lua_StatBonuses::GetHeroicCHA() const { + Lua_Safe_Call_Int(); + return self->HeroicCHA; +} + +int32 Lua_StatBonuses::GetMR() const { + Lua_Safe_Call_Int(); + return self->MR; +} + +int32 Lua_StatBonuses::GetMRCapMod() const { + Lua_Safe_Call_Int(); + return self->MRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicMR() const { + Lua_Safe_Call_Int(); + return self->HeroicMR; +} + +int32 Lua_StatBonuses::GetFR() const { + Lua_Safe_Call_Int(); + return self->FR; +} + +int32 Lua_StatBonuses::GetFRCapMod() const { + Lua_Safe_Call_Int(); + return self->FRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicFR() const { + Lua_Safe_Call_Int(); + return self->HeroicFR; +} + +int32 Lua_StatBonuses::GetCR() const { + Lua_Safe_Call_Int(); + return self->CR; +} + +int32 Lua_StatBonuses::GetCRCapMod() const { + Lua_Safe_Call_Int(); + return self->CRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicCR() const { + Lua_Safe_Call_Int(); + return self->HeroicCR; +} + +int32 Lua_StatBonuses::GetPR() const { + Lua_Safe_Call_Int(); + return self->PR; +} + +int32 Lua_StatBonuses::GetPRCapMod() const { + Lua_Safe_Call_Int(); + return self->PRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicPR() const { + Lua_Safe_Call_Int(); + return self->HeroicPR; +} + +int32 Lua_StatBonuses::GetDR() const { + Lua_Safe_Call_Int(); + return self->DR; +} + +int32 Lua_StatBonuses::GetDRCapMod() const { + Lua_Safe_Call_Int(); + return self->DRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicDR() const { + Lua_Safe_Call_Int(); + return self->HeroicDR; +} + +int32 Lua_StatBonuses::GetCorrup() const { + Lua_Safe_Call_Int(); + return self->Corrup; +} + +int32 Lua_StatBonuses::GetCorrupCapMod() const { + Lua_Safe_Call_Int(); + return self->CorrupCapMod; +} + +int32 Lua_StatBonuses::GetHeroicCorrup() const { + Lua_Safe_Call_Int(); + return self->HeroicCorrup; +} + +uint16 Lua_StatBonuses::GetDamageShieldSpellID() const { + Lua_Safe_Call_Int(); + return self->DamageShieldSpellID; +} + +int Lua_StatBonuses::GetDamageShield() const { + Lua_Safe_Call_Int(); + return self->DamageShield; +} + +int Lua_StatBonuses::GetDamageShieldType() const { + Lua_Safe_Call_Int(); + return self->DamageShieldType; +} + +int Lua_StatBonuses::GetSpellDamageShield() const { + Lua_Safe_Call_Int(); + return self->SpellDamageShield; +} + +int Lua_StatBonuses::GetSpellShield() const { + Lua_Safe_Call_Int(); + return self->SpellShield; +} + +int Lua_StatBonuses::GetReverseDamageShield() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShield; +} + +uint16 Lua_StatBonuses::GetReverseDamageShieldSpellID() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShieldSpellID; +} + +int Lua_StatBonuses::GetReverseDamageShieldType() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShieldType; +} + +int Lua_StatBonuses::Getmovementspeed() const { + Lua_Safe_Call_Int(); + return self->movementspeed; +} + +int32 Lua_StatBonuses::Gethaste() const { + Lua_Safe_Call_Int(); + return self->haste; +} + +int32 Lua_StatBonuses::Gethastetype2() const { + Lua_Safe_Call_Int(); + return self->hastetype2; +} + +int32 Lua_StatBonuses::Gethastetype3() const { + Lua_Safe_Call_Int(); + return self->hastetype3; +} + +int32 Lua_StatBonuses::Getinhibitmelee() const { + Lua_Safe_Call_Int(); + return self->inhibitmelee; +} + +float Lua_StatBonuses::GetAggroRange() const { + Lua_Safe_Call_Real(); + return self->AggroRange; +} + +float Lua_StatBonuses::GetAssistRange() const { + Lua_Safe_Call_Real(); + return self->AssistRange; +} + +int32 Lua_StatBonuses::Getskillmod(int idx) const { + Lua_Safe_Call_Int(); + return self->skillmod[idx]; +} + +int32 Lua_StatBonuses::Getskillmodmax(int idx) const { + Lua_Safe_Call_Int(); + return self->skillmodmax[idx]; +} + +int Lua_StatBonuses::Geteffective_casting_level() const { + Lua_Safe_Call_Int(); + return self->effective_casting_level; +} + +int Lua_StatBonuses::Getreflect_chance() const { + Lua_Safe_Call_Int(); + return self->reflect_chance; +} + +uint32 Lua_StatBonuses::GetsingingMod() const { + Lua_Safe_Call_Int(); + return self->singingMod; +} + +uint32 Lua_StatBonuses::GetAmplification() const { + Lua_Safe_Call_Int(); + return self->Amplification; +} + +uint32 Lua_StatBonuses::GetbrassMod() const { + Lua_Safe_Call_Int(); + return self->brassMod; +} + +uint32 Lua_StatBonuses::GetpercussionMod() const { + Lua_Safe_Call_Int(); + return self->percussionMod; +} + +uint32 Lua_StatBonuses::GetwindMod() const { + Lua_Safe_Call_Int(); + return self->windMod; +} + +uint32 Lua_StatBonuses::GetstringedMod() const { + Lua_Safe_Call_Int(); + return self->stringedMod; +} + +uint32 Lua_StatBonuses::GetsongModCap() const { + Lua_Safe_Call_Int(); + return self->songModCap; +} + +int8 Lua_StatBonuses::Gethatemod() const { + Lua_Safe_Call_Int(); + return self->hatemod; +} + +int32 Lua_StatBonuses::GetEnduranceReduction() const { + Lua_Safe_Call_Int(); + return self->EnduranceReduction; +} + +int32 Lua_StatBonuses::GetStrikeThrough() const { + Lua_Safe_Call_Int(); + return self->StrikeThrough; +} + +int32 Lua_StatBonuses::GetMeleeMitigation() const { + Lua_Safe_Call_Int(); + return self->MeleeMitigation; +} + +int32 Lua_StatBonuses::GetMeleeMitigationEffect() const { + Lua_Safe_Call_Int(); + return self->MeleeMitigationEffect; +} + +int32 Lua_StatBonuses::GetCriticalHitChance(int idx) const { + Lua_Safe_Call_Int(); + return self->CriticalHitChance[idx]; +} + +int32 Lua_StatBonuses::GetCriticalSpellChance() const { + Lua_Safe_Call_Int(); + return self->CriticalSpellChance; +} + +int32 Lua_StatBonuses::GetSpellCritDmgIncrease() const { + Lua_Safe_Call_Int(); + return self->SpellCritDmgIncrease; +} + +int32 Lua_StatBonuses::GetSpellCritDmgIncNoStack() const { + Lua_Safe_Call_Int(); + return self->SpellCritDmgIncNoStack; +} + +int32 Lua_StatBonuses::GetDotCritDmgIncrease() const { + Lua_Safe_Call_Int(); + return self->DotCritDmgIncrease; +} + +int32 Lua_StatBonuses::GetCriticalHealChance() const { + Lua_Safe_Call_Int(); + return self->CriticalHealChance; +} + +int32 Lua_StatBonuses::GetCriticalHealOverTime() const { + Lua_Safe_Call_Int(); + return self->CriticalHealOverTime; +} + +int32 Lua_StatBonuses::GetCriticalDoTChance() const { + Lua_Safe_Call_Int(); + return self->CriticalDoTChance; +} + +int32 Lua_StatBonuses::GetCrippBlowChance() const { + Lua_Safe_Call_Int(); + return self->CrippBlowChance; +} + +int32 Lua_StatBonuses::GetAvoidMeleeChance() const { + Lua_Safe_Call_Int(); + return self->AvoidMeleeChance; +} + +int32 Lua_StatBonuses::GetAvoidMeleeChanceEffect() const { + Lua_Safe_Call_Int(); + return self->AvoidMeleeChanceEffect; +} + +int32 Lua_StatBonuses::GetRiposteChance() const { + Lua_Safe_Call_Int(); + return self->RiposteChance; +} + +int32 Lua_StatBonuses::GetDodgeChance() const { + Lua_Safe_Call_Int(); + return self->DodgeChance; +} + +int32 Lua_StatBonuses::GetParryChance() const { + Lua_Safe_Call_Int(); + return self->ParryChance; +} + +int32 Lua_StatBonuses::GetDualWieldChance() const { + Lua_Safe_Call_Int(); + return self->DualWieldChance; +} + +int32 Lua_StatBonuses::GetDoubleAttackChance() const { + Lua_Safe_Call_Int(); + return self->DoubleAttackChance; +} + +int32 Lua_StatBonuses::GetTripleAttackChance() const { + Lua_Safe_Call_Int(); + return self->TripleAttackChance; +} + +int32 Lua_StatBonuses::GetDoubleRangedAttack() const { + Lua_Safe_Call_Int(); + return self->DoubleRangedAttack; +} + +int32 Lua_StatBonuses::GetResistSpellChance() const { + Lua_Safe_Call_Int(); + return self->ResistSpellChance; +} + +int32 Lua_StatBonuses::GetResistFearChance() const { + Lua_Safe_Call_Int(); + return self->ResistFearChance; +} + +bool Lua_StatBonuses::GetFearless() const { + Lua_Safe_Call_Bool(); + return self->Fearless; +} + +bool Lua_StatBonuses::GetIsFeared() const { + Lua_Safe_Call_Bool(); + return self->IsFeared; +} + +bool Lua_StatBonuses::GetIsBlind() const { + Lua_Safe_Call_Bool(); + return self->IsBlind; +} + +int32 Lua_StatBonuses::GetStunResist() const { + Lua_Safe_Call_Int(); + return self->StunResist; +} + +int32 Lua_StatBonuses::GetMeleeSkillCheck() const { + Lua_Safe_Call_Int(); + return self->MeleeSkillCheck; +} + +uint8 Lua_StatBonuses::GetMeleeSkillCheckSkill() const { + Lua_Safe_Call_Int(); + return self->MeleeSkillCheckSkill; +} + +int32 Lua_StatBonuses::GetHitChance() const { + Lua_Safe_Call_Int(); + return self->HitChance; +} + +int32 Lua_StatBonuses::GetHitChanceEffect(int idx) const { + Lua_Safe_Call_Int(); + return self->HitChanceEffect[idx]; +} + +int32 Lua_StatBonuses::GetDamageModifier(int idx) const { + Lua_Safe_Call_Int(); + return self->DamageModifier[idx]; +} + +int32 Lua_StatBonuses::GetDamageModifier2(int idx) const { + Lua_Safe_Call_Int(); + return self->DamageModifier2[idx]; +} + +int32 Lua_StatBonuses::GetMinDamageModifier(int idx) const { + Lua_Safe_Call_Int(); + return self->MinDamageModifier[idx]; +} + +int32 Lua_StatBonuses::GetProcChance() const { + Lua_Safe_Call_Int(); + return self->ProcChance; +} + +int32 Lua_StatBonuses::GetProcChanceSPA() const { + Lua_Safe_Call_Int(); + return self->ProcChanceSPA; +} + +int32 Lua_StatBonuses::GetExtraAttackChance() const { + Lua_Safe_Call_Int(); + return self->ExtraAttackChance; +} + +int32 Lua_StatBonuses::GetDoTShielding() const { + Lua_Safe_Call_Int(); + return self->DoTShielding; +} + +int32 Lua_StatBonuses::GetFlurryChance() const { + Lua_Safe_Call_Int(); + return self->FlurryChance; +} + +int32 Lua_StatBonuses::GetHundredHands() const { + Lua_Safe_Call_Int(); + return self->HundredHands; +} + +int32 Lua_StatBonuses::GetMeleeLifetap() const { + Lua_Safe_Call_Int(); + return self->MeleeLifetap; +} + +int32 Lua_StatBonuses::GetVampirism() const { + Lua_Safe_Call_Int(); + return self->Vampirism; +} + +int32 Lua_StatBonuses::GetHealRate() const { + Lua_Safe_Call_Int(); + return self->HealRate; +} + +int32 Lua_StatBonuses::GetMaxHPChange() const { + Lua_Safe_Call_Int(); + return self->MaxHPChange; +} + +int32 Lua_StatBonuses::GetHealAmt() const { + Lua_Safe_Call_Int(); + return self->HealAmt; +} + +int32 Lua_StatBonuses::GetSpellDmg() const { + Lua_Safe_Call_Int(); + return self->SpellDmg; +} + +int32 Lua_StatBonuses::GetClairvoyance() const { + Lua_Safe_Call_Int(); + return self->Clairvoyance; +} + +int32 Lua_StatBonuses::GetDSMitigation() const { + Lua_Safe_Call_Int(); + return self->DSMitigation; +} + +int32 Lua_StatBonuses::GetDSMitigationOffHand() const { + Lua_Safe_Call_Int(); + return self->DSMitigationOffHand; +} + +int32 Lua_StatBonuses::GetTwoHandBluntBlock() const { + Lua_Safe_Call_Int(); + return self->TwoHandBluntBlock; +} + +uint32 Lua_StatBonuses::GetItemManaRegenCap() const { + Lua_Safe_Call_Int(); + return self->ItemManaRegenCap; +} + +int32 Lua_StatBonuses::GetGravityEffect() const { + Lua_Safe_Call_Int(); + return self->GravityEffect; +} + +bool Lua_StatBonuses::GetAntiGate() const { + Lua_Safe_Call_Bool(); + return self->AntiGate; +} + +bool Lua_StatBonuses::GetMagicWeapon() const { + Lua_Safe_Call_Bool(); + return self->MagicWeapon; +} + +int32 Lua_StatBonuses::GetIncreaseBlockChance() const { + Lua_Safe_Call_Int(); + return self->IncreaseBlockChance; +} + +uint32 Lua_StatBonuses::GetPersistantCasting() const { + Lua_Safe_Call_Int(); + return self->PersistantCasting; +} + +int Lua_StatBonuses::GetXPRateMod() const { + Lua_Safe_Call_Int(); + return self->XPRateMod; +} + +bool Lua_StatBonuses::GetBlockNextSpell() const { + Lua_Safe_Call_Bool(); + return self->BlockNextSpell; +} + +bool Lua_StatBonuses::GetImmuneToFlee() const { + Lua_Safe_Call_Bool(); + return self->ImmuneToFlee; +} + +uint32 Lua_StatBonuses::GetVoiceGraft() const { + Lua_Safe_Call_Int(); + return self->VoiceGraft; +} + +int32 Lua_StatBonuses::GetSpellProcChance() const { + Lua_Safe_Call_Int(); + return self->SpellProcChance; +} + +int32 Lua_StatBonuses::GetCharmBreakChance() const { + Lua_Safe_Call_Int(); + return self->CharmBreakChance; +} + +int32 Lua_StatBonuses::GetSongRange() const { + Lua_Safe_Call_Int(); + return self->SongRange; +} + +uint32 Lua_StatBonuses::GetHPToManaConvert() const { + Lua_Safe_Call_Int(); + return self->HPToManaConvert; +} + +bool Lua_StatBonuses::GetNegateEffects() const { + Lua_Safe_Call_Bool(); + return self->NegateEffects; +} + +bool Lua_StatBonuses::GetTriggerMeleeThreshold() const { + Lua_Safe_Call_Bool(); + return self->TriggerMeleeThreshold; +} + +bool Lua_StatBonuses::GetTriggerSpellThreshold() const { + Lua_Safe_Call_Bool(); + return self->TriggerSpellThreshold; +} + +int32 Lua_StatBonuses::GetShieldBlock() const { + Lua_Safe_Call_Int(); + return self->ShieldBlock; +} + +int32 Lua_StatBonuses::GetBlockBehind() const { + Lua_Safe_Call_Int(); + return self->BlockBehind; +} + +bool Lua_StatBonuses::GetCriticalRegenDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalRegenDecay; +} + +bool Lua_StatBonuses::GetCriticalHealDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalHealDecay; +} + +bool Lua_StatBonuses::GetCriticalDotDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalDotDecay; +} + +bool Lua_StatBonuses::GetDivineAura() const { + Lua_Safe_Call_Bool(); + return self->DivineAura; +} + +bool Lua_StatBonuses::GetDistanceRemoval() const { + Lua_Safe_Call_Bool(); + return self->DistanceRemoval; +} + +int32 Lua_StatBonuses::GetFrenziedDevastation() const { + Lua_Safe_Call_Int(); + return self->FrenziedDevastation; +} + +bool Lua_StatBonuses::GetNegateIfCombat() const { + Lua_Safe_Call_Bool(); + return self->NegateIfCombat; +} + +int8 Lua_StatBonuses::GetScreech() const { + Lua_Safe_Call_Int(); + return self->Screech; +} + +int32 Lua_StatBonuses::GetAlterNPCLevel() const { + Lua_Safe_Call_Int(); + return self->AlterNPCLevel; +} + +bool Lua_StatBonuses::GetBerserkSPA() const { + Lua_Safe_Call_Bool(); + return self->BerserkSPA; +} + +int32 Lua_StatBonuses::GetMetabolism() const { + Lua_Safe_Call_Int(); + return self->Metabolism; +} + +bool Lua_StatBonuses::GetSanctuary() const { + Lua_Safe_Call_Bool(); + return self->Sanctuary; +} + +int32 Lua_StatBonuses::GetFactionModPct() const { + Lua_Safe_Call_Int(); + return self->FactionModPct; +} + +uint32 Lua_StatBonuses::GetPC_Pet_Flurry() const { + Lua_Safe_Call_Int(); + return self->PC_Pet_Flurry; +} + +int8 Lua_StatBonuses::GetPackrat() const { + Lua_Safe_Call_Int(); + return self->Packrat; +} + +uint8 Lua_StatBonuses::GetBuffSlotIncrease() const { + Lua_Safe_Call_Int(); + return self->BuffSlotIncrease; +} + +uint32 Lua_StatBonuses::GetDelayDeath() const { + Lua_Safe_Call_Int(); + return self->DelayDeath; +} + +int8 Lua_StatBonuses::GetBaseMovementSpeed() const { + Lua_Safe_Call_Int(); + return self->BaseMovementSpeed; +} + +uint8 Lua_StatBonuses::GetIncreaseRunSpeedCap() const { + Lua_Safe_Call_Int(); + return self->IncreaseRunSpeedCap; +} + +int32 Lua_StatBonuses::GetDoubleSpecialAttack() const { + Lua_Safe_Call_Int(); + return self->DoubleSpecialAttack; +} + +uint8 Lua_StatBonuses::GetFrontalStunResist() const { + Lua_Safe_Call_Int(); + return self->FrontalStunResist; +} + +int32 Lua_StatBonuses::GetBindWound() const { + Lua_Safe_Call_Int(); + return self->BindWound; +} + +int32 Lua_StatBonuses::GetMaxBindWound() const { + Lua_Safe_Call_Int(); + return self->MaxBindWound; +} + +int32 Lua_StatBonuses::GetChannelChanceSpells() const { + Lua_Safe_Call_Int(); + return self->ChannelChanceSpells; +} + +int32 Lua_StatBonuses::GetChannelChanceItems() const { + Lua_Safe_Call_Int(); + return self->ChannelChanceItems; +} + +uint8 Lua_StatBonuses::GetSeeInvis() const { + Lua_Safe_Call_Int(); + return self->SeeInvis; +} + +uint8 Lua_StatBonuses::GetTripleBackstab() const { + Lua_Safe_Call_Int(); + return self->TripleBackstab; +} + +bool Lua_StatBonuses::GetFrontalBackstabMinDmg() const { + Lua_Safe_Call_Bool(); + return self->FrontalBackstabMinDmg; +} + +uint8 Lua_StatBonuses::GetFrontalBackstabChance() const { + Lua_Safe_Call_Int(); + return self->FrontalBackstabChance; +} + +uint8 Lua_StatBonuses::GetConsumeProjectile() const { + Lua_Safe_Call_Int(); + return self->ConsumeProjectile; +} + +uint8 Lua_StatBonuses::GetForageAdditionalItems() const { + Lua_Safe_Call_Int(); + return self->ForageAdditionalItems; +} + +uint8 Lua_StatBonuses::GetSalvageChance() const { + Lua_Safe_Call_Int(); + return self->SalvageChance; +} + +uint32 Lua_StatBonuses::GetArcheryDamageModifier() const { + Lua_Safe_Call_Int(); + return self->ArcheryDamageModifier; +} + +bool Lua_StatBonuses::GetSecondaryDmgInc() const { + Lua_Safe_Call_Bool(); + return self->SecondaryDmgInc; +} + +uint32 Lua_StatBonuses::GetGiveDoubleAttack() const { + Lua_Safe_Call_Int(); + return self->GiveDoubleAttack; +} + +int32 Lua_StatBonuses::GetPetCriticalHit() const { + Lua_Safe_Call_Int(); + return self->PetCriticalHit; +} + +int32 Lua_StatBonuses::GetPetAvoidance() const { + Lua_Safe_Call_Int(); + return self->PetAvoidance; +} + +int32 Lua_StatBonuses::GetCombatStability() const { + Lua_Safe_Call_Int(); + return self->CombatStability; +} + +int32 Lua_StatBonuses::GetDoubleRiposte() const { + Lua_Safe_Call_Int(); + return self->DoubleRiposte; +} + +int32 Lua_StatBonuses::GetAmbidexterity() const { + Lua_Safe_Call_Int(); + return self->Ambidexterity; +} + +int32 Lua_StatBonuses::GetPetMaxHP() const { + Lua_Safe_Call_Int(); + return self->PetMaxHP; +} + +int32 Lua_StatBonuses::GetPetFlurry() const { + Lua_Safe_Call_Int(); + return self->PetFlurry; +} + +uint8 Lua_StatBonuses::GetMasteryofPast() const { + Lua_Safe_Call_Int(); + return self->MasteryofPast; +} + +bool Lua_StatBonuses::GetGivePetGroupTarget() const { + Lua_Safe_Call_Bool(); + return self->GivePetGroupTarget; +} + +int32 Lua_StatBonuses::GetRootBreakChance() const { + Lua_Safe_Call_Int(); + return self->RootBreakChance; +} + +int32 Lua_StatBonuses::GetUnfailingDivinity() const { + Lua_Safe_Call_Int(); + return self->UnfailingDivinity; +} + +int32 Lua_StatBonuses::GetItemHPRegenCap() const { + Lua_Safe_Call_Int(); + return self->ItemHPRegenCap; +} + +int32 Lua_StatBonuses::GetOffhandRiposteFail() const { + Lua_Safe_Call_Int(); + return self->OffhandRiposteFail; +} + +int32 Lua_StatBonuses::GetItemATKCap() const { + Lua_Safe_Call_Int(); + return self->ItemATKCap; +} + +int32 Lua_StatBonuses::GetShieldEquipDmgMod() const { + Lua_Safe_Call_Int(); + return self->ShieldEquipDmgMod; +} + +bool Lua_StatBonuses::GetTriggerOnValueAmount() const { + Lua_Safe_Call_Bool(); + return self->TriggerOnValueAmount; +} + +int8 Lua_StatBonuses::GetStunBashChance() const { + Lua_Safe_Call_Int(); + return self->StunBashChance; +} + +int8 Lua_StatBonuses::GetIncreaseChanceMemwipe() const { + Lua_Safe_Call_Int(); + return self->IncreaseChanceMemwipe; +} + +int8 Lua_StatBonuses::GetCriticalMend() const { + Lua_Safe_Call_Int(); + return self->CriticalMend; +} + +int32 Lua_StatBonuses::GetImprovedReclaimEnergy() const { + Lua_Safe_Call_Int(); + return self->ImprovedReclaimEnergy; +} + +int32 Lua_StatBonuses::GetPetMeleeMitigation() const { + Lua_Safe_Call_Int(); + return self->PetMeleeMitigation; +} + +bool Lua_StatBonuses::GetIllusionPersistence() const { + Lua_Safe_Call_Bool(); + return self->IllusionPersistence; +} + +uint16 Lua_StatBonuses::Getextra_xtargets() const { + Lua_Safe_Call_Int(); + return self->extra_xtargets; +} + +bool Lua_StatBonuses::GetShroudofStealth() const { + Lua_Safe_Call_Bool(); + return self->ShroudofStealth; +} + +uint16 Lua_StatBonuses::GetReduceFallDamage() const { + Lua_Safe_Call_Int(); + return self->ReduceFallDamage; +} + +uint8 Lua_StatBonuses::GetTradeSkillMastery() const { + Lua_Safe_Call_Int(); + return self->TradeSkillMastery; +} + +int16 Lua_StatBonuses::GetNoBreakAESneak() const { + Lua_Safe_Call_Int(); + return self->NoBreakAESneak; +} + +int16 Lua_StatBonuses::GetFeignedCastOnChance() const { + Lua_Safe_Call_Int(); + return self->FeignedCastOnChance; +} + +int32 Lua_StatBonuses::GetDivineSaveChance(int idx) const { + Lua_Safe_Call_Int(); + return self->DivineSaveChance[idx]; +} + +uint32 Lua_StatBonuses::GetDeathSave(int idx) const { + Lua_Safe_Call_Int(); + return self->DeathSave[idx]; +} + +int32 Lua_StatBonuses::GetAccuracy(int idx) const { + Lua_Safe_Call_Int(); + return self->Accuracy[idx]; +} + +int16 Lua_StatBonuses::GetSkillDmgTaken(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDmgTaken[idx]; +} + +uint32 Lua_StatBonuses::GetSpellTriggers(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellTriggers[idx]; +} + +uint32 Lua_StatBonuses::GetSpellOnKill(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellOnKill[idx]; +} + +uint32 Lua_StatBonuses::GetSpellOnDeath(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellOnDeath[idx]; +} + +int32 Lua_StatBonuses::GetCritDmgMod(int idx) const { + Lua_Safe_Call_Int(); + return self->CritDmgMod[idx]; +} + +int32 Lua_StatBonuses::GetSkillReuseTime(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillReuseTime[idx]; +} + +int32 Lua_StatBonuses::GetSkillDamageAmount(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDamageAmount[idx]; +} + +int Lua_StatBonuses::GetHPPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->HPPercCap[idx]; +} + +int Lua_StatBonuses::GetManaPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->ManaPercCap[idx]; +} + +int Lua_StatBonuses::GetEndPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->EndPercCap[idx]; +} + +uint8 Lua_StatBonuses::GetFocusEffects(int idx) const { + Lua_Safe_Call_Int(); + return self->FocusEffects[idx]; +} + +int16 Lua_StatBonuses::GetFocusEffectsWorn(int idx) const { + Lua_Safe_Call_Int(); + return self->FocusEffectsWorn[idx]; +} + +int32 Lua_StatBonuses::GetSkillDamageAmount2(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDamageAmount2[idx]; +} + +uint32 Lua_StatBonuses::GetNegateAttacks(int idx) const { + Lua_Safe_Call_Int(); + return self->NegateAttacks[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateMeleeRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateMeleeRune[idx]; +} + +uint32 Lua_StatBonuses::GetMeleeThresholdGuard(int idx) const { + Lua_Safe_Call_Int(); + return self->MeleeThresholdGuard[idx]; +} + +uint32 Lua_StatBonuses::GetSpellThresholdGuard(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellThresholdGuard[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateSpellRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateSpellRune[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateDotRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateDotRune[idx]; +} + +uint32 Lua_StatBonuses::GetManaAbsorbPercentDamage(int idx) const { + Lua_Safe_Call_Int(); + return self->ManaAbsorbPercentDamage[idx]; +} + +int32 Lua_StatBonuses::GetImprovedTaunt(int idx) const { + Lua_Safe_Call_Int(); + return self->ImprovedTaunt[idx]; +} + +int8 Lua_StatBonuses::GetRoot(int idx) const { + Lua_Safe_Call_Int(); + return self->Root[idx]; +} + +uint32 Lua_StatBonuses::GetAbsorbMagicAtt(int idx) const { + Lua_Safe_Call_Int(); + return self->AbsorbMagicAtt[idx]; +} + +uint32 Lua_StatBonuses::GetMeleeRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MeleeRune[idx]; +} + +int32 Lua_StatBonuses::GetAStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->AStacker[idx]; +} + +int32 Lua_StatBonuses::GetBStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->BStacker[idx]; +} + +int32 Lua_StatBonuses::GetCStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->CStacker[idx]; +} + +int32 Lua_StatBonuses::GetDStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->DStacker[idx]; +} + +bool Lua_StatBonuses::GetLimitToSkill(int idx) const { + Lua_Safe_Call_Bool(); + return self->LimitToSkill[idx]; +} + +uint32 Lua_StatBonuses::GetSkillProc(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillProc[idx]; +} + +uint32 Lua_StatBonuses::GetSkillProcSuccess(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillProcSuccess[idx]; +} + +uint32 Lua_StatBonuses::GetPC_Pet_Rampage(int idx) const { + Lua_Safe_Call_Int(); + return self->PC_Pet_Rampage[idx]; +} + +int32 Lua_StatBonuses::GetSkillAttackProc(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillAttackProc[idx]; +} + +int32 Lua_StatBonuses::GetSlayUndead(int idx) const { + Lua_Safe_Call_Int(); + return self->SlayUndead[idx]; +} + +int32 Lua_StatBonuses::GetGiveDoubleRiposte(int idx) const { + Lua_Safe_Call_Int(); + return self->GiveDoubleRiposte[idx]; +} + +uint32 Lua_StatBonuses::GetRaiseSkillCap(int idx) const { + Lua_Safe_Call_Int(); + return self->RaiseSkillCap[idx]; +} + +int32 Lua_StatBonuses::GetSEResist(int idx) const { + Lua_Safe_Call_Int(); + return self->SEResist[idx]; +} + +int32 Lua_StatBonuses::GetFinishingBlow(int idx) const { + Lua_Safe_Call_Int(); + return self->FinishingBlow[idx]; +} + +uint32 Lua_StatBonuses::GetFinishingBlowLvl(int idx) const { + Lua_Safe_Call_Int(); + return self->FinishingBlowLvl[idx]; +} + +uint32 Lua_StatBonuses::GetHeadShot(int idx) const { + Lua_Safe_Call_Int(); + return self->HeadShot[idx]; +} + +uint8 Lua_StatBonuses::GetHSLevel(int idx) const { + Lua_Safe_Call_Int(); + return self->HSLevel[idx]; +} + +uint32 Lua_StatBonuses::GetAssassinate(int idx) const { + Lua_Safe_Call_Int(); + return self->Assassinate[idx]; +} + +uint8 Lua_StatBonuses::GetAssassinateLevel(int idx) const { + Lua_Safe_Call_Int(); + return self->AssassinateLevel[idx]; +} + +int32 Lua_StatBonuses::GetReduceTradeskillFail(int idx) const { + Lua_Safe_Call_Int(); + return self->ReduceTradeskillFail[idx]; +} + +luabind::scope lua_register_stat_bonuses() { + return luabind::class_("StatBonuses") + .def(luabind::constructor<>()) + .def("AC", &Lua_StatBonuses::GetAC) + .def("HP", &Lua_StatBonuses::GetHP) + .def("HPRegen", &Lua_StatBonuses::GetHPRegen) + .def("MaxHP", &Lua_StatBonuses::GetMaxHP) + .def("ManaRegen", &Lua_StatBonuses::GetManaRegen) + .def("EnduranceRegen", &Lua_StatBonuses::GetEnduranceRegen) + .def("Mana", &Lua_StatBonuses::GetMana) + .def("Endurance", &Lua_StatBonuses::GetEndurance) + .def("ATK", &Lua_StatBonuses::GetATK) + .def("STR", &Lua_StatBonuses::GetSTR) + .def("STRCapMod", &Lua_StatBonuses::GetSTRCapMod) + .def("HeroicSTR", &Lua_StatBonuses::GetHeroicSTR) + .def("STA", &Lua_StatBonuses::GetSTA) + .def("STACapMod", &Lua_StatBonuses::GetSTACapMod) + .def("HeroicSTA", &Lua_StatBonuses::GetHeroicSTA) + .def("DEX", &Lua_StatBonuses::GetDEX) + .def("DEXCapMod", &Lua_StatBonuses::GetDEXCapMod) + .def("HeroicDEX", &Lua_StatBonuses::GetHeroicDEX) + .def("AGI", &Lua_StatBonuses::GetAGI) + .def("AGICapMod", &Lua_StatBonuses::GetAGICapMod) + .def("HeroicAGI", &Lua_StatBonuses::GetHeroicAGI) + .def("INT", &Lua_StatBonuses::GetINT) + .def("INTCapMod", &Lua_StatBonuses::GetINTCapMod) + .def("HeroicINT", &Lua_StatBonuses::GetHeroicINT) + .def("WIS", &Lua_StatBonuses::GetWIS) + .def("WISCapMod", &Lua_StatBonuses::GetWISCapMod) + .def("HeroicWIS", &Lua_StatBonuses::GetHeroicWIS) + .def("CHA", &Lua_StatBonuses::GetCHA) + .def("CHACapMod", &Lua_StatBonuses::GetCHACapMod) + .def("HeroicCHA", &Lua_StatBonuses::GetHeroicCHA) + .def("MR", &Lua_StatBonuses::GetMR) + .def("MRCapMod", &Lua_StatBonuses::GetMRCapMod) + .def("HeroicMR", &Lua_StatBonuses::GetHeroicMR) + .def("FR", &Lua_StatBonuses::GetFR) + .def("FRCapMod", &Lua_StatBonuses::GetFRCapMod) + .def("HeroicFR", &Lua_StatBonuses::GetHeroicFR) + .def("CR", &Lua_StatBonuses::GetCR) + .def("CRCapMod", &Lua_StatBonuses::GetCRCapMod) + .def("HeroicCR", &Lua_StatBonuses::GetHeroicCR) + .def("PR", &Lua_StatBonuses::GetPR) + .def("PRCapMod", &Lua_StatBonuses::GetPRCapMod) + .def("HeroicPR", &Lua_StatBonuses::GetHeroicPR) + .def("DR", &Lua_StatBonuses::GetDR) + .def("DRCapMod", &Lua_StatBonuses::GetDRCapMod) + .def("HeroicDR", &Lua_StatBonuses::GetHeroicDR) + .def("Corrup", &Lua_StatBonuses::GetCorrup) + .def("CorrupCapMod", &Lua_StatBonuses::GetCorrupCapMod) + .def("HeroicCorrup", &Lua_StatBonuses::GetHeroicCorrup) + .def("DamageShieldSpellID", &Lua_StatBonuses::GetDamageShieldSpellID) + .def("DamageShield", &Lua_StatBonuses::GetDamageShield) + .def("DamageShieldType", &Lua_StatBonuses::GetDamageShieldType) + .def("SpellDamageShield", &Lua_StatBonuses::GetSpellDamageShield) + .def("SpellShield", &Lua_StatBonuses::GetSpellShield) + .def("ReverseDamageShield", &Lua_StatBonuses::GetReverseDamageShield) + .def("ReverseDamageShieldSpellID", &Lua_StatBonuses::GetReverseDamageShieldSpellID) + .def("ReverseDamageShieldType", &Lua_StatBonuses::GetReverseDamageShieldType) + .def("movementspeed", &Lua_StatBonuses::Getmovementspeed) + .def("haste", &Lua_StatBonuses::Gethaste) + .def("hastetype2", &Lua_StatBonuses::Gethastetype2) + .def("hastetype3", &Lua_StatBonuses::Gethastetype3) + .def("inhibitmelee", &Lua_StatBonuses::Getinhibitmelee) + .def("AggroRange", &Lua_StatBonuses::GetAggroRange) + .def("AssistRange", &Lua_StatBonuses::GetAssistRange) + .def("skillmod", &Lua_StatBonuses::Getskillmod) + .def("skillmodmax", &Lua_StatBonuses::Getskillmodmax) + .def("effective_casting_level", &Lua_StatBonuses::Geteffective_casting_level) + .def("reflect_chance", &Lua_StatBonuses::Getreflect_chance) + .def("singingMod", &Lua_StatBonuses::GetsingingMod) + .def("Amplification", &Lua_StatBonuses::GetAmplification) + .def("brassMod", &Lua_StatBonuses::GetbrassMod) + .def("percussionMod", &Lua_StatBonuses::GetpercussionMod) + .def("windMod", &Lua_StatBonuses::GetwindMod) + .def("stringedMod", &Lua_StatBonuses::GetstringedMod) + .def("songModCap", &Lua_StatBonuses::GetsongModCap) + .def("hatemod", &Lua_StatBonuses::Gethatemod) + .def("EnduranceReduction", &Lua_StatBonuses::GetEnduranceReduction) + .def("StrikeThrough", &Lua_StatBonuses::GetStrikeThrough) + .def("MeleeMitigation", &Lua_StatBonuses::GetMeleeMitigation) + .def("MeleeMitigationEffect", &Lua_StatBonuses::GetMeleeMitigationEffect) + .def("CriticalHitChance", &Lua_StatBonuses::GetCriticalHitChance) + .def("CriticalSpellChance", &Lua_StatBonuses::GetCriticalSpellChance) + .def("SpellCritDmgIncrease", &Lua_StatBonuses::GetSpellCritDmgIncrease) + .def("SpellCritDmgIncNoStack", &Lua_StatBonuses::GetSpellCritDmgIncNoStack) + .def("DotCritDmgIncrease", &Lua_StatBonuses::GetDotCritDmgIncrease) + .def("CriticalHealChance", &Lua_StatBonuses::GetCriticalHealChance) + .def("CriticalHealOverTime", &Lua_StatBonuses::GetCriticalHealOverTime) + .def("CriticalDoTChance", &Lua_StatBonuses::GetCriticalDoTChance) + .def("CrippBlowChance", &Lua_StatBonuses::GetCrippBlowChance) + .def("AvoidMeleeChance", &Lua_StatBonuses::GetAvoidMeleeChance) + .def("AvoidMeleeChanceEffect", &Lua_StatBonuses::GetAvoidMeleeChanceEffect) + .def("RiposteChance", &Lua_StatBonuses::GetRiposteChance) + .def("DodgeChance", &Lua_StatBonuses::GetDodgeChance) + .def("ParryChance", &Lua_StatBonuses::GetParryChance) + .def("DualWieldChance", &Lua_StatBonuses::GetDualWieldChance) + .def("DoubleAttackChance", &Lua_StatBonuses::GetDoubleAttackChance) + .def("TripleAttackChance", &Lua_StatBonuses::GetTripleAttackChance) + .def("DoubleRangedAttack", &Lua_StatBonuses::GetDoubleRangedAttack) + .def("ResistSpellChance", &Lua_StatBonuses::GetResistSpellChance) + .def("ResistFearChance", &Lua_StatBonuses::GetResistFearChance) + .def("Fearless", &Lua_StatBonuses::GetFearless) + .def("IsFeared", &Lua_StatBonuses::GetIsFeared) + .def("IsBlind", &Lua_StatBonuses::GetIsBlind) + .def("StunResist", &Lua_StatBonuses::GetStunResist) + .def("MeleeSkillCheck", &Lua_StatBonuses::GetMeleeSkillCheck) + .def("MeleeSkillCheckSkill", &Lua_StatBonuses::GetMeleeSkillCheckSkill) + .def("HitChance", &Lua_StatBonuses::GetHitChance) + .def("HitChanceEffect", &Lua_StatBonuses::GetHitChanceEffect) + .def("DamageModifier", &Lua_StatBonuses::GetDamageModifier) + .def("DamageModifier2", &Lua_StatBonuses::GetDamageModifier2) + .def("MinDamageModifier", &Lua_StatBonuses::GetMinDamageModifier) + .def("ProcChance", &Lua_StatBonuses::GetProcChance) + .def("ProcChanceSPA", &Lua_StatBonuses::GetProcChanceSPA) + .def("ExtraAttackChance", &Lua_StatBonuses::GetExtraAttackChance) + .def("DoTShielding", &Lua_StatBonuses::GetDoTShielding) + .def("FlurryChance", &Lua_StatBonuses::GetFlurryChance) + .def("HundredHands", &Lua_StatBonuses::GetHundredHands) + .def("MeleeLifetap", &Lua_StatBonuses::GetMeleeLifetap) + .def("Vampirism", &Lua_StatBonuses::GetVampirism) + .def("HealRate", &Lua_StatBonuses::GetHealRate) + .def("MaxHPChange", &Lua_StatBonuses::GetMaxHPChange) + .def("HealAmt", &Lua_StatBonuses::GetHealAmt) + .def("SpellDmg", &Lua_StatBonuses::GetSpellDmg) + .def("Clairvoyance", &Lua_StatBonuses::GetClairvoyance) + .def("DSMitigation", &Lua_StatBonuses::GetDSMitigation) + .def("DSMitigationOffHand", &Lua_StatBonuses::GetDSMitigationOffHand) + .def("TwoHandBluntBlock", &Lua_StatBonuses::GetTwoHandBluntBlock) + .def("ItemManaRegenCap", &Lua_StatBonuses::GetItemManaRegenCap) + .def("GravityEffect", &Lua_StatBonuses::GetGravityEffect) + .def("AntiGate", &Lua_StatBonuses::GetAntiGate) + .def("MagicWeapon", &Lua_StatBonuses::GetMagicWeapon) + .def("IncreaseBlockChance", &Lua_StatBonuses::GetIncreaseBlockChance) + .def("PersistantCasting", &Lua_StatBonuses::GetPersistantCasting) + .def("XPRateMod", &Lua_StatBonuses::GetXPRateMod) + .def("BlockNextSpell", &Lua_StatBonuses::GetBlockNextSpell) + .def("ImmuneToFlee", &Lua_StatBonuses::GetImmuneToFlee) + .def("VoiceGraft", &Lua_StatBonuses::GetVoiceGraft) + .def("SpellProcChance", &Lua_StatBonuses::GetSpellProcChance) + .def("CharmBreakChance", &Lua_StatBonuses::GetCharmBreakChance) + .def("SongRange", &Lua_StatBonuses::GetSongRange) + .def("HPToManaConvert", &Lua_StatBonuses::GetHPToManaConvert) + .def("NegateEffects", &Lua_StatBonuses::GetNegateEffects) + .def("TriggerMeleeThreshold", &Lua_StatBonuses::GetTriggerMeleeThreshold) + .def("TriggerSpellThreshold", &Lua_StatBonuses::GetTriggerSpellThreshold) + .def("ShieldBlock", &Lua_StatBonuses::GetShieldBlock) + .def("BlockBehind", &Lua_StatBonuses::GetBlockBehind) + .def("CriticalRegenDecay", &Lua_StatBonuses::GetCriticalRegenDecay) + .def("CriticalHealDecay", &Lua_StatBonuses::GetCriticalHealDecay) + .def("CriticalDotDecay", &Lua_StatBonuses::GetCriticalDotDecay) + .def("DivineAura", &Lua_StatBonuses::GetDivineAura) + .def("DistanceRemoval", &Lua_StatBonuses::GetDistanceRemoval) + .def("FrenziedDevastation", &Lua_StatBonuses::GetFrenziedDevastation) + .def("NegateIfCombat", &Lua_StatBonuses::GetNegateIfCombat) + .def("Screech", &Lua_StatBonuses::GetScreech) + .def("AlterNPCLevel", &Lua_StatBonuses::GetAlterNPCLevel) + .def("BerserkSPA", &Lua_StatBonuses::GetBerserkSPA) + .def("Metabolism", &Lua_StatBonuses::GetMetabolism) + .def("Sanctuary", &Lua_StatBonuses::GetSanctuary) + .def("FactionModPct", &Lua_StatBonuses::GetFactionModPct) + .def("PC_Pet_Flurry", &Lua_StatBonuses::GetPC_Pet_Flurry) + .def("Packrat", &Lua_StatBonuses::GetPackrat) + .def("BuffSlotIncrease", &Lua_StatBonuses::GetBuffSlotIncrease) + .def("DelayDeath", &Lua_StatBonuses::GetDelayDeath) + .def("BaseMovementSpeed", &Lua_StatBonuses::GetBaseMovementSpeed) + .def("IncreaseRunSpeedCap", &Lua_StatBonuses::GetIncreaseRunSpeedCap) + .def("DoubleSpecialAttack", &Lua_StatBonuses::GetDoubleSpecialAttack) + .def("FrontalStunResist", &Lua_StatBonuses::GetFrontalStunResist) + .def("BindWound", &Lua_StatBonuses::GetBindWound) + .def("MaxBindWound", &Lua_StatBonuses::GetMaxBindWound) + .def("ChannelChanceSpells", &Lua_StatBonuses::GetChannelChanceSpells) + .def("ChannelChanceItems", &Lua_StatBonuses::GetChannelChanceItems) + .def("SeeInvis", &Lua_StatBonuses::GetSeeInvis) + .def("TripleBackstab", &Lua_StatBonuses::GetTripleBackstab) + .def("FrontalBackstabMinDmg", &Lua_StatBonuses::GetFrontalBackstabMinDmg) + .def("FrontalBackstabChance", &Lua_StatBonuses::GetFrontalBackstabChance) + .def("ConsumeProjectile", &Lua_StatBonuses::GetConsumeProjectile) + .def("ForageAdditionalItems", &Lua_StatBonuses::GetForageAdditionalItems) + .def("SalvageChance", &Lua_StatBonuses::GetSalvageChance) + .def("ArcheryDamageModifier", &Lua_StatBonuses::GetArcheryDamageModifier) + .def("SecondaryDmgInc", &Lua_StatBonuses::GetSecondaryDmgInc) + .def("GiveDoubleAttack", &Lua_StatBonuses::GetGiveDoubleAttack) + .def("PetCriticalHit", &Lua_StatBonuses::GetPetCriticalHit) + .def("PetAvoidance", &Lua_StatBonuses::GetPetAvoidance) + .def("CombatStability", &Lua_StatBonuses::GetCombatStability) + .def("DoubleRiposte", &Lua_StatBonuses::GetDoubleRiposte) + .def("Ambidexterity", &Lua_StatBonuses::GetAmbidexterity) + .def("PetMaxHP", &Lua_StatBonuses::GetPetMaxHP) + .def("PetFlurry", &Lua_StatBonuses::GetPetFlurry) + .def("MasteryofPast", &Lua_StatBonuses::GetMasteryofPast) + .def("GivePetGroupTarget", &Lua_StatBonuses::GetGivePetGroupTarget) + .def("RootBreakChance", &Lua_StatBonuses::GetRootBreakChance) + .def("UnfailingDivinity", &Lua_StatBonuses::GetUnfailingDivinity) + .def("ItemHPRegenCap", &Lua_StatBonuses::GetItemHPRegenCap) + .def("OffhandRiposteFail", &Lua_StatBonuses::GetOffhandRiposteFail) + .def("ItemATKCap", &Lua_StatBonuses::GetItemATKCap) + .def("ShieldEquipDmgMod", &Lua_StatBonuses::GetShieldEquipDmgMod) + .def("TriggerOnValueAmount", &Lua_StatBonuses::GetTriggerOnValueAmount) + .def("StunBashChance", &Lua_StatBonuses::GetStunBashChance) + .def("IncreaseChanceMemwipe", &Lua_StatBonuses::GetIncreaseChanceMemwipe) + .def("CriticalMend", &Lua_StatBonuses::GetCriticalMend) + .def("ImprovedReclaimEnergy", &Lua_StatBonuses::GetImprovedReclaimEnergy) + .def("PetMeleeMitigation", &Lua_StatBonuses::GetPetMeleeMitigation) + .def("IllusionPersistence", &Lua_StatBonuses::GetIllusionPersistence) + .def("extra_xtargets", &Lua_StatBonuses::Getextra_xtargets) + .def("ShroudofStealth", &Lua_StatBonuses::GetShroudofStealth) + .def("ReduceFallDamage", &Lua_StatBonuses::GetReduceFallDamage) + .def("TradeSkillMastery", &Lua_StatBonuses::GetTradeSkillMastery) + .def("NoBreakAESneak", &Lua_StatBonuses::GetNoBreakAESneak) + .def("FeignedCastOnChance", &Lua_StatBonuses::GetFeignedCastOnChance) + .def("DivineSaveChance", &Lua_StatBonuses::GetDivineSaveChance) + .def("DeathSave", &Lua_StatBonuses::GetDeathSave) + .def("Accuracy", &Lua_StatBonuses::GetAccuracy) + .def("SkillDmgTaken", &Lua_StatBonuses::GetSkillDmgTaken) + .def("SpellTriggers", &Lua_StatBonuses::GetSpellTriggers) + .def("SpellOnKill", &Lua_StatBonuses::GetSpellOnKill) + .def("SpellOnDeath", &Lua_StatBonuses::GetSpellOnDeath) + .def("CritDmgMod", &Lua_StatBonuses::GetCritDmgMod) + .def("SkillReuseTime", &Lua_StatBonuses::GetSkillReuseTime) + .def("SkillDamageAmount", &Lua_StatBonuses::GetSkillDamageAmount) + .def("HPPercCap", &Lua_StatBonuses::GetHPPercCap) + .def("ManaPercCap", &Lua_StatBonuses::GetManaPercCap) + .def("EndPercCap", &Lua_StatBonuses::GetEndPercCap) + .def("FocusEffects", &Lua_StatBonuses::GetFocusEffects) + .def("FocusEffectsWorn", &Lua_StatBonuses::GetFocusEffectsWorn) + .def("SkillDamageAmount2", &Lua_StatBonuses::GetSkillDamageAmount2) + .def("NegateAttacks", &Lua_StatBonuses::GetNegateAttacks) + .def("MitigateMeleeRune", &Lua_StatBonuses::GetMitigateMeleeRune) + .def("MeleeThresholdGuard", &Lua_StatBonuses::GetMeleeThresholdGuard) + .def("SpellThresholdGuard", &Lua_StatBonuses::GetSpellThresholdGuard) + .def("MitigateSpellRune", &Lua_StatBonuses::GetMitigateSpellRune) + .def("MitigateDotRune", &Lua_StatBonuses::GetMitigateDotRune) + .def("ManaAbsorbPercentDamage", &Lua_StatBonuses::GetManaAbsorbPercentDamage) + .def("ImprovedTaunt", &Lua_StatBonuses::GetImprovedTaunt) + .def("Root", &Lua_StatBonuses::GetRoot) + .def("AbsorbMagicAtt", &Lua_StatBonuses::GetAbsorbMagicAtt) + .def("MeleeRune", &Lua_StatBonuses::GetMeleeRune) + .def("AStacker", &Lua_StatBonuses::GetAStacker) + .def("BStacker", &Lua_StatBonuses::GetBStacker) + .def("CStacker", &Lua_StatBonuses::GetCStacker) + .def("DStacker", &Lua_StatBonuses::GetDStacker) + .def("LimitToSkill", &Lua_StatBonuses::GetLimitToSkill) + .def("SkillProc", &Lua_StatBonuses::GetSkillProc) + .def("SkillProcSuccess", &Lua_StatBonuses::GetSkillProcSuccess) + .def("PC_Pet_Rampage", &Lua_StatBonuses::GetPC_Pet_Rampage) + .def("SkillAttackProc", &Lua_StatBonuses::GetSkillAttackProc) + .def("SlayUndead", &Lua_StatBonuses::GetSlayUndead) + .def("GiveDoubleRiposte", &Lua_StatBonuses::GetGiveDoubleRiposte) + .def("RaiseSkillCap", &Lua_StatBonuses::GetRaiseSkillCap) + .def("SEResist", &Lua_StatBonuses::GetSEResist) + .def("FinishingBlow", &Lua_StatBonuses::GetFinishingBlow) + .def("FinishingBlowLvl", &Lua_StatBonuses::GetFinishingBlowLvl) + .def("HeadShot", &Lua_StatBonuses::GetHeadShot) + .def("HSLevel", &Lua_StatBonuses::GetHSLevel) + .def("Assassinate", &Lua_StatBonuses::GetAssassinate) + .def("AssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel) + .def("ReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail); +} \ No newline at end of file diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h new file mode 100644 index 000000000..9ad04d681 --- /dev/null +++ b/zone/lua_stat_bonuses.h @@ -0,0 +1,285 @@ +#pragma once + +#ifdef LUA_EQEMU + +#include "lua_ptr.h" +#include "common.h" + +struct StatBonuses; + +namespace luabind { + struct scope; +} + +luabind::scope lua_register_stat_bonuses(); + +class Lua_StatBonuses : public Lua_Ptr +{ + typedef StatBonuses NativeType; +public: + Lua_StatBonuses() : Lua_Ptr(nullptr) { } + Lua_StatBonuses(StatBonuses *d) : Lua_Ptr(d) { } + virtual ~Lua_StatBonuses() { } + + operator StatBonuses*() { + return reinterpret_cast(GetLuaPtrData()); + } + + int32 GetAC() const; + int32 GetHP() const; + int32 GetHPRegen() const; + int32 GetMaxHP() const; + int32 GetManaRegen() const; + int32 GetEnduranceRegen() const; + int32 GetMana() const; + int32 GetEndurance() const; + int32 GetATK() const; + int32 GetSTR() const; + int32 GetSTRCapMod() const; + int32 GetHeroicSTR() const; + int32 GetSTA() const; + int32 GetSTACapMod() const; + int32 GetHeroicSTA() const; + int32 GetDEX() const; + int32 GetDEXCapMod() const; + int32 GetHeroicDEX() const; + int32 GetAGI() const; + int32 GetAGICapMod() const; + int32 GetHeroicAGI() const; + int32 GetINT() const; + int32 GetINTCapMod() const; + int32 GetHeroicINT() const; + int32 GetWIS() const; + int32 GetWISCapMod() const; + int32 GetHeroicWIS() const; + int32 GetCHA() const; + int32 GetCHACapMod() const; + int32 GetHeroicCHA() const; + int32 GetMR() const; + int32 GetMRCapMod() const; + int32 GetHeroicMR() const; + int32 GetFR() const; + int32 GetFRCapMod() const; + int32 GetHeroicFR() const; + int32 GetCR() const; + int32 GetCRCapMod() const; + int32 GetHeroicCR() const; + int32 GetPR() const; + int32 GetPRCapMod() const; + int32 GetHeroicPR() const; + int32 GetDR() const; + int32 GetDRCapMod() const; + int32 GetHeroicDR() const; + int32 GetCorrup() const; + int32 GetCorrupCapMod() const; + int32 GetHeroicCorrup() const; + uint16 GetDamageShieldSpellID() const; + int GetDamageShield() const; + int GetDamageShieldType() const; + int GetSpellDamageShield() const; + int GetSpellShield() const; + int GetReverseDamageShield() const; + uint16 GetReverseDamageShieldSpellID() const; + int GetReverseDamageShieldType() const; + int Getmovementspeed() const; + int32 Gethaste() const; + int32 Gethastetype2() const; + int32 Gethastetype3() const; + int32 Getinhibitmelee() const; + float GetAggroRange() const; + float GetAssistRange() const; + int32 Getskillmod(int idx) const; + int32 Getskillmodmax(int idx) const; + int Geteffective_casting_level() const; + int Getreflect_chance() const; + uint32 GetsingingMod() const; + uint32 GetAmplification() const; + uint32 GetbrassMod() const; + uint32 GetpercussionMod() const; + uint32 GetwindMod() const; + uint32 GetstringedMod() const; + uint32 GetsongModCap() const; + int8 Gethatemod() const; + int32 GetEnduranceReduction() const; + int32 GetStrikeThrough() const; + int32 GetMeleeMitigation() const; + int32 GetMeleeMitigationEffect() const; + int32 GetCriticalHitChance(int idx) const; + int32 GetCriticalSpellChance() const; + int32 GetSpellCritDmgIncrease() const; + int32 GetSpellCritDmgIncNoStack() const; + int32 GetDotCritDmgIncrease() const; + int32 GetCriticalHealChance() const; + int32 GetCriticalHealOverTime() const; + int32 GetCriticalDoTChance() const; + int32 GetCrippBlowChance() const; + int32 GetAvoidMeleeChance() const; + int32 GetAvoidMeleeChanceEffect() const; + int32 GetRiposteChance() const; + int32 GetDodgeChance() const; + int32 GetParryChance() const; + int32 GetDualWieldChance() const; + int32 GetDoubleAttackChance() const; + int32 GetTripleAttackChance() const; + int32 GetDoubleRangedAttack() const; + int32 GetResistSpellChance() const; + int32 GetResistFearChance() const; + bool GetFearless() const; + bool GetIsFeared() const; + bool GetIsBlind() const; + int32 GetStunResist() const; + int32 GetMeleeSkillCheck() const; + uint8 GetMeleeSkillCheckSkill() const; + int32 GetHitChance() const; + int32 GetHitChanceEffect(int idx) const; + int32 GetDamageModifier(int idx) const; + int32 GetDamageModifier2(int idx) const; + int32 GetMinDamageModifier(int idx) const; + int32 GetProcChance() const; + int32 GetProcChanceSPA() const; + int32 GetExtraAttackChance() const; + int32 GetDoTShielding() const; + int32 GetFlurryChance() const; + int32 GetHundredHands() const; + int32 GetMeleeLifetap() const; + int32 GetVampirism() const; + int32 GetHealRate() const; + int32 GetMaxHPChange() const; + int32 GetHealAmt() const; + int32 GetSpellDmg() const; + int32 GetClairvoyance() const; + int32 GetDSMitigation() const; + int32 GetDSMitigationOffHand() const; + int32 GetTwoHandBluntBlock() const; + uint32 GetItemManaRegenCap() const; + int32 GetGravityEffect() const; + bool GetAntiGate() const; + bool GetMagicWeapon() const; + int32 GetIncreaseBlockChance() const; + uint32 GetPersistantCasting() const; + int GetXPRateMod() const; + bool GetBlockNextSpell() const; + bool GetImmuneToFlee() const; + uint32 GetVoiceGraft() const; + int32 GetSpellProcChance() const; + int32 GetCharmBreakChance() const; + int32 GetSongRange() const; + uint32 GetHPToManaConvert() const; + bool GetNegateEffects() const; + bool GetTriggerMeleeThreshold() const; + bool GetTriggerSpellThreshold() const; + int32 GetShieldBlock() const; + int32 GetBlockBehind() const; + bool GetCriticalRegenDecay() const; + bool GetCriticalHealDecay() const; + bool GetCriticalDotDecay() const; + bool GetDivineAura() const; + bool GetDistanceRemoval() const; + int32 GetFrenziedDevastation() const; + bool GetNegateIfCombat() const; + int8 GetScreech() const; + int32 GetAlterNPCLevel() const; + bool GetBerserkSPA() const; + int32 GetMetabolism() const; + bool GetSanctuary() const; + int32 GetFactionModPct() const; + uint32 GetPC_Pet_Flurry() const; + int8 GetPackrat() const; + uint8 GetBuffSlotIncrease() const; + uint32 GetDelayDeath() const; + int8 GetBaseMovementSpeed() const; + uint8 GetIncreaseRunSpeedCap() const; + int32 GetDoubleSpecialAttack() const; + uint8 GetFrontalStunResist() const; + int32 GetBindWound() const; + int32 GetMaxBindWound() const; + int32 GetChannelChanceSpells() const; + int32 GetChannelChanceItems() const; + uint8 GetSeeInvis() const; + uint8 GetTripleBackstab() const; + bool GetFrontalBackstabMinDmg() const; + uint8 GetFrontalBackstabChance() const; + uint8 GetConsumeProjectile() const; + uint8 GetForageAdditionalItems() const; + uint8 GetSalvageChance() const; + uint32 GetArcheryDamageModifier() const; + bool GetSecondaryDmgInc() const; + uint32 GetGiveDoubleAttack() const; + int32 GetPetCriticalHit() const; + int32 GetPetAvoidance() const; + int32 GetCombatStability() const; + int32 GetDoubleRiposte() const; + int32 GetAmbidexterity() const; + int32 GetPetMaxHP() const; + int32 GetPetFlurry() const; + uint8 GetMasteryofPast() const; + bool GetGivePetGroupTarget() const; + int32 GetRootBreakChance() const; + int32 GetUnfailingDivinity() const; + int32 GetItemHPRegenCap() const; + int32 GetOffhandRiposteFail() const; + int32 GetItemATKCap() const; + int32 GetShieldEquipDmgMod() const; + bool GetTriggerOnValueAmount() const; + int8 GetStunBashChance() const; + int8 GetIncreaseChanceMemwipe() const; + int8 GetCriticalMend() const; + int32 GetImprovedReclaimEnergy() const; + int32 GetPetMeleeMitigation() const; + bool GetIllusionPersistence() const; + uint16 Getextra_xtargets() const; + bool GetShroudofStealth() const; + uint16 GetReduceFallDamage() const; + uint8 GetTradeSkillMastery() const; + int16 GetNoBreakAESneak() const; + int16 GetFeignedCastOnChance() const; + int32 GetDivineSaveChance(int idx) const; + uint32 GetDeathSave(int idx) const; + int32 GetAccuracy(int idx) const; + int16 GetSkillDmgTaken(int idx) const; + uint32 GetSpellTriggers(int idx) const; + uint32 GetSpellOnKill(int idx) const; + uint32 GetSpellOnDeath(int idx) const; + int32 GetCritDmgMod(int idx) const; + int32 GetSkillReuseTime(int idx) const; + int32 GetSkillDamageAmount(int idx) const; + int GetHPPercCap(int idx) const; + int GetManaPercCap(int idx) const; + int GetEndPercCap(int idx) const; + uint8 GetFocusEffects(int idx) const; + int16 GetFocusEffectsWorn(int idx) const; + int32 GetSkillDamageAmount2(int idx) const; + uint32 GetNegateAttacks(int idx) const; + uint32 GetMitigateMeleeRune(int idx) const; + uint32 GetMeleeThresholdGuard(int idx) const; + uint32 GetSpellThresholdGuard(int idx) const; + uint32 GetMitigateSpellRune(int idx) const; + uint32 GetMitigateDotRune(int idx) const; + uint32 GetManaAbsorbPercentDamage(int idx) const; + int32 GetImprovedTaunt(int idx) const; + int8 GetRoot(int idx) const; + uint32 GetAbsorbMagicAtt(int idx) const; + uint32 GetMeleeRune(int idx) const; + int32 GetAStacker(int idx) const; + int32 GetBStacker(int idx) const; + int32 GetCStacker(int idx) const; + int32 GetDStacker(int idx) const; + bool GetLimitToSkill(int idx) const; + uint32 GetSkillProc(int idx) const; + uint32 GetSkillProcSuccess(int idx) const; + uint32 GetPC_Pet_Rampage(int idx) const; + int32 GetSkillAttackProc(int idx) const; + int32 GetSlayUndead(int idx) const; + int32 GetGiveDoubleRiposte(int idx) const; + uint32 GetRaiseSkillCap(int idx) const; + int32 GetSEResist(int idx) const; + int32 GetFinishingBlow(int idx) const; + uint32 GetFinishingBlowLvl(int idx) const; + uint32 GetHeadShot(int idx) const; + uint8 GetHSLevel(int idx) const; + uint32 GetAssassinate(int idx) const; + uint8 GetAssassinateLevel(int idx) const; + int32 GetReduceTradeskillFail(int idx) const; +}; + +#endif diff --git a/zone/mob.cpp b/zone/mob.cpp index 5ac331c01..64ada4b71 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4677,16 +4677,13 @@ bool Mob::TrySpellOnDeath() //in death because the heal will not register before the script kills you. } -int16 Mob::GetCritDmgMob(uint16 skill) +int16 Mob::GetCritDmgMod(uint16 skill) { int critDmg_mod = 0; // All skill dmg mod + Skill specific - critDmg_mod += itembonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + - itembonuses.CritDmgMob[skill] + spellbonuses.CritDmgMob[skill] + aabonuses.CritDmgMob[skill]; - - if(critDmg_mod < -100) - critDmg_mod = -100; + critDmg_mod += itembonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + + itembonuses.CritDmgMod[skill] + spellbonuses.CritDmgMod[skill] + aabonuses.CritDmgMod[skill]; return critDmg_mod; } diff --git a/zone/mob.h b/zone/mob.h index cba96f372..f2516b613 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -233,7 +233,7 @@ public: inline bool SeeImprovedHide() const { return see_improved_hide; } bool IsInvisible(Mob* other = 0) const; void SetInvisible(uint8 state); - bool AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const EQEmu::ItemInstance* weapon); + EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon); //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); @@ -446,6 +446,9 @@ public: inline StatBonuses GetItemBonuses() const { return itembonuses; } inline StatBonuses GetSpellBonuses() const { return spellbonuses; } inline StatBonuses GetAABonuses() const { return aabonuses; } + inline StatBonuses* GetItemBonusesPtr() { return &itembonuses; } + inline StatBonuses* GetSpellBonusesPtr() { return &spellbonuses; } + inline StatBonuses* GetAABonusesPtr() { return &aabonuses; } inline virtual int32 GetMaxSTR() const { return GetSTR(); } inline virtual int32 GetMaxSTA() const { return GetSTA(); } inline virtual int32 GetMaxDEX() const { return GetDEX(); } @@ -694,7 +697,7 @@ public: void CastOnCure(uint32 spell_id); void CastOnNumHitFade(uint32 spell_id); void SlowMitigation(Mob* caster); - int16 GetCritDmgMob(uint16 skill); + int16 GetCritDmgMod(uint16 skill); int16 GetMeleeDamageMod_SE(uint16 skill); int16 GetMeleeMinDamageMod_SE(uint16 skill); int16 GetCrippBlowChance(); @@ -1060,6 +1063,8 @@ public: void AddAssistCap() { ++npc_assist_cap; } void DelAssistCap() { --npc_assist_cap; } void ResetAssistCap() { npc_assist_cap = 0; } + int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); + int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); // Bots HealRotation methods #ifdef BOTS @@ -1209,8 +1214,6 @@ protected: virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::inventory::slotPrimary, Mob *on = nullptr); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); - int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); #ifdef BOTS virtual #endif diff --git a/zone/net.cpp b/zone/net.cpp index 982b45d02..f51d50bb4 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -391,8 +391,7 @@ int main(int argc, char** argv) { parse = new QuestParserCollection(); #ifdef LUA_EQEMU - auto lua_parser = new LuaParser(); - parse->RegisterQuestInterface(lua_parser, "lua"); + parse->RegisterQuestInterface(LuaParser::Instance(), "lua"); #endif #ifdef EMBPERL @@ -565,10 +564,6 @@ int main(int argc, char** argv) { safe_delete(perl_parser); #endif -#ifdef LUA_EQEMU - safe_delete(lua_parser); -#endif - safe_delete(Config); if (zone != 0) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index ef97aee39..57ea1c781 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -23,6 +23,7 @@ #include "entity.h" #include "mob.h" #include "string_ids.h" +#include "lua_parser.h" #include @@ -758,7 +759,6 @@ void Mob::DoArcheryAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon, uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed) { - if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { diff --git a/zone/tune.cpp b/zone/tune.cpp index bbb56217e..36be51905 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -596,8 +596,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) } } - EQEmu::skills::SkillType skillinuse; - AttackAnimation(skillinuse, Hand, weapon); + EQEmu::skills::SkillType skillinuse = AttackAnimation(Hand, weapon); int damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; @@ -665,16 +664,16 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotPrimary, weapon); } else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotSecondary, weapon); else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotRange, weapon); } } } @@ -745,16 +744,16 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotPrimary, weapon); } else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotSecondary, weapon); else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotRange, weapon); } } }