Merge branch 'luamod'

This commit is contained in:
KimLS 2017-06-19 14:45:08 -07:00
commit 0a8b21d4ab
54 changed files with 5567 additions and 147 deletions

2
.gitignore vendored
View File

@ -33,5 +33,7 @@ Build_32/
build_32/
Build_64/
build_64/
x64/
x86/
log/
logs/

View File

@ -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)

View File

@ -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
)

View File

@ -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<void(void)> 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());

View File

@ -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<void(void)> onTell);
private:
void ConnectionDisconnected(ConsoleServerConnection *c);
void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd);

View File

@ -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<TCPConnection> 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<void(void)> 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) {

View File

@ -4,6 +4,8 @@
#include <memory>
#include <map>
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<void(void)> onTell);
private:
void OnRead(TCPConnection* c, const unsigned char* data, size_t sz);
void OnDisconnect(TCPConnection* c);

View File

@ -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;
}
}
}

View File

@ -8,6 +8,7 @@
#include <functional>
#include <memory>
#include <map>
#include <unordered_map>
#include <queue>
#include <list>
@ -155,13 +156,13 @@ namespace EQ
uint16_t sequence_in;
uint16_t sequence_out;
std::map<uint16_t, Packet*> packet_queue;
std::unordered_map<uint16_t, Packet*> packet_queue;
DynamicPacket fragment_packet;
uint32_t fragment_current_bytes;
uint32_t fragment_total_bytes;
std::map<uint16_t, DaybreakSentPacket> sent_packets;
std::unordered_map<uint16_t, DaybreakSentPacket> 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;
};
}
}
}

49
common/util/directory.cpp Normal file
View File

@ -0,0 +1,49 @@
#include "directory.h"
#ifdef _WIN32
#include "win_dirent.h"
#else
#include <dirent.h>
#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<std::string>& 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);
}
}

19
common/util/directory.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <string>
#include <vector>
namespace EQ {
class Directory
{
public:
Directory(const std::string &path);
~Directory();
bool Exists();
void GetFiles(std::vector<std::string> &files);
private:
struct impl;
impl *m_impl;
};
}

928
common/util/win_dirent.h Normal file
View File

@ -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 <windows.h>
#include <stdio.h>
#include <stdarg.h>
#include <wchar.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
/* 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*/

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
legacy_combat.lua

View File

@ -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<EQ::Net::ServertalkServerConnection> connection) {
server_connection->OnConnectionIdentified("Zone", [&console](std::shared_ptr<EQ::Net::ServertalkServerConnection> 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<EQ::Net::ServertalkServerConnection> connection) {

View File

@ -46,7 +46,7 @@ extern UCSConnection UCSLink;
extern QueryServConnection QSLink;
void CatchSignal(int sig_num);
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection)
ZoneServer::ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> 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<EQ::Net::ServertalkServerConnection> 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;

View File

@ -22,6 +22,7 @@
#include "../net/servertalk_server.h"
#include "../event/timer.h"
#include "../timer.h"
#include "console.h"
#include <string.h>
#include <string>
@ -31,7 +32,7 @@ class ServerPacket;
class ZoneServer : public WorldTCPConnection {
public:
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> connection);
ZoneServer(std::shared_ptr<EQ::Net::ServertalkServerConnection> 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

View File

@ -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

View File

@ -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);

View File

@ -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 <assert.h>
#include <stdio.h>
@ -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))

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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);
}

View File

@ -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() {

View File

@ -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

View File

@ -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)

View File

@ -44,6 +44,8 @@ public:
bool IsDoor();
bool IsTrap();
bool IsBeacon();
bool IsEncounter();
bool IsBot();
int GetID();
Lua_Client CastToClient();

View File

@ -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() {

View File

@ -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);

View File

@ -7,6 +7,10 @@
#include <list>
#include <map>
#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_<Events>("Event")
.enum_("constants")
@ -1863,4 +1916,355 @@ luabind::scope lua_register_appearance() {
];
}
luabind::scope lua_register_classes() {
return luabind::class_<Classes>("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_<Skills>("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_<BodyTypes>("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_<Filters>("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_<MessageTypes>("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>("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

View File

@ -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
#endif

View File

@ -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<EQEmu::skills::SkillType>(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_<Lua_Mob, Lua_Entity>("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() {

View File

@ -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

631
zone/lua_mod.cpp Normal file
View File

@ -0,0 +1,631 @@
#include "lua.hpp"
#include <luabind/luabind.hpp>
#include <luabind/object.hpp>
#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<int>(base_damage);
}
if (luabind::type(min_damage) == LUA_TNUMBER) {
hit.min_damage = luabind::object_cast<int>(min_damage);
}
if (luabind::type(damage_done) == LUA_TNUMBER) {
hit.damage_done = luabind::object_cast<int>(damage_done);
}
if (luabind::type(offense) == LUA_TNUMBER) {
hit.offense = luabind::object_cast<int>(offense);
}
if (luabind::type(tohit) == LUA_TNUMBER) {
hit.tohit = luabind::object_cast<int>(tohit);
}
if (luabind::type(hand) == LUA_TNUMBER) {
hit.hand = luabind::object_cast<int>(hand);
}
if (luabind::type(skill) == LUA_TNUMBER) {
hit.skill = (EQEmu::skills::SkillType)luabind::object_cast<int>(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<float>(damage_percent);
}
if (luabind::type(damage_flat) == LUA_TNUMBER) {
opts->damage_flat = luabind::object_cast<int>(damage_flat);
}
if (luabind::type(armor_pen_percent) == LUA_TNUMBER) {
opts->armor_pen_percent = luabind::object_cast<float>(armor_pen_percent);
}
if (luabind::type(armor_pen_flat) == LUA_TNUMBER) {
opts->armor_pen_flat = luabind::object_cast<int>(armor_pen_flat);
}
if (luabind::type(crit_percent) == LUA_TNUMBER) {
opts->crit_percent = luabind::object_cast<float>(crit_percent);
}
if (luabind::type(crit_flat) == LUA_TNUMBER) {
opts->crit_flat = luabind::object_cast<float>(crit_flat);
}
if (luabind::type(hate_percent) == LUA_TNUMBER) {
opts->hate_percent = luabind::object_cast<float>(hate_percent);
}
if (luabind::type(hate_flat) == LUA_TNUMBER) {
opts->hate_flat = luabind::object_cast<int>(hate_flat);
}
if (luabind::type(hit_chance) == LUA_TNUMBER) {
opts->hit_chance = luabind::object_cast<int>(hit_chance);
}
if (luabind::type(melee_damage_bonus_flat) == LUA_TNUMBER) {
opts->melee_damage_bonus_flat = luabind::object_cast<int>(melee_damage_bonus_flat);
}
if (luabind::type(skilldmgtaken_bonus_flat) == LUA_TNUMBER) {
opts->skilldmgtaken_bonus_flat = luabind::object_cast<int>(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<bool>(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<bool>(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<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TBOOLEAN) {
returnValue = luabind::object_cast<bool>(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<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TBOOLEAN) {
returnValue = luabind::object_cast<bool>(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<bool>(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<bool>(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<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
returnValue = luabind::object_cast<uint32>(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<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
returnValue = luabind::object_cast<uint32>(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<bool>(IgnoreDefaultObj);
}
auto returnValueObj = ret["ReturnValue"];
if (luabind::type(returnValueObj) == LUA_TNUMBER) {
returnValue = luabind::object_cast<uint32>(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);
}
}

43
zone/lua_mod.h Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <string>
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;
};

View File

@ -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_<Lua_NPC, Lua_Mob>("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

View File

@ -125,6 +125,8 @@ public:
void MerchantCloseShop();
void SetMerchantProbability(uint8 amt);
uint8 GetMerchantProbability();
int GetRawAC();
int GetAvoidanceRating();
};
#endif

View File

@ -10,8 +10,13 @@
#include <vector>
#include <algorithm>
#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;
}

View File

@ -7,8 +7,10 @@
#include <string>
#include <list>
#include <map>
#include <exception>
#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<EQEmu::Any> *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<EQEmu::Any> *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<EQEmu::Any> *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<std::string, std::string> vars_;
std::map<std::string, bool> loaded_;
std::vector<LuaMod> mods_;
lua_State *L;
NPCArgumentHandler NPCArgumentDispatch[_LargestEventID];

View File

@ -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<NativeType*>(d_)
#define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Int() if(!d_) { return 0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Real() if(!d_) { return 0.0; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_String() if(!d_) { return ""; } NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Class(type) if(!d_) { return type(); } NativeType *self = reinterpret_cast<NativeType*>(d_)
#else
#define Lua_Safe_Call_Void() NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Bool() NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Int() NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Real() NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_String() NativeType *self = reinterpret_cast<NativeType*>(d_)
#define Lua_Safe_Call_Class(type) NativeType *self = reinterpret_cast<NativeType*>(d_)
#endif
template<typename T>
class Lua_Ptr

1539
zone/lua_stat_bonuses.cpp Normal file

File diff suppressed because it is too large Load Diff

285
zone/lua_stat_bonuses.h Normal file
View File

@ -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<StatBonuses>
{
typedef StatBonuses NativeType;
public:
Lua_StatBonuses() : Lua_Ptr(nullptr) { }
Lua_StatBonuses(StatBonuses *d) : Lua_Ptr(d) { }
virtual ~Lua_StatBonuses() { }
operator StatBonuses*() {
return reinterpret_cast<StatBonuses*>(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

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -23,6 +23,7 @@
#include "entity.h"
#include "mob.h"
#include "string_ids.h"
#include "lua_parser.h"
#include <string.h>
@ -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)))) {

View File

@ -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);
}
}
}