From a834ec92a5e040a6f5fdd078b941418bbe2b898b Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 18 Apr 2017 20:06:40 -0700 Subject: [PATCH 001/218] Fix for openssl find on win --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 95f21acee..53969c7ee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,7 +78,7 @@ IF(MSVC) SET(MYSQL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/mysql_x86") SET(LUA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/luaj_x86") SET(SODIUM_INCLUDE_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/include") - SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x64") + SET(OPENSSL_ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/openssl_x86") IF(MSVC_VERSION GREATER 1800) SET(SODIUM_LIBRARY_HINTS "${CMAKE_CURRENT_SOURCE_DIR}/dependencies/libsodium/Win32/Release/v140/dynamic") ELSEIF(MSVC_VERSION EQUAL 1800) From cfd7e9f4d39d403dd77f09c419576b4b23e93765 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 18 Apr 2017 20:14:30 -0700 Subject: [PATCH 002/218] Crash fix for trying to write a 0 length packet to another packet. --- common/net/packet.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/common/net/packet.cpp b/common/net/packet.cpp index 347774459..4c7dc74b6 100644 --- a/common/net/packet.cpp +++ b/common/net/packet.cpp @@ -139,6 +139,10 @@ void EQ::Net::Packet::PutCString(size_t offset, const char *str) void EQ::Net::Packet::PutPacket(size_t offset, const Packet &p) { + if (p.Length() == 0) { + return; + } + if (Length() < offset + p.Length()) { if (!Resize(offset + p.Length())) { throw std::out_of_range("Packet::PutPacket(), could not resize packet and would of written past the end."); @@ -150,6 +154,10 @@ void EQ::Net::Packet::PutPacket(size_t offset, const Packet &p) void EQ::Net::Packet::PutData(size_t offset, void *data, size_t length) { + if (length == 0) { + return; + } + if (Length() < offset + length) { if (!Resize(offset + length)) { throw std::out_of_range("Packet::PutData(), could not resize packet and would of written past the end."); From f2b9c1a247c25d815982bb4d42e8f379ad74f8c5 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Wed, 19 Apr 2017 19:24:21 -0500 Subject: [PATCH 003/218] Added wget to Debian/Ubuntu section Ubuntu 17 doesn't seem to have wget installed on a minimal installation. Added a line to install it. --- utils/scripts/linux_installer/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 97cfa582e..12db7d6a2 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -114,6 +114,7 @@ if [[ "$OS" == "Debian" ]]; then apt-get $apt_options install open-vm-tools apt-get $apt_options install unzip apt-get $apt_options install uuid-dev + apt-get $apt_options install wget apt-get $apt_options install zlib-bin apt-get $apt_options install zlibc From 77a2a249c2f77121a7893f34c8406f2cc4896bb1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 20 Apr 2017 16:22:45 -0500 Subject: [PATCH 004/218] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 057937a0c..c30fe7eda 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,14 @@ * [Easy Install](http://wiki.eqemulator.org/p?Akkas_PEQ_Server_Installer&frm=Main#from-scratch-installation-instructions-windows) * [Advanced Setup](http://wiki.eqemulator.org/p?Complete_Windows-based_Server_Setup_Guide) -### > Debian/Ubuntu + + +### > Debian/Ubuntu/CentOS/Fedora +* You can use curl or wget to kick off the installer (whichever your OS has) +> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh > wget --no-check-certificate https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh -O install.sh && chmod 755 install.sh && ./install.sh -### > CentOS/Fedora - -> curl -O https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/linux_installer/install.sh install.sh && chmod 755 install.sh && ./install.sh - ## Supported Clients |Titanium Edition|Secrets of Faydwer|Seeds of Destruction|Underfoot|Rain of Fear| From 4d39c76c195326924a33b45753696f25138dd60b Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 21 Apr 2017 17:59:53 -0700 Subject: [PATCH 005/218] Remove some unused opts --- CMakeLists.txt | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53969c7ee..ce1a3bc9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,12 +13,6 @@ #EQEMU_LOG_LEVEL_QUEST #EQEMU_LOG_LEVEL_COMMANDS #EQEMU_LOG_LEVEL_CRASH -#EQEMU_STREAM_SEND_RATE -#EQEMU_STREAM_DECAY_RATE -#EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL -#EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX -#EQEMU_STREAM_AVERAGE_DELTA_MAX -#EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS #EQEMU_DEPOP_INVALIDATES_CACHE #EQEMU_ENABLE_BOTS #EQEMU_DISABLE_LOGSYS @@ -237,14 +231,6 @@ SET(EQEMU_LOG_LEVEL_CRASH 3 CACHE STRING "EQEmu logging level for [Crash]: MARK_AS_ADVANCED(EQEMU_LOG_LEVEL_STATUS EQEMU_LOG_LEVEL_NORMAL EQEMU_LOG_LEVEL_ERROR EQEMU_LOG_LEVEL_DEBUG EQEMU_LOG_LEVEL_QUEST EQEMU_LOG_LEVEL_COMMANDS EQEMU_LOG_LEVEL_CRASH) -SET(EQEMU_STREAM_SEND_RATE 1048576 CACHE STRING "Advanced: Base amount of data stream can send before throttle.") -SET(EQEMU_STREAM_DECAY_RATE 78642 CACHE STRING "Advanced: Base amount of data stream recovers per tic.") -SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL 3.0 CACHE STRING "Advanced: Multiplier on retransmit timeout.") -SET(EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX 5000 CACHE STRING "Advanced: Max in ms for retransmit timeout timer.") -SET(EQEMU_STREAM_AVERAGE_DELTA_MAX 2500 CACHE STRING "Advanced: The maximum average delta in ms allowed.") -SET(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS TRUE CACHE BOOL "Advanced: Whether or not acked packets can be retransmitted") -MARK_AS_ADVANCED(EQEMU_STREAM_SEND_RATE EQEMU_STREAM_DECAY_RATE EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX EQEMU_STREAM_AVERAGE_DELTA_MAX EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - #NPC Types Cache Behavior OPTION(EQEMU_DEPOP_INVALIDATES_CACHE "#repop invalidates the npc_types cache (will cause a larger database hit on #repop but is more convienent)." ON) @@ -306,11 +292,6 @@ ADD_DEFINITIONS(-DEQDEBUG=${EQEMU_DEBUG_LEVEL}) ADD_DEFINITIONS(-DINVERSEXY) ADD_DEFINITIONS(-DFIELD_ITEMS) ADD_DEFINITIONS(-DMAP_DIR="${EQEMU_MAP_DIR}") -ADD_DEFINITIONS(-DRATEBASE=${EQEMU_STREAM_SEND_RATE}) -ADD_DEFINITIONS(-DDECAYBASE=${EQEMU_STREAM_DECAY_RATE}) -ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MULT=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MUL}) -ADD_DEFINITIONS(-DRETRANSMIT_TIMEOUT_MAX=${EQEMU_STREAM_RETRANSMIT_TIMEOUT_MAX}) -ADD_DEFINITIONS(-DAVERAGE_DELTA_MAX=${EQEMU_STREAM_AVERAGE_DELTA_MAX}) ADD_DEFINITIONS(-DLOG_LEVEL_STATUS=${EQEMU_LOG_LEVEL_STATUS}) ADD_DEFINITIONS(-DLOG_LEVEL_NORMAL=${EQEMU_LOG_LEVEL_NORMAL}) ADD_DEFINITIONS(-DLOG_LEVEL_ERROR=${EQEMU_LOG_LEVEL_ERROR}) @@ -320,12 +301,6 @@ ADD_DEFINITIONS(-DLOG_LEVEL_COMMANDS=${EQEMU_LOG_LEVEL_COMMANDS}) ADD_DEFINITIONS(-DLOG_LEVEL_CRASH=${EQEMU_LOG_LEVEL_CRASH}) ADD_DEFINITIONS(-DGLM_FORCE_RADIANS) -IF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=true) -ELSE(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - ADD_DEFINITIONS(-DRETRANSMIT_ACKED_PACKETS=false) -ENDIF(EQEMU_STREAM_RETRANSMIT_ACKED_PACKETS) - #Find everything we need FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(MySQL REQUIRED) From 3b62cf9fd5cfdfaf04dd305f5e73f55ca47cb7ae Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 22 Apr 2017 16:40:01 -0700 Subject: [PATCH 006/218] Some work --- common/CMakeLists.txt | 4 ++ zone/attack.cpp | 10 +++++ zone/lua_parser.cpp | 95 ++++++++++++++++++++++++++++++++++++++++--- zone/lua_parser.h | 25 +++++++++++- zone/net.cpp | 7 +--- 5 files changed, 127 insertions(+), 14 deletions(-) diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 06486d2db..d65efd183 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -103,6 +103,7 @@ SET(common_sources tinyxml/tinyxml.cpp tinyxml/tinyxmlerror.cpp tinyxml/tinyxmlparser.cpp + util/directory.cpp util/uuid.cpp ) @@ -257,6 +258,7 @@ SET(common_headers tinyxml/tinystr.h tinyxml/tinyxml.h util/memory_stream.h + util/directory.h util/uuid.h ) @@ -366,6 +368,8 @@ SOURCE_GROUP(TinyXML FILES SOURCE_GROUP(Util FILES util/memory_stream.h + util/directory.cpp + util/directory.h util/uuid.cpp util/uuid.h ) diff --git a/zone/attack.cpp b/zone/attack.cpp index 2b9d081bf..0cdce489f 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "water_map.h" #include "worldserver.h" #include "zone.h" +#include "lua_parser.h" #include #include @@ -1237,6 +1238,15 @@ 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); + +#ifdef LUA_EQEMU + try { + LuaParser::Instance()->DoAttack(this, other, hit, opts); + } catch(IgnoreDefaultException) { + return; + } +#endif + // check to see if we hit.. if (other->AvoidDamage(this, hit)) { int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 92f0adbea..1b58379bb 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -10,8 +10,14 @@ #include #include -#include "masterentity.h" #include "../common/spdat.h" +#include "../common/util/directory.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,10 +37,6 @@ #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" const char *LuaEvents[_LargestEventID] = { @@ -135,6 +137,75 @@ std::map> lua_encounter_events_regi std::map lua_encounters_loaded; std::map lua_encounters; +void LuaParser::DoAttack(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) +{ + int start = lua_gettop(L); + bool ignoreDefault = false; + + for (auto &mod : mods_) { + try { + lua_getfield(L, LUA_REGISTRYINDEX, mod.c_str()); + lua_getfield(L, -1, "DoAttack"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + + luabind::adl::object e = luabind::newtable(L); + luabind::adl::object lua_hit = luabind::newtable(L); + lua_hit["base_damage"] = hit.base_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["self"] = luabind::adl::object(L, l_self); + e["other"] = luabind::adl::object(L, l_other); + e["hit"] = lua_hit; + 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; + } + else { + e["opts"] = luabind::nil; + } + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + AddError(error); + } + } + catch (std::exception &ex) { + std::string error = "Lua Exception: "; + error += std::string(ex.what()); + AddError(error); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + } + + if (ignoreDefault) { + throw IgnoreDefaultException(); + } +} + LuaParser::LuaParser() { for(int i = 0; i < _LargestEventID; ++i) { NPCArgumentDispatch[i] = handle_npc_null; @@ -797,6 +868,7 @@ void LuaParser::Init() { void LuaParser::ReloadQuests() { loaded_.clear(); errors_.clear(); + mods_.clear(); lua_encounter_events_registered.clear(); lua_encounters_loaded.clear(); @@ -828,7 +900,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"); @@ -949,6 +1021,17 @@ void LuaParser::ReloadQuests() { } } } + + EQ::Directory dir("mods"); + std::vector mods; + dir.GetFiles(mods); + + for (auto &mod : mods) { + if (mod.find_first_of(".lua") != std::string::npos) { + LoadScript("mods/" + mod, mod); + mods_.push_back(mod); + } + } } void LuaParser::LoadScript(std::string filename, std::string package_name) { diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 003c936ce..d23d963dd 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "zone_config.h" @@ -30,9 +31,17 @@ namespace luabind { } } +class IgnoreDefaultException : std::exception { +public: + IgnoreDefaultException() { }; + IgnoreDefaultException(const exception&) { }; + IgnoreDefaultException& operator= (const exception&) { return *this; } + virtual ~IgnoreDefaultException() { } + virtual const char* what() const { return "Ignore Default Action"; } +}; + class LuaParser : public QuestInterface { public: - LuaParser(); ~LuaParser(); virtual int EventNPC(QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, @@ -81,7 +90,19 @@ public: virtual int DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, uint32 spell_id, uint32 extra_data, std::vector *extra_pointers); + static LuaParser* Instance() { + static LuaParser inst; + return &inst; + } + + //Mod Extensions + void DoAttack(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts); + private: + LuaParser(); + LuaParser(const LuaParser&); + LuaParser& operator=(const LuaParser&); + int _EventNPC(std::string package_name, QuestEventID evt, NPC* npc, Mob *init, std::string data, uint32 extra_data, std::vector *extra_pointers, luabind::adl::object *l_func = nullptr); int _EventPlayer(std::string package_name, QuestEventID evt, Client *client, std::string data, uint32 extra_data, @@ -95,12 +116,12 @@ private: void LoadScript(std::string filename, std::string package_name); bool HasFunction(std::string function, std::string package_name); - void ClearStates(); void MapFunctions(lua_State *L); QuestEventID ConvertLuaEvent(QuestEventID evt); std::map vars_; std::map loaded_; + std::vector mods_; lua_State *L; NPCArgumentHandler NPCArgumentDispatch[_LargestEventID]; diff --git a/zone/net.cpp b/zone/net.cpp index 982b45d02..f51d50bb4 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -391,8 +391,7 @@ int main(int argc, char** argv) { parse = new QuestParserCollection(); #ifdef LUA_EQEMU - auto lua_parser = new LuaParser(); - parse->RegisterQuestInterface(lua_parser, "lua"); + parse->RegisterQuestInterface(LuaParser::Instance(), "lua"); #endif #ifdef EMBPERL @@ -565,10 +564,6 @@ int main(int argc, char** argv) { safe_delete(perl_parser); #endif -#ifdef LUA_EQEMU - safe_delete(lua_parser); -#endif - safe_delete(Config); if (zone != 0) From 7606ca2a0cb459672a02c9ac282c51f30affe39a Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 22 Apr 2017 16:40:34 -0700 Subject: [PATCH 007/218] Missed dir files --- common/util/directory.cpp | 42 ++ common/util/directory.h | 20 + common/util/win_dirent.h | 928 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 990 insertions(+) create mode 100644 common/util/directory.cpp create mode 100644 common/util/directory.h create mode 100644 common/util/win_dirent.h diff --git a/common/util/directory.cpp b/common/util/directory.cpp new file mode 100644 index 000000000..557a7a006 --- /dev/null +++ b/common/util/directory.cpp @@ -0,0 +1,42 @@ +#include "directory.h" + +#ifdef _WIN32 +#include "win_dirent.h" +#else +#include +#endif + +EQ::Directory::Directory(const std::string &path) +{ + m_dir = opendir(path.c_str()); +} + +EQ::Directory::~Directory() +{ + if (m_dir) { + closedir(m_dir); + } +} + +bool EQ::Directory::Exists() +{ + return m_dir != nullptr; +} + +void EQ::Directory::GetFiles(std::vector& files) +{ + if (m_dir) { + struct dirent *ent; + while ((ent = readdir(m_dir)) != nullptr) { + switch (ent->d_type) { + case DT_REG: + files.push_back(ent->d_name); + break; + default: + break; + } + } + + rewinddir(m_dir); + } +} diff --git a/common/util/directory.h b/common/util/directory.h new file mode 100644 index 000000000..aa4cc9ecb --- /dev/null +++ b/common/util/directory.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +struct DIR; + +namespace EQ { + class Directory + { + public: + Directory(const std::string &path); + ~Directory(); + + bool Exists(); + void GetFiles(std::vector &files); + private: + DIR *m_dir; + }; +} diff --git a/common/util/win_dirent.h b/common/util/win_dirent.h new file mode 100644 index 000000000..89f4df49f --- /dev/null +++ b/common/util/win_dirent.h @@ -0,0 +1,928 @@ +/* + * Dirent interface for Microsoft Visual Studio + * Version 1.21 + * + * Copyright (C) 2006-2012 Toni Ronkko + * This file is part of dirent. Dirent may be freely distributed + * under the MIT license. For all details and documentation, see + * https://github.com/tronkko/dirent + */ +#ifndef DIRENT_H +#define DIRENT_H + +/* + * Include windows.h without Windows Sockets 1.1 to prevent conflicts with + * Windows Sockets 2.0. + */ +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Indicates that d_type field is available in dirent structure */ +#define _DIRENT_HAVE_D_TYPE + +/* Indicates that d_namlen field is available in dirent structure */ +#define _DIRENT_HAVE_D_NAMLEN + +/* Entries missing from MSVC 6.0 */ +#if !defined(FILE_ATTRIBUTE_DEVICE) +# define FILE_ATTRIBUTE_DEVICE 0x40 +#endif + +/* File type and permission flags for stat(), general mask */ +#if !defined(S_IFMT) +# define S_IFMT _S_IFMT +#endif + +/* Directory bit */ +#if !defined(S_IFDIR) +# define S_IFDIR _S_IFDIR +#endif + +/* Character device bit */ +#if !defined(S_IFCHR) +# define S_IFCHR _S_IFCHR +#endif + +/* Pipe bit */ +#if !defined(S_IFFIFO) +# define S_IFFIFO _S_IFFIFO +#endif + +/* Regular file bit */ +#if !defined(S_IFREG) +# define S_IFREG _S_IFREG +#endif + +/* Read permission */ +#if !defined(S_IREAD) +# define S_IREAD _S_IREAD +#endif + +/* Write permission */ +#if !defined(S_IWRITE) +# define S_IWRITE _S_IWRITE +#endif + +/* Execute permission */ +#if !defined(S_IEXEC) +# define S_IEXEC _S_IEXEC +#endif + +/* Pipe */ +#if !defined(S_IFIFO) +# define S_IFIFO _S_IFIFO +#endif + +/* Block device */ +#if !defined(S_IFBLK) +# define S_IFBLK 0 +#endif + +/* Link */ +#if !defined(S_IFLNK) +# define S_IFLNK 0 +#endif + +/* Socket */ +#if !defined(S_IFSOCK) +# define S_IFSOCK 0 +#endif + +/* Read user permission */ +#if !defined(S_IRUSR) +# define S_IRUSR S_IREAD +#endif + +/* Write user permission */ +#if !defined(S_IWUSR) +# define S_IWUSR S_IWRITE +#endif + +/* Execute user permission */ +#if !defined(S_IXUSR) +# define S_IXUSR 0 +#endif + +/* Read group permission */ +#if !defined(S_IRGRP) +# define S_IRGRP 0 +#endif + +/* Write group permission */ +#if !defined(S_IWGRP) +# define S_IWGRP 0 +#endif + +/* Execute group permission */ +#if !defined(S_IXGRP) +# define S_IXGRP 0 +#endif + +/* Read others permission */ +#if !defined(S_IROTH) +# define S_IROTH 0 +#endif + +/* Write others permission */ +#if !defined(S_IWOTH) +# define S_IWOTH 0 +#endif + +/* Execute others permission */ +#if !defined(S_IXOTH) +# define S_IXOTH 0 +#endif + +/* Maximum length of file name */ +#if !defined(PATH_MAX) +# define PATH_MAX MAX_PATH +#endif +#if !defined(FILENAME_MAX) +# define FILENAME_MAX MAX_PATH +#endif +#if !defined(NAME_MAX) +# define NAME_MAX FILENAME_MAX +#endif + +/* File type flags for d_type */ +#define DT_UNKNOWN 0 +#define DT_REG S_IFREG +#define DT_DIR S_IFDIR +#define DT_FIFO S_IFIFO +#define DT_SOCK S_IFSOCK +#define DT_CHR S_IFCHR +#define DT_BLK S_IFBLK +#define DT_LNK S_IFLNK + +/* Macros for converting between st_mode and d_type */ +#define IFTODT(mode) ((mode) & S_IFMT) +#define DTTOIF(type) (type) + +/* + * File type macros. Note that block devices, sockets and links cannot be + * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are + * only defined for compatibility. These macros should always return false + * on Windows. + */ +#if !defined(S_ISFIFO) +# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif +#if !defined(S_ISDIR) +# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif +#if !defined(S_ISREG) +# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif +#if !defined(S_ISLNK) +# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK) +#endif +#if !defined(S_ISSOCK) +# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK) +#endif +#if !defined(S_ISCHR) +# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR) +#endif +#if !defined(S_ISBLK) +# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK) +#endif + +/* Return the exact length of d_namlen without zero terminator */ +#define _D_EXACT_NAMLEN(p) ((p)->d_namlen) + +/* Return number of bytes needed to store d_namlen */ +#define _D_ALLOC_NAMLEN(p) (PATH_MAX) + + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Wide-character version */ +struct _wdirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + wchar_t d_name[PATH_MAX]; +}; +typedef struct _wdirent _wdirent; + +struct _WDIR { + /* Current directory entry */ + struct _wdirent ent; + + /* Private file data */ + WIN32_FIND_DATAW data; + + /* True if data is valid */ + int cached; + + /* Win32 search handle */ + HANDLE handle; + + /* Initial directory name */ + wchar_t *patt; +}; +typedef struct _WDIR _WDIR; + +static _WDIR *_wopendir (const wchar_t *dirname); +static struct _wdirent *_wreaddir (_WDIR *dirp); +static int _wclosedir (_WDIR *dirp); +static void _wrewinddir (_WDIR* dirp); + + +/* For compatibility with Symbian */ +#define wdirent _wdirent +#define WDIR _WDIR +#define wopendir _wopendir +#define wreaddir _wreaddir +#define wclosedir _wclosedir +#define wrewinddir _wrewinddir + + +/* Multi-byte character versions */ +struct dirent { + /* Always zero */ + long d_ino; + + /* Structure size */ + unsigned short d_reclen; + + /* Length of name without \0 */ + size_t d_namlen; + + /* File type */ + int d_type; + + /* File name */ + char d_name[PATH_MAX]; +}; +typedef struct dirent dirent; + +struct DIR { + struct dirent ent; + struct _WDIR *wdirp; +}; +typedef struct DIR DIR; + +static DIR *opendir (const char *dirname); +static struct dirent *readdir (DIR *dirp); +static int closedir (DIR *dirp); +static void rewinddir (DIR* dirp); + + +/* Internal utility functions */ +static WIN32_FIND_DATAW *dirent_first (_WDIR *dirp); +static WIN32_FIND_DATAW *dirent_next (_WDIR *dirp); + +static int dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count); + +static int dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, + const wchar_t *wcstr, + size_t count); + +static void dirent_set_errno (int error); + +/* + * Open directory stream DIRNAME for read and return a pointer to the + * internal working area that is used to retrieve individual directory + * entries. + */ +static _WDIR* +_wopendir( + const wchar_t *dirname) +{ + _WDIR *dirp = NULL; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate new _WDIR structure */ + dirp = (_WDIR*) malloc (sizeof (struct _WDIR)); + if (dirp != NULL) { + DWORD n; + + /* Reset _WDIR structure */ + dirp->handle = INVALID_HANDLE_VALUE; + dirp->patt = NULL; + dirp->cached = 0; + + /* Compute the length of full path plus zero terminator + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + n = wcslen(dirname); +# else + n = GetFullPathNameW (dirname, 0, NULL, NULL); +# endif + + /* Allocate room for absolute directory name and search pattern */ + dirp->patt = (wchar_t*) malloc (sizeof (wchar_t) * n + 16); + if (dirp->patt) { + + /* + * Convert relative directory name to an absolute one. This + * allows rewinddir() to function correctly even when current + * working directory is changed between opendir() and rewinddir(). + * + * Note that on WinRT there's no way to convert relative paths + * into absolute paths, so just assume its an absolute path. + */ +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) + wcsncpy_s(dirp->patt, n+1, dirname, n); +# else + n = GetFullPathNameW (dirname, n, dirp->patt, NULL); +# endif + if (n > 0) { + wchar_t *p; + + /* Append search pattern \* to the directory name */ + p = dirp->patt + n; + if (dirp->patt < p) { + switch (p[-1]) { + case '\\': + case '/': + case ':': + /* Directory ends in path separator, e.g. c:\temp\ */ + /*NOP*/; + break; + + default: + /* Directory name doesn't end in path separator */ + *p++ = '\\'; + } + } + *p++ = '*'; + *p = '\0'; + + /* Open directory stream and retrieve the first entry */ + if (dirent_first (dirp)) { + /* Directory stream opened successfully */ + error = 0; + } else { + /* Cannot retrieve first entry */ + error = 1; + dirent_set_errno (ENOENT); + } + + } else { + /* Cannot retrieve full path name */ + dirent_set_errno (ENOENT); + error = 1; + } + + } else { + /* Cannot allocate memory for search pattern */ + error = 1; + } + + } else { + /* Cannot allocate _WDIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + _wclosedir (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. The directory entry is returned in dirent + * structure in the d_name field. Individual directory entries returned by + * this function include regular files, sub-directories, pseudo-directories + * "." and ".." as well as volume labels, hidden files and system files. + */ +static struct _wdirent* +_wreaddir( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct _wdirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp); + if (datap) { + size_t n; + DWORD attr; + + /* Pointer to directory entry to return */ + entp = &dirp->ent; + + /* + * Copy file name as wide-character string. If the file name is too + * long to fit in to the destination buffer, then truncate file name + * to PATH_MAX characters and zero-terminate the buffer. + */ + n = 0; + while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) { + entp->d_name[n] = datap->cFileName[n]; + n++; + } + dirp->ent.d_name[n] = 0; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n; + + /* File type */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct _wdirent); + + } else { + + /* Last directory entry read */ + entp = NULL; + + } + + return entp; +} + +/* + * Close directory stream opened by opendir() function. This invalidates the + * DIR structure as well as any directory entry read previously by + * _wreaddir(). + */ +static int +_wclosedir( + _WDIR *dirp) +{ + int ok; + if (dirp) { + + /* Release search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + } + + /* Release search pattern */ + if (dirp->patt) { + free (dirp->patt); + dirp->patt = NULL; + } + + /* Release directory structure */ + free (dirp); + ok = /*success*/0; + + } else { + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + } + return ok; +} + +/* + * Rewind directory stream such that _wreaddir() returns the very first + * file name again. + */ +static void +_wrewinddir( + _WDIR* dirp) +{ + if (dirp) { + /* Release existing search handle */ + if (dirp->handle != INVALID_HANDLE_VALUE) { + FindClose (dirp->handle); + } + + /* Open new search handle */ + dirent_first (dirp); + } +} + +/* Get first directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_first( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *datap; + + /* Open directory and retrieve the first entry */ + dirp->handle = FindFirstFileExW( + dirp->patt, FindExInfoStandard, &dirp->data, + FindExSearchNameMatch, NULL, 0); + if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* a directory entry is now waiting in memory */ + datap = &dirp->data; + dirp->cached = 1; + + } else { + + /* Failed to re-open directory: no directory entry in memory */ + dirp->cached = 0; + datap = NULL; + + } + return datap; +} + +/* Get next directory entry (internal) */ +static WIN32_FIND_DATAW* +dirent_next( + _WDIR *dirp) +{ + WIN32_FIND_DATAW *p; + + /* Get next directory entry */ + if (dirp->cached != 0) { + + /* A valid directory entry already in memory */ + p = &dirp->data; + dirp->cached = 0; + + } else if (dirp->handle != INVALID_HANDLE_VALUE) { + + /* Get the next directory entry from stream */ + if (FindNextFileW (dirp->handle, &dirp->data) != FALSE) { + /* Got a file */ + p = &dirp->data; + } else { + /* The very last entry has been processed or an error occured */ + FindClose (dirp->handle); + dirp->handle = INVALID_HANDLE_VALUE; + p = NULL; + } + + } else { + + /* End of directory stream reached */ + p = NULL; + + } + + return p; +} + +/* + * Open directory stream using plain old C-string. + */ +static DIR* +opendir( + const char *dirname) +{ + struct DIR *dirp; + int error; + + /* Must have directory name */ + if (dirname == NULL || dirname[0] == '\0') { + dirent_set_errno (ENOENT); + return NULL; + } + + /* Allocate memory for DIR structure */ + dirp = (DIR*) malloc (sizeof (struct DIR)); + if (dirp) { + wchar_t wname[PATH_MAX]; + size_t n; + + /* Convert directory name to wide-character string */ + error = dirent_mbstowcs_s (&n, wname, PATH_MAX, dirname, PATH_MAX); + if (!error) { + + /* Open directory stream using wide-character name */ + dirp->wdirp = _wopendir (wname); + if (dirp->wdirp) { + /* Directory stream opened */ + error = 0; + } else { + /* Failed to open directory stream */ + error = 1; + } + + } else { + /* + * Cannot convert file name to wide-character string. This + * occurs if the string contains invalid multi-byte sequences or + * the output buffer is too small to contain the resulting + * string. + */ + error = 1; + } + + } else { + /* Cannot allocate DIR structure */ + error = 1; + } + + /* Clean up in case of error */ + if (error && dirp) { + free (dirp); + dirp = NULL; + } + + return dirp; +} + +/* + * Read next directory entry. + * + * When working with text consoles, please note that file names returned by + * readdir() are represented in the default ANSI code page while any output to + * console is typically formatted on another code page. Thus, non-ASCII + * characters in file names will not usually display correctly on console. The + * problem can be fixed in two ways: (1) change the character set of console + * to 1252 using chcp utility and use Lucida Console font, or (2) use + * _cprintf function when writing to console. The _cprinf() will re-encode + * ANSI strings to the console code page so many non-ASCII characters will + * display correcly. + */ +static struct dirent* +readdir( + DIR *dirp) +{ + WIN32_FIND_DATAW *datap; + struct dirent *entp; + + /* Read next directory entry */ + datap = dirent_next (dirp->wdirp); + if (datap) { + size_t n; + int error; + + /* Attempt to convert file name to multi-byte string */ + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX); + + /* + * If the file name cannot be represented by a multi-byte string, + * then attempt to use old 8+3 file name. This allows traditional + * Unix-code to access some file names despite of unicode + * characters, although file names may seem unfamiliar to the user. + * + * Be ware that the code below cannot come up with a short file + * name unless the file system provides one. At least + * VirtualBox shared folders fail to do this. + */ + if (error && datap->cAlternateFileName[0] != '\0') { + error = dirent_wcstombs_s( + &n, dirp->ent.d_name, PATH_MAX, + datap->cAlternateFileName, PATH_MAX); + } + + if (!error) { + DWORD attr; + + /* Initialize directory entry for return */ + entp = &dirp->ent; + + /* Length of file name excluding zero terminator */ + entp->d_namlen = n - 1; + + /* File attributes */ + attr = datap->dwFileAttributes; + if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) { + entp->d_type = DT_CHR; + } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + entp->d_type = DT_DIR; + } else { + entp->d_type = DT_REG; + } + + /* Reset dummy fields */ + entp->d_ino = 0; + entp->d_reclen = sizeof (struct dirent); + + } else { + /* + * Cannot convert file name to multi-byte string so construct + * an errornous directory entry and return that. Note that + * we cannot return NULL as that would stop the processing + * of directory entries completely. + */ + entp = &dirp->ent; + entp->d_name[0] = '?'; + entp->d_name[1] = '\0'; + entp->d_namlen = 1; + entp->d_type = DT_UNKNOWN; + entp->d_ino = 0; + entp->d_reclen = 0; + } + + } else { + /* No more directory entries */ + entp = NULL; + } + + return entp; +} + +/* + * Close directory stream. + */ +static int +closedir( + DIR *dirp) +{ + int ok; + if (dirp) { + + /* Close wide-character directory stream */ + ok = _wclosedir (dirp->wdirp); + dirp->wdirp = NULL; + + /* Release multi-byte character version */ + free (dirp); + + } else { + + /* Invalid directory stream */ + dirent_set_errno (EBADF); + ok = /*failure*/-1; + + } + return ok; +} + +/* + * Rewind directory stream to beginning. + */ +static void +rewinddir( + DIR* dirp) +{ + /* Rewind wide-character string directory stream */ + _wrewinddir (dirp->wdirp); +} + +/* Convert multi-byte string to wide character string */ +static int +dirent_mbstowcs_s( + size_t *pReturnValue, + wchar_t *wcstr, + size_t sizeInWords, + const char *mbstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = mbstowcs_s (pReturnValue, wcstr, sizeInWords, mbstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to wide-character string (or count characters) */ + n = mbstowcs (wcstr, mbstr, sizeInWords); + if (!wcstr || n < count) { + + /* Zero-terminate output buffer */ + if (wcstr && sizeInWords) { + if (n >= sizeInWords) { + n = sizeInWords - 1; + } + wcstr[n] = 0; + } + + /* Length of resuting multi-byte string WITH zero terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Could not convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Convert wide-character string to multi-byte string */ +static int +dirent_wcstombs_s( + size_t *pReturnValue, + char *mbstr, + size_t sizeInBytes, /* max size of mbstr */ + const wchar_t *wcstr, + size_t count) +{ + int error; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 or later */ + error = wcstombs_s (pReturnValue, mbstr, sizeInBytes, wcstr, count); + +#else + + /* Older Visual Studio or non-Microsoft compiler */ + size_t n; + + /* Convert to multi-byte string (or count the number of bytes needed) */ + n = wcstombs (mbstr, wcstr, sizeInBytes); + if (!mbstr || n < count) { + + /* Zero-terminate output buffer */ + if (mbstr && sizeInBytes) { + if (n >= sizeInBytes) { + n = sizeInBytes - 1; + } + mbstr[n] = '\0'; + } + + /* Length of resulting multi-bytes string WITH zero-terminator */ + if (pReturnValue) { + *pReturnValue = n + 1; + } + + /* Success */ + error = 0; + + } else { + + /* Cannot convert string */ + error = 1; + + } + +#endif + + return error; +} + +/* Set errno variable */ +static void +dirent_set_errno( + int error) +{ +#if defined(_MSC_VER) && _MSC_VER >= 1400 + + /* Microsoft Visual Studio 2005 and later */ + _set_errno (error); + +#else + + /* Non-Microsoft compiler or older Microsoft compiler */ + errno = error; + +#endif +} + + +#ifdef __cplusplus +} +#endif +#endif /*DIRENT_H*/ From 36be32f36f4fa2a5fecd36d733d549049c5d070d Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sun, 23 Apr 2017 01:57:08 -0700 Subject: [PATCH 008/218] Change item effects to int32 Check range on AEDuration spells --- common/item_data.h | 2 +- zone/spells.cpp | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/common/item_data.h b/common/item_data.h index e5d1a24f2..ae7e3bbdb 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -332,7 +332,7 @@ namespace EQEmu }; struct ItemEffect_Struct { - int16 Effect; + int32 Effect; uint8 Type; uint8 Level; uint8 Level2; diff --git a/zone/spells.cpp b/zone/spells.cpp index 001c6895c..2be0a0bce 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2140,6 +2140,27 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui spell_target->CalcSpellPowerDistanceMod(spell_id, dist2); } + //AE Duration spells were ignoring distance check from item clickies + if(ae_center != nullptr && ae_center != this) { + //casting a spell on somebody but ourself, make sure they are in range + float dist2 = DistanceSquared(m_Position, ae_center->GetPosition()); + float range2 = range * range; + float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; + if(dist2 > range2) { + //target is out of range. + Log(Logs::Detail, Logs::Spells, "Spell %d: Spell target is out of range (squared: %f > %f)", spell_id, dist2, range2); + Message_StringID(13, TARGET_OUT_OF_RANGE); + return(false); + } + else if (dist2 < min_range2){ + //target is too close range. + Log(Logs::Detail, Logs::Spells, "Spell %d: Spell target is too close (squared: %f < %f)", spell_id, dist2, min_range2); + Message_StringID(13, TARGET_TOO_CLOSE); + return(false); + } + + ae_center->CalcSpellPowerDistanceMod(spell_id, dist2); + } // // Switch #2 - execute the spell From e15f8a2cb646ab2110d352dfdc86e7d14e846e88 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 23 Apr 2017 13:26:21 -0400 Subject: [PATCH 009/218] Fix some OOZ group disband issues --- zone/groups.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/groups.cpp b/zone/groups.cpp index d2342b4d9..6216de4ac 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -648,7 +648,7 @@ bool Group::DelMember(Mob* oldmember, bool ignoresender) } } - if (GetLeader() == nullptr) + if (!GetLeaderName()) { DisbandGroup(); return true; From f75e48b1e7f08da64bd2d3cabff2d5f12054f1ec Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 23 Apr 2017 12:52:47 -0500 Subject: [PATCH 010/218] Update Fedora package install method Split each package install out to its own line. This will cause the install to iterate though the package manager for each package installation. This will take a bit longer but will be less stringent. A package can be missing and not cause the others to fail. --- utils/scripts/linux_installer/install.sh | 28 ++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 12db7d6a2..5673508c3 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -150,8 +150,32 @@ EOF elif [[ "$OS" == "fedora_core" ]]; then # Do Fedora stuff - dnf -y install open-vm-tools vim cmake boost-devel zlib-devel mariadb-server mariadb-devel mariadb-libs perl perl-DBD-MySQL perl-IO-stringy perl-devel lua-devel lua-sql-mysql dos2unix php-mysql proftpd wget compat-lua-libs compat-lua-devel compat-lua perl-Time-HiRes - dnf -y groupinstall "Development Tools" "Basic Web Server" "C Development Tools and Libraries" + dnf -y install open-vm-tools + dnf -y install vim + dnf -y install cmake + dnf -y install boost-devel + dnf -y install zlib-devel + dnf -y install mariadb-server + dnf -y install mariadb-devel + dnf -y install mariadb-libs + dnf -y install perl + dnf -y install perl-DBD-MySQL + dnf -y install perl-IO-stringy + dnf -y install perl-devel + dnf -y install lua-devel + dnf -y install lua-sql-mysql + dnf -y install dos2unix + dnf -y install php-mysql + dnf -y install php-mysqlnd + dnf -y install proftpd + dnf -y install wget + dnf -y install compat-lua-libs + dnf -y install compat-lua-devel + dnf -y install compat-lua + dnf -y install perl-Time-HiRes + dnf -y groupinstall "Development Tools" + dnf -y groupinstall "Basic Web Server" + dnf -y groupinstall "C Development Tools and Libraries" fi if [[ "$OS" == "fedora_core" ]] || [[ "$OS" == "red_hat" ]]; then From 33202070864179c047276a42543b4adfe32de5ef Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 23 Apr 2017 14:56:22 -0500 Subject: [PATCH 011/218] Install uuid dev package --- utils/scripts/linux_installer/install.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 5673508c3..ffc06bc30 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -173,6 +173,7 @@ elif [[ "$OS" == "fedora_core" ]]; then dnf -y install compat-lua-devel dnf -y install compat-lua dnf -y install perl-Time-HiRes + dnf -y install libuuid-devel dnf -y groupinstall "Development Tools" dnf -y groupinstall "Basic Web Server" dnf -y groupinstall "C Development Tools and Libraries" From 208918b57f72388ee062ad6aac2df63135899c60 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 23 Apr 2017 15:19:40 -0500 Subject: [PATCH 012/218] Added Sodium libraries to FC25 --- utils/scripts/linux_installer/install.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index ffc06bc30..e23d6f582 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -174,6 +174,8 @@ elif [[ "$OS" == "fedora_core" ]]; then dnf -y install compat-lua dnf -y install perl-Time-HiRes dnf -y install libuuid-devel + dnf -y install libsodium + dnf -y install libsodium-devel dnf -y groupinstall "Development Tools" dnf -y groupinstall "Basic Web Server" dnf -y groupinstall "C Development Tools and Libraries" From 05ee69de557f20f91199358f3ef825cab1997cfe Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Sun, 23 Apr 2017 15:53:29 -0500 Subject: [PATCH 013/218] Added Sodium libraries to Ubuntu/Debian --- utils/scripts/linux_installer/install.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index e23d6f582..0b0a84640 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -117,6 +117,8 @@ if [[ "$OS" == "Debian" ]]; then apt-get $apt_options install wget apt-get $apt_options install zlib-bin apt-get $apt_options install zlibc + apt-get $apt_options install libsodium-dev + apt-get $apt_options install libsodium18 #::: Install FTP for remote FTP access echo "proftpd-basic shared/proftpd/inetd_or_standalone select standalone" | debconf-set-selections From 78a73cab857e928e94000502776a82f7dd5d5bde Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 23 Apr 2017 21:58:56 -0700 Subject: [PATCH 014/218] Work on lua parser --- zone/lua_parser.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 1b58379bb..201563ec9 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -187,6 +187,8 @@ void LuaParser::DoAttack(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackO std::string error = lua_tostring(L, -1); AddError(error); } + + } catch (std::exception &ex) { std::string error = "Lua Exception: "; From 8a6c37f2d43371c711d4188084dccc8b75f36ab9 Mon Sep 17 00:00:00 2001 From: Kurt Gilpin Date: Mon, 24 Apr 2017 21:29:36 -0500 Subject: [PATCH 015/218] Sodium library install on Debian --- utils/scripts/linux_installer/install.sh | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 0b0a84640..55972e8c8 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -119,7 +119,19 @@ if [[ "$OS" == "Debian" ]]; then apt-get $apt_options install zlibc apt-get $apt_options install libsodium-dev apt-get $apt_options install libsodium18 - + + # If libsodium18 isn't installed (Debian), let's download both that and the dev package and install them. + if dpkg-query -s "libsodium18" 1>/dev/null 2>&1; then + echo "Sodium library already installed." + else + wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium-dev_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium-dev.deb + wget http://ftp.us.debian.org/debian/pool/main/libs/libsodium/libsodium18_1.0.11-1~bpo8+1_amd64.deb -O /home/eqemu/libsodium18.deb + dpkg -i /home/eqemu/libsodium*.deb + # Cleanup after ourselves + rm -f /home/eqemu/libsodium-dev.deb + rm -f /home/eqemu/libsodium18.deb + fi + #::: Install FTP for remote FTP access echo "proftpd-basic shared/proftpd/inetd_or_standalone select standalone" | debconf-set-selections apt-get -y -q install proftpd From 34549a4bdb163a1b5a33146807f5304c4c24410d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 25 Apr 2017 02:13:31 -0400 Subject: [PATCH 016/218] Change clientpackets to std::deque from LinkedList This should be better performance, but I couldn't really push local testing to hit the performance issues ... --- zone/client.cpp | 18 ++++++++---------- zone/client.h | 3 ++- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index e2a94638e..2321797e3 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -697,12 +697,13 @@ bool Client::AddPacket(const EQApplicationPacket *pApp, bool bAckreq) { //drop the packet because it will never get sent. return(false); } - auto c = new CLIENTPACKET; + + auto c = std::unique_ptr(new CLIENTPACKET); c->ack_req = bAckreq; c->app = pApp->Copy(); - clientpackets.Append(c); + clientpackets.push_back(std::move(c)); return true; } @@ -714,26 +715,23 @@ bool Client::AddPacket(EQApplicationPacket** pApp, bool bAckreq) { //drop the packet because it will never get sent. return(false); } - auto c = new CLIENTPACKET; + auto c = std::unique_ptr(new CLIENTPACKET); c->ack_req = bAckreq; c->app = *pApp; *pApp = nullptr; - clientpackets.Append(c); + clientpackets.push_back(std::move(c)); return true; } bool Client::SendAllPackets() { - LinkedListIterator iterator(clientpackets); - CLIENTPACKET* cp = nullptr; - iterator.Reset(); - while(iterator.MoreElements()) { - cp = iterator.GetData(); + while (!clientpackets.empty()) { + cp = clientpackets.front().get(); if(eqs) eqs->FastQueuePacket((EQApplicationPacket **)&cp->app, cp->ack_req); - iterator.RemoveCurrent(); + clientpackets.pop_front(); Log(Logs::Moderate, Logs::Client_Server_Packet, "Transmitting a packet"); } return true; diff --git a/zone/client.h b/zone/client.h index aeabbd63a..f47ac2b31 100644 --- a/zone/client.h +++ b/zone/client.h @@ -70,6 +70,7 @@ namespace EQEmu #include #include #include +#include #define CLIENT_TIMEOUT 90000 @@ -1424,7 +1425,7 @@ private: bool AddPacket(const EQApplicationPacket *, bool); bool AddPacket(EQApplicationPacket**, bool); bool SendAllPackets(); - LinkedList clientpackets; + std::deque> clientpackets; //Zoning related stuff void SendZoneCancel(ZoneChange_Struct *zc); From 6d59baffaf334cae98366cb72afd48d8933640e3 Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 26 Apr 2017 22:56:18 -0700 Subject: [PATCH 017/218] Basic mod setup only supports combat hooks for now I'll add a few more before i push this --- common/net/daybreak_connection.cpp | 10 +- common/net/daybreak_connection.h | 8 +- zone/CMakeLists.txt | 2 + zone/attack.cpp | 46 +- zone/lua_mob.cpp | 44 +- zone/lua_mob.h | 7 + zone/lua_parser.cpp | 489 +++++++-- zone/lua_parser.h | 14 +- zone/lua_stat_bonuses.cpp | 1539 ++++++++++++++++++++++++++++ zone/lua_stat_bonuses.h | 285 ++++++ zone/mob.h | 3 + 11 files changed, 2322 insertions(+), 125 deletions(-) create mode 100644 zone/lua_stat_bonuses.cpp create mode 100644 zone/lua_stat_bonuses.h diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 68fc24ad2..b203c0155 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -277,7 +277,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_encode_passes[1] = owner->m_options.encode_passes[1]; m_hold_time = Clock::now(); m_buffered_packets_length = 0; - m_rolling_ping = 500; + m_rolling_ping = 900; m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms; m_combined.reset(new char[512]); m_combined[0] = 0; @@ -300,7 +300,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_crc_bytes = 0; m_hold_time = Clock::now(); m_buffered_packets_length = 0; - m_rolling_ping = 500; + m_rolling_ping = 900; m_resend_delay = (m_rolling_ping * m_owner->m_options.resend_delay_factor) + m_owner->m_options.resend_delay_ms; m_combined.reset(new char[512]); m_combined[0] = 0; @@ -1026,7 +1026,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + m_rolling_ping += 300; } } else { @@ -1040,7 +1040,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + m_rolling_ping += 300; } } } @@ -1061,7 +1061,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; + m_rolling_ping = (m_rolling_ping * 3 + round_time) / 4; iter = s->sent_packets.erase(iter); } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 409471589..ecbd1569c 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -205,10 +205,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 = 300; + resend_delay_max = 6000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -282,4 +282,4 @@ namespace EQ friend class DaybreakConnection; }; } -} \ No newline at end of file +} diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index b267ae11b..afa58f50c 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -59,6 +59,7 @@ SET(zone_sources lua_raid.cpp lua_spawn.cpp lua_spell.cpp + lua_stat_bonuses.cpp embperl.cpp embxs.cpp entity.cpp @@ -182,6 +183,7 @@ SET(zone_headers lua_raid.h lua_spawn.h lua_spell.h + lua_stat_bonuses.h map.h masterentity.h maxskill.h diff --git a/zone/attack.cpp b/zone/attack.cpp index 0cdce489f..b0465553a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -272,6 +272,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()); @@ -302,6 +312,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. * @@ -872,6 +892,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; @@ -1239,14 +1268,6 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) 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); -#ifdef LUA_EQEMU - try { - LuaParser::Instance()->DoAttack(this, other, hit, opts); - } catch(IgnoreDefaultException) { - return; - } -#endif - // check to see if we hit.. if (other->AvoidDamage(this, hit)) { int strike_through = itembonuses.StrikeThrough + spellbonuses.StrikeThrough + aabonuses.StrikeThrough; @@ -4537,6 +4558,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 diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 190db1f18..86c8f564c 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -10,6 +10,7 @@ #include "lua_mob.h" #include "lua_hate_list.h" #include "lua_client.h" +#include "lua_stat_bonuses.h" struct SpecialAbilities { }; @@ -1985,6 +1986,41 @@ 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); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2330,7 +2366,13 @@ 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); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 08502b1a9..f83583ac3 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -8,6 +8,7 @@ class Mob; struct Lua_HateList; class Lua_Item; class Lua_ItemInst; +class Lua_StatBonuses; namespace luabind { struct scope; @@ -381,6 +382,12 @@ 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); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 201563ec9..12a02623e 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -11,7 +11,6 @@ #include #include "../common/spdat.h" -#include "../common/util/directory.h" #include "masterentity.h" #include "questmgr.h" #include "zone.h" @@ -38,6 +37,7 @@ #include "lua_packet.h" #include "lua_general.h" #include "lua_encounter.h" +#include "lua_stat_bonuses.h" const char *LuaEvents[_LargestEventID] = { "event_say", @@ -137,77 +137,6 @@ std::map> lua_encounter_events_regi std::map lua_encounters_loaded; std::map lua_encounters; -void LuaParser::DoAttack(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) -{ - int start = lua_gettop(L); - bool ignoreDefault = false; - - for (auto &mod : mods_) { - try { - lua_getfield(L, LUA_REGISTRYINDEX, mod.c_str()); - lua_getfield(L, -1, "DoAttack"); - - Lua_Mob l_self(self); - Lua_Mob l_other(other); - - luabind::adl::object e = luabind::newtable(L); - luabind::adl::object lua_hit = luabind::newtable(L); - lua_hit["base_damage"] = hit.base_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["self"] = luabind::adl::object(L, l_self); - e["other"] = luabind::adl::object(L, l_other); - e["hit"] = lua_hit; - 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; - } - else { - e["opts"] = luabind::nil; - } - - e.push(L); - - if (lua_pcall(L, 1, 1, 0)) { - std::string error = lua_tostring(L, -1); - AddError(error); - } - - - } - catch (std::exception &ex) { - std::string error = "Lua Exception: "; - error += std::string(ex.what()); - AddError(error); - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - } - - if (ignoreDefault) { - throw IgnoreDefaultException(); - } -} - LuaParser::LuaParser() { for(int i = 0; i < _LargestEventID; ++i) { NPCArgumentDispatch[i] = handle_npc_null; @@ -877,6 +806,7 @@ void LuaParser::ReloadQuests() { 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 @@ -889,6 +819,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); @@ -1005,35 +937,41 @@ 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); + } } } } - EQ::Directory dir("mods"); - std::vector mods; - dir.GetFiles(mods); - - for (auto &mod : mods) { - if (mod.find_first_of(".lua") != std::string::npos) { - LoadScript("mods/" + mod, mod); - mods_.push_back(mod); + 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) { + LoadScript("mods/" + std::string(file_name), file_name); + mods_.push_back(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) { @@ -1042,6 +980,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); @@ -1069,14 +1008,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()) { @@ -1137,7 +1082,8 @@ 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() ]; } catch(std::exception &ex) { @@ -1310,6 +1256,355 @@ int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, ui return ret; } +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["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 damage_done = luaHitTable["damage_done"]; + auto offense = luaHitTable["offense"]; + auto tohit = luaHitTable["tohit"]; + auto hand = luaHitTable["hand"]; + auto skill = luaHitTable["skill"]; + + if (luabind::type(base_damage) == LUA_TNUMBER) { + hit.base_damage = luabind::object_cast(base_damage); + } + + if (luabind::type(damage_done) == LUA_TNUMBER) { + hit.damage_done = luabind::object_cast(damage_done); + } + + if (luabind::type(offense) == LUA_TNUMBER) { + hit.offense = luabind::object_cast(offense); + } + + if (luabind::type(tohit) == LUA_TNUMBER) { + hit.tohit = luabind::object_cast(tohit); + } + + if (luabind::type(hand) == LUA_TNUMBER) { + hit.hand = luabind::object_cast(hand); + } + + if (luabind::type(skill) == LUA_TNUMBER) { + hit.skill = (EQEmu::skills::SkillType)luabind::object_cast(skill); + } + } +} + +void PutExtraAttackOptions(lua_State *L, luabind::adl::object &e, ExtraAttackOptions *opts) { + if (opts) { + luabind::adl::object lua_opts = luabind::newtable(L); + lua_opts["damage_percent"] = opts->damage_percent; + lua_opts["damage_flat"] = opts->damage_flat; + lua_opts["armor_pen_percent"] = opts->armor_pen_percent; + lua_opts["armor_pen_flat"] = opts->armor_pen_flat; + lua_opts["crit_percent"] = opts->crit_percent; + lua_opts["crit_flat"] = opts->crit_flat; + lua_opts["hate_percent"] = opts->hate_percent; + lua_opts["hate_flat"] = opts->hate_flat; + lua_opts["hit_chance"] = opts->hit_chance; + lua_opts["melee_damage_bonus_flat"] = opts->melee_damage_bonus_flat; + lua_opts["skilldmgtaken_bonus_flat"] = opts->skilldmgtaken_bonus_flat; + e["opts"] = lua_opts; + } +} + +void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) { + if (opts) { + auto luaOptsTable = ret["opts"]; + if (luabind::type(luaOptsTable) == LUA_TTABLE) { + auto damage_percent = luaOptsTable["damage_percent"]; + auto damage_flat = luaOptsTable["damage_flat"]; + auto armor_pen_percent = luaOptsTable["armor_pen_percent"]; + auto armor_pen_flat = luaOptsTable["armor_pen_flat"]; + auto crit_percent = luaOptsTable["crit_percent"]; + auto crit_flat = luaOptsTable["crit_flat"]; + auto hate_percent = luaOptsTable["hate_percent"]; + auto hate_flat = luaOptsTable["hate_flat"]; + auto hit_chance = luaOptsTable["hit_chance"]; + auto melee_damage_bonus_flat = luaOptsTable["melee_damage_bonus_flat"]; + auto skilldmgtaken_bonus_flat = luaOptsTable["skilldmgtaken_bonus_flat"]; + + if (luabind::type(damage_percent) == LUA_TNUMBER) { + opts->damage_percent = luabind::object_cast(damage_percent); + } + + if (luabind::type(damage_flat) == LUA_TNUMBER) { + opts->damage_flat = luabind::object_cast(damage_flat); + } + + if (luabind::type(armor_pen_percent) == LUA_TNUMBER) { + opts->armor_pen_percent = luabind::object_cast(armor_pen_percent); + } + + if (luabind::type(armor_pen_flat) == LUA_TNUMBER) { + opts->armor_pen_flat = luabind::object_cast(armor_pen_flat); + } + + if (luabind::type(crit_percent) == LUA_TNUMBER) { + opts->crit_percent = luabind::object_cast(crit_percent); + } + + if (luabind::type(crit_flat) == LUA_TNUMBER) { + opts->crit_flat = luabind::object_cast(crit_flat); + } + + if (luabind::type(hate_percent) == LUA_TNUMBER) { + opts->hate_percent = luabind::object_cast(hate_percent); + } + + if (luabind::type(hate_flat) == LUA_TNUMBER) { + opts->hate_flat = luabind::object_cast(hate_flat); + } + + if (luabind::type(hit_chance) == LUA_TNUMBER) { + opts->hit_chance = luabind::object_cast(hit_chance); + } + + if (luabind::type(melee_damage_bonus_flat) == LUA_TNUMBER) { + opts->melee_damage_bonus_flat = luabind::object_cast(melee_damage_bonus_flat); + } + + if (luabind::type(skilldmgtaken_bonus_flat) == LUA_TNUMBER) { + opts->skilldmgtaken_bonus_flat = luabind::object_cast(skilldmgtaken_bonus_flat); + } + } + } +} + +void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + + for (auto &mod : mods_) { + try { + if (!HasFunction("MeleeMitigation", mod)) { + continue; + } + + lua_getfield(L, LUA_REGISTRYINDEX, mod.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); + AddError(error); + lua_pop(L, 1); + continue; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + AddError(ex.what()); + } + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaParser::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + + for (auto &mod : mods_) { + try { + if (!HasFunction("ApplyDamageTable", mod)) { + continue; + } + + lua_getfield(L, LUA_REGISTRYINDEX, mod.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); + AddError(error); + lua_pop(L, 1); + continue; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + AddError(ex.what()); + } + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +bool LuaParser::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + for (auto &mod : mods_) { + try { + if (!HasFunction("AvoidDamage", mod)) { + continue; + } + + lua_getfield(L, LUA_REGISTRYINDEX, mod.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); + AddError(error); + lua_pop(L, 1); + continue; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + retval = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + AddError(ex.what()); + } + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +bool LuaParser::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + for (auto &mod : mods_) { + try { + if (!HasFunction("CheckHitChance", mod)) { + continue; + } + + lua_getfield(L, LUA_REGISTRYINDEX, mod.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); + AddError(error); + lua_pop(L, 1); + continue; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + retval = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + AddError(ex.what()); + } + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { switch(evt) { case EVENT_SLAY: diff --git a/zone/lua_parser.h b/zone/lua_parser.h index d23d963dd..a0f0fea89 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -31,15 +31,6 @@ namespace luabind { } } -class IgnoreDefaultException : std::exception { -public: - IgnoreDefaultException() { }; - IgnoreDefaultException(const exception&) { }; - IgnoreDefaultException& operator= (const exception&) { return *this; } - virtual ~IgnoreDefaultException() { } - virtual const char* what() const { return "Ignore Default Action"; } -}; - class LuaParser : public QuestInterface { public: ~LuaParser(); @@ -96,7 +87,10 @@ public: } //Mod Extensions - void DoAttack(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts); + 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); private: LuaParser(); diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp new file mode 100644 index 000000000..bf3f22586 --- /dev/null +++ b/zone/lua_stat_bonuses.cpp @@ -0,0 +1,1539 @@ +#include "lua.hpp" +#include + +#include "lua_stat_bonuses.h" + +int32 Lua_StatBonuses::GetAC() const { + Lua_Safe_Call_Int(); + return self->AC; +} + +int32 Lua_StatBonuses::GetHP() const { + Lua_Safe_Call_Int(); + return self->HP; +} + +int32 Lua_StatBonuses::GetHPRegen() const { + Lua_Safe_Call_Int(); + return self->HPRegen; +} + +int32 Lua_StatBonuses::GetMaxHP() const { + Lua_Safe_Call_Int(); + return self->MaxHP; +} + +int32 Lua_StatBonuses::GetManaRegen() const { + Lua_Safe_Call_Int(); + return self->ManaRegen; +} + +int32 Lua_StatBonuses::GetEnduranceRegen() const { + Lua_Safe_Call_Int(); + return self->EnduranceRegen; +} + +int32 Lua_StatBonuses::GetMana() const { + Lua_Safe_Call_Int(); + return self->Mana; +} + +int32 Lua_StatBonuses::GetEndurance() const { + Lua_Safe_Call_Int(); + return self->Endurance; +} + +int32 Lua_StatBonuses::GetATK() const { + Lua_Safe_Call_Int(); + return self->ATK; +} + +int32 Lua_StatBonuses::GetSTR() const { + Lua_Safe_Call_Int(); + return self->STR; +} + +int32 Lua_StatBonuses::GetSTRCapMod() const { + Lua_Safe_Call_Int(); + return self->STRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicSTR() const { + Lua_Safe_Call_Int(); + return self->HeroicSTR; +} + +int32 Lua_StatBonuses::GetSTA() const { + Lua_Safe_Call_Int(); + return self->STA; +} + +int32 Lua_StatBonuses::GetSTACapMod() const { + Lua_Safe_Call_Int(); + return self->STACapMod; +} + +int32 Lua_StatBonuses::GetHeroicSTA() const { + Lua_Safe_Call_Int(); + return self->HeroicSTA; +} + +int32 Lua_StatBonuses::GetDEX() const { + Lua_Safe_Call_Int(); + return self->DEX; +} + +int32 Lua_StatBonuses::GetDEXCapMod() const { + Lua_Safe_Call_Int(); + return self->DEXCapMod; +} + +int32 Lua_StatBonuses::GetHeroicDEX() const { + Lua_Safe_Call_Int(); + return self->HeroicDEX; +} + +int32 Lua_StatBonuses::GetAGI() const { + Lua_Safe_Call_Int(); + return self->AGI; +} + +int32 Lua_StatBonuses::GetAGICapMod() const { + Lua_Safe_Call_Int(); + return self->AGICapMod; +} + +int32 Lua_StatBonuses::GetHeroicAGI() const { + Lua_Safe_Call_Int(); + return self->HeroicAGI; +} + +int32 Lua_StatBonuses::GetINT() const { + Lua_Safe_Call_Int(); + return self->INT; +} + +int32 Lua_StatBonuses::GetINTCapMod() const { + Lua_Safe_Call_Int(); + return self->INTCapMod; +} + +int32 Lua_StatBonuses::GetHeroicINT() const { + Lua_Safe_Call_Int(); + return self->HeroicINT; +} + +int32 Lua_StatBonuses::GetWIS() const { + Lua_Safe_Call_Int(); + return self->WIS; +} + +int32 Lua_StatBonuses::GetWISCapMod() const { + Lua_Safe_Call_Int(); + return self->WISCapMod; +} + +int32 Lua_StatBonuses::GetHeroicWIS() const { + Lua_Safe_Call_Int(); + return self->HeroicWIS; +} + +int32 Lua_StatBonuses::GetCHA() const { + Lua_Safe_Call_Int(); + return self->CHA; +} + +int32 Lua_StatBonuses::GetCHACapMod() const { + Lua_Safe_Call_Int(); + return self->CHACapMod; +} + +int32 Lua_StatBonuses::GetHeroicCHA() const { + Lua_Safe_Call_Int(); + return self->HeroicCHA; +} + +int32 Lua_StatBonuses::GetMR() const { + Lua_Safe_Call_Int(); + return self->MR; +} + +int32 Lua_StatBonuses::GetMRCapMod() const { + Lua_Safe_Call_Int(); + return self->MRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicMR() const { + Lua_Safe_Call_Int(); + return self->HeroicMR; +} + +int32 Lua_StatBonuses::GetFR() const { + Lua_Safe_Call_Int(); + return self->FR; +} + +int32 Lua_StatBonuses::GetFRCapMod() const { + Lua_Safe_Call_Int(); + return self->FRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicFR() const { + Lua_Safe_Call_Int(); + return self->HeroicFR; +} + +int32 Lua_StatBonuses::GetCR() const { + Lua_Safe_Call_Int(); + return self->CR; +} + +int32 Lua_StatBonuses::GetCRCapMod() const { + Lua_Safe_Call_Int(); + return self->CRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicCR() const { + Lua_Safe_Call_Int(); + return self->HeroicCR; +} + +int32 Lua_StatBonuses::GetPR() const { + Lua_Safe_Call_Int(); + return self->PR; +} + +int32 Lua_StatBonuses::GetPRCapMod() const { + Lua_Safe_Call_Int(); + return self->PRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicPR() const { + Lua_Safe_Call_Int(); + return self->HeroicPR; +} + +int32 Lua_StatBonuses::GetDR() const { + Lua_Safe_Call_Int(); + return self->DR; +} + +int32 Lua_StatBonuses::GetDRCapMod() const { + Lua_Safe_Call_Int(); + return self->DRCapMod; +} + +int32 Lua_StatBonuses::GetHeroicDR() const { + Lua_Safe_Call_Int(); + return self->HeroicDR; +} + +int32 Lua_StatBonuses::GetCorrup() const { + Lua_Safe_Call_Int(); + return self->Corrup; +} + +int32 Lua_StatBonuses::GetCorrupCapMod() const { + Lua_Safe_Call_Int(); + return self->CorrupCapMod; +} + +int32 Lua_StatBonuses::GetHeroicCorrup() const { + Lua_Safe_Call_Int(); + return self->HeroicCorrup; +} + +uint16 Lua_StatBonuses::GetDamageShieldSpellID() const { + Lua_Safe_Call_Int(); + return self->DamageShieldSpellID; +} + +int Lua_StatBonuses::GetDamageShield() const { + Lua_Safe_Call_Int(); + return self->DamageShield; +} + +int Lua_StatBonuses::GetDamageShieldType() const { + Lua_Safe_Call_Int(); + return self->DamageShieldType; +} + +int Lua_StatBonuses::GetSpellDamageShield() const { + Lua_Safe_Call_Int(); + return self->SpellDamageShield; +} + +int Lua_StatBonuses::GetSpellShield() const { + Lua_Safe_Call_Int(); + return self->SpellShield; +} + +int Lua_StatBonuses::GetReverseDamageShield() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShield; +} + +uint16 Lua_StatBonuses::GetReverseDamageShieldSpellID() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShieldSpellID; +} + +int Lua_StatBonuses::GetReverseDamageShieldType() const { + Lua_Safe_Call_Int(); + return self->ReverseDamageShieldType; +} + +int Lua_StatBonuses::Getmovementspeed() const { + Lua_Safe_Call_Int(); + return self->movementspeed; +} + +int32 Lua_StatBonuses::Gethaste() const { + Lua_Safe_Call_Int(); + return self->haste; +} + +int32 Lua_StatBonuses::Gethastetype2() const { + Lua_Safe_Call_Int(); + return self->hastetype2; +} + +int32 Lua_StatBonuses::Gethastetype3() const { + Lua_Safe_Call_Int(); + return self->hastetype3; +} + +int32 Lua_StatBonuses::Getinhibitmelee() const { + Lua_Safe_Call_Int(); + return self->inhibitmelee; +} + +float Lua_StatBonuses::GetAggroRange() const { + Lua_Safe_Call_Real(); + return self->AggroRange; +} + +float Lua_StatBonuses::GetAssistRange() const { + Lua_Safe_Call_Real(); + return self->AssistRange; +} + +int32 Lua_StatBonuses::Getskillmod(int idx) const { + Lua_Safe_Call_Int(); + return self->skillmod[idx]; +} + +int32 Lua_StatBonuses::Getskillmodmax(int idx) const { + Lua_Safe_Call_Int(); + return self->skillmodmax[idx]; +} + +int Lua_StatBonuses::Geteffective_casting_level() const { + Lua_Safe_Call_Int(); + return self->effective_casting_level; +} + +int Lua_StatBonuses::Getreflect_chance() const { + Lua_Safe_Call_Int(); + return self->reflect_chance; +} + +uint32 Lua_StatBonuses::GetsingingMod() const { + Lua_Safe_Call_Int(); + return self->singingMod; +} + +uint32 Lua_StatBonuses::GetAmplification() const { + Lua_Safe_Call_Int(); + return self->Amplification; +} + +uint32 Lua_StatBonuses::GetbrassMod() const { + Lua_Safe_Call_Int(); + return self->brassMod; +} + +uint32 Lua_StatBonuses::GetpercussionMod() const { + Lua_Safe_Call_Int(); + return self->percussionMod; +} + +uint32 Lua_StatBonuses::GetwindMod() const { + Lua_Safe_Call_Int(); + return self->windMod; +} + +uint32 Lua_StatBonuses::GetstringedMod() const { + Lua_Safe_Call_Int(); + return self->stringedMod; +} + +uint32 Lua_StatBonuses::GetsongModCap() const { + Lua_Safe_Call_Int(); + return self->songModCap; +} + +int8 Lua_StatBonuses::Gethatemod() const { + Lua_Safe_Call_Int(); + return self->hatemod; +} + +int32 Lua_StatBonuses::GetEnduranceReduction() const { + Lua_Safe_Call_Int(); + return self->EnduranceReduction; +} + +int32 Lua_StatBonuses::GetStrikeThrough() const { + Lua_Safe_Call_Int(); + return self->StrikeThrough; +} + +int32 Lua_StatBonuses::GetMeleeMitigation() const { + Lua_Safe_Call_Int(); + return self->MeleeMitigation; +} + +int32 Lua_StatBonuses::GetMeleeMitigationEffect() const { + Lua_Safe_Call_Int(); + return self->MeleeMitigationEffect; +} + +int32 Lua_StatBonuses::GetCriticalHitChance(int idx) const { + Lua_Safe_Call_Int(); + return self->CriticalHitChance[idx]; +} + +int32 Lua_StatBonuses::GetCriticalSpellChance() const { + Lua_Safe_Call_Int(); + return self->CriticalSpellChance; +} + +int32 Lua_StatBonuses::GetSpellCritDmgIncrease() const { + Lua_Safe_Call_Int(); + return self->SpellCritDmgIncrease; +} + +int32 Lua_StatBonuses::GetSpellCritDmgIncNoStack() const { + Lua_Safe_Call_Int(); + return self->SpellCritDmgIncNoStack; +} + +int32 Lua_StatBonuses::GetDotCritDmgIncrease() const { + Lua_Safe_Call_Int(); + return self->DotCritDmgIncrease; +} + +int32 Lua_StatBonuses::GetCriticalHealChance() const { + Lua_Safe_Call_Int(); + return self->CriticalHealChance; +} + +int32 Lua_StatBonuses::GetCriticalHealOverTime() const { + Lua_Safe_Call_Int(); + return self->CriticalHealOverTime; +} + +int32 Lua_StatBonuses::GetCriticalDoTChance() const { + Lua_Safe_Call_Int(); + return self->CriticalDoTChance; +} + +int32 Lua_StatBonuses::GetCrippBlowChance() const { + Lua_Safe_Call_Int(); + return self->CrippBlowChance; +} + +int32 Lua_StatBonuses::GetAvoidMeleeChance() const { + Lua_Safe_Call_Int(); + return self->AvoidMeleeChance; +} + +int32 Lua_StatBonuses::GetAvoidMeleeChanceEffect() const { + Lua_Safe_Call_Int(); + return self->AvoidMeleeChanceEffect; +} + +int32 Lua_StatBonuses::GetRiposteChance() const { + Lua_Safe_Call_Int(); + return self->RiposteChance; +} + +int32 Lua_StatBonuses::GetDodgeChance() const { + Lua_Safe_Call_Int(); + return self->DodgeChance; +} + +int32 Lua_StatBonuses::GetParryChance() const { + Lua_Safe_Call_Int(); + return self->ParryChance; +} + +int32 Lua_StatBonuses::GetDualWieldChance() const { + Lua_Safe_Call_Int(); + return self->DualWieldChance; +} + +int32 Lua_StatBonuses::GetDoubleAttackChance() const { + Lua_Safe_Call_Int(); + return self->DoubleAttackChance; +} + +int32 Lua_StatBonuses::GetTripleAttackChance() const { + Lua_Safe_Call_Int(); + return self->TripleAttackChance; +} + +int32 Lua_StatBonuses::GetDoubleRangedAttack() const { + Lua_Safe_Call_Int(); + return self->DoubleRangedAttack; +} + +int32 Lua_StatBonuses::GetResistSpellChance() const { + Lua_Safe_Call_Int(); + return self->ResistSpellChance; +} + +int32 Lua_StatBonuses::GetResistFearChance() const { + Lua_Safe_Call_Int(); + return self->ResistFearChance; +} + +bool Lua_StatBonuses::GetFearless() const { + Lua_Safe_Call_Bool(); + return self->Fearless; +} + +bool Lua_StatBonuses::GetIsFeared() const { + Lua_Safe_Call_Bool(); + return self->IsFeared; +} + +bool Lua_StatBonuses::GetIsBlind() const { + Lua_Safe_Call_Bool(); + return self->IsBlind; +} + +int32 Lua_StatBonuses::GetStunResist() const { + Lua_Safe_Call_Int(); + return self->StunResist; +} + +int32 Lua_StatBonuses::GetMeleeSkillCheck() const { + Lua_Safe_Call_Int(); + return self->MeleeSkillCheck; +} + +uint8 Lua_StatBonuses::GetMeleeSkillCheckSkill() const { + Lua_Safe_Call_Int(); + return self->MeleeSkillCheckSkill; +} + +int32 Lua_StatBonuses::GetHitChance() const { + Lua_Safe_Call_Int(); + return self->HitChance; +} + +int32 Lua_StatBonuses::GetHitChanceEffect(int idx) const { + Lua_Safe_Call_Int(); + return self->HitChanceEffect[idx]; +} + +int32 Lua_StatBonuses::GetDamageModifier(int idx) const { + Lua_Safe_Call_Int(); + return self->DamageModifier[idx]; +} + +int32 Lua_StatBonuses::GetDamageModifier2(int idx) const { + Lua_Safe_Call_Int(); + return self->DamageModifier2[idx]; +} + +int32 Lua_StatBonuses::GetMinDamageModifier(int idx) const { + Lua_Safe_Call_Int(); + return self->MinDamageModifier[idx]; +} + +int32 Lua_StatBonuses::GetProcChance() const { + Lua_Safe_Call_Int(); + return self->ProcChance; +} + +int32 Lua_StatBonuses::GetProcChanceSPA() const { + Lua_Safe_Call_Int(); + return self->ProcChanceSPA; +} + +int32 Lua_StatBonuses::GetExtraAttackChance() const { + Lua_Safe_Call_Int(); + return self->ExtraAttackChance; +} + +int32 Lua_StatBonuses::GetDoTShielding() const { + Lua_Safe_Call_Int(); + return self->DoTShielding; +} + +int32 Lua_StatBonuses::GetFlurryChance() const { + Lua_Safe_Call_Int(); + return self->FlurryChance; +} + +int32 Lua_StatBonuses::GetHundredHands() const { + Lua_Safe_Call_Int(); + return self->HundredHands; +} + +int32 Lua_StatBonuses::GetMeleeLifetap() const { + Lua_Safe_Call_Int(); + return self->MeleeLifetap; +} + +int32 Lua_StatBonuses::GetVampirism() const { + Lua_Safe_Call_Int(); + return self->Vampirism; +} + +int32 Lua_StatBonuses::GetHealRate() const { + Lua_Safe_Call_Int(); + return self->HealRate; +} + +int32 Lua_StatBonuses::GetMaxHPChange() const { + Lua_Safe_Call_Int(); + return self->MaxHPChange; +} + +int32 Lua_StatBonuses::GetHealAmt() const { + Lua_Safe_Call_Int(); + return self->HealAmt; +} + +int32 Lua_StatBonuses::GetSpellDmg() const { + Lua_Safe_Call_Int(); + return self->SpellDmg; +} + +int32 Lua_StatBonuses::GetClairvoyance() const { + Lua_Safe_Call_Int(); + return self->Clairvoyance; +} + +int32 Lua_StatBonuses::GetDSMitigation() const { + Lua_Safe_Call_Int(); + return self->DSMitigation; +} + +int32 Lua_StatBonuses::GetDSMitigationOffHand() const { + Lua_Safe_Call_Int(); + return self->DSMitigationOffHand; +} + +int32 Lua_StatBonuses::GetTwoHandBluntBlock() const { + Lua_Safe_Call_Int(); + return self->TwoHandBluntBlock; +} + +uint32 Lua_StatBonuses::GetItemManaRegenCap() const { + Lua_Safe_Call_Int(); + return self->ItemManaRegenCap; +} + +int32 Lua_StatBonuses::GetGravityEffect() const { + Lua_Safe_Call_Int(); + return self->GravityEffect; +} + +bool Lua_StatBonuses::GetAntiGate() const { + Lua_Safe_Call_Bool(); + return self->AntiGate; +} + +bool Lua_StatBonuses::GetMagicWeapon() const { + Lua_Safe_Call_Bool(); + return self->MagicWeapon; +} + +int32 Lua_StatBonuses::GetIncreaseBlockChance() const { + Lua_Safe_Call_Int(); + return self->IncreaseBlockChance; +} + +uint32 Lua_StatBonuses::GetPersistantCasting() const { + Lua_Safe_Call_Int(); + return self->PersistantCasting; +} + +int Lua_StatBonuses::GetXPRateMod() const { + Lua_Safe_Call_Int(); + return self->XPRateMod; +} + +bool Lua_StatBonuses::GetBlockNextSpell() const { + Lua_Safe_Call_Bool(); + return self->BlockNextSpell; +} + +bool Lua_StatBonuses::GetImmuneToFlee() const { + Lua_Safe_Call_Bool(); + return self->ImmuneToFlee; +} + +uint32 Lua_StatBonuses::GetVoiceGraft() const { + Lua_Safe_Call_Int(); + return self->VoiceGraft; +} + +int32 Lua_StatBonuses::GetSpellProcChance() const { + Lua_Safe_Call_Int(); + return self->SpellProcChance; +} + +int32 Lua_StatBonuses::GetCharmBreakChance() const { + Lua_Safe_Call_Int(); + return self->CharmBreakChance; +} + +int32 Lua_StatBonuses::GetSongRange() const { + Lua_Safe_Call_Int(); + return self->SongRange; +} + +uint32 Lua_StatBonuses::GetHPToManaConvert() const { + Lua_Safe_Call_Int(); + return self->HPToManaConvert; +} + +bool Lua_StatBonuses::GetNegateEffects() const { + Lua_Safe_Call_Bool(); + return self->NegateEffects; +} + +bool Lua_StatBonuses::GetTriggerMeleeThreshold() const { + Lua_Safe_Call_Bool(); + return self->TriggerMeleeThreshold; +} + +bool Lua_StatBonuses::GetTriggerSpellThreshold() const { + Lua_Safe_Call_Bool(); + return self->TriggerSpellThreshold; +} + +int32 Lua_StatBonuses::GetShieldBlock() const { + Lua_Safe_Call_Int(); + return self->ShieldBlock; +} + +int32 Lua_StatBonuses::GetBlockBehind() const { + Lua_Safe_Call_Int(); + return self->BlockBehind; +} + +bool Lua_StatBonuses::GetCriticalRegenDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalRegenDecay; +} + +bool Lua_StatBonuses::GetCriticalHealDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalHealDecay; +} + +bool Lua_StatBonuses::GetCriticalDotDecay() const { + Lua_Safe_Call_Bool(); + return self->CriticalDotDecay; +} + +bool Lua_StatBonuses::GetDivineAura() const { + Lua_Safe_Call_Bool(); + return self->DivineAura; +} + +bool Lua_StatBonuses::GetDistanceRemoval() const { + Lua_Safe_Call_Bool(); + return self->DistanceRemoval; +} + +int32 Lua_StatBonuses::GetFrenziedDevastation() const { + Lua_Safe_Call_Int(); + return self->FrenziedDevastation; +} + +bool Lua_StatBonuses::GetNegateIfCombat() const { + Lua_Safe_Call_Bool(); + return self->NegateIfCombat; +} + +int8 Lua_StatBonuses::GetScreech() const { + Lua_Safe_Call_Int(); + return self->Screech; +} + +int32 Lua_StatBonuses::GetAlterNPCLevel() const { + Lua_Safe_Call_Int(); + return self->AlterNPCLevel; +} + +bool Lua_StatBonuses::GetBerserkSPA() const { + Lua_Safe_Call_Bool(); + return self->BerserkSPA; +} + +int32 Lua_StatBonuses::GetMetabolism() const { + Lua_Safe_Call_Int(); + return self->Metabolism; +} + +bool Lua_StatBonuses::GetSanctuary() const { + Lua_Safe_Call_Bool(); + return self->Sanctuary; +} + +int32 Lua_StatBonuses::GetFactionModPct() const { + Lua_Safe_Call_Int(); + return self->FactionModPct; +} + +uint32 Lua_StatBonuses::GetPC_Pet_Flurry() const { + Lua_Safe_Call_Int(); + return self->PC_Pet_Flurry; +} + +int8 Lua_StatBonuses::GetPackrat() const { + Lua_Safe_Call_Int(); + return self->Packrat; +} + +uint8 Lua_StatBonuses::GetBuffSlotIncrease() const { + Lua_Safe_Call_Int(); + return self->BuffSlotIncrease; +} + +uint32 Lua_StatBonuses::GetDelayDeath() const { + Lua_Safe_Call_Int(); + return self->DelayDeath; +} + +int8 Lua_StatBonuses::GetBaseMovementSpeed() const { + Lua_Safe_Call_Int(); + return self->BaseMovementSpeed; +} + +uint8 Lua_StatBonuses::GetIncreaseRunSpeedCap() const { + Lua_Safe_Call_Int(); + return self->IncreaseRunSpeedCap; +} + +int32 Lua_StatBonuses::GetDoubleSpecialAttack() const { + Lua_Safe_Call_Int(); + return self->DoubleSpecialAttack; +} + +uint8 Lua_StatBonuses::GetFrontalStunResist() const { + Lua_Safe_Call_Int(); + return self->FrontalStunResist; +} + +int32 Lua_StatBonuses::GetBindWound() const { + Lua_Safe_Call_Int(); + return self->BindWound; +} + +int32 Lua_StatBonuses::GetMaxBindWound() const { + Lua_Safe_Call_Int(); + return self->MaxBindWound; +} + +int32 Lua_StatBonuses::GetChannelChanceSpells() const { + Lua_Safe_Call_Int(); + return self->ChannelChanceSpells; +} + +int32 Lua_StatBonuses::GetChannelChanceItems() const { + Lua_Safe_Call_Int(); + return self->ChannelChanceItems; +} + +uint8 Lua_StatBonuses::GetSeeInvis() const { + Lua_Safe_Call_Int(); + return self->SeeInvis; +} + +uint8 Lua_StatBonuses::GetTripleBackstab() const { + Lua_Safe_Call_Int(); + return self->TripleBackstab; +} + +bool Lua_StatBonuses::GetFrontalBackstabMinDmg() const { + Lua_Safe_Call_Bool(); + return self->FrontalBackstabMinDmg; +} + +uint8 Lua_StatBonuses::GetFrontalBackstabChance() const { + Lua_Safe_Call_Int(); + return self->FrontalBackstabChance; +} + +uint8 Lua_StatBonuses::GetConsumeProjectile() const { + Lua_Safe_Call_Int(); + return self->ConsumeProjectile; +} + +uint8 Lua_StatBonuses::GetForageAdditionalItems() const { + Lua_Safe_Call_Int(); + return self->ForageAdditionalItems; +} + +uint8 Lua_StatBonuses::GetSalvageChance() const { + Lua_Safe_Call_Int(); + return self->SalvageChance; +} + +uint32 Lua_StatBonuses::GetArcheryDamageModifier() const { + Lua_Safe_Call_Int(); + return self->ArcheryDamageModifier; +} + +bool Lua_StatBonuses::GetSecondaryDmgInc() const { + Lua_Safe_Call_Bool(); + return self->SecondaryDmgInc; +} + +uint32 Lua_StatBonuses::GetGiveDoubleAttack() const { + Lua_Safe_Call_Int(); + return self->GiveDoubleAttack; +} + +int32 Lua_StatBonuses::GetPetCriticalHit() const { + Lua_Safe_Call_Int(); + return self->PetCriticalHit; +} + +int32 Lua_StatBonuses::GetPetAvoidance() const { + Lua_Safe_Call_Int(); + return self->PetAvoidance; +} + +int32 Lua_StatBonuses::GetCombatStability() const { + Lua_Safe_Call_Int(); + return self->CombatStability; +} + +int32 Lua_StatBonuses::GetDoubleRiposte() const { + Lua_Safe_Call_Int(); + return self->DoubleRiposte; +} + +int32 Lua_StatBonuses::GetAmbidexterity() const { + Lua_Safe_Call_Int(); + return self->Ambidexterity; +} + +int32 Lua_StatBonuses::GetPetMaxHP() const { + Lua_Safe_Call_Int(); + return self->PetMaxHP; +} + +int32 Lua_StatBonuses::GetPetFlurry() const { + Lua_Safe_Call_Int(); + return self->PetFlurry; +} + +uint8 Lua_StatBonuses::GetMasteryofPast() const { + Lua_Safe_Call_Int(); + return self->MasteryofPast; +} + +bool Lua_StatBonuses::GetGivePetGroupTarget() const { + Lua_Safe_Call_Bool(); + return self->GivePetGroupTarget; +} + +int32 Lua_StatBonuses::GetRootBreakChance() const { + Lua_Safe_Call_Int(); + return self->RootBreakChance; +} + +int32 Lua_StatBonuses::GetUnfailingDivinity() const { + Lua_Safe_Call_Int(); + return self->UnfailingDivinity; +} + +int32 Lua_StatBonuses::GetItemHPRegenCap() const { + Lua_Safe_Call_Int(); + return self->ItemHPRegenCap; +} + +int32 Lua_StatBonuses::GetOffhandRiposteFail() const { + Lua_Safe_Call_Int(); + return self->OffhandRiposteFail; +} + +int32 Lua_StatBonuses::GetItemATKCap() const { + Lua_Safe_Call_Int(); + return self->ItemATKCap; +} + +int32 Lua_StatBonuses::GetShieldEquipDmgMod() const { + Lua_Safe_Call_Int(); + return self->ShieldEquipDmgMod; +} + +bool Lua_StatBonuses::GetTriggerOnValueAmount() const { + Lua_Safe_Call_Bool(); + return self->TriggerOnValueAmount; +} + +int8 Lua_StatBonuses::GetStunBashChance() const { + Lua_Safe_Call_Int(); + return self->StunBashChance; +} + +int8 Lua_StatBonuses::GetIncreaseChanceMemwipe() const { + Lua_Safe_Call_Int(); + return self->IncreaseChanceMemwipe; +} + +int8 Lua_StatBonuses::GetCriticalMend() const { + Lua_Safe_Call_Int(); + return self->CriticalMend; +} + +int32 Lua_StatBonuses::GetImprovedReclaimEnergy() const { + Lua_Safe_Call_Int(); + return self->ImprovedReclaimEnergy; +} + +int32 Lua_StatBonuses::GetPetMeleeMitigation() const { + Lua_Safe_Call_Int(); + return self->PetMeleeMitigation; +} + +bool Lua_StatBonuses::GetIllusionPersistence() const { + Lua_Safe_Call_Bool(); + return self->IllusionPersistence; +} + +uint16 Lua_StatBonuses::Getextra_xtargets() const { + Lua_Safe_Call_Int(); + return self->extra_xtargets; +} + +bool Lua_StatBonuses::GetShroudofStealth() const { + Lua_Safe_Call_Bool(); + return self->ShroudofStealth; +} + +uint16 Lua_StatBonuses::GetReduceFallDamage() const { + Lua_Safe_Call_Int(); + return self->ReduceFallDamage; +} + +uint8 Lua_StatBonuses::GetTradeSkillMastery() const { + Lua_Safe_Call_Int(); + return self->TradeSkillMastery; +} + +int16 Lua_StatBonuses::GetNoBreakAESneak() const { + Lua_Safe_Call_Int(); + return self->NoBreakAESneak; +} + +int16 Lua_StatBonuses::GetFeignedCastOnChance() const { + Lua_Safe_Call_Int(); + return self->FeignedCastOnChance; +} + +int32 Lua_StatBonuses::GetDivineSaveChance(int idx) const { + Lua_Safe_Call_Int(); + return self->DivineSaveChance[idx]; +} + +uint32 Lua_StatBonuses::GetDeathSave(int idx) const { + Lua_Safe_Call_Int(); + return self->DeathSave[idx]; +} + +int32 Lua_StatBonuses::GetAccuracy(int idx) const { + Lua_Safe_Call_Int(); + return self->Accuracy[idx]; +} + +int16 Lua_StatBonuses::GetSkillDmgTaken(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDmgTaken[idx]; +} + +uint32 Lua_StatBonuses::GetSpellTriggers(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellTriggers[idx]; +} + +uint32 Lua_StatBonuses::GetSpellOnKill(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellOnKill[idx]; +} + +uint32 Lua_StatBonuses::GetSpellOnDeath(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellOnDeath[idx]; +} + +int32 Lua_StatBonuses::GetCritDmgMob(int idx) const { + Lua_Safe_Call_Int(); + return self->CritDmgMob[idx]; +} + +int32 Lua_StatBonuses::GetSkillReuseTime(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillReuseTime[idx]; +} + +int32 Lua_StatBonuses::GetSkillDamageAmount(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDamageAmount[idx]; +} + +int Lua_StatBonuses::GetHPPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->HPPercCap[idx]; +} + +int Lua_StatBonuses::GetManaPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->ManaPercCap[idx]; +} + +int Lua_StatBonuses::GetEndPercCap(int idx) const { + Lua_Safe_Call_Int(); + return self->EndPercCap[idx]; +} + +uint8 Lua_StatBonuses::GetFocusEffects(int idx) const { + Lua_Safe_Call_Int(); + return self->FocusEffects[idx]; +} + +int16 Lua_StatBonuses::GetFocusEffectsWorn(int idx) const { + Lua_Safe_Call_Int(); + return self->FocusEffectsWorn[idx]; +} + +int32 Lua_StatBonuses::GetSkillDamageAmount2(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillDamageAmount2[idx]; +} + +uint32 Lua_StatBonuses::GetNegateAttacks(int idx) const { + Lua_Safe_Call_Int(); + return self->NegateAttacks[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateMeleeRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateMeleeRune[idx]; +} + +uint32 Lua_StatBonuses::GetMeleeThresholdGuard(int idx) const { + Lua_Safe_Call_Int(); + return self->MeleeThresholdGuard[idx]; +} + +uint32 Lua_StatBonuses::GetSpellThresholdGuard(int idx) const { + Lua_Safe_Call_Int(); + return self->SpellThresholdGuard[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateSpellRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateSpellRune[idx]; +} + +uint32 Lua_StatBonuses::GetMitigateDotRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MitigateDotRune[idx]; +} + +uint32 Lua_StatBonuses::GetManaAbsorbPercentDamage(int idx) const { + Lua_Safe_Call_Int(); + return self->ManaAbsorbPercentDamage[idx]; +} + +int32 Lua_StatBonuses::GetImprovedTaunt(int idx) const { + Lua_Safe_Call_Int(); + return self->ImprovedTaunt[idx]; +} + +int8 Lua_StatBonuses::GetRoot(int idx) const { + Lua_Safe_Call_Int(); + return self->Root[idx]; +} + +uint32 Lua_StatBonuses::GetAbsorbMagicAtt(int idx) const { + Lua_Safe_Call_Int(); + return self->AbsorbMagicAtt[idx]; +} + +uint32 Lua_StatBonuses::GetMeleeRune(int idx) const { + Lua_Safe_Call_Int(); + return self->MeleeRune[idx]; +} + +int32 Lua_StatBonuses::GetAStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->AStacker[idx]; +} + +int32 Lua_StatBonuses::GetBStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->BStacker[idx]; +} + +int32 Lua_StatBonuses::GetCStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->CStacker[idx]; +} + +int32 Lua_StatBonuses::GetDStacker(int idx) const { + Lua_Safe_Call_Int(); + return self->DStacker[idx]; +} + +bool Lua_StatBonuses::GetLimitToSkill(int idx) const { + Lua_Safe_Call_Bool(); + return self->LimitToSkill[idx]; +} + +uint32 Lua_StatBonuses::GetSkillProc(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillProc[idx]; +} + +uint32 Lua_StatBonuses::GetSkillProcSuccess(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillProcSuccess[idx]; +} + +uint32 Lua_StatBonuses::GetPC_Pet_Rampage(int idx) const { + Lua_Safe_Call_Int(); + return self->PC_Pet_Rampage[idx]; +} + +int32 Lua_StatBonuses::GetSkillAttackProc(int idx) const { + Lua_Safe_Call_Int(); + return self->SkillAttackProc[idx]; +} + +int32 Lua_StatBonuses::GetSlayUndead(int idx) const { + Lua_Safe_Call_Int(); + return self->SlayUndead[idx]; +} + +int32 Lua_StatBonuses::GetGiveDoubleRiposte(int idx) const { + Lua_Safe_Call_Int(); + return self->GiveDoubleRiposte[idx]; +} + +uint32 Lua_StatBonuses::GetRaiseSkillCap(int idx) const { + Lua_Safe_Call_Int(); + return self->RaiseSkillCap[idx]; +} + +int32 Lua_StatBonuses::GetSEResist(int idx) const { + Lua_Safe_Call_Int(); + return self->SEResist[idx]; +} + +int32 Lua_StatBonuses::GetFinishingBlow(int idx) const { + Lua_Safe_Call_Int(); + return self->FinishingBlow[idx]; +} + +uint32 Lua_StatBonuses::GetFinishingBlowLvl(int idx) const { + Lua_Safe_Call_Int(); + return self->FinishingBlowLvl[idx]; +} + +uint32 Lua_StatBonuses::GetHeadShot(int idx) const { + Lua_Safe_Call_Int(); + return self->HeadShot[idx]; +} + +uint8 Lua_StatBonuses::GetHSLevel(int idx) const { + Lua_Safe_Call_Int(); + return self->HSLevel[idx]; +} + +uint32 Lua_StatBonuses::GetAssassinate(int idx) const { + Lua_Safe_Call_Int(); + return self->Assassinate[idx]; +} + +uint8 Lua_StatBonuses::GetAssassinateLevel(int idx) const { + Lua_Safe_Call_Int(); + return self->AssassinateLevel[idx]; +} + +int32 Lua_StatBonuses::GetReduceTradeskillFail(int idx) const { + Lua_Safe_Call_Int(); + return self->ReduceTradeskillFail[idx]; +} + +luabind::scope lua_register_stat_bonuses() { + return luabind::class_("StatBonuses") + .def(luabind::constructor<>()) + .def("GetAC", &Lua_StatBonuses::GetAC) + .def("GetHP", &Lua_StatBonuses::GetHP) + .def("GetHPRegen", &Lua_StatBonuses::GetHPRegen) + .def("GetMaxHP", &Lua_StatBonuses::GetMaxHP) + .def("GetManaRegen", &Lua_StatBonuses::GetManaRegen) + .def("GetEnduranceRegen", &Lua_StatBonuses::GetEnduranceRegen) + .def("GetMana", &Lua_StatBonuses::GetMana) + .def("GetEndurance", &Lua_StatBonuses::GetEndurance) + .def("GetATK", &Lua_StatBonuses::GetATK) + .def("GetSTR", &Lua_StatBonuses::GetSTR) + .def("GetSTRCapMod", &Lua_StatBonuses::GetSTRCapMod) + .def("GetHeroicSTR", &Lua_StatBonuses::GetHeroicSTR) + .def("GetSTA", &Lua_StatBonuses::GetSTA) + .def("GetSTACapMod", &Lua_StatBonuses::GetSTACapMod) + .def("GetHeroicSTA", &Lua_StatBonuses::GetHeroicSTA) + .def("GetDEX", &Lua_StatBonuses::GetDEX) + .def("GetDEXCapMod", &Lua_StatBonuses::GetDEXCapMod) + .def("GetHeroicDEX", &Lua_StatBonuses::GetHeroicDEX) + .def("GetAGI", &Lua_StatBonuses::GetAGI) + .def("GetAGICapMod", &Lua_StatBonuses::GetAGICapMod) + .def("GetHeroicAGI", &Lua_StatBonuses::GetHeroicAGI) + .def("GetINT", &Lua_StatBonuses::GetINT) + .def("GetINTCapMod", &Lua_StatBonuses::GetINTCapMod) + .def("GetHeroicINT", &Lua_StatBonuses::GetHeroicINT) + .def("GetWIS", &Lua_StatBonuses::GetWIS) + .def("GetWISCapMod", &Lua_StatBonuses::GetWISCapMod) + .def("GetHeroicWIS", &Lua_StatBonuses::GetHeroicWIS) + .def("GetCHA", &Lua_StatBonuses::GetCHA) + .def("GetCHACapMod", &Lua_StatBonuses::GetCHACapMod) + .def("GetHeroicCHA", &Lua_StatBonuses::GetHeroicCHA) + .def("GetMR", &Lua_StatBonuses::GetMR) + .def("GetMRCapMod", &Lua_StatBonuses::GetMRCapMod) + .def("GetHeroicMR", &Lua_StatBonuses::GetHeroicMR) + .def("GetFR", &Lua_StatBonuses::GetFR) + .def("GetFRCapMod", &Lua_StatBonuses::GetFRCapMod) + .def("GetHeroicFR", &Lua_StatBonuses::GetHeroicFR) + .def("GetCR", &Lua_StatBonuses::GetCR) + .def("GetCRCapMod", &Lua_StatBonuses::GetCRCapMod) + .def("GetHeroicCR", &Lua_StatBonuses::GetHeroicCR) + .def("GetPR", &Lua_StatBonuses::GetPR) + .def("GetPRCapMod", &Lua_StatBonuses::GetPRCapMod) + .def("GetHeroicPR", &Lua_StatBonuses::GetHeroicPR) + .def("GetDR", &Lua_StatBonuses::GetDR) + .def("GetDRCapMod", &Lua_StatBonuses::GetDRCapMod) + .def("GetHeroicDR", &Lua_StatBonuses::GetHeroicDR) + .def("GetCorrup", &Lua_StatBonuses::GetCorrup) + .def("GetCorrupCapMod", &Lua_StatBonuses::GetCorrupCapMod) + .def("GetHeroicCorrup", &Lua_StatBonuses::GetHeroicCorrup) + .def("GetDamageShieldSpellID", &Lua_StatBonuses::GetDamageShieldSpellID) + .def("GetDamageShield", &Lua_StatBonuses::GetDamageShield) + .def("GetDamageShieldType", &Lua_StatBonuses::GetDamageShieldType) + .def("GetSpellDamageShield", &Lua_StatBonuses::GetSpellDamageShield) + .def("GetSpellShield", &Lua_StatBonuses::GetSpellShield) + .def("GetReverseDamageShield", &Lua_StatBonuses::GetReverseDamageShield) + .def("GetReverseDamageShieldSpellID", &Lua_StatBonuses::GetReverseDamageShieldSpellID) + .def("GetReverseDamageShieldType", &Lua_StatBonuses::GetReverseDamageShieldType) + .def("Getmovementspeed", &Lua_StatBonuses::Getmovementspeed) + .def("Gethaste", &Lua_StatBonuses::Gethaste) + .def("Gethastetype2", &Lua_StatBonuses::Gethastetype2) + .def("Gethastetype3", &Lua_StatBonuses::Gethastetype3) + .def("Getinhibitmelee", &Lua_StatBonuses::Getinhibitmelee) + .def("GetAggroRange", &Lua_StatBonuses::GetAggroRange) + .def("GetAssistRange", &Lua_StatBonuses::GetAssistRange) + .def("Getskillmod", &Lua_StatBonuses::Getskillmod) + .def("Getskillmodmax", &Lua_StatBonuses::Getskillmodmax) + .def("Geteffective_casting_level", &Lua_StatBonuses::Geteffective_casting_level) + .def("Getreflect_chance", &Lua_StatBonuses::Getreflect_chance) + .def("GetsingingMod", &Lua_StatBonuses::GetsingingMod) + .def("GetAmplification", &Lua_StatBonuses::GetAmplification) + .def("GetbrassMod", &Lua_StatBonuses::GetbrassMod) + .def("GetpercussionMod", &Lua_StatBonuses::GetpercussionMod) + .def("GetwindMod", &Lua_StatBonuses::GetwindMod) + .def("GetstringedMod", &Lua_StatBonuses::GetstringedMod) + .def("GetsongModCap", &Lua_StatBonuses::GetsongModCap) + .def("Gethatemod", &Lua_StatBonuses::Gethatemod) + .def("GetEnduranceReduction", &Lua_StatBonuses::GetEnduranceReduction) + .def("GetStrikeThrough", &Lua_StatBonuses::GetStrikeThrough) + .def("GetMeleeMitigation", &Lua_StatBonuses::GetMeleeMitigation) + .def("GetMeleeMitigationEffect", &Lua_StatBonuses::GetMeleeMitigationEffect) + .def("GetCriticalHitChance", &Lua_StatBonuses::GetCriticalHitChance) + .def("GetCriticalSpellChance", &Lua_StatBonuses::GetCriticalSpellChance) + .def("GetSpellCritDmgIncrease", &Lua_StatBonuses::GetSpellCritDmgIncrease) + .def("GetSpellCritDmgIncNoStack", &Lua_StatBonuses::GetSpellCritDmgIncNoStack) + .def("GetDotCritDmgIncrease", &Lua_StatBonuses::GetDotCritDmgIncrease) + .def("GetCriticalHealChance", &Lua_StatBonuses::GetCriticalHealChance) + .def("GetCriticalHealOverTime", &Lua_StatBonuses::GetCriticalHealOverTime) + .def("GetCriticalDoTChance", &Lua_StatBonuses::GetCriticalDoTChance) + .def("GetCrippBlowChance", &Lua_StatBonuses::GetCrippBlowChance) + .def("GetAvoidMeleeChance", &Lua_StatBonuses::GetAvoidMeleeChance) + .def("GetAvoidMeleeChanceEffect", &Lua_StatBonuses::GetAvoidMeleeChanceEffect) + .def("GetRiposteChance", &Lua_StatBonuses::GetRiposteChance) + .def("GetDodgeChance", &Lua_StatBonuses::GetDodgeChance) + .def("GetParryChance", &Lua_StatBonuses::GetParryChance) + .def("GetDualWieldChance", &Lua_StatBonuses::GetDualWieldChance) + .def("GetDoubleAttackChance", &Lua_StatBonuses::GetDoubleAttackChance) + .def("GetTripleAttackChance", &Lua_StatBonuses::GetTripleAttackChance) + .def("GetDoubleRangedAttack", &Lua_StatBonuses::GetDoubleRangedAttack) + .def("GetResistSpellChance", &Lua_StatBonuses::GetResistSpellChance) + .def("GetResistFearChance", &Lua_StatBonuses::GetResistFearChance) + .def("GetFearless", &Lua_StatBonuses::GetFearless) + .def("GetIsFeared", &Lua_StatBonuses::GetIsFeared) + .def("GetIsBlind", &Lua_StatBonuses::GetIsBlind) + .def("GetStunResist", &Lua_StatBonuses::GetStunResist) + .def("GetMeleeSkillCheck", &Lua_StatBonuses::GetMeleeSkillCheck) + .def("GetMeleeSkillCheckSkill", &Lua_StatBonuses::GetMeleeSkillCheckSkill) + .def("GetHitChance", &Lua_StatBonuses::GetHitChance) + .def("GetHitChanceEffect", &Lua_StatBonuses::GetHitChanceEffect) + .def("GetDamageModifier", &Lua_StatBonuses::GetDamageModifier) + .def("GetDamageModifier2", &Lua_StatBonuses::GetDamageModifier2) + .def("GetMinDamageModifier", &Lua_StatBonuses::GetMinDamageModifier) + .def("GetProcChance", &Lua_StatBonuses::GetProcChance) + .def("GetProcChanceSPA", &Lua_StatBonuses::GetProcChanceSPA) + .def("GetExtraAttackChance", &Lua_StatBonuses::GetExtraAttackChance) + .def("GetDoTShielding", &Lua_StatBonuses::GetDoTShielding) + .def("GetFlurryChance", &Lua_StatBonuses::GetFlurryChance) + .def("GetHundredHands", &Lua_StatBonuses::GetHundredHands) + .def("GetMeleeLifetap", &Lua_StatBonuses::GetMeleeLifetap) + .def("GetVampirism", &Lua_StatBonuses::GetVampirism) + .def("GetHealRate", &Lua_StatBonuses::GetHealRate) + .def("GetMaxHPChange", &Lua_StatBonuses::GetMaxHPChange) + .def("GetHealAmt", &Lua_StatBonuses::GetHealAmt) + .def("GetSpellDmg", &Lua_StatBonuses::GetSpellDmg) + .def("GetClairvoyance", &Lua_StatBonuses::GetClairvoyance) + .def("GetDSMitigation", &Lua_StatBonuses::GetDSMitigation) + .def("GetDSMitigationOffHand", &Lua_StatBonuses::GetDSMitigationOffHand) + .def("GetTwoHandBluntBlock", &Lua_StatBonuses::GetTwoHandBluntBlock) + .def("GetItemManaRegenCap", &Lua_StatBonuses::GetItemManaRegenCap) + .def("GetGravityEffect", &Lua_StatBonuses::GetGravityEffect) + .def("GetAntiGate", &Lua_StatBonuses::GetAntiGate) + .def("GetMagicWeapon", &Lua_StatBonuses::GetMagicWeapon) + .def("GetIncreaseBlockChance", &Lua_StatBonuses::GetIncreaseBlockChance) + .def("GetPersistantCasting", &Lua_StatBonuses::GetPersistantCasting) + .def("GetXPRateMod", &Lua_StatBonuses::GetXPRateMod) + .def("GetBlockNextSpell", &Lua_StatBonuses::GetBlockNextSpell) + .def("GetImmuneToFlee", &Lua_StatBonuses::GetImmuneToFlee) + .def("GetVoiceGraft", &Lua_StatBonuses::GetVoiceGraft) + .def("GetSpellProcChance", &Lua_StatBonuses::GetSpellProcChance) + .def("GetCharmBreakChance", &Lua_StatBonuses::GetCharmBreakChance) + .def("GetSongRange", &Lua_StatBonuses::GetSongRange) + .def("GetHPToManaConvert", &Lua_StatBonuses::GetHPToManaConvert) + .def("GetNegateEffects", &Lua_StatBonuses::GetNegateEffects) + .def("GetTriggerMeleeThreshold", &Lua_StatBonuses::GetTriggerMeleeThreshold) + .def("GetTriggerSpellThreshold", &Lua_StatBonuses::GetTriggerSpellThreshold) + .def("GetShieldBlock", &Lua_StatBonuses::GetShieldBlock) + .def("GetBlockBehind", &Lua_StatBonuses::GetBlockBehind) + .def("GetCriticalRegenDecay", &Lua_StatBonuses::GetCriticalRegenDecay) + .def("GetCriticalHealDecay", &Lua_StatBonuses::GetCriticalHealDecay) + .def("GetCriticalDotDecay", &Lua_StatBonuses::GetCriticalDotDecay) + .def("GetDivineAura", &Lua_StatBonuses::GetDivineAura) + .def("GetDistanceRemoval", &Lua_StatBonuses::GetDistanceRemoval) + .def("GetFrenziedDevastation", &Lua_StatBonuses::GetFrenziedDevastation) + .def("GetNegateIfCombat", &Lua_StatBonuses::GetNegateIfCombat) + .def("GetScreech", &Lua_StatBonuses::GetScreech) + .def("GetAlterNPCLevel", &Lua_StatBonuses::GetAlterNPCLevel) + .def("GetBerserkSPA", &Lua_StatBonuses::GetBerserkSPA) + .def("GetMetabolism", &Lua_StatBonuses::GetMetabolism) + .def("GetSanctuary", &Lua_StatBonuses::GetSanctuary) + .def("GetFactionModPct", &Lua_StatBonuses::GetFactionModPct) + .def("GetPC_Pet_Flurry", &Lua_StatBonuses::GetPC_Pet_Flurry) + .def("GetPackrat", &Lua_StatBonuses::GetPackrat) + .def("GetBuffSlotIncrease", &Lua_StatBonuses::GetBuffSlotIncrease) + .def("GetDelayDeath", &Lua_StatBonuses::GetDelayDeath) + .def("GetBaseMovementSpeed", &Lua_StatBonuses::GetBaseMovementSpeed) + .def("GetIncreaseRunSpeedCap", &Lua_StatBonuses::GetIncreaseRunSpeedCap) + .def("GetDoubleSpecialAttack", &Lua_StatBonuses::GetDoubleSpecialAttack) + .def("GetFrontalStunResist", &Lua_StatBonuses::GetFrontalStunResist) + .def("GetBindWound", &Lua_StatBonuses::GetBindWound) + .def("GetMaxBindWound", &Lua_StatBonuses::GetMaxBindWound) + .def("GetChannelChanceSpells", &Lua_StatBonuses::GetChannelChanceSpells) + .def("GetChannelChanceItems", &Lua_StatBonuses::GetChannelChanceItems) + .def("GetSeeInvis", &Lua_StatBonuses::GetSeeInvis) + .def("GetTripleBackstab", &Lua_StatBonuses::GetTripleBackstab) + .def("GetFrontalBackstabMinDmg", &Lua_StatBonuses::GetFrontalBackstabMinDmg) + .def("GetFrontalBackstabChance", &Lua_StatBonuses::GetFrontalBackstabChance) + .def("GetConsumeProjectile", &Lua_StatBonuses::GetConsumeProjectile) + .def("GetForageAdditionalItems", &Lua_StatBonuses::GetForageAdditionalItems) + .def("GetSalvageChance", &Lua_StatBonuses::GetSalvageChance) + .def("GetArcheryDamageModifier", &Lua_StatBonuses::GetArcheryDamageModifier) + .def("GetSecondaryDmgInc", &Lua_StatBonuses::GetSecondaryDmgInc) + .def("GetGiveDoubleAttack", &Lua_StatBonuses::GetGiveDoubleAttack) + .def("GetPetCriticalHit", &Lua_StatBonuses::GetPetCriticalHit) + .def("GetPetAvoidance", &Lua_StatBonuses::GetPetAvoidance) + .def("GetCombatStability", &Lua_StatBonuses::GetCombatStability) + .def("GetDoubleRiposte", &Lua_StatBonuses::GetDoubleRiposte) + .def("GetAmbidexterity", &Lua_StatBonuses::GetAmbidexterity) + .def("GetPetMaxHP", &Lua_StatBonuses::GetPetMaxHP) + .def("GetPetFlurry", &Lua_StatBonuses::GetPetFlurry) + .def("GetMasteryofPast", &Lua_StatBonuses::GetMasteryofPast) + .def("GetGivePetGroupTarget", &Lua_StatBonuses::GetGivePetGroupTarget) + .def("GetRootBreakChance", &Lua_StatBonuses::GetRootBreakChance) + .def("GetUnfailingDivinity", &Lua_StatBonuses::GetUnfailingDivinity) + .def("GetItemHPRegenCap", &Lua_StatBonuses::GetItemHPRegenCap) + .def("GetOffhandRiposteFail", &Lua_StatBonuses::GetOffhandRiposteFail) + .def("GetItemATKCap", &Lua_StatBonuses::GetItemATKCap) + .def("GetShieldEquipDmgMod", &Lua_StatBonuses::GetShieldEquipDmgMod) + .def("GetTriggerOnValueAmount", &Lua_StatBonuses::GetTriggerOnValueAmount) + .def("GetStunBashChance", &Lua_StatBonuses::GetStunBashChance) + .def("GetIncreaseChanceMemwipe", &Lua_StatBonuses::GetIncreaseChanceMemwipe) + .def("GetCriticalMend", &Lua_StatBonuses::GetCriticalMend) + .def("GetImprovedReclaimEnergy", &Lua_StatBonuses::GetImprovedReclaimEnergy) + .def("GetPetMeleeMitigation", &Lua_StatBonuses::GetPetMeleeMitigation) + .def("GetIllusionPersistence", &Lua_StatBonuses::GetIllusionPersistence) + .def("Getextra_xtargets", &Lua_StatBonuses::Getextra_xtargets) + .def("GetShroudofStealth", &Lua_StatBonuses::GetShroudofStealth) + .def("GetReduceFallDamage", &Lua_StatBonuses::GetReduceFallDamage) + .def("GetTradeSkillMastery", &Lua_StatBonuses::GetTradeSkillMastery) + .def("GetNoBreakAESneak", &Lua_StatBonuses::GetNoBreakAESneak) + .def("GetFeignedCastOnChance", &Lua_StatBonuses::GetFeignedCastOnChance) + .def("GetDivineSaveChance", &Lua_StatBonuses::GetDivineSaveChance) + .def("GetDeathSave", &Lua_StatBonuses::GetDeathSave) + .def("GetAccuracy", &Lua_StatBonuses::GetAccuracy) + .def("GetSkillDmgTaken", &Lua_StatBonuses::GetSkillDmgTaken) + .def("GetSpellTriggers", &Lua_StatBonuses::GetSpellTriggers) + .def("GetSpellOnKill", &Lua_StatBonuses::GetSpellOnKill) + .def("GetSpellOnDeath", &Lua_StatBonuses::GetSpellOnDeath) + .def("GetCritDmgMob", &Lua_StatBonuses::GetCritDmgMob) + .def("GetSkillReuseTime", &Lua_StatBonuses::GetSkillReuseTime) + .def("GetSkillDamageAmount", &Lua_StatBonuses::GetSkillDamageAmount) + .def("GetHPPercCap", &Lua_StatBonuses::GetHPPercCap) + .def("GetManaPercCap", &Lua_StatBonuses::GetManaPercCap) + .def("GetEndPercCap", &Lua_StatBonuses::GetEndPercCap) + .def("GetFocusEffects", &Lua_StatBonuses::GetFocusEffects) + .def("GetFocusEffectsWorn", &Lua_StatBonuses::GetFocusEffectsWorn) + .def("GetSkillDamageAmount2", &Lua_StatBonuses::GetSkillDamageAmount2) + .def("GetNegateAttacks", &Lua_StatBonuses::GetNegateAttacks) + .def("GetMitigateMeleeRune", &Lua_StatBonuses::GetMitigateMeleeRune) + .def("GetMeleeThresholdGuard", &Lua_StatBonuses::GetMeleeThresholdGuard) + .def("GetSpellThresholdGuard", &Lua_StatBonuses::GetSpellThresholdGuard) + .def("GetMitigateSpellRune", &Lua_StatBonuses::GetMitigateSpellRune) + .def("GetMitigateDotRune", &Lua_StatBonuses::GetMitigateDotRune) + .def("GetManaAbsorbPercentDamage", &Lua_StatBonuses::GetManaAbsorbPercentDamage) + .def("GetImprovedTaunt", &Lua_StatBonuses::GetImprovedTaunt) + .def("GetRoot", &Lua_StatBonuses::GetRoot) + .def("GetAbsorbMagicAtt", &Lua_StatBonuses::GetAbsorbMagicAtt) + .def("GetMeleeRune", &Lua_StatBonuses::GetMeleeRune) + .def("GetAStacker", &Lua_StatBonuses::GetAStacker) + .def("GetBStacker", &Lua_StatBonuses::GetBStacker) + .def("GetCStacker", &Lua_StatBonuses::GetCStacker) + .def("GetDStacker", &Lua_StatBonuses::GetDStacker) + .def("GetLimitToSkill", &Lua_StatBonuses::GetLimitToSkill) + .def("GetSkillProc", &Lua_StatBonuses::GetSkillProc) + .def("GetSkillProcSuccess", &Lua_StatBonuses::GetSkillProcSuccess) + .def("GetPC_Pet_Rampage", &Lua_StatBonuses::GetPC_Pet_Rampage) + .def("GetSkillAttackProc", &Lua_StatBonuses::GetSkillAttackProc) + .def("GetSlayUndead", &Lua_StatBonuses::GetSlayUndead) + .def("GetGiveDoubleRiposte", &Lua_StatBonuses::GetGiveDoubleRiposte) + .def("GetRaiseSkillCap", &Lua_StatBonuses::GetRaiseSkillCap) + .def("GetSEResist", &Lua_StatBonuses::GetSEResist) + .def("GetFinishingBlow", &Lua_StatBonuses::GetFinishingBlow) + .def("GetFinishingBlowLvl", &Lua_StatBonuses::GetFinishingBlowLvl) + .def("GetHeadShot", &Lua_StatBonuses::GetHeadShot) + .def("GetHSLevel", &Lua_StatBonuses::GetHSLevel) + .def("GetAssassinate", &Lua_StatBonuses::GetAssassinate) + .def("GetAssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel) + .def("GetReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail); +} \ No newline at end of file diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h new file mode 100644 index 000000000..52aa53f8c --- /dev/null +++ b/zone/lua_stat_bonuses.h @@ -0,0 +1,285 @@ +#pragma once + +#ifdef LUA_EQEMU + +#include "lua_ptr.h" +#include "common.h" + +struct StatBonuses; + +namespace luabind { + struct scope; +} + +luabind::scope lua_register_stat_bonuses(); + +class Lua_StatBonuses : public Lua_Ptr +{ + typedef StatBonuses NativeType; +public: + Lua_StatBonuses() : Lua_Ptr(nullptr) { } + Lua_StatBonuses(StatBonuses *d) : Lua_Ptr(d) { } + virtual ~Lua_StatBonuses() { } + + operator StatBonuses*() { + return reinterpret_cast(GetLuaPtrData()); + } + + int32 GetAC() const; + int32 GetHP() const; + int32 GetHPRegen() const; + int32 GetMaxHP() const; + int32 GetManaRegen() const; + int32 GetEnduranceRegen() const; + int32 GetMana() const; + int32 GetEndurance() const; + int32 GetATK() const; + int32 GetSTR() const; + int32 GetSTRCapMod() const; + int32 GetHeroicSTR() const; + int32 GetSTA() const; + int32 GetSTACapMod() const; + int32 GetHeroicSTA() const; + int32 GetDEX() const; + int32 GetDEXCapMod() const; + int32 GetHeroicDEX() const; + int32 GetAGI() const; + int32 GetAGICapMod() const; + int32 GetHeroicAGI() const; + int32 GetINT() const; + int32 GetINTCapMod() const; + int32 GetHeroicINT() const; + int32 GetWIS() const; + int32 GetWISCapMod() const; + int32 GetHeroicWIS() const; + int32 GetCHA() const; + int32 GetCHACapMod() const; + int32 GetHeroicCHA() const; + int32 GetMR() const; + int32 GetMRCapMod() const; + int32 GetHeroicMR() const; + int32 GetFR() const; + int32 GetFRCapMod() const; + int32 GetHeroicFR() const; + int32 GetCR() const; + int32 GetCRCapMod() const; + int32 GetHeroicCR() const; + int32 GetPR() const; + int32 GetPRCapMod() const; + int32 GetHeroicPR() const; + int32 GetDR() const; + int32 GetDRCapMod() const; + int32 GetHeroicDR() const; + int32 GetCorrup() const; + int32 GetCorrupCapMod() const; + int32 GetHeroicCorrup() const; + uint16 GetDamageShieldSpellID() const; + int GetDamageShield() const; + int GetDamageShieldType() const; + int GetSpellDamageShield() const; + int GetSpellShield() const; + int GetReverseDamageShield() const; + uint16 GetReverseDamageShieldSpellID() const; + int GetReverseDamageShieldType() const; + int Getmovementspeed() const; + int32 Gethaste() const; + int32 Gethastetype2() const; + int32 Gethastetype3() const; + int32 Getinhibitmelee() const; + float GetAggroRange() const; + float GetAssistRange() const; + int32 Getskillmod(int idx) const; + int32 Getskillmodmax(int idx) const; + int Geteffective_casting_level() const; + int Getreflect_chance() const; + uint32 GetsingingMod() const; + uint32 GetAmplification() const; + uint32 GetbrassMod() const; + uint32 GetpercussionMod() const; + uint32 GetwindMod() const; + uint32 GetstringedMod() const; + uint32 GetsongModCap() const; + int8 Gethatemod() const; + int32 GetEnduranceReduction() const; + int32 GetStrikeThrough() const; + int32 GetMeleeMitigation() const; + int32 GetMeleeMitigationEffect() const; + int32 GetCriticalHitChance(int idx) const; + int32 GetCriticalSpellChance() const; + int32 GetSpellCritDmgIncrease() const; + int32 GetSpellCritDmgIncNoStack() const; + int32 GetDotCritDmgIncrease() const; + int32 GetCriticalHealChance() const; + int32 GetCriticalHealOverTime() const; + int32 GetCriticalDoTChance() const; + int32 GetCrippBlowChance() const; + int32 GetAvoidMeleeChance() const; + int32 GetAvoidMeleeChanceEffect() const; + int32 GetRiposteChance() const; + int32 GetDodgeChance() const; + int32 GetParryChance() const; + int32 GetDualWieldChance() const; + int32 GetDoubleAttackChance() const; + int32 GetTripleAttackChance() const; + int32 GetDoubleRangedAttack() const; + int32 GetResistSpellChance() const; + int32 GetResistFearChance() const; + bool GetFearless() const; + bool GetIsFeared() const; + bool GetIsBlind() const; + int32 GetStunResist() const; + int32 GetMeleeSkillCheck() const; + uint8 GetMeleeSkillCheckSkill() const; + int32 GetHitChance() const; + int32 GetHitChanceEffect(int idx) const; + int32 GetDamageModifier(int idx) const; + int32 GetDamageModifier2(int idx) const; + int32 GetMinDamageModifier(int idx) const; + int32 GetProcChance() const; + int32 GetProcChanceSPA() const; + int32 GetExtraAttackChance() const; + int32 GetDoTShielding() const; + int32 GetFlurryChance() const; + int32 GetHundredHands() const; + int32 GetMeleeLifetap() const; + int32 GetVampirism() const; + int32 GetHealRate() const; + int32 GetMaxHPChange() const; + int32 GetHealAmt() const; + int32 GetSpellDmg() const; + int32 GetClairvoyance() const; + int32 GetDSMitigation() const; + int32 GetDSMitigationOffHand() const; + int32 GetTwoHandBluntBlock() const; + uint32 GetItemManaRegenCap() const; + int32 GetGravityEffect() const; + bool GetAntiGate() const; + bool GetMagicWeapon() const; + int32 GetIncreaseBlockChance() const; + uint32 GetPersistantCasting() const; + int GetXPRateMod() const; + bool GetBlockNextSpell() const; + bool GetImmuneToFlee() const; + uint32 GetVoiceGraft() const; + int32 GetSpellProcChance() const; + int32 GetCharmBreakChance() const; + int32 GetSongRange() const; + uint32 GetHPToManaConvert() const; + bool GetNegateEffects() const; + bool GetTriggerMeleeThreshold() const; + bool GetTriggerSpellThreshold() const; + int32 GetShieldBlock() const; + int32 GetBlockBehind() const; + bool GetCriticalRegenDecay() const; + bool GetCriticalHealDecay() const; + bool GetCriticalDotDecay() const; + bool GetDivineAura() const; + bool GetDistanceRemoval() const; + int32 GetFrenziedDevastation() const; + bool GetNegateIfCombat() const; + int8 GetScreech() const; + int32 GetAlterNPCLevel() const; + bool GetBerserkSPA() const; + int32 GetMetabolism() const; + bool GetSanctuary() const; + int32 GetFactionModPct() const; + uint32 GetPC_Pet_Flurry() const; + int8 GetPackrat() const; + uint8 GetBuffSlotIncrease() const; + uint32 GetDelayDeath() const; + int8 GetBaseMovementSpeed() const; + uint8 GetIncreaseRunSpeedCap() const; + int32 GetDoubleSpecialAttack() const; + uint8 GetFrontalStunResist() const; + int32 GetBindWound() const; + int32 GetMaxBindWound() const; + int32 GetChannelChanceSpells() const; + int32 GetChannelChanceItems() const; + uint8 GetSeeInvis() const; + uint8 GetTripleBackstab() const; + bool GetFrontalBackstabMinDmg() const; + uint8 GetFrontalBackstabChance() const; + uint8 GetConsumeProjectile() const; + uint8 GetForageAdditionalItems() const; + uint8 GetSalvageChance() const; + uint32 GetArcheryDamageModifier() const; + bool GetSecondaryDmgInc() const; + uint32 GetGiveDoubleAttack() const; + int32 GetPetCriticalHit() const; + int32 GetPetAvoidance() const; + int32 GetCombatStability() const; + int32 GetDoubleRiposte() const; + int32 GetAmbidexterity() const; + int32 GetPetMaxHP() const; + int32 GetPetFlurry() const; + uint8 GetMasteryofPast() const; + bool GetGivePetGroupTarget() const; + int32 GetRootBreakChance() const; + int32 GetUnfailingDivinity() const; + int32 GetItemHPRegenCap() const; + int32 GetOffhandRiposteFail() const; + int32 GetItemATKCap() const; + int32 GetShieldEquipDmgMod() const; + bool GetTriggerOnValueAmount() const; + int8 GetStunBashChance() const; + int8 GetIncreaseChanceMemwipe() const; + int8 GetCriticalMend() const; + int32 GetImprovedReclaimEnergy() const; + int32 GetPetMeleeMitigation() const; + bool GetIllusionPersistence() const; + uint16 Getextra_xtargets() const; + bool GetShroudofStealth() const; + uint16 GetReduceFallDamage() const; + uint8 GetTradeSkillMastery() const; + int16 GetNoBreakAESneak() const; + int16 GetFeignedCastOnChance() const; + int32 GetDivineSaveChance(int idx) const; + uint32 GetDeathSave(int idx) const; + int32 GetAccuracy(int idx) const; + int16 GetSkillDmgTaken(int idx) const; + uint32 GetSpellTriggers(int idx) const; + uint32 GetSpellOnKill(int idx) const; + uint32 GetSpellOnDeath(int idx) const; + int32 GetCritDmgMob(int idx) const; + int32 GetSkillReuseTime(int idx) const; + int32 GetSkillDamageAmount(int idx) const; + int GetHPPercCap(int idx) const; + int GetManaPercCap(int idx) const; + int GetEndPercCap(int idx) const; + uint8 GetFocusEffects(int idx) const; + int16 GetFocusEffectsWorn(int idx) const; + int32 GetSkillDamageAmount2(int idx) const; + uint32 GetNegateAttacks(int idx) const; + uint32 GetMitigateMeleeRune(int idx) const; + uint32 GetMeleeThresholdGuard(int idx) const; + uint32 GetSpellThresholdGuard(int idx) const; + uint32 GetMitigateSpellRune(int idx) const; + uint32 GetMitigateDotRune(int idx) const; + uint32 GetManaAbsorbPercentDamage(int idx) const; + int32 GetImprovedTaunt(int idx) const; + int8 GetRoot(int idx) const; + uint32 GetAbsorbMagicAtt(int idx) const; + uint32 GetMeleeRune(int idx) const; + int32 GetAStacker(int idx) const; + int32 GetBStacker(int idx) const; + int32 GetCStacker(int idx) const; + int32 GetDStacker(int idx) const; + bool GetLimitToSkill(int idx) const; + uint32 GetSkillProc(int idx) const; + uint32 GetSkillProcSuccess(int idx) const; + uint32 GetPC_Pet_Rampage(int idx) const; + int32 GetSkillAttackProc(int idx) const; + int32 GetSlayUndead(int idx) const; + int32 GetGiveDoubleRiposte(int idx) const; + uint32 GetRaiseSkillCap(int idx) const; + int32 GetSEResist(int idx) const; + int32 GetFinishingBlow(int idx) const; + uint32 GetFinishingBlowLvl(int idx) const; + uint32 GetHeadShot(int idx) const; + uint8 GetHSLevel(int idx) const; + uint32 GetAssassinate(int idx) const; + uint8 GetAssassinateLevel(int idx) const; + int32 GetReduceTradeskillFail(int idx) const; +}; + +#endif diff --git a/zone/mob.h b/zone/mob.h index 4d43a9572..f280f5600 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -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(); } From 8d391a7e3f3cb3e6ab189b88f2eef8bf5a77a8aa Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 26 Apr 2017 22:58:36 -0700 Subject: [PATCH 018/218] Daybreak connection setting tweaks --- common/net/daybreak_connection.cpp | 2 +- common/net/daybreak_connection.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index b203c0155..19b5ee5d1 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -1061,7 +1061,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 3 + round_time) / 4; + m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; iter = s->sent_packets.erase(iter); } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index ecbd1569c..9d885e81d 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -207,8 +207,8 @@ namespace EQ keepalive_delay_ms = 9000; resend_delay_ms = 300; resend_delay_factor = 1.5; - resend_delay_min = 300; - resend_delay_max = 6000; + resend_delay_min = 350; + resend_delay_max = 8000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; From 4ab420ed998a673328c5177a0d4f2c1c9562e1b6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 27 Apr 2017 13:36:02 -0400 Subject: [PATCH 019/218] Quick fix for RoF+ AugDistiller 0 This needs more work, but it works for now --- zone/client_packet.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4a9c9c22a..05c397fb4 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2993,9 +2993,12 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (!solvent) { - Log(Logs::General, Logs::Error, "Player tried to safely remove an augment without a distiller."); - Message(13, "Error: Missing an augmentation distiller for safely removing this augment."); - return; + old_aug = tobe_auged->GetAugment(in_augment->augment_index); + if (!old_aug || old_aug->GetItem()->AugDistiller != 0) { + Log(Logs::General, Logs::Error, "Player tried to safely remove an augment without a distiller."); + Message(13, "Error: Missing an augmentation distiller for safely removing this augment."); + return; + } } else if (solvent->GetItem()->ItemType == EQEmu::item::ItemTypeAugmentationDistiller) { @@ -3159,7 +3162,8 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) if (itemOneToPush && itemTwoToPush) { // Consume the augment distiller - DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true); + if (solvent) + DeleteItemInInventory(solvent_slot, solvent->IsStackable() ? 1 : 0, true); // Remove the augmented item DeleteItemInInventory(item_slot, 0, true); From 89587970dd3f557f51c2c3341552d848c2fe18e2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 28 Apr 2017 13:37:54 -0400 Subject: [PATCH 020/218] Add invis messages --- zone/client_packet.cpp | 11 ++++++++++- zone/string_ids.h | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 05c397fb4..a6014d4cf 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4806,6 +4806,7 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) mod_consider(tmob, con); QueuePacket(outapp); + safe_delete(outapp); // only wanted to check raid target once // and need con to still be around so, do it here! if (tmob->IsRaidTarget()) { @@ -4843,7 +4844,15 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) SendColoredText(color, std::string("This creature would take an army to defeat!")); } - safe_delete(outapp); + + // this could be done better, but this is only called when you con so w/e + // Shroud of Stealth has a special message + if (improved_hidden && !tmob->see_improved_hide) + Message_StringID(10, SOS_KEEPS_HIDDEN); + // we are trying to hide but they can see us + else if ((invisible || invisible_undead || hidden || invisible_animals) && !IsInvisible(tmob)) + Message_StringID(10, SUSPECT_SEES_YOU); + return; } diff --git a/zone/string_ids.h b/zone/string_ids.h index f03d8f44d..b1c2b1071 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -288,6 +288,7 @@ #define CORPSEDRAG_BEGIN 4064 //You begin to drag %1. #define CORPSEDRAG_STOPALL 4065 //You stop dragging the corpses. #define CORPSEDRAG_STOP 4066 //You stop dragging the corpse. +#define SOS_KEEPS_HIDDEN 4086 //Your Shroud of Stealth keeps you hidden from watchful eyes.␣␣ #define TARGET_TOO_CLOSE 4602 //You are too close to your target. Get farther away. #define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters. #define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3' @@ -302,6 +303,7 @@ #define PET_ATTACKING 5501 //%1 tells you, 'Attacking %2 Master.' #define AVOID_STUNNING_BLOW 5753 //You avoid the stunning blow. #define FATAL_BOW_SHOT 5745 //%1 performs a FATAL BOW SHOT!! +#define SUSPECT_SEES_YOU 5746 //You suspect that this being can see you. #define MELEE_SILENCE 5806 //You *CANNOT* use this melee ability, you are suffering from amnesia! #define DISCIPLINE_REUSE_MSG 5807 //You can use the ability %1 again in %2 hour(s) %3 minute(s) %4 seconds. #define DISCIPLINE_REUSE_MSG2 5808 //You can use the ability %1 again in %2 minute(s) %3 seconds. From cfd1b9a5eedfbbd0d32f3fdb08b75731eb23218f Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 28 Apr 2017 13:52:16 -0400 Subject: [PATCH 021/218] SoS message is only if they would otherwise see you --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index a6014d4cf..e43cc3d9e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4847,7 +4847,7 @@ void Client::Handle_OP_Consider(const EQApplicationPacket *app) // this could be done better, but this is only called when you con so w/e // Shroud of Stealth has a special message - if (improved_hidden && !tmob->see_improved_hide) + if (improved_hidden && (!tmob->see_improved_hide && (tmob->see_invis || tmob->see_hide))) Message_StringID(10, SOS_KEEPS_HIDDEN); // we are trying to hide but they can see us else if ((invisible || invisible_undead || hidden || invisible_animals) && !IsInvisible(tmob)) From 682dc35d80c9314550bdaed2afec54ed2cfa820a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Apr 2017 16:30:52 -0400 Subject: [PATCH 022/218] Update README.md [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c30fe7eda..f99b17975 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ **EQEmulator is a custom completely from-scratch open source server implementation for EverQuest built mostly on C++** * MySQL/MariaDB is used as the database engine (over 200+ tables) * Perl and LUA are both supported scripting languages for NPC/Player/Quest oriented events - * Open source database (Project EQ) has content up to expansion GoD (included in server installs) + * Open source database (Project EQ) has content up to expansion OoW (included in server installs) * Game server environments and databases can be heavily customized to create all new experiences * Hundreds of Quests/events created and maintained by Project EQ From 0fd6815f815cacabb5642e160d52398a210dc748 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 30 Apr 2017 00:30:23 -0700 Subject: [PATCH 023/218] Mods get their own file so i can take the big chunks of code out of lua parser --- zone/CMakeLists.txt | 2 + zone/attack.cpp | 22 ++ zone/bot.cpp | 11 + zone/lua_mod.cpp | 778 +++++++++++++++++++++++++++++++++++++++ zone/lua_mod.h | 53 +++ zone/lua_parser.cpp | 452 +++++------------------ zone/lua_parser.h | 17 +- zone/special_attacks.cpp | 46 +++ 8 files changed, 1028 insertions(+), 353 deletions(-) create mode 100644 zone/lua_mod.cpp create mode 100644 zone/lua_mod.h diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index afa58f50c..0c2c9bd63 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -51,6 +51,7 @@ SET(zone_sources lua_item.cpp lua_iteminst.cpp lua_mob.cpp + lua_mod.cpp lua_npc.cpp lua_object.cpp lua_packet.cpp @@ -174,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 diff --git a/zone/attack.cpp b/zone/attack.cpp index b0465553a..583f8ab01 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1306,6 +1306,16 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { +#ifdef LUA_EQEMU + bool lua_ret = false; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->ClientAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to Client::Attack() for evaluation!"); @@ -1829,6 +1839,16 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { +#ifdef LUA_EQEMU + bool lua_ret = false; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->NPCAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); @@ -2827,6 +2847,8 @@ uint8 Mob::GetWeaponDamageBonus(const EQEmu::ItemData *weapon, bool offhand) } return damage_bonus; } + + return 0; } int Mob::GetHandToHandDamage(void) diff --git a/zone/bot.cpp b/zone/bot.cpp index c66fdeb56..683faf1f2 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -22,6 +22,7 @@ #include "object.h" #include "doors.h" #include "quest_parser_collection.h" +#include "lua_parser.h" #include "../common/string_util.h" #include "../common/say_link.h" @@ -3857,6 +3858,16 @@ void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp } bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { +#ifdef LUA_EQEMU + bool lua_ret = false; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->BotAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to Bot::Attack for evaluation!"); diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp new file mode 100644 index 000000000..48dc29e66 --- /dev/null +++ b/zone/lua_mod.cpp @@ -0,0 +1,778 @@ +#include "lua.hpp" +#include +#include + +#include "../common/spdat.h" +#include "masterentity.h" +#include "questmgr.h" +#include "zone.h" +#include "zone_config.h" + +#include "lua_parser.h" +#include "lua_mod.h" +#include "lua_bit.h" +#include "lua_entity.h" +#include "lua_item.h" +#include "lua_iteminst.h" +#include "lua_mob.h" +#include "lua_hate_list.h" +#include "lua_client.h" +#include "lua_inventory.h" +#include "lua_npc.h" +#include "lua_spell.h" +#include "lua_entity_list.h" +#include "lua_group.h" +#include "lua_raid.h" +#include "lua_corpse.h" +#include "lua_object.h" +#include "lua_door.h" +#include "lua_spawn.h" +#include "lua_packet.h" +#include "lua_general.h" +#include "lua_encounter.h" +#include "lua_stat_bonuses.h" + +void LuaMod::Init() +{ + m_has_client_attack = parser_->HasFunction("ClientAttack", package_name_); + m_has_npc_attack = parser_->HasFunction("NPCAttack", package_name_); + m_has_bot_attack = parser_->HasFunction("BotAttack", package_name_); + 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_do_special_attack_damage = parser_->HasFunction("DoSpecialAttackDamage", package_name_); + m_has_do_ranged_attack_dmg = parser_->HasFunction("DoRangedAttackDmg", package_name_); + m_has_do_archery_attack_dmg = parser_->HasFunction("DoArcheryAttackDmg", package_name_); + m_has_do_throwing_attack_dmg = parser_->HasFunction("DoThrowingAttackDmg", package_name_); + m_has_do_melee_skill_attack_dmg = parser_->HasFunction("DoMeleeSkillAttackDmg", 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["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 damage_done = luaHitTable["damage_done"]; + auto offense = luaHitTable["offense"]; + auto tohit = luaHitTable["tohit"]; + auto hand = luaHitTable["hand"]; + auto skill = luaHitTable["skill"]; + + if (luabind::type(base_damage) == LUA_TNUMBER) { + hit.base_damage = luabind::object_cast(base_damage); + } + + if (luabind::type(damage_done) == LUA_TNUMBER) { + hit.damage_done = luabind::object_cast(damage_done); + } + + if (luabind::type(offense) == LUA_TNUMBER) { + hit.offense = luabind::object_cast(offense); + } + + if (luabind::type(tohit) == LUA_TNUMBER) { + hit.tohit = luabind::object_cast(tohit); + } + + if (luabind::type(hand) == LUA_TNUMBER) { + hit.hand = luabind::object_cast(hand); + } + + if (luabind::type(skill) == LUA_TNUMBER) { + hit.skill = (EQEmu::skills::SkillType)luabind::object_cast(skill); + } + } +} + +void PutExtraAttackOptions(lua_State *L, luabind::adl::object &e, ExtraAttackOptions *opts) { + if (opts) { + luabind::adl::object lua_opts = luabind::newtable(L); + lua_opts["damage_percent"] = opts->damage_percent; + lua_opts["damage_flat"] = opts->damage_flat; + lua_opts["armor_pen_percent"] = opts->armor_pen_percent; + lua_opts["armor_pen_flat"] = opts->armor_pen_flat; + lua_opts["crit_percent"] = opts->crit_percent; + lua_opts["crit_flat"] = opts->crit_flat; + lua_opts["hate_percent"] = opts->hate_percent; + lua_opts["hate_flat"] = opts->hate_flat; + lua_opts["hit_chance"] = opts->hit_chance; + lua_opts["melee_damage_bonus_flat"] = opts->melee_damage_bonus_flat; + lua_opts["skilldmgtaken_bonus_flat"] = opts->skilldmgtaken_bonus_flat; + e["opts"] = lua_opts; + } +} + +void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) { + if (opts) { + auto luaOptsTable = ret["opts"]; + if (luabind::type(luaOptsTable) == LUA_TTABLE) { + auto damage_percent = luaOptsTable["damage_percent"]; + auto damage_flat = luaOptsTable["damage_flat"]; + auto armor_pen_percent = luaOptsTable["armor_pen_percent"]; + auto armor_pen_flat = luaOptsTable["armor_pen_flat"]; + auto crit_percent = luaOptsTable["crit_percent"]; + auto crit_flat = luaOptsTable["crit_flat"]; + auto hate_percent = luaOptsTable["hate_percent"]; + auto hate_flat = luaOptsTable["hate_flat"]; + auto hit_chance = luaOptsTable["hit_chance"]; + auto melee_damage_bonus_flat = luaOptsTable["melee_damage_bonus_flat"]; + auto skilldmgtaken_bonus_flat = luaOptsTable["skilldmgtaken_bonus_flat"]; + + if (luabind::type(damage_percent) == LUA_TNUMBER) { + opts->damage_percent = luabind::object_cast(damage_percent); + } + + if (luabind::type(damage_flat) == LUA_TNUMBER) { + opts->damage_flat = luabind::object_cast(damage_flat); + } + + if (luabind::type(armor_pen_percent) == LUA_TNUMBER) { + opts->armor_pen_percent = luabind::object_cast(armor_pen_percent); + } + + if (luabind::type(armor_pen_flat) == LUA_TNUMBER) { + opts->armor_pen_flat = luabind::object_cast(armor_pen_flat); + } + + if (luabind::type(crit_percent) == LUA_TNUMBER) { + opts->crit_percent = luabind::object_cast(crit_percent); + } + + if (luabind::type(crit_flat) == LUA_TNUMBER) { + opts->crit_flat = luabind::object_cast(crit_flat); + } + + if (luabind::type(hate_percent) == LUA_TNUMBER) { + opts->hate_percent = luabind::object_cast(hate_percent); + } + + if (luabind::type(hate_flat) == LUA_TNUMBER) { + opts->hate_flat = luabind::object_cast(hate_flat); + } + + if (luabind::type(hit_chance) == LUA_TNUMBER) { + opts->hit_chance = luabind::object_cast(hit_chance); + } + + if (luabind::type(melee_damage_bonus_flat) == LUA_TNUMBER) { + opts->melee_damage_bonus_flat = luabind::object_cast(melee_damage_bonus_flat); + } + + if (luabind::type(skilldmgtaken_bonus_flat) == LUA_TNUMBER) { + opts->skilldmgtaken_bonus_flat = luabind::object_cast(skilldmgtaken_bonus_flat); + } + } + } +} + +bool LuaMod::ClientAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + if (!m_has_client_attack) { + return retval; + } + + retval = CommonAttack("ClientAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +bool LuaMod::NPCAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + if (!m_has_npc_attack) { + return retval; + } + + retval = CommonAttack("NPCAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +bool LuaMod::BotAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + if (!m_has_bot_attack) { + return retval; + } + + retval = CommonAttack("BotAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +bool LuaMod::CommonAttack(const std::string &fn, Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) { + bool retval = false; + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, fn.c_str()); + + 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; + e["Hand"] = Hand; + e["bRiposte"] = bRiposte; + e["IsStrikethrough"] = IsStrikethrough; + e["IsFromSpell"] = IsFromSpell; + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + retval = luabind::object_cast(returnValueObj); + } + + GetExtraAttackOptions(ret, opts); + } + + return retval; +} + +void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_melee_mitigation) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "MeleeMitigation"); + + Lua_Mob l_self(self); + Lua_Mob l_other(attacker); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +void LuaMod::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_apply_damage_table) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "ApplyDamageTable"); + + Lua_Mob l_self(self); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + + PutDamageHitInfo(L, e, hit); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + +bool LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + try { + if (!m_has_avoid_damage) { + return retval; + } + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + retval = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + bool retval = false; + + try { + if (!m_has_check_hit_chance) { + return retval; + } + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { + retval = luabind::object_cast(returnValueObj); + } + + GetDamageHitInfo(ret, hit); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +void LuaMod::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_do_special_attack_damage) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "DoSpecialAttackDamage"); + + Lua_Mob l_self(self); + Lua_Mob l_other(who); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + e["skill"] = (int)skill; + e["base_damage"] = base_damage; + e["min_damage"] = min_damage; + e["hate_override"] = hate_override; + e["ReuseTime"] = ReuseTime; + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + } + } + 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::DoRangedAttackDmg(Mob *self, Mob *other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_do_ranged_attack_dmg) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "DoRangedAttackDmg"); + + 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; + e["Launch"] = Launch; + e["damage_mod"] = damage_mod; + e["chance_mod"] = chance_mod; + e["skill"] = (int)skill; + e["speed"] = speed; + e["IDFile"] = IDFile ? IDFile : ""; + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + } + } + 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::DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_do_archery_attack_dmg) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "DoArcheryAttackDmg"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + Lua_ItemInst l_RangeWeapon(const_cast(RangeWeapon)); + Lua_ItemInst l_Ammo(const_cast(Ammo)); + Lua_Item l_AmmoItem(const_cast(AmmoItem)); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + e["RangeWeapon"] = l_RangeWeapon; + e["Ammo"] = l_Ammo; + e["weapon_damage"] = weapon_damage; + e["chance_mod"] = chance_mod; + e["focus"] = focus; + e["ReuseTime"] = ReuseTime; + e["range_id"] = range_id; + e["ammo_id"] = ammo_id; + e["AmmoItem"] = l_AmmoItem; + e["AmmoSlot"] = AmmoSlot; + e["speed"] = speed; + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + } + } + 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::DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_do_throwing_attack_dmg) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "DoThrowingAttackDmg"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + Lua_ItemInst l_RangeWeapon(const_cast(RangeWeapon)); + Lua_Item l_AmmoItem(const_cast(AmmoItem)); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + e["RangeWeapon"] = l_RangeWeapon; + e["weapon_damage"] = weapon_damage; + e["chance_mod"] = chance_mod; + e["focus"] = focus; + e["ReuseTime"] = ReuseTime; + e["range_id"] = range_id; + e["AmmoItem"] = l_AmmoItem; + e["AmmoSlot"] = AmmoSlot; + e["speed"] = speed; + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + } + } + 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::DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, + bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_do_melee_skill_attack_dmg) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "DoMeleeSkillAttackDmg"); + + 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; + e["weapon_damage"] = weapon_damage; + e["skillinuse"] = (int)skillinuse; + e["chance_mod"] = chance_mod; + e["focus"] = focus; + e["CanRiposte"] = CanRiposte; + e["ReuseTime"] = ReuseTime; + + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} \ No newline at end of file diff --git a/zone/lua_mod.h b/zone/lua_mod.h new file mode 100644 index 000000000..73792e25c --- /dev/null +++ b/zone/lua_mod.h @@ -0,0 +1,53 @@ +#pragma once + +#include + +struct lua_State; + +class LuaParser; +class LuaMod +{ +public: + LuaMod(lua_State *ls, LuaParser *lp, const std::string &package_name) { + L = ls; + parser_ = lp; + package_name_ = package_name; + Init(); + } + ~LuaMod() { } + void Init(); + + bool ClientAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + bool NPCAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + bool BotAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + bool CommonAttack(const std::string &fn, Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + 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 DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault); + void DoRangedAttackDmg(Mob *self, Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault); + void DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault); + void DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault); + void DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, + bool &ignoreDefault); +private: + LuaParser *parser_; + lua_State *L; + std::string package_name_; + + bool m_has_client_attack; + bool m_has_npc_attack; + bool m_has_bot_attack; + 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_do_special_attack_damage; + bool m_has_do_ranged_attack_dmg; + bool m_has_do_archery_attack_dmg; + bool m_has_do_throwing_attack_dmg; + bool m_has_do_melee_skill_attack_dmg; +}; diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 12a02623e..8748494c7 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -960,7 +960,7 @@ void LuaParser::ReloadQuests() { char file_name[256] = { 0 }; while (fgets(file_name, 256, load_order) != nullptr) { LoadScript("mods/" + std::string(file_name), file_name); - mods_.push_back(file_name); + mods_.push_back(LuaMod(L, this, file_name)); } fclose(load_order); @@ -971,7 +971,6 @@ void LuaParser::ReloadQuests() { if (n > 0) { lua_pop(L, n); } - } void LuaParser::LoadScript(std::string filename, std::string package_name) { @@ -1256,355 +1255,6 @@ int LuaParser::DispatchEventSpell(QuestEventID evt, NPC* npc, Client *client, ui return ret; } -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["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 damage_done = luaHitTable["damage_done"]; - auto offense = luaHitTable["offense"]; - auto tohit = luaHitTable["tohit"]; - auto hand = luaHitTable["hand"]; - auto skill = luaHitTable["skill"]; - - if (luabind::type(base_damage) == LUA_TNUMBER) { - hit.base_damage = luabind::object_cast(base_damage); - } - - if (luabind::type(damage_done) == LUA_TNUMBER) { - hit.damage_done = luabind::object_cast(damage_done); - } - - if (luabind::type(offense) == LUA_TNUMBER) { - hit.offense = luabind::object_cast(offense); - } - - if (luabind::type(tohit) == LUA_TNUMBER) { - hit.tohit = luabind::object_cast(tohit); - } - - if (luabind::type(hand) == LUA_TNUMBER) { - hit.hand = luabind::object_cast(hand); - } - - if (luabind::type(skill) == LUA_TNUMBER) { - hit.skill = (EQEmu::skills::SkillType)luabind::object_cast(skill); - } - } -} - -void PutExtraAttackOptions(lua_State *L, luabind::adl::object &e, ExtraAttackOptions *opts) { - if (opts) { - luabind::adl::object lua_opts = luabind::newtable(L); - lua_opts["damage_percent"] = opts->damage_percent; - lua_opts["damage_flat"] = opts->damage_flat; - lua_opts["armor_pen_percent"] = opts->armor_pen_percent; - lua_opts["armor_pen_flat"] = opts->armor_pen_flat; - lua_opts["crit_percent"] = opts->crit_percent; - lua_opts["crit_flat"] = opts->crit_flat; - lua_opts["hate_percent"] = opts->hate_percent; - lua_opts["hate_flat"] = opts->hate_flat; - lua_opts["hit_chance"] = opts->hit_chance; - lua_opts["melee_damage_bonus_flat"] = opts->melee_damage_bonus_flat; - lua_opts["skilldmgtaken_bonus_flat"] = opts->skilldmgtaken_bonus_flat; - e["opts"] = lua_opts; - } -} - -void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) { - if (opts) { - auto luaOptsTable = ret["opts"]; - if (luabind::type(luaOptsTable) == LUA_TTABLE) { - auto damage_percent = luaOptsTable["damage_percent"]; - auto damage_flat = luaOptsTable["damage_flat"]; - auto armor_pen_percent = luaOptsTable["armor_pen_percent"]; - auto armor_pen_flat = luaOptsTable["armor_pen_flat"]; - auto crit_percent = luaOptsTable["crit_percent"]; - auto crit_flat = luaOptsTable["crit_flat"]; - auto hate_percent = luaOptsTable["hate_percent"]; - auto hate_flat = luaOptsTable["hate_flat"]; - auto hit_chance = luaOptsTable["hit_chance"]; - auto melee_damage_bonus_flat = luaOptsTable["melee_damage_bonus_flat"]; - auto skilldmgtaken_bonus_flat = luaOptsTable["skilldmgtaken_bonus_flat"]; - - if (luabind::type(damage_percent) == LUA_TNUMBER) { - opts->damage_percent = luabind::object_cast(damage_percent); - } - - if (luabind::type(damage_flat) == LUA_TNUMBER) { - opts->damage_flat = luabind::object_cast(damage_flat); - } - - if (luabind::type(armor_pen_percent) == LUA_TNUMBER) { - opts->armor_pen_percent = luabind::object_cast(armor_pen_percent); - } - - if (luabind::type(armor_pen_flat) == LUA_TNUMBER) { - opts->armor_pen_flat = luabind::object_cast(armor_pen_flat); - } - - if (luabind::type(crit_percent) == LUA_TNUMBER) { - opts->crit_percent = luabind::object_cast(crit_percent); - } - - if (luabind::type(crit_flat) == LUA_TNUMBER) { - opts->crit_flat = luabind::object_cast(crit_flat); - } - - if (luabind::type(hate_percent) == LUA_TNUMBER) { - opts->hate_percent = luabind::object_cast(hate_percent); - } - - if (luabind::type(hate_flat) == LUA_TNUMBER) { - opts->hate_flat = luabind::object_cast(hate_flat); - } - - if (luabind::type(hit_chance) == LUA_TNUMBER) { - opts->hit_chance = luabind::object_cast(hit_chance); - } - - if (luabind::type(melee_damage_bonus_flat) == LUA_TNUMBER) { - opts->melee_damage_bonus_flat = luabind::object_cast(melee_damage_bonus_flat); - } - - if (luabind::type(skilldmgtaken_bonus_flat) == LUA_TNUMBER) { - opts->skilldmgtaken_bonus_flat = luabind::object_cast(skilldmgtaken_bonus_flat); - } - } - } -} - -void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { - int start = lua_gettop(L); - ignoreDefault = false; - - for (auto &mod : mods_) { - try { - if (!HasFunction("MeleeMitigation", mod)) { - continue; - } - - lua_getfield(L, LUA_REGISTRYINDEX, mod.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); - AddError(error); - lua_pop(L, 1); - continue; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - - GetDamageHitInfo(ret, hit); - GetExtraAttackOptions(ret, opts); - } - } - catch (std::exception &ex) { - AddError(ex.what()); - } - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } -} - -void LuaParser::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) { - int start = lua_gettop(L); - ignoreDefault = false; - - for (auto &mod : mods_) { - try { - if (!HasFunction("ApplyDamageTable", mod)) { - continue; - } - - lua_getfield(L, LUA_REGISTRYINDEX, mod.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); - AddError(error); - lua_pop(L, 1); - continue; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - - GetDamageHitInfo(ret, hit); - } - } - catch (std::exception &ex) { - AddError(ex.what()); - } - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } -} - -bool LuaParser::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) { - int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; - - for (auto &mod : mods_) { - try { - if (!HasFunction("AvoidDamage", mod)) { - continue; - } - - lua_getfield(L, LUA_REGISTRYINDEX, mod.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); - AddError(error); - lua_pop(L, 1); - continue; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - - auto returnValueObj = ret["ReturnValue"]; - if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { - retval = luabind::object_cast(returnValueObj); - } - - GetDamageHitInfo(ret, hit); - } - } - catch (std::exception &ex) { - AddError(ex.what()); - } - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - - return retval; -} - -bool LuaParser::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault) { - int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; - - for (auto &mod : mods_) { - try { - if (!HasFunction("CheckHitChance", mod)) { - continue; - } - - lua_getfield(L, LUA_REGISTRYINDEX, mod.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); - AddError(error); - lua_pop(L, 1); - continue; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - - auto returnValueObj = ret["ReturnValue"]; - if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { - retval = luabind::object_cast(returnValueObj); - } - - GetDamageHitInfo(ret, hit); - } - } - catch (std::exception &ex) { - AddError(ex.what()); - } - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - - return retval; -} - QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { switch(evt) { case EVENT_SLAY: @@ -1629,3 +1279,103 @@ QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { } #endif + +bool LuaParser::ClientAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + retval = mod.ClientAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + } + + return retval; +} + +bool LuaParser::NPCAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + retval = mod.NPCAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + } + + return retval; +} + +bool LuaParser::BotAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + retval = mod.BotAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); + } + + return retval; +} + +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_) { + retval = mod.AvoidDamage(self, other, hit, ignoreDefault); + } + return retval; +} + +bool LuaParser::CheckHitChance(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) +{ + bool retval = false; + for (auto &mod : mods_) { + retval = mod.CheckHitChance(self, other, hit, ignoreDefault); + } + return retval; +} + +void LuaParser::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.DoSpecialAttackDamage(self, who, skill, base_damage, min_damage, hate_override, ReuseTime, ignoreDefault); + } +} + +void LuaParser::DoRangedAttackDmg(Mob *self, Mob *other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.DoRangedAttackDmg(self, other, Launch, damage_mod, chance_mod, skill, speed, IDFile, ignoreDefault); + } +} + +void LuaParser::DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.DoArcheryAttackDmg(self, other, RangeWeapon, Ammo, weapon_damage, chance_mod, focus, ReuseTime, range_id, ammo_id, AmmoItem, AmmoSlot, speed, ignoreDefault); + } +} + +void LuaParser::DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.DoThrowingAttackDmg(self, other, RangeWeapon, AmmoItem, weapon_damage, chance_mod, focus, ReuseTime, range_id, AmmoSlot, speed, ignoreDefault); + } +} + +void LuaParser::DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, + int ReuseTime, bool &ignoreDefault) +{ + for (auto &mod : mods_) { + mod.DoMeleeSkillAttackDmg(self, other, weapon_damage, skillinuse, chance_mod, focus, CanRiposte, ReuseTime, ignoreDefault); + } +} diff --git a/zone/lua_parser.h b/zone/lua_parser.h index a0f0fea89..0d1f1256c 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -10,6 +10,7 @@ #include #include "zone_config.h" +#include "lua_mod.h" extern const ZoneConfig *Config; @@ -86,11 +87,24 @@ public: return &inst; } + bool HasFunction(std::string function, std::string package_name); + //Mod Extensions + bool ClientAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + bool NPCAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); + bool BotAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); 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 DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault); + void DoRangedAttackDmg(Mob *self, Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault); + void DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault); + void DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, + int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault); + void DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, + bool &ignoreDefault); private: LuaParser(); @@ -109,13 +123,12 @@ private: std::vector *extra_pointers); void LoadScript(std::string filename, std::string package_name); - bool HasFunction(std::string function, std::string package_name); void MapFunctions(lua_State *L); QuestEventID ConvertLuaEvent(QuestEventID evt); std::map vars_; std::map loaded_; - std::vector mods_; + std::vector mods_; lua_State *L; NPCArgumentHandler NPCArgumentDispatch[_LargestEventID]; diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index ef97aee39..ed3f39074 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -23,6 +23,7 @@ #include "entity.h" #include "mob.h" #include "string_ids.h" +#include "lua_parser.h" #include @@ -137,6 +138,15 @@ int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->DoSpecialAttackDamage(this, who, skill, base_damage, min_damage, hate_override, ReuseTime, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + // this really should go through the same code as normal melee damage to // pick up all the special behavior there @@ -758,6 +768,15 @@ 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) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->DoArcheryAttackDmg(this, other, RangeWeapon, Ammo, weapon_damage, chance_mod, focus, ReuseTime, range_id, ammo_id, AmmoItem, AmmoSlot, speed, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || @@ -1138,6 +1157,15 @@ void NPC::RangedAttack(Mob* other) void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->DoRangedAttackDmg(this, other, Launch, damage_mod, chance_mod, skill, speed, IDFile, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if ((other == nullptr || (other->HasDied())) || HasDied() || @@ -1302,6 +1330,15 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->DoThrowingAttackDmg(this, other, RangeWeapon, AmmoItem, weapon_damage, chance_mod, focus, ReuseTime, range_id, AmmoSlot, speed, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { @@ -2086,6 +2123,15 @@ int Mob::TryAssassinate(Mob *defender, EQEmu::skills::SkillType skillInUse) void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->DoMeleeSkillAttackDmg(this, other, weapon_damage, skillinuse, chance_mod, focus, CanRiposte, ReuseTime, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + if (!CanDoSpecialAttack(other)) return; From 34c535ef819677795ebcfb2bcf33593bd579abee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 1 May 2017 15:11:57 -0400 Subject: [PATCH 024/218] Fix Pet Equipment Sets --- zone/pets.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/pets.cpp b/zone/pets.cpp index 39eeaeb5c..0c150f743 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -706,7 +706,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { // all of the result rows. Check if we have something in the slot // already. If no, add the item id to the equipment array. while (curset >= 0 && depth < 5) { - std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%s'", curset); + std::string query = StringFormat("SELECT nested_set FROM pets_equipmentset WHERE set_id = '%d'", curset); auto results = QueryDatabase(query); if (!results.Success()) { return false; @@ -721,7 +721,7 @@ bool ZoneDatabase::GetBasePetItems(int32 equipmentset, uint32 *items) { auto row = results.begin(); nextset = atoi(row[0]); - query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%s'", curset); + query = StringFormat("SELECT slot, item_id FROM pets_equipmentset_entries WHERE set_id='%d'", curset); results = QueryDatabase(query); if (results.Success()) { for (row = results.begin(); row != results.end(); ++row) From baca139f9bf0a84f614880940fe91a9270d105a7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 May 2017 16:35:04 -0400 Subject: [PATCH 025/218] /pet leader should only cause NPCs to respond Client also checks if it's an NPC so we got other bugs here ... Shouldn't ever be sending this packet with a client targeted ... --- zone/client_packet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e43cc3d9e..981c5048d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9952,7 +9952,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) Mob *Owner = mypet->GetOwner(); if (Owner) mypet->Say_StringID(PET_LEADERIS, Owner->GetCleanName()); - else + else if (mypet->IsNPC()) mypet->Say_StringID(I_FOLLOW_NOONE); } } From 3ca8ddbff1a0b3bacdbd3dfb609753ec4fa368fe Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 May 2017 17:05:58 -0400 Subject: [PATCH 026/218] Nuke PET_SLUMBER since they're wrong --- zone/client_packet.cpp | 38 ------------------------------ zone/pets.h | 52 +++++++++++++++++++++++------------------- 2 files changed, 28 insertions(+), 62 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 981c5048d..7c7ddaf4a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10195,44 +10195,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } - case PET_SLUMBER: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - - if (mypet->GetPetType() != petAnimation) { - // Needs to have an IsSleeping() check added and this case should toggle on/off - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(SPO_Sit); - mypet->SetRunAnimSpeed(0); - if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet - mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting - mypet->SendAppearancePacket(AT_Anim, ANIM_DEATH); - } - break; - } - case PET_SLUMBER_ON: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - - if (mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(SPO_Sit); - mypet->SetRunAnimSpeed(0); - if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet - mypet->InterruptSpell(); //No cast 4 u. //i guess the pet should start casting - mypet->SendAppearancePacket(AT_Anim, ANIM_DEATH); - } - break; - } - case PET_SLUMBER_OFF: { - if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - - if (mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); - mypet->SetPetOrder(SPO_Follow); - mypet->SetRunAnimSpeed(mypet->GetBaseRunspeed()); - mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); - } - break; - } case PET_HOLD: { if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { if (mypet->IsFeared()) diff --git a/zone/pets.h b/zone/pets.h index 8d14d8a48..2aa59cc59 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -3,35 +3,39 @@ // Defines based on the RoF2 Client #define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window -#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window -#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window +#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window +#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window #define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window -#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window -#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window -#define PET_SIT 6 // 0x06 - /pet sit or Pet Window -#define PET_SITDOWN 7 // 0x07 - /pet sit on -#define PET_STANDUP 8 // 0x08 - /pet sit off +#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window +#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window +#define PET_SIT 6 // 0x06 - /pet sit or Pet Window +#define PET_SITDOWN 7 // 0x07 - /pet sit on +#define PET_STANDUP 8 // 0x08 - /pet sit off #define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented #define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented #define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented -#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window -#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on +#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window +#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on #define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off -#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window -#define PET_HOLD_ON 16 // 0x10 - /pet hold on -#define PET_HOLD_OFF 17 // 0x11 - /pet hold off -#define PET_SLUMBER 18 // 0x12 - What activates this? - define guessed -#define PET_SLUMBER_ON 19 // 0x13 - What activates this? - define guessed -#define PET_SLUMBER_OFF 20 // 0x14 - What activates this? - define guessed -#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window -#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on -#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off -#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window -#define PET_FOCUS_ON 25 // 0x19 - /pet focus on -#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off -#define PET_BACKOFF 28 // 0x1c - /pet back off -#define PET_GETLOST 29 // 0x1d - /pet get lost -#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client +#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking +#define PET_HOLD_ON 16 // 0x10 - /pet hold on +#define PET_HOLD_OFF 17 // 0x11 - /pet hold off +#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to +#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on +#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off +#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window +#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on +#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off +#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window +#define PET_FOCUS_ON 25 // 0x19 - /pet focus on +#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off +#define PET_FEIGN 27 // 0x1b - /pet feign +#define PET_BACKOFF 28 // 0x1c - /pet back off +#define PET_GETLOST 29 // 0x1d - /pet get lost +#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet +#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list +#define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup +#define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup class Mob; struct NPCType; From 14c9ddf15a1ac36140fe547c5b75b6828fd83d33 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 May 2017 17:27:29 -0400 Subject: [PATCH 027/218] Change pet attack to be live like Classic behavior will be restored as a rule at a later date --- zone/client_packet.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7c7ddaf4a..995a38672 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10012,7 +10012,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } } zone->AddAggroMob(); - mypet->AddToHateList(target, 1); + // classic acts like qattack + int hate = 1; + if (IsEngaged()) { + auto top = hate_list.GetEntWithMostHateOnList(this); + if (top) + hate += hate_list.GetEntHateAmount(top); + } + mypet->AddToHateList(target, hate); Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName()); } } From b3d8bcab4a953a10964f87885a32955ed9408cc0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 3 May 2017 23:41:06 -0400 Subject: [PATCH 028/218] More pet command changes Tweaks to attack Initial implementation of ghold Tweaks to hold --- utils/patches/patch_RoF.conf | 1 + utils/patches/patch_RoF2.conf | 1 + utils/patches/patch_UF.conf | 1 + zone/attack.cpp | 26 +++++++++----- zone/bot.cpp | 4 +-- zone/bot.h | 2 +- zone/client_packet.cpp | 66 ++++++++++++++++++++--------------- zone/mob.h | 5 ++- zone/pets.h | 12 +++++++ zone/string_ids.h | 3 ++ 10 files changed, 80 insertions(+), 41 deletions(-) diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index ad54b6341..a746804d9 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -196,6 +196,7 @@ OP_Consent=0x400e OP_ConsentDeny=0x34c1 OP_AutoFire=0x314e OP_PetCommands=0x0093 +OP_PetCommandState=0x74ed OP_PetHoTT=0x0df4 OP_DeleteSpell=0x305c OP_Surname=0x1a87 diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index 9f588d18f..ee9b0e646 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -195,6 +195,7 @@ OP_Consent=0x1fd1 OP_ConsentDeny=0x7a45 OP_AutoFire=0x241e OP_PetCommands=0x0159 +OP_PetCommandState=0x1dc8 OP_PetHoTT=0x794a OP_DeleteSpell=0x3358 OP_Surname=0x0423 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index f41b62740..2002a85f9 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -198,6 +198,7 @@ OP_Consent=0x6bb9 # C OP_ConsentDeny=0x4cd1 # C OP_AutoFire=0x5db5 # C OP_PetCommands=0x7706 # C +OP_PetCommandState=0x1a79 OP_PetHoTT=0x2528 OP_DeleteSpell=0x0698 # C OP_Surname=0x44ae # C diff --git a/zone/attack.cpp b/zone/attack.cpp index 2b9d081bf..bbb17d2ec 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2477,7 +2477,7 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil return true; } -void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/, uint16 spell_id) +void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, bool iYellForHelp /*= true*/, bool bFrenzy /*= false*/, bool iBuffTic /*= false*/, uint16 spell_id, bool pet_command) { if (!other) return; @@ -2516,13 +2516,18 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } - if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && !IsFocused()) { //ignore aggro if hold and !focus - return; - } + // Pet that is /pet hold on will not add to their hate list if they're not engaged + // Pet that is /pet hold on and /pet focus on will not add others to their hate list + // Pet that is /pet ghold on will never add to their hate list unless /pet attack or /pet qattack - if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline) && IsHeld() && GetOwner()->GetAA(aaAdvancedPetDiscipline) >= 1 && IsFocused()) { - if (!targetmob) - return; + // we skip these checks if it's forced through a pet command + if (!pet_command) { + if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline)) { + if ((IsGHeld() || (IsHeld() && IsFocused())) && !on_hatelist) // we want them to be able to climb the hate list + return; + if (IsHeld() && !wasengaged) + return; + } } if (other->IsNPC() && (other->IsPet() || other->CastToNPC()->GetSwarmOwner() > 0)) @@ -3306,7 +3311,10 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const } //end `if there is some damage being done and theres anattacker person involved` Mob *pet = GetPet(); - if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse()) + // pets that have GHold will never automatically add NPCs + // pets that have Hold and no Focus will add NPCs if they're engaged + // pets that have Hold and Focus will not add NPCs + if (pet && !pet->IsFamiliar() && !pet->GetSpecialAbility(IMMUNE_AGGRO) && !pet->IsEngaged() && attacker && attacker != this && !attacker->IsCorpse() && !pet->IsGHeld()) { if (!pet->IsHeld()) { Log(Logs::Detail, Logs::Aggro, "Sending pet %s into battle due to attack.", pet->GetName()); @@ -5295,4 +5303,4 @@ void Mob::DoOffHandAttackRounds(Mob *target, ExtraAttackOptions *opts) } } } -} \ No newline at end of file +} diff --git a/zone/bot.cpp b/zone/bot.cpp index c66fdeb56..d87bd472e 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3852,8 +3852,8 @@ void Bot::Damage(Mob *from, int32 damage, uint16 spell_id, EQEmu::skills::SkillT } //void Bot::AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false) -void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic) { - Mob::AddToHateList(other, hate, damage, iYellForHelp, bFrenzy, iBuffTic); +void Bot::AddToHateList(Mob* other, uint32 hate, int32 damage, bool iYellForHelp, bool bFrenzy, bool iBuffTic, bool pet_command) { + 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) { diff --git a/zone/bot.h b/zone/bot.h index 6c1dfc53f..1a6bcf7cd 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -325,7 +325,7 @@ public: bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color); void Camp(bool databaseSave = true); - virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false); + virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false); virtual void SetTarget(Mob* mob); virtual void Zone(); std::vector GetBotSpells() { return AIspells; } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 995a38672..3ed19d37a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10001,26 +10001,17 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { - if (mypet->IsHeld()) { - if (!mypet->IsFocused()) { - mypet->SetHeld(false); //break the hold and guard if we explicitly tell the pet to attack. - if (mypet->GetPetOrder() != SPO_Guard) - mypet->SetPetOrder(SPO_Follow); - } - else { - mypet->SetTarget(target); - } - } zone->AddAggroMob(); // classic acts like qattack int hate = 1; - if (IsEngaged()) { - auto top = hate_list.GetEntWithMostHateOnList(this); - if (top) - hate += hate_list.GetEntHateAmount(top); + if (mypet->IsEngaged()) { + auto top = mypet->GetHateMost(); + if (top && top != target) + hate += mypet->GetHateAmount(top) - mypet->GetHateAmount(target) + 100; // should be enough to cause target change } - mypet->AddToHateList(target, hate); + mypet->AddToHateList(target, hate, 0, true, false, false, SPELL_UNKNOWN, true); Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), target->GetCleanName()); + SetTarget(target); } } break; @@ -10044,7 +10035,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { zone->AddAggroMob(); - mypet->AddToHateList(GetTarget(), 1); + mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); } } @@ -10098,7 +10089,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { if (mypet->IsNPC()) { - mypet->SetHeld(false); mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE); mypet->SetPetOrder(SPO_Guard); mypet->CastToNPC()->SaveGuardSpot(); @@ -10110,7 +10100,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { - mypet->SetHeld(false); mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10150,7 +10139,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { - mypet->SetHeld(false); mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10204,30 +10192,24 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } case PET_HOLD: { if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { - if (mypet->IsFeared()) - break; //could be exploited like PET_BACKOFF - if (mypet->IsHeld()) { mypet->SetHeld(false); } else { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); - mypet->WipeHateList(); + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // they use new messages now, but only SoD+? mypet->SetHeld(true); } + mypet->SetGHeld(false); } break; } case PET_HOLD_ON: { if (GetAA(aaPetDiscipline) && mypet->IsNPC() && !mypet->IsHeld()) { - if (mypet->IsFeared()) - break; //could be exploited like PET_BACKOFF - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); - mypet->WipeHateList(); mypet->SetHeld(true); + mypet->SetGHeld(false); } break; } @@ -10236,6 +10218,34 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetHeld(false); break; } + case PET_GHOLD: { + if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (mypet->IsGHeld()) + { + mypet->SetGHeld(false); + } + else + { + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // message wrong + mypet->SetGHeld(true); + } + mypet->SetHeld(false); + } + break; + } + case PET_GHOLD_ON: { + if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SetGHeld(true); + mypet->SetHeld(false); + } + break; + } + case PET_GHOLD_OFF: { + if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsGHeld()) + mypet->SetGHeld(false); + break; + } case PET_SPELLHOLD: { if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { if (mypet->IsFeared()) diff --git a/zone/mob.h b/zone/mob.h index 4d43a9572..9a1ff67a0 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -533,7 +533,7 @@ public: inline uint32 GetLevelCon(uint8 iOtherLevel) const { return this ? GetLevelCon(GetLevel(), iOtherLevel) : CON_GRAY; } virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, - bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN); + bool bFrenzy = false, bool iBuffTic = false, uint16 spell_id = SPELL_UNKNOWN, bool pet_comand = false); bool RemoveFromHateList(Mob* mob); void SetHateAmountOnEnt(Mob* other, int32 hate = 0, int32 damage = 0) { hate_list.SetHateAmountOnEnt(other,hate,damage);} void HalveAggro(Mob *other) { uint32 in_hate = GetHateAmount(other); SetHateAmountOnEnt(other, (in_hate > 1 ? in_hate / 2 : 1)); } @@ -869,6 +869,8 @@ public: inline const eStandingPetOrder GetPetOrder() const { return pStandingPetOrder; } inline void SetHeld(bool nState) { held = nState; } inline const bool IsHeld() const { return held; } + inline void SetGHeld(bool nState) { gheld = nState; } + inline const bool IsGHeld() const { return gheld; } inline void SetNoCast(bool nState) { nocast = nState; } inline const bool IsNoCast() const { return nocast; } inline void SetFocused(bool nState) { focused = nState; } @@ -1179,6 +1181,7 @@ protected: uint32 pLastChange; bool held; + bool gheld; bool nocast; bool focused; bool spawned; diff --git a/zone/pets.h b/zone/pets.h index 2aa59cc59..3a7f5932c 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -37,6 +37,18 @@ #define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup #define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup +// can change the state of these buttons with a packet +#define PET_BUTTON_SIT 0 +#define PET_BUTTON_STOP 1 +#define PET_BUTTON_REGROUP 2 +#define PET_BUTTON_FOLLOW 3 +#define PET_BUTTON_GUARD 4 +#define PET_BUTTON_TAUNT 5 +#define PET_BUTTON_HOLD 6 +#define PET_BUTTON_GHOLD 7 +#define PET_BUTTON_FOCUS 8 +#define PET_BUTTON_SPELLHOLD 9 + class Mob; struct NPCType; diff --git a/zone/string_ids.h b/zone/string_ids.h index b1c2b1071..0326cff7e 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -322,6 +322,9 @@ #define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel. #define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel. #define IDENTIFY_SPELL 6765 //Item Lore: %1. +#define PET_ON_GHOLD 6843 //Pet greater hold has been set to on. +#define PET_OFF_GHOLD 6846 //Pet greater hold has been set to off. +#define PET_GHOLD_ON_MSG 6847 //Now greater holding master. I will only attack something new if ordered. #define BUFF_NOT_BLOCKABLE 7608 //You cannot block this effect. #define LDON_DONT_KNOW_TRAPPED 7552 //You do not know if this object is trapped. #define LDON_HAVE_DISARMED 7553 //You have disarmed %1! From 9229ca4f799a9e27ce5e10d13a90fee18134fdda Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 00:27:42 -0400 Subject: [PATCH 029/218] Add OP_PetCommandState for ghold/hold --- common/emu_oplist.h | 1 + common/eq_packet_structs.h | 5 +++++ zone/client.cpp | 9 +++++++++ zone/client.h | 2 ++ zone/client_packet.cpp | 4 ++++ 5 files changed, 21 insertions(+) diff --git a/common/emu_oplist.h b/common/emu_oplist.h index cf6f4ca28..e695c94a9 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -355,6 +355,7 @@ N(OP_OpenTributeMaster), N(OP_PDeletePetition), N(OP_PetBuffWindow), N(OP_PetCommands), +N(OP_PetCommandState), N(OP_PetHoTT), N(OP_Petition), N(OP_PetitionBug), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 3730e1d14..c84c4073a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1116,6 +1116,11 @@ struct PetCommand_Struct { /*004*/ uint32 target; }; +struct PetCommandState_Struct { +/*00*/ uint32 button_id; +/*04*/ uint32 state; +}; + /* ** Delete Spawn ** Length: 4 Bytes diff --git a/zone/client.cpp b/zone/client.cpp index 2321797e3..3b2b5fd23 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8935,3 +8935,12 @@ void Client::ProcessAggroMeter() } } +void Client::SetPetCommandState(int button, int state) +{ + auto app = new EQApplicationPacket(OP_PetCommandState, sizeof(PetCommandState_Struct)); + auto pcs = (PetCommandState_Struct *)app->pBuffer; + pcs->button_id = button; + pcs->state = state; + FastQueuePacket(&app); +} + diff --git a/zone/client.h b/zone/client.h index f47ac2b31..19dc4c05b 100644 --- a/zone/client.h +++ b/zone/client.h @@ -352,6 +352,8 @@ public: inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } + void SetPetCommandState(int button, int state); + bool CheckAccess(int16 iDBLevel, int16 iDefaultLevel); void CheckQuests(const char* zonename, const char* message, uint32 npc_id, uint32 item_id, Mob* other); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3ed19d37a..b8661e79e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10202,6 +10202,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetHeld(true); } mypet->SetGHeld(false); + SetPetCommandState(PET_BUTTON_GHOLD, 0); } break; } @@ -10210,6 +10211,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); mypet->SetGHeld(false); + SetPetCommandState(PET_BUTTON_GHOLD, 0); } break; } @@ -10230,6 +10232,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetGHeld(true); } mypet->SetHeld(false); + SetPetCommandState(PET_BUTTON_HOLD, 0); } break; } @@ -10238,6 +10241,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetGHeld(true); mypet->SetHeld(false); + SetPetCommandState(PET_BUTTON_HOLD, 0); } break; } From 2a97d980b7f8bc390974dcc0bc85a06302817222 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 01:13:41 -0400 Subject: [PATCH 030/218] Make TemporaryPets take into account pet power --- zone/aa.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 2fb99a6fb..664a2c375 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -46,8 +46,20 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u if (targ != nullptr && targ->IsCorpse()) return; + // yep, even these need pet power! + int act_power = 0; + + if (IsClient()) { + act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); + act_power = CastToClient()->mod_pet_power(act_power, spell_id); + } +#ifdef BOTS + else if (this->IsBot()) + act_power = CastToBot()->GetBotFocusEffect(Bot::BotfocusPetPower, spell_id); +#endif + PetRecord record; - if (!database.GetPetEntry(spells[spell_id].teleport_zone, &record)) + if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record)) { Log(Logs::General, Logs::Error, "Unknown swarm pet spell id: %d, check pets table", spell_id); Message(13, "Unable to find data for pet %s", spells[spell_id].teleport_zone); From 797c35230f204c966b336595181a84385298618d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 01:18:33 -0400 Subject: [PATCH 031/218] Screw bots! do later --- zone/aa.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 664a2c375..e002dd4f2 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -53,10 +53,6 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); act_power = CastToClient()->mod_pet_power(act_power, spell_id); } -#ifdef BOTS - else if (this->IsBot()) - act_power = CastToBot()->GetBotFocusEffect(Bot::BotfocusPetPower, spell_id); -#endif PetRecord record; if (!database.GetPoweredPetEntry(spells[spell_id].teleport_zone, act_power, &record)) From 8435fa269d4dfaa6e7fdb80da8fcd071b66a3173 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 01:39:24 -0400 Subject: [PATCH 032/218] Pet Command hack for UF+ --- zone/client.cpp | 15 +++++++++++++++ zone/client_packet.cpp | 15 +++++++++++++++ zone/spell_effects.cpp | 18 ++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/zone/client.cpp b/zone/client.cpp index 3b2b5fd23..cf3814a7d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -54,6 +54,7 @@ extern volatile bool RunLoops; #include "guild_mgr.h" #include "quest_parser_collection.h" #include "queryserv.h" +#include "pets.h" extern QueryServ* QServ; extern EntityList entity_list; @@ -5713,6 +5714,20 @@ void Client::SuspendMinion() Message_StringID(clientMessageTell, SUSPEND_MINION_UNSUSPEND, CurrentPet->GetCleanName()); memset(&m_suspendedminion, 0, sizeof(struct PetInfo)); + // TODO: These pet command states need to be synced ... + // Will just fix them for now + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { + SetPetCommandState(PET_BUTTON_SIT, 0); + SetPetCommandState(PET_BUTTON_STOP, 0); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + SetPetCommandState(PET_BUTTON_FOLLOW, 1); + SetPetCommandState(PET_BUTTON_GUARD, 0); + SetPetCommandState(PET_BUTTON_TAUNT, 1); + SetPetCommandState(PET_BUTTON_HOLD, 0); + SetPetCommandState(PET_BUTTON_GHOLD, 0); + SetPetCommandState(PET_BUTTON_FOCUS, 0); + SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + } } else return; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index b8661e79e..499402997 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -858,6 +858,21 @@ void Client::CompleteConnect() CastToClient()->FastQueuePacket(&outapp); } + // TODO: load these states + // We at least will set them to the correct state for now + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater && GetPet()) { + SetPetCommandState(PET_BUTTON_SIT, 0); + SetPetCommandState(PET_BUTTON_STOP, 0); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + SetPetCommandState(PET_BUTTON_FOLLOW, 1); + SetPetCommandState(PET_BUTTON_GUARD, 0); + SetPetCommandState(PET_BUTTON_TAUNT, 1); + SetPetCommandState(PET_BUTTON_HOLD, 0); + SetPetCommandState(PET_BUTTON_GHOLD, 0); + SetPetCommandState(PET_BUTTON_FOCUS, 0); + SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + } + entity_list.RefreshClientXTargets(this); worldserver.RequestTellQueue(GetName()); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index af96a7e2e..ceffc1ef3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -30,6 +30,7 @@ #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" +#include "pets.h" #include @@ -1240,6 +1241,23 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove else { MakePet(spell_id, spell.teleport_zone); + // TODO: we need to sync the states for these clients ... + // Will fix buttons for now + if (IsClient()) { + auto c = CastToClient(); + if (c->ClientVersionBit() & EQEmu::versions::bit_UFAndLater) { + c->SetPetCommandState(PET_BUTTON_SIT, 0); + c->SetPetCommandState(PET_BUTTON_STOP, 0); + c->SetPetCommandState(PET_BUTTON_REGROUP, 0); + c->SetPetCommandState(PET_BUTTON_FOLLOW, 1); + c->SetPetCommandState(PET_BUTTON_GUARD, 0); + c->SetPetCommandState(PET_BUTTON_TAUNT, 1); + c->SetPetCommandState(PET_BUTTON_HOLD, 0); + c->SetPetCommandState(PET_BUTTON_GHOLD, 0); + c->SetPetCommandState(PET_BUTTON_FOCUS, 0); + c->SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); + } + } } break; } From c1ee88a90e14d893bd97cfea8543149a8b9da7f9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 4 May 2017 01:57:27 -0500 Subject: [PATCH 033/218] Update eqemu_server.pl to use wget for windows for more reliable web requests that don't hang infinitely [skip ci] --- utils/scripts/eqemu_server.pl | 78 +++++++---------------------------- 1 file changed, 16 insertions(+), 62 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e9ba02099..c67170785 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -49,6 +49,7 @@ if(-e "eqemu_server_skip_update.txt"){ #::: Check for script self update do_self_update_check_routine() if !$skip_self_update_check; +get_windows_wget(); get_perl_version(); read_eqemu_config_xml(); get_mysql_path(); @@ -517,6 +518,13 @@ sub get_perl_version { no warnings; } +sub get_windows_wget { + if(!-e "wget.exe" && $OS eq "Windows"){ + eval "use LWP::Simple qw(getstore);"; + getstore("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/wget.exe", "wget.exe"); + } +} + sub do_self_update_check_routine { #::: Check for internet connection before updating @@ -524,7 +532,7 @@ sub do_self_update_check_routine { print "[Update] Cannot check update without internet connection...\n"; return; } - + #::: Check for script changes :: eqemu_server.pl get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); @@ -997,68 +1005,14 @@ sub get_remote_file{ } } - if($OS eq "Windows"){ - #::: For non-text type requests... - if($content_type == 1){ - $break = 0; - while($break == 0) { - eval "use LWP::Simple qw(getstore);"; - # use LWP::Simple qw(getstore); - # print "request is " . $request_url . "\n"; - # print "destination file is supposed to be " . $destination_file . "\n"; - if(!getstore($request_url, $destination_file)){ - print "[Download] Error, no connection or failed request...\n\n"; - } - # sleep(1); - #::: Make sure the file exists before continuing... - if(-e $destination_file) { - $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - } else { $break = 0; } - usleep(500); - - if($no_retry){ - $break = 1; - } - } - } - else{ - $break = 0; - while($break == 0) { - require LWP::UserAgent; - my $ua = LWP::UserAgent->new; - $ua->timeout(10); - $ua->env_proxy; - my $response = $ua->get($request_url); - if ($response->is_success){ - open (FILE, '> ' . $destination_file . ''); - print FILE $response->decoded_content; - close (FILE); - } - else { - print "[Download] Error, no connection or failed request...\n\n"; - } - if(-e $destination_file) { - $break = 1; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - } else { $break = 0; } - usleep(500); - - if($no_retry){ - $break = 1; - } - } - } - } - if($OS eq "Linux"){ - #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $wget = `wget --no-check-certificate --quiet -O $destination_file $request_url`; - print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; - if($wget=~/unable to resolve/i){ - print "Error, no connection or failed request...\n\n"; - #die; - } + #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt + $wget = `wget -N --no-check-certificate --quiet -O $destination_file $request_url`; + print "[Download] Saved: (" . $destination_file . ") from " . $request_url . "\n" if !$silent_download; + if($wget=~/unable to resolve/i){ + print "Error, no connection or failed request...\n\n"; + #die; } + } #::: Trim Whitespaces From 21f02f4ce429e02fdbb1d492ab06034f7d7ad401 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 13:35:19 -0400 Subject: [PATCH 034/218] Move pet command/button defines to common.h I didn't want to include pets.h everywhere --- zone/client.cpp | 1 - zone/common.h | 48 ++++++++++++++++++++++++++++++++++++++++++ zone/pets.h | 48 ------------------------------------------ zone/spell_effects.cpp | 1 - 4 files changed, 48 insertions(+), 50 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index cf3814a7d..4ec1ba898 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -54,7 +54,6 @@ extern volatile bool RunLoops; #include "guild_mgr.h" #include "quest_parser_collection.h" #include "queryserv.h" -#include "pets.h" extern QueryServ* QServ; extern EntityList entity_list; diff --git a/zone/common.h b/zone/common.h index f1f965740..02d26b041 100644 --- a/zone/common.h +++ b/zone/common.h @@ -56,6 +56,54 @@ //Maximum distance from a zone point if zone was specified #define ZONEPOINT_ZONE_RANGE 40000.0f +// Defines based on the RoF2 Client +#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window +#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window +#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window +#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window +#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window +#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window +#define PET_SIT 6 // 0x06 - /pet sit or Pet Window +#define PET_SITDOWN 7 // 0x07 - /pet sit on +#define PET_STANDUP 8 // 0x08 - /pet sit off +#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented +#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented +#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented +#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window +#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on +#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off +#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking +#define PET_HOLD_ON 16 // 0x10 - /pet hold on +#define PET_HOLD_OFF 17 // 0x11 - /pet hold off +#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to +#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on +#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off +#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window +#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on +#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off +#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window +#define PET_FOCUS_ON 25 // 0x19 - /pet focus on +#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off +#define PET_FEIGN 27 // 0x1b - /pet feign +#define PET_BACKOFF 28 // 0x1c - /pet back off +#define PET_GETLOST 29 // 0x1d - /pet get lost +#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet +#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list +#define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup +#define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup + +// can change the state of these buttons with a packet +#define PET_BUTTON_SIT 0 +#define PET_BUTTON_STOP 1 +#define PET_BUTTON_REGROUP 2 +#define PET_BUTTON_FOLLOW 3 +#define PET_BUTTON_GUARD 4 +#define PET_BUTTON_TAUNT 5 +#define PET_BUTTON_HOLD 6 +#define PET_BUTTON_GHOLD 7 +#define PET_BUTTON_FOCUS 8 +#define PET_BUTTON_SPELLHOLD 9 + typedef enum { //focus types focusSpellHaste = 1, focusSpellDuration, diff --git a/zone/pets.h b/zone/pets.h index 3a7f5932c..edb6dbe95 100644 --- a/zone/pets.h +++ b/zone/pets.h @@ -1,54 +1,6 @@ #ifndef PETS_H #define PETS_H -// Defines based on the RoF2 Client -#define PET_HEALTHREPORT 0 // 0x00 - /pet health or Pet Window -#define PET_LEADER 1 // 0x01 - /pet leader or Pet Window -#define PET_ATTACK 2 // 0x02 - /pet attack or Pet Window -#define PET_QATTACK 3 // 0x03 - /pet qattack or Pet Window -#define PET_FOLLOWME 4 // 0x04 - /pet follow or Pet Window -#define PET_GUARDHERE 5 // 0x05 - /pet guard or Pet Window -#define PET_SIT 6 // 0x06 - /pet sit or Pet Window -#define PET_SITDOWN 7 // 0x07 - /pet sit on -#define PET_STANDUP 8 // 0x08 - /pet sit off -#define PET_STOP 9 // 0x09 - /pet stop or Pet Window - Not implemented -#define PET_STOP_ON 10 // 0x0a - /pet stop on - Not implemented -#define PET_STOP_OFF 11 // 0x0b - /pet stop off - Not implemented -#define PET_TAUNT 12 // 0x0c - /pet taunt or Pet Window -#define PET_TAUNT_ON 13 // 0x0d - /pet taunt on -#define PET_TAUNT_OFF 14 // 0x0e - /pet taunt off -#define PET_HOLD 15 // 0x0f - /pet hold or Pet Window, won't add to hate list unless attacking -#define PET_HOLD_ON 16 // 0x10 - /pet hold on -#define PET_HOLD_OFF 17 // 0x11 - /pet hold off -#define PET_GHOLD 18 // 0x12 - /pet ghold, will never add to hate list unless told to -#define PET_GHOLD_ON 19 // 0x13 - /pet ghold on -#define PET_GHOLD_OFF 20 // 0x14 - /pet ghold off -#define PET_SPELLHOLD 21 // 0x15 - /pet no cast or /pet spellhold or Pet Window -#define PET_SPELLHOLD_ON 22 // 0x16 - /pet spellhold on -#define PET_SPELLHOLD_OFF 23 // 0x17 - /pet spellhold off -#define PET_FOCUS 24 // 0x18 - /pet focus or Pet Window -#define PET_FOCUS_ON 25 // 0x19 - /pet focus on -#define PET_FOCUS_OFF 26 // 0x1a - /pet focus off -#define PET_FEIGN 27 // 0x1b - /pet feign -#define PET_BACKOFF 28 // 0x1c - /pet back off -#define PET_GETLOST 29 // 0x1d - /pet get lost -#define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet -#define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list -#define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup -#define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup - -// can change the state of these buttons with a packet -#define PET_BUTTON_SIT 0 -#define PET_BUTTON_STOP 1 -#define PET_BUTTON_REGROUP 2 -#define PET_BUTTON_FOLLOW 3 -#define PET_BUTTON_GUARD 4 -#define PET_BUTTON_TAUNT 5 -#define PET_BUTTON_HOLD 6 -#define PET_BUTTON_GHOLD 7 -#define PET_BUTTON_FOCUS 8 -#define PET_BUTTON_SPELLHOLD 9 - class Mob; struct NPCType; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ceffc1ef3..1823afb67 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -30,7 +30,6 @@ #include "quest_parser_collection.h" #include "string_ids.h" #include "worldserver.h" -#include "pets.h" #include From 04cf511e4fb26151939c00d04a4eff7cf3ce9482 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 15:41:00 -0400 Subject: [PATCH 035/218] Clean up older clients PetCommand translations --- common/patches/sod.cpp | 87 ++++++++++++++++--------------------- common/patches/sof.cpp | 87 ++++++++++++++++--------------------- common/patches/titanium.cpp | 87 ++++++++++++++++--------------------- 3 files changed, 111 insertions(+), 150 deletions(-) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 9d4db7737..c68bfacef 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -3291,73 +3291,60 @@ namespace SoD switch (eq->command) { - case 0x04: - emu->command = 0x00; // /pet health + case 1: // back off + emu->command = 28; break; - case 0x10: - emu->command = 0x01; // /pet leader + case 2: // get lost + emu->command = 29; break; - case 0x07: - emu->command = 0x02; // /pet attack or Pet Window + case 3: // as you were ??? + emu->command = 4; // fuck it follow break; - case 0x03: // Case Guessed - emu->command = 0x03; // /pet qattack - case 0x08: - emu->command = 0x04; // /pet follow or Pet Window + case 4: // report HP + emu->command = 0; break; - case 0x05: - emu->command = 0x05; // /pet guard or Pet Window + case 5: // guard here + emu->command = 5; break; - case 0x09: - emu->command = 0x07; // /pet sit or Pet Window + case 6: // guard me + emu->command = 4; // fuck it follow break; - case 0x0a: - emu->command = 0x08; // /pet stand or Pet Window + case 7: // attack + emu->command = 2; break; - case 0x06: - emu->command = 0x1e; // /pet guard me + case 8: // follow + emu->command = 4; break; - case 0x0f: // Case Made Up - emu->command = 0x09; // /pet stop + case 9: // sit down + emu->command = 7; break; - case 0x0b: - emu->command = 0x0d; // /pet taunt or Pet Window + case 10: // stand up + emu->command = 8; break; - case 0x0e: - emu->command = 0x0e; // /pet notaunt or Pet Window + case 11: // taunt toggle + emu->command = 12; break; - case 0x0c: - emu->command = 0x0f; // /pet hold + case 12: // hold toggle + emu->command = 15; break; - case 0x1b: - emu->command = 0x10; // /pet hold on + case 13: // taunt on + emu->command = 13; break; - case 0x1c: - emu->command = 0x11; // /pet hold off + case 14: // no taunt + emu->command = 14; break; - case 0x11: - emu->command = 0x12; // Slumber? + // 15 is target, doesn't send packet + case 16: // leader + emu->command = 1; break; - case 0x12: - emu->command = 0x15; // /pet no cast + case 17: // feign + emu->command = 27; break; - case 0x0d: // Case Made Up - emu->command = 0x16; // Pet Window No Cast + case 18: // no cast toggle + emu->command = 21; break; - case 0x13: - emu->command = 0x18; // /pet focus - break; - case 0x19: - emu->command = 0x19; // /pet focus on - break; - case 0x1a: - emu->command = 0x1a; // /pet focus off - break; - case 0x01: - emu->command = 0x1c; // /pet back off - break; - case 0x02: - emu->command = 0x1d; // /pet get lost + case 19: // focus toggle + emu->command = 24; break; default: emu->command = eq->command; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 456bc7339..44f093044 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2675,73 +2675,60 @@ namespace SoF switch (eq->command) { - case 0x04: - emu->command = 0x00; // /pet health + case 1: // back off + emu->command = 28; break; - case 0x10: - emu->command = 0x01; // /pet leader + case 2: // get lost + emu->command = 29; break; - case 0x07: - emu->command = 0x02; // /pet attack or Pet Window + case 3: // as you were ??? + emu->command = 4; // fuck it follow break; - case 0x03: // Case Guessed - emu->command = 0x03; // /pet qattack - case 0x08: - emu->command = 0x04; // /pet follow or Pet Window + case 4: // report HP + emu->command = 0; break; - case 0x05: - emu->command = 0x05; // /pet guard or Pet Window + case 5: // guard here + emu->command = 5; break; - case 0x09: - emu->command = 0x07; // /pet sit or Pet Window + case 6: // guard me + emu->command = 4; // fuck it follow break; - case 0x0a: - emu->command = 0x08; // /pet stand or Pet Window + case 7: // attack + emu->command = 2; break; - case 0x06: - emu->command = 0x1e; // /pet guard me + case 8: // follow + emu->command = 4; break; - case 0x0f: // Case Made Up - emu->command = 0x09; // Stop? + case 9: // sit down + emu->command = 7; break; - case 0x0b: - emu->command = 0x0d; // /pet taunt or Pet Window + case 10: // stand up + emu->command = 8; break; - case 0x0e: - emu->command = 0x0e; // /pet notaunt or Pet Window + case 11: // taunt toggle + emu->command = 12; break; - case 0x0c: - emu->command = 0x0f; // /pet hold + case 12: // hold toggle + emu->command = 15; break; - case 0x1b: - emu->command = 0x10; // /pet hold on + case 13: // taunt on + emu->command = 13; break; - case 0x1c: - emu->command = 0x11; // /pet hold off + case 14: // no taunt + emu->command = 14; break; - case 0x11: - emu->command = 0x12; // Slumber? + // 15 is target, doesn't send packet + case 16: // leader + emu->command = 1; break; - case 0x12: - emu->command = 0x15; // /pet no cast + case 17: // feign + emu->command = 27; break; - case 0x0d: // Case Made Up - emu->command = 0x16; // Pet Window No Cast + case 18: // no cast toggle + emu->command = 21; break; - case 0x13: - emu->command = 0x18; // /pet focus - break; - case 0x19: - emu->command = 0x19; // /pet focus on - break; - case 0x1a: - emu->command = 0x1a; // /pet focus off - break; - case 0x01: - emu->command = 0x1c; // /pet back off - break; - case 0x02: - emu->command = 0x1d; // /pet get lost + case 19: // focus toggle + emu->command = 24; break; default: emu->command = eq->command; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 302befb6a..e9679dc06 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2030,73 +2030,60 @@ namespace Titanium switch (eq->command) { - case 0x04: - emu->command = 0x00; // /pet health + case 1: // back off + emu->command = 28; break; - case 0x10: - emu->command = 0x01; // /pet leader + case 2: // get lost + emu->command = 29; break; - case 0x07: - emu->command = 0x02; // /pet attack or Pet Window + case 3: // as you were ??? + emu->command = 4; // fuck it follow break; - case 0x03: // Case Guessed - emu->command = 0x03; // /pet qattack - case 0x08: - emu->command = 0x04; // /pet follow or Pet Window + case 4: // report HP + emu->command = 0; break; - case 0x05: - emu->command = 0x05; // /pet guard or Pet Window + case 5: // guard here + emu->command = 5; break; - case 0x09: - emu->command = 0x07; // /pet sit or Pet Window + case 6: // guard me + emu->command = 4; // fuck it follow break; - case 0x0a: - emu->command = 0x08; // /pet stand or Pet Window + case 7: // attack + emu->command = 2; break; - case 0x06: - emu->command = 0x1e; // /pet guard me + case 8: // follow + emu->command = 4; break; - case 0x0f: // Case Made Up - emu->command = 0x09; // Stop? + case 9: // sit down + emu->command = 7; break; - case 0x0b: - emu->command = 0x0d; // /pet taunt or Pet Window + case 10: // stand up + emu->command = 8; break; - case 0x0e: - emu->command = 0x0e; // /pet notaunt or Pet Window + case 11: // taunt toggle + emu->command = 12; break; - case 0x0c: - emu->command = 0x0f; // /pet hold + case 12: // hold toggle + emu->command = 15; break; - case 0x1b: - emu->command = 0x10; // /pet hold on + case 13: // taunt on + emu->command = 13; break; - case 0x1c: - emu->command = 0x11; // /pet hold off + case 14: // no taunt + emu->command = 14; break; - case 0x11: - emu->command = 0x12; // Slumber? + // 15 is target, doesn't send packet + case 16: // leader + emu->command = 1; break; - case 0x12: - emu->command = 0x15; // /pet no cast + case 17: // feign + emu->command = 27; break; - case 0x0d: // Case Made Up - emu->command = 0x16; // Pet Window No Cast + case 18: // no cast toggle + emu->command = 21; break; - case 0x13: - emu->command = 0x18; // /pet focus - break; - case 0x19: - emu->command = 0x19; // /pet focus on - break; - case 0x1a: - emu->command = 0x1a; // /pet focus off - break; - case 0x01: - emu->command = 0x1c; // /pet back off - break; - case 0x02: - emu->command = 0x1d; // /pet get lost + case 19: // focus toggle + emu->command = 24; break; default: emu->command = eq->command; From 84bcb3ac037e4505e5684d28869ca9efd7b1a17c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 17:48:32 -0400 Subject: [PATCH 036/218] Use PetCommands SPA instead of GetAA --- common/spdat.h | 4 +-- zone/attack.cpp | 4 +-- zone/bonuses.cpp | 14 +++++++--- zone/client_packet.cpp | 58 ++++++++++++++++++++---------------------- zone/common.h | 3 +++ 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/common/spdat.h b/common/spdat.h index 913ee5a4b..bd1dacdf8 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -468,7 +468,7 @@ typedef enum { #define SE_Blank 254 // implemented #define SE_ShieldDuration 255 // not implemented as bonus - increases duration of /shield #define SE_ShroudofStealth 256 // implemented -#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold +#define SE_PetDiscipline 257 // not implemented as bonus - /pet hold - official name is GivePetHold #define SE_TripleBackstab 258 // implemented[AA] - chance to perform a triple backstab #define SE_CombatStability 259 // implemented[AA] - damage mitigation #define SE_AddSingingMod 260 // implemented[AA] - Instrument/Singing Mastery, base1 is the mod, base2 is the ItemType @@ -478,7 +478,7 @@ typedef enum { #define SE_HastenedAASkill 264 // implemented #define SE_MasteryofPast 265 // implemented[AA] - Spells less than effect values level can not be fizzled #define SE_ExtraAttackChance 266 // implemented - increase chance to score an extra attack with a 2-Handed Weapon. -#define SE_PetDiscipline2 267 // *not implemented - /pet focus, /pet no cast +#define SE_AddPetCommand 267 // implemented - sets command base2 to base1 #define SE_ReduceTradeskillFail 268 // implemented - reduces chance to fail with given tradeskill by a percent chance #define SE_MaxBindWound 269 // implemented[AA] - Increase max HP you can bind wound. #define SE_BardSongRange 270 // implemented[AA] - increase range of beneficial bard songs (Sionachie's Crescendo) diff --git a/zone/attack.cpp b/zone/attack.cpp index bbb17d2ec..179534966 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2522,7 +2522,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b // we skip these checks if it's forced through a pet command if (!pet_command) { - if (IsPet() && GetOwner() && GetOwner()->GetAA(aaPetDiscipline)) { + if (IsPet()) { if ((IsGHeld() || (IsHeld() && IsFocused())) && !on_hatelist) // we want them to be able to climb the hate list return; if (IsHeld() && !wasengaged) @@ -2632,7 +2632,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } - if (mypet && (!(GetAA(aaPetDiscipline) && mypet->IsHeld()))) { // I have a pet, add other to it + if (mypet && !mypet->IsHeld()) { // I have a pet, add other to it if (!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index e732d596b..7544ceb5f 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1442,11 +1442,19 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->FeignedCastOnChance = base1; break; + case SE_AddPetCommand: + if (base1 && base2 < PET_MAXCOMMANDS) + newbon->PetCommands[base2] = true; + break; + + case SE_FeignedMinion: + if (newbon->FeignedMinionChance < base1) + newbon->FeignedMinionChance = base1; + break; + // to do case SE_PetDiscipline: break; - case SE_PetDiscipline2: - break; case SE_PotionBeltSlots: break; case SE_BandolierSlots: @@ -1465,8 +1473,6 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; case SE_TrapCircumvention: break; - case SE_FeignedMinion: - break; // not handled here case SE_HastenedAASkill: diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 499402997..600d02757 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9978,9 +9978,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->GetPetType() == petTargetLock && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST)) return; - if (mypet->GetPetType() == petAnimation && (pet->command != PET_HEALTHREPORT && pet->command != PET_GETLOST) && !GetAA(aaAnimationEmpathy)) - return; - // just let the command "/pet get lost" work for familiars if (mypet->GetPetType() == petFamiliar && pet->command != PET_GETLOST) return; @@ -10014,7 +10011,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { zone->AddAggroMob(); // classic acts like qattack @@ -10047,7 +10044,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 2) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { zone->AddAggroMob(); mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); @@ -10059,7 +10056,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_BACKOFF: { if (mypet->IsFeared()) break; //keeps pet running while feared - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_CALMING); mypet->WipeHateList(); mypet->SetTarget(nullptr); @@ -10067,9 +10064,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HEALTHREPORT: { - Message_StringID(MT_PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); - mypet->ShowBuffList(this); - //Message(10,"%s tells you, 'I have %d percent of my hit points left.'",mypet->GetName(),(uint8)mypet->GetHPRatio()); + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + Message_StringID(MT_PetResponse, PET_REPORT_HP, ConvertArrayF(mypet->GetHPRatio(), val1)); + mypet->ShowBuffList(this); + } break; } case PET_GETLOST: { @@ -10102,7 +10100,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_GUARDHERE: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->IsNPC()) { mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE); mypet->SetPetOrder(SPO_Guard); @@ -10114,7 +10112,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_FOLLOWME: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10122,7 +10120,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_TAUNT: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->CastToNPC()->IsTaunting()) { Message_StringID(MT_PetResponse, PET_NO_TAUNT); @@ -10137,14 +10135,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_TAUNT_ON: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_DO_TAUNT); mypet->CastToNPC()->SetTaunting(true); } break; } case PET_TAUNT_OFF: { - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { Message_StringID(MT_PetResponse, PET_NO_TAUNT); mypet->CastToNPC()->SetTaunting(false); } @@ -10153,7 +10151,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_GUARDME: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 1) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10163,7 +10161,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_SIT: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->GetPetOrder() == SPO_Sit) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); @@ -10185,7 +10183,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_STANDUP: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); @@ -10195,7 +10193,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) case PET_SITDOWN: { if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF - if ((mypet->GetPetType() == petAnimation && GetAA(aaAnimationEmpathy) >= 3) || mypet->GetPetType() != petAnimation) { + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Sit); mypet->SetRunAnimSpeed(0); @@ -10206,7 +10204,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsHeld()) { mypet->SetHeld(false); @@ -10222,7 +10220,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD_ON: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && !mypet->IsHeld()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) { mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); mypet->SetGHeld(false); @@ -10231,12 +10229,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD_OFF: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) mypet->SetHeld(false); break; } case PET_GHOLD: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsGHeld()) { mypet->SetGHeld(false); @@ -10252,7 +10250,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_GHOLD_ON: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetGHeld(true); mypet->SetHeld(false); @@ -10261,12 +10259,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_GHOLD_OFF: { - if (GetAA(aaPetDiscipline) && mypet->IsNPC() && mypet->IsGHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) mypet->SetGHeld(false); break; } case PET_SPELLHOLD: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsNoCast()) { @@ -10281,7 +10279,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_SPELLHOLD_ON: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (!mypet->IsNoCast()) { @@ -10292,7 +10290,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_SPELLHOLD_OFF: { - if (GetAA(aaAdvancedPetDiscipline) == 2 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsNoCast()) { @@ -10303,7 +10301,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsFocused()) { @@ -10318,7 +10316,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS_ON: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (!mypet->IsFocused()) { @@ -10329,7 +10327,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_FOCUS_OFF: { - if (GetAA(aaAdvancedPetDiscipline) >= 1 && mypet->IsNPC()) { + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsFeared()) break; if (mypet->IsFocused()) { diff --git a/zone/common.h b/zone/common.h index 02d26b041..dad32925e 100644 --- a/zone/common.h +++ b/zone/common.h @@ -91,6 +91,7 @@ #define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list #define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup #define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup +#define PET_MAXCOMMANDS PET_REGROUPOFF + 1 // can change the state of these buttons with a packet #define PET_BUTTON_SIT 0 @@ -533,6 +534,8 @@ struct StatBonuses { uint8 TradeSkillMastery; // Allow number of tradeskills to exceed 200 skill. int16 NoBreakAESneak; // Percent value int16 FeignedCastOnChance; // Percent Value + bool PetCommands[PET_MAXCOMMANDS]; // SPA 267 + int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD }; typedef struct From 15d81eee21f917a881d8a0325e8c9c03dac15999 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 19:42:13 -0400 Subject: [PATCH 037/218] Remove unnecessary CastToNPC in PetCommands --- zone/client_packet.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 600d02757..d4ab27d9e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10269,11 +10269,11 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_CASTING); - mypet->CastToNPC()->SetNoCast(false); + mypet->SetNoCast(false); } else { Message_StringID(MT_PetResponse, PET_NOT_CASTING); - mypet->CastToNPC()->SetNoCast(true); + mypet->SetNoCast(true); } } break; @@ -10284,7 +10284,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (!mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_NOT_CASTING); - mypet->CastToNPC()->SetNoCast(true); + mypet->SetNoCast(true); } } break; @@ -10295,7 +10295,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_CASTING); - mypet->CastToNPC()->SetNoCast(false); + mypet->SetNoCast(false); } } break; @@ -10306,11 +10306,11 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOT_FOCUSING); - mypet->CastToNPC()->SetFocused(false); + mypet->SetFocused(false); } else { Message_StringID(MT_PetResponse, PET_NOW_FOCUSING); - mypet->CastToNPC()->SetFocused(true); + mypet->SetFocused(true); } } break; @@ -10321,7 +10321,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (!mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOW_FOCUSING); - mypet->CastToNPC()->SetFocused(true); + mypet->SetFocused(true); } } break; @@ -10332,7 +10332,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOT_FOCUSING); - mypet->CastToNPC()->SetFocused(false); + mypet->SetFocused(false); } } break; From 9f8ad1a32c8545def94be03b58a44512fce40d30 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 20:23:42 -0400 Subject: [PATCH 038/218] Fix pets ghosting if moving when you hit guard --- zone/client_packet.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index d4ab27d9e..4d32a0ea9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10105,6 +10105,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE); mypet->SetPetOrder(SPO_Guard); mypet->CastToNPC()->SaveGuardSpot(); + if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down + mypet->SetCurrentSpeed(0); } } break; From 7e2136a5a8ceed3845d26b92a57ba23cf9854845 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 22:28:48 -0400 Subject: [PATCH 039/218] Implement Pet Command Stop --- zone/attack.cpp | 5 +++- zone/client_packet.cpp | 61 ++++++++++++++++++++++++++++++++++++++++++ zone/mob.cpp | 2 ++ zone/mob.h | 3 +++ zone/mob_ai.cpp | 5 +++- 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 179534966..7ffbc07bf 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2516,6 +2516,9 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } + if (IsPetStop()) + return; + // Pet that is /pet hold on will not add to their hate list if they're not engaged // Pet that is /pet hold on and /pet focus on will not add others to their hate list // Pet that is /pet ghold on will never add to their hate list unless /pet attack or /pet qattack @@ -2632,7 +2635,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } - if (mypet && !mypet->IsHeld()) { // I have a pet, add other to it + if (mypet && !mypet->IsHeld() && !mypet->IsPetStop()) { // I have a pet, add other to it if (!mypet->IsFamiliar() && !mypet->GetSpecialAbility(IMMUNE_AGGRO)) mypet->hate_list.AddEntToHateList(other, 0, 0, bFrenzy); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 4d32a0ea9..aa64b5d82 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10013,6 +10013,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (target != this && DistanceSquaredNoZ(mypet->GetPosition(), target->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } zone->AddAggroMob(); // classic acts like qattack int hate = 1; @@ -10046,6 +10050,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (GetTarget() != this && DistanceSquaredNoZ(mypet->GetPosition(), GetTarget()->GetPosition()) <= (RuleR(Pets, AttackCommandRange)*RuleR(Pets, AttackCommandRange))) { + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } zone->AddAggroMob(); mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); @@ -10060,6 +10068,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_CALMING); mypet->WipeHateList(); mypet->SetTarget(nullptr); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } } break; } @@ -10107,6 +10119,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->CastToNPC()->SaveGuardSpot(); if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down mypet->SetCurrentSpeed(0); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } } } break; @@ -10118,6 +10134,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } } break; } @@ -10157,6 +10177,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } } break; } @@ -10339,6 +10363,43 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_STOP: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + } else { + mypet->SetPetStop(true); + mypet->SetCurrentSpeed(0); + mypet->WipeHateList(); + mypet->SetTarget(nullptr); + } + mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + } + break; + } + case PET_STOP_ON: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetPetStop(true); + mypet->SetCurrentSpeed(0); + mypet->WipeHateList(); + mypet->SetTarget(nullptr); + mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + } + break; + } + case PET_STOP_OFF: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { + mypet->SetPetStop(false); + mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + } + break; + } default: printf("Client attempted to use a unknown pet command:\n"); break; diff --git a/zone/mob.cpp b/zone/mob.cpp index d219a27af..7f1adedc3 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -344,8 +344,10 @@ Mob::Mob(const char* in_name, typeofpet = petNone; // default to not a pet petpower = 0; held = false; + gheld = false; nocast = false; focused = false; + pet_stop = false; _IsTempPet = false; pet_owner_client = false; pet_targetlock_id = 0; diff --git a/zone/mob.h b/zone/mob.h index 9a1ff67a0..53a890132 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -875,6 +875,8 @@ public: inline const bool IsNoCast() const { return nocast; } inline void SetFocused(bool nState) { focused = nState; } inline const bool IsFocused() const { return focused; } + inline void SetPetStop(bool nState) { pet_stop = nState; } + inline const bool IsPetStop() const { return pet_stop; } inline const bool IsRoamer() const { return roamer; } inline const int GetWanderType() const { return wandertype; } inline const bool IsRooted() const { return rooted || permarooted; } @@ -1184,6 +1186,7 @@ protected: bool gheld; bool nocast; bool focused; + bool pet_stop; bool spawned; void CalcSpellBonuses(StatBonuses* newbon); virtual void CalcBonuses(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index ddd6d1c76..ac77c9c74 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -943,7 +943,7 @@ void Mob::AI_Process() { // if(RuleB(Combat, EnableFearPathing)){ if(currently_fleeing) { - if(IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) { + if((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop()) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) { @@ -1304,6 +1304,9 @@ void Mob::AI_Process() { if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); + if (IsPetStop()) // pet stop won't be engaged, so we will always get here and we want the above branch to execute + return; + if(zone->CanDoCombat() && AI_feign_remember_timer->Check()) { // 6/14/06 // Improved Feign Death Memory From fe9fb72dffbb35eef9a10ff90b240b5d2a999320 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 22:55:17 -0400 Subject: [PATCH 040/218] Update pet command messages --- zone/client_packet.cpp | 61 +++++++++++++++++++++++++++++++++++++----- zone/string_ids.h | 7 +++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index aa64b5d82..6281a5af8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10233,11 +10233,20 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsHeld()) { + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_HOLD_SET_OFF); mypet->SetHeld(false); } else { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // they use new messages now, but only SoD+? + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_HOLD_SET_ON); + + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) + mypet->Say_StringID(MT_PetResponse, PET_NOW_HOLDING); + else + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SetHeld(true); } mypet->SetGHeld(false); @@ -10247,7 +10256,13 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } case PET_HOLD_ON: { if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && !mypet->IsHeld()) { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_HOLD_SET_ON); + + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) + mypet->Say_StringID(MT_PetResponse, PET_NOW_HOLDING); + else + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); mypet->SetGHeld(false); SetPetCommandState(PET_BUTTON_GHOLD, 0); @@ -10255,19 +10270,29 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_HOLD_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsHeld()) { + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_HOLD_SET_OFF); mypet->SetHeld(false); + } break; } case PET_GHOLD: { if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (mypet->IsGHeld()) { + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) + Message_StringID(MT_PetResponse, PET_OFF_GHOLD); mypet->SetGHeld(false); } else { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); // message wrong + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { + Message_StringID(MT_PetResponse, PET_ON_GHOLD); + mypet->Say_StringID(MT_PetResponse, PET_GHOLD_ON_MSG); + } else { + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + } mypet->SetGHeld(true); } mypet->SetHeld(false); @@ -10277,7 +10302,12 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } case PET_GHOLD_ON: { if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { + Message_StringID(MT_PetResponse, PET_ON_GHOLD); + mypet->Say_StringID(MT_PetResponse, PET_GHOLD_ON_MSG); + } else { + mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + } mypet->SetGHeld(true); mypet->SetHeld(false); SetPetCommandState(PET_BUTTON_HOLD, 0); @@ -10285,8 +10315,11 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; } case PET_GHOLD_OFF: { - if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) + if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC() && mypet->IsGHeld()) { + if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) + Message_StringID(MT_PetResponse, PET_OFF_GHOLD); mypet->SetGHeld(false); + } break; } case PET_SPELLHOLD: { @@ -10295,10 +10328,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_CASTING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_OFF); mypet->SetNoCast(false); } else { Message_StringID(MT_PetResponse, PET_NOT_CASTING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_ON); mypet->SetNoCast(true); } } @@ -10310,6 +10347,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (!mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_NOT_CASTING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_ON); mypet->SetNoCast(true); } } @@ -10321,6 +10360,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsNoCast()) { Message_StringID(MT_PetResponse, PET_CASTING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_SPELLHOLD_SET_OFF); mypet->SetNoCast(false); } } @@ -10332,10 +10373,14 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOT_FOCUSING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_FOCUS_SET_OFF); mypet->SetFocused(false); } else { Message_StringID(MT_PetResponse, PET_NOW_FOCUSING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_FOCUS_SET_ON); mypet->SetFocused(true); } } @@ -10347,6 +10392,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (!mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOW_FOCUSING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_FOCUS_SET_ON); mypet->SetFocused(true); } } @@ -10358,6 +10405,8 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; if (mypet->IsFocused()) { Message_StringID(MT_PetResponse, PET_NOT_FOCUSING); + if (m_ClientVersionBit & EQEmu::versions::bit_SoDAndLater) + Message_StringID(MT_PetResponse, PET_FOCUS_SET_OFF); mypet->SetFocused(false); } } diff --git a/zone/string_ids.h b/zone/string_ids.h index 0326cff7e..ee4203a0e 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -164,6 +164,12 @@ #define PVP_ON 552 //You are now player kill and follow the ways of Discord. #define GENERIC_STRINGID_SAY 554 //%1 says '%T2' #define CANNOT_WAKE 555 //%1 tells you, 'I am unable to wake %2, master.' +#define PET_HOLD_SET_ON 698 //The pet hold mode has been set to on. +#define PET_HOLD_SET_OFF 699 //The pet hold mode has been set to off. +#define PET_FOCUS_SET_ON 700 //The pet focus mode has been set to on. +#define PET_FOCUS_SET_OFF 701 //The pet focus mode has been set to off. +#define PET_SPELLHOLD_SET_ON 702 //The pet spellhold mode has been set to on. +#define PET_SPELLHOLD_SET_OFF 703 //The pet spellhold mode has been set to off. #define GUILD_NAME_IN_USE 711 //You cannot create a guild with that name, that guild already exists on this server. #define GM_GAINXP 1002 //[GM] You have gained %1 AXP and %2 EXP (%3). #define MALE_SLAYUNDEAD 1007 //%1's holy blade cleanses his target!(%2) @@ -322,6 +328,7 @@ #define SENTINEL_TRIG_YOU 6724 //You have triggered your sentinel. #define SENTINEL_TRIG_OTHER 6725 //%1 has triggered your sentinel. #define IDENTIFY_SPELL 6765 //Item Lore: %1. +#define PET_NOW_HOLDING 6834 //Now holding, Master. I will not start attacks until ordered. #define PET_ON_GHOLD 6843 //Pet greater hold has been set to on. #define PET_OFF_GHOLD 6846 //Pet greater hold has been set to off. #define PET_GHOLD_ON_MSG 6847 //Now greater holding master. I will only attack something new if ordered. From 0e96e6689afedfe54e77a616c76072c55215d969 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 23:08:46 -0400 Subject: [PATCH 041/218] Pet stop does not clear aggro --- zone/client_packet.cpp | 2 -- zone/mob_ai.cpp | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 6281a5af8..15c5e8301 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10421,7 +10421,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } else { mypet->SetPetStop(true); mypet->SetCurrentSpeed(0); - mypet->WipeHateList(); mypet->SetTarget(nullptr); } mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); @@ -10434,7 +10433,6 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->SetPetStop(true); mypet->SetCurrentSpeed(0); - mypet->WipeHateList(); mypet->SetTarget(nullptr); mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index ac77c9c74..47cd0b1d4 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -935,7 +935,7 @@ void Mob::AI_Process() { bool engaged = IsEngaged(); bool doranged = false; - if (!zone->CanDoCombat()) { + if (!zone->CanDoCombat() || IsPetStop()) { engaged = false; } @@ -1300,7 +1300,6 @@ void Mob::AI_Process() { } } else { - if (m_PlayerState & static_cast(PlayerState::Aggressive)) SendRemovePlayerState(PlayerState::Aggressive); From d6b61b91638d80bb49987c78aee3466ea5062802 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 4 May 2017 23:48:47 -0400 Subject: [PATCH 042/218] Implement pet regroup Tweaks to stop as well --- zone/attack.cpp | 5 +--- zone/client_packet.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++ zone/common.h | 6 ++--- zone/mob.cpp | 1 + zone/mob.h | 3 +++ zone/mob_ai.cpp | 6 +++-- zone/string_ids.h | 2 ++ 7 files changed, 72 insertions(+), 9 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 7ffbc07bf..144578561 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2516,9 +2516,6 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b } } - if (IsPetStop()) - return; - // Pet that is /pet hold on will not add to their hate list if they're not engaged // Pet that is /pet hold on and /pet focus on will not add others to their hate list // Pet that is /pet ghold on will never add to their hate list unless /pet attack or /pet qattack @@ -2528,7 +2525,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b if (IsPet()) { if ((IsGHeld() || (IsHeld() && IsFocused())) && !on_hatelist) // we want them to be able to climb the hate list return; - if (IsHeld() && !wasengaged) + if ((IsHeld() || IsPetStop() || IsPetRegroup()) && !wasengaged) // not 100% sure on stop/regroup kind of hard to test, but regroup is like "classic hold" return; } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 15c5e8301..090f92816 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10017,6 +10017,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetPetStop(false); SetPetCommandState(PET_BUTTON_STOP, 0); } + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } zone->AddAggroMob(); // classic acts like qattack int hate = 1; @@ -10054,6 +10058,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetPetStop(false); SetPetCommandState(PET_BUTTON_STOP, 0); } + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } zone->AddAggroMob(); mypet->AddToHateList(GetTarget(), 1, 0, true, false, false, SPELL_UNKNOWN, true); Message_StringID(MT_PetResponse, PET_ATTACKING, mypet->GetCleanName(), GetTarget()->GetCleanName()); @@ -10422,6 +10430,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetPetStop(true); mypet->SetCurrentSpeed(0); mypet->SetTarget(nullptr); + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } } mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); } @@ -10435,6 +10447,10 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetCurrentSpeed(0); mypet->SetTarget(nullptr); mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + SetPetCommandState(PET_BUTTON_REGROUP, 0); + } } break; } @@ -10447,6 +10463,48 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } break; } + case PET_REGROUP: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if (aabonuses.PetCommands[PetCommand]) { + if (mypet->IsPetRegroup()) { + mypet->SetPetRegroup(false); + mypet->Say_StringID(MT_PetResponse, PET_OFF_REGROUPING); + } else { + mypet->SetPetRegroup(true); + mypet->SetTarget(nullptr); + mypet->Say_StringID(MT_PetResponse, PET_ON_REGROUPING); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } + } + } + break; + } + case PET_REGROUP_ON: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if (aabonuses.PetCommands[PetCommand]) { + mypet->SetPetRegroup(true); + mypet->SetTarget(nullptr); + mypet->Say_StringID(MT_PetResponse, PET_ON_REGROUPING); + if (mypet->IsPetStop()) { + mypet->SetPetStop(false); + SetPetCommandState(PET_BUTTON_STOP, 0); + } + } + break; + } + case PET_REGROUP_OFF: { + if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF + + if (aabonuses.PetCommands[PetCommand]) { + mypet->SetPetRegroup(false); + mypet->Say_StringID(MT_PetResponse, PET_OFF_REGROUPING); + } + break; + } default: printf("Client attempted to use a unknown pet command:\n"); break; diff --git a/zone/common.h b/zone/common.h index dad32925e..7b63174d4 100644 --- a/zone/common.h +++ b/zone/common.h @@ -89,9 +89,9 @@ #define PET_GETLOST 29 // 0x1d - /pet get lost #define PET_GUARDME 30 // 0x1e - Same as /pet follow, but different message in older clients - define not from client /pet target in modern clients but doesn't send packet #define PET_REGROUP 31 // 0x1f - /pet regroup, acts like classic hold. Stops attack and moves back to guard/you but doesn't clear hate list -#define PET_REGROUPON 32 // 0x20 - /pet regroup on, turns on regroup -#define PET_REGROUPOFF 33 // 0x21 - /pet regroup off, turns off regroup -#define PET_MAXCOMMANDS PET_REGROUPOFF + 1 +#define PET_REGROUP_ON 32 // 0x20 - /pet regroup on, turns on regroup +#define PET_REGROUP_OFF 33 // 0x21 - /pet regroup off, turns off regroup +#define PET_MAXCOMMANDS PET_REGROUP_OFF + 1 // can change the state of these buttons with a packet #define PET_BUTTON_SIT 0 diff --git a/zone/mob.cpp b/zone/mob.cpp index 7f1adedc3..b9cb0ddaf 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -348,6 +348,7 @@ Mob::Mob(const char* in_name, nocast = false; focused = false; pet_stop = false; + pet_regroup = false; _IsTempPet = false; pet_owner_client = false; pet_targetlock_id = 0; diff --git a/zone/mob.h b/zone/mob.h index 53a890132..cd17067d6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -877,6 +877,8 @@ public: inline const bool IsFocused() const { return focused; } inline void SetPetStop(bool nState) { pet_stop = nState; } inline const bool IsPetStop() const { return pet_stop; } + inline void SetPetRegroup(bool nState) { pet_regroup = nState; } + inline const bool IsPetRegroup() const { return pet_regroup; } inline const bool IsRoamer() const { return roamer; } inline const int GetWanderType() const { return wandertype; } inline const bool IsRooted() const { return rooted || permarooted; } @@ -1187,6 +1189,7 @@ protected: bool nocast; bool focused; bool pet_stop; + bool pet_regroup; bool spawned; void CalcSpellBonuses(StatBonuses* newbon); virtual void CalcBonuses(); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 47cd0b1d4..fd0ec5d81 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -935,7 +935,7 @@ void Mob::AI_Process() { bool engaged = IsEngaged(); bool doranged = false; - if (!zone->CanDoCombat() || IsPetStop()) { + if (!zone->CanDoCombat() || IsPetStop() || IsPetRegroup()) { engaged = false; } @@ -943,7 +943,7 @@ void Mob::AI_Process() { // if(RuleB(Combat, EnableFearPathing)){ if(currently_fleeing) { - if((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop()) { + if((IsRooted() || (IsBlind() && CombatRange(hate_list.GetClosestEntOnHateList(this)))) && !IsPetStop() && !IsPetRegroup()) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) { @@ -1411,6 +1411,8 @@ void Mob::AI_Process() { break; } } + if (IsPetRegroup()) + return; } /* Entity has been assigned another entity to follow */ else if (GetFollowID()) diff --git a/zone/string_ids.h b/zone/string_ids.h index ee4203a0e..65810d576 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -332,6 +332,8 @@ #define PET_ON_GHOLD 6843 //Pet greater hold has been set to on. #define PET_OFF_GHOLD 6846 //Pet greater hold has been set to off. #define PET_GHOLD_ON_MSG 6847 //Now greater holding master. I will only attack something new if ordered. +#define PET_ON_REGROUPING 6854 //Now regrouping, master. +#define PET_OFF_REGROUPING 6855 //No longer regrouping, master. #define BUFF_NOT_BLOCKABLE 7608 //You cannot block this effect. #define LDON_DONT_KNOW_TRAPPED 7552 //You do not know if this object is trapped. #define LDON_HAVE_DISARMED 7553 //You have disarmed %1! From 6e70d12b0a2a531959cddfddb3d850e70c2228a3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 May 2017 23:45:14 -0400 Subject: [PATCH 043/218] Add Mob::SayTo_StringID so we don't have to spam --- zone/mob.cpp | 20 ++++++++++++++++++++ zone/mob.h | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/zone/mob.cpp b/zone/mob.cpp index b9cb0ddaf..ae036398a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3096,6 +3096,26 @@ void Mob::Say_StringID(uint32 type, uint32 string_id, const char *message3, cons ); } +void Mob::SayTo_StringID(Client *to, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) +{ + if (!to) + return; + + auto string_id_str = std::to_string(string_id); + + to->Message_StringID(10, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9); +} + +void Mob::SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3, const char *message4, const char *message5, const char *message6, const char *message7, const char *message8, const char *message9) +{ + if (!to) + return; + + auto string_id_str = std::to_string(string_id); + + to->Message_StringID(type, GENERIC_STRINGID_SAY, GetCleanName(), string_id_str.c_str(), message3, message4, message5, message6, message7, message8, message9); +} + void Mob::Shout(const char *format, ...) { char buf[1000]; diff --git a/zone/mob.h b/zone/mob.h index cd17067d6..cba96f372 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -642,6 +642,10 @@ public: const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); void Say_StringID(uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); + void SayTo_StringID(Client *to, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, + const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); + void SayTo_StringID(Client *to, uint32 type, uint32 string_id, const char *message3 = 0, const char *message4 = 0, const char *message5 = 0, + const char *message6 = 0, const char *message7 = 0, const char *message8 = 0, const char *message9 = 0); void Shout(const char *format, ...); void Emote(const char *format, ...); void QuestJournalledSay(Client *QuestInitiator, const char *str); From 82776deb8961e7ae1d5a5346d3d91dc4d9106eaf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 5 May 2017 23:52:54 -0400 Subject: [PATCH 044/218] Pet commands only reply to master now (except leader) --- zone/client_packet.cpp | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 090f92816..bbd76183d 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -10007,7 +10007,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) break; //prevent pet from attacking stuff while feared if (!mypet->IsAttackAllowed(target)) { - mypet->Say_StringID(NOT_LEGAL_TARGET); + mypet->SayTo_StringID(this, NOT_LEGAL_TARGET); break; } @@ -10048,7 +10048,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) } if (!mypet->IsAttackAllowed(GetTarget())) { - mypet->Say_StringID(NOT_LEGAL_TARGET); + mypet->SayTo_StringID(this, NOT_LEGAL_TARGET); break; } @@ -10073,7 +10073,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //keeps pet running while feared if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_CALMING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_CALMING); mypet->WipeHateList(); mypet->SetTarget(nullptr); if (mypet->IsPetStop()) { @@ -10104,7 +10104,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) SetPet(nullptr); } - mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GETLOST_STRING); mypet->CastToNPC()->Depop(); //Oddly, the client (Titanium) will still allow "/pet get lost" command despite me adding the code below. If someone can figure that out, you can uncomment this code and use it. @@ -10122,7 +10122,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->IsNPC()) { - mypet->Say_StringID(MT_PetResponse, PET_GUARDINGLIFE); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GUARDINGLIFE); mypet->SetPetOrder(SPO_Guard); mypet->CastToNPC()->SaveGuardSpot(); if (!mypet->GetTarget()) // want them to not twitch if they're chasing something down @@ -10139,7 +10139,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_FOLLOWING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_FOLLOWING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); if (mypet->IsPetStop()) { @@ -10182,7 +10182,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_GUARDME_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GUARDME_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); if (mypet->IsPetStop()) { @@ -10198,13 +10198,13 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { if (mypet->GetPetOrder() == SPO_Sit) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); } else { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Sit); mypet->SetRunAnimSpeed(0); if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet @@ -10218,7 +10218,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Follow); mypet->SendAppearancePacket(AT_Anim, ANIM_STAND); } @@ -10228,7 +10228,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (mypet->IsFeared()) break; //could be exploited like PET_BACKOFF if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { - mypet->Say_StringID(MT_PetResponse, PET_SIT_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_SIT_STRING); mypet->SetPetOrder(SPO_Sit); mypet->SetRunAnimSpeed(0); if (!mypet->UseBardSpellLogic()) //maybe we can have a bard pet @@ -10251,9 +10251,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) Message_StringID(MT_PetResponse, PET_HOLD_SET_ON); if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) - mypet->Say_StringID(MT_PetResponse, PET_NOW_HOLDING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_NOW_HOLDING); else - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); } @@ -10268,9 +10268,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) Message_StringID(MT_PetResponse, PET_HOLD_SET_ON); if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) - mypet->Say_StringID(MT_PetResponse, PET_NOW_HOLDING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_NOW_HOLDING); else - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD); mypet->SetHeld(true); mypet->SetGHeld(false); SetPetCommandState(PET_BUTTON_GHOLD, 0); @@ -10297,9 +10297,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) { if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { Message_StringID(MT_PetResponse, PET_ON_GHOLD); - mypet->Say_StringID(MT_PetResponse, PET_GHOLD_ON_MSG); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GHOLD_ON_MSG); } else { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD); } mypet->SetGHeld(true); } @@ -10312,9 +10312,9 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (aabonuses.PetCommands[PetCommand] && mypet->IsNPC()) { if (m_ClientVersionBit & EQEmu::versions::bit_UFAndLater) { Message_StringID(MT_PetResponse, PET_ON_GHOLD); - mypet->Say_StringID(MT_PetResponse, PET_GHOLD_ON_MSG); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GHOLD_ON_MSG); } else { - mypet->Say_StringID(MT_PetResponse, PET_ON_HOLD); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_HOLD); } mypet->SetGHeld(true); mypet->SetHeld(false); @@ -10435,7 +10435,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) SetPetCommandState(PET_BUTTON_REGROUP, 0); } } - mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GETLOST_STRING); } break; } @@ -10446,7 +10446,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) mypet->SetPetStop(true); mypet->SetCurrentSpeed(0); mypet->SetTarget(nullptr); - mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GETLOST_STRING); if (mypet->IsPetRegroup()) { mypet->SetPetRegroup(false); SetPetCommandState(PET_BUTTON_REGROUP, 0); @@ -10459,7 +10459,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if ((mypet->GetPetType() == petAnimation && aabonuses.PetCommands[PetCommand]) || mypet->GetPetType() != petAnimation) { mypet->SetPetStop(false); - mypet->Say_StringID(MT_PetResponse, PET_GETLOST_STRING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_GETLOST_STRING); } break; } @@ -10469,11 +10469,11 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (aabonuses.PetCommands[PetCommand]) { if (mypet->IsPetRegroup()) { mypet->SetPetRegroup(false); - mypet->Say_StringID(MT_PetResponse, PET_OFF_REGROUPING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_OFF_REGROUPING); } else { mypet->SetPetRegroup(true); mypet->SetTarget(nullptr); - mypet->Say_StringID(MT_PetResponse, PET_ON_REGROUPING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_REGROUPING); if (mypet->IsPetStop()) { mypet->SetPetStop(false); SetPetCommandState(PET_BUTTON_STOP, 0); @@ -10488,7 +10488,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (aabonuses.PetCommands[PetCommand]) { mypet->SetPetRegroup(true); mypet->SetTarget(nullptr); - mypet->Say_StringID(MT_PetResponse, PET_ON_REGROUPING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_ON_REGROUPING); if (mypet->IsPetStop()) { mypet->SetPetStop(false); SetPetCommandState(PET_BUTTON_STOP, 0); @@ -10501,7 +10501,7 @@ void Client::Handle_OP_PetCommands(const EQApplicationPacket *app) if (aabonuses.PetCommands[PetCommand]) { mypet->SetPetRegroup(false); - mypet->Say_StringID(MT_PetResponse, PET_OFF_REGROUPING); + mypet->SayTo_StringID(this, MT_PetResponse, PET_OFF_REGROUPING); } break; } From abeeb8072723e4d73123beb7a00247a924b4fa66 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 13 May 2017 07:30:57 -0700 Subject: [PATCH 045/218] Fix SE_ResourceTap where 1000 base is 100% and math fix (ty kayen) --- zone/spell_effects.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 1823afb67..e04a136e6 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6686,23 +6686,26 @@ void Mob::ResourceTap(int32 damage, uint16 spellid) for (int i = 0; i < EFFECT_COUNT; i++) { if (spells[spellid].effectid[i] == SE_ResourceTap) { - damage += (damage * spells[spellid].base[i]) / 100; - - if (spells[spellid].max[i] && (damage > spells[spellid].max[i])) - damage = spells[spellid].max[i]; - - if (spells[spellid].base2[i] == 0) { // HP Tap - if (damage > 0) - HealDamage(damage); - else - Damage(this, -damage, 0, EQEmu::skills::SkillEvocation, false); + damage = (damage * spells[spellid].base[i]) / 1000; + + if (damage) { + if (spells[spellid].max[i] && (damage > spells[spellid].max[i])) + damage = spells[spellid].max[i]; + + if (spells[spellid].base2[i] == 0) { // HP Tap + if (damage > 0) + HealDamage(damage); + else + Damage(this, -damage, 0, EQEmu::skills::SkillEvocation, false); + } + + if (spells[spellid].base2[i] == 1) // Mana Tap + SetMana(GetMana() + damage); + + if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap + CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage); + } - - if (spells[spellid].base2[i] == 1) // Mana Tap - SetMana(GetMana() + damage); - - if (spells[spellid].base2[i] == 2 && IsClient()) // Endurance Tap - CastToClient()->SetEndurance(CastToClient()->GetEndurance() + damage); } } } From 28fd766278ace294bb03a2a51ccd98ae46dc2e1f Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 15 May 2017 15:46:19 -0700 Subject: [PATCH 046/218] Export many things --- common/net/daybreak_connection.h | 5 +- zone/attack.cpp | 9 +- zone/bot.cpp | 2 +- zone/lua_client.cpp | 14 +- zone/lua_client.h | 1 + zone/lua_general.cpp | 92 +++++- zone/lua_general.h | 4 +- zone/lua_mob.cpp | 38 ++- zone/lua_mob.h | 6 + zone/lua_mod.cpp | 6 + zone/lua_parser.cpp | 2 + zone/lua_ptr.h | 10 +- zone/lua_stat_bonuses.cpp | 510 +++++++++++++++---------------- zone/mob.h | 6 +- zone/tune.cpp | 15 +- 15 files changed, 438 insertions(+), 282 deletions(-) diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 9d885e81d..2d99153e9 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -155,13 +156,13 @@ namespace EQ uint16_t sequence_in; uint16_t sequence_out; - std::map packet_queue; + std::unordered_map packet_queue; DynamicPacket fragment_packet; uint32_t fragment_current_bytes; uint32_t fragment_total_bytes; - std::map sent_packets; + std::unordered_map sent_packets; }; DaybreakStream m_streams[4]; diff --git a/zone/attack.cpp b/zone/attack.cpp index 583f8ab01..6019fa820 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -53,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()) { @@ -138,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) @@ -1372,7 +1373,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 @@ -1943,7 +1944,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) { diff --git a/zone/bot.cpp b/zone/bot.cpp index 683faf1f2..08b17ff17 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3930,7 +3930,7 @@ bool Bot::Attack(Mob* other, int Hand, bool FromRiposte, bool IsStrikethrough, b // calculate attack_skill and skillinuse depending on hand and weapon // also send Packet to near clients DamageHitInfo my_hit; - AttackAnimation(my_hit.skill, Hand, weapon); + my_hit.skill = AttackAnimation(Hand, weapon); Log(Logs::Detail, Logs::Combat, "Attacking with %s in slot %d using skill %d", weapon?weapon->GetItem()->Name:"Fist", Hand, my_hit.skill); // Now figure out damage diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index dde90988c..26acdd156 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1172,6 +1172,11 @@ uint64 Lua_Client::GetAllMoney() { return self->GetAllMoney(); } +uint32 Lua_Client::GetMoney(uint8 type, uint8 subtype) { + Lua_Safe_Call_Int(); + return self->GetMoney(type, subtype); +} + void Lua_Client::OpenLFGuildWindow() { Lua_Safe_Call_Void(); self->OpenLFGuildWindow(); @@ -1414,9 +1419,9 @@ 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) { - Lua_Safe_Call_Int(); - return self->GetMoney(type, subtype); +bool Lua_Client::IsDead() { + Lua_Safe_Call_Bool(); + return self->IsDead(); } luabind::scope lua_register_client() { @@ -1653,6 +1658,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 +1693,7 @@ 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); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index d7cf4f75f..cd9206728 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -297,6 +297,7 @@ 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(); }; #endif diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index bc6205c85..dd9eda5af 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -7,6 +7,9 @@ #include #include +#include "../common/timer.h" +#include "../common/eqemu_logsys.h" +#include "../common/classes.h" #include "lua_parser.h" #include "lua_item.h" #include "lua_iteminst.h" @@ -16,8 +19,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 +28,7 @@ struct Slots { }; struct Materials { }; struct ClientVersions { }; struct Appearances { }; +struct Classes { }; struct lua_registered_event { std::string encounter_name; @@ -1458,6 +1460,27 @@ 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); +} + luabind::scope lua_register_general() { return luabind::namespace_("eq") [ @@ -1658,6 +1681,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("Roll", &random_roll_real), + luabind::def("Roll0", &random_roll0) + ]; +} + + luabind::scope lua_register_events() { return luabind::class_("Event") .enum_("constants") @@ -1857,4 +1892,57 @@ luabind::scope lua_register_appearance() { ]; } +luabind::scope lua_register_classes() { + return luabind::class_("Classes") + .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("DiscordMerchant", DISCORD_MERCHANT), + luabind::value("AdventureRecruiter", ADVENTURERECRUITER), + luabind::value("AdventureMerchant", ADVENTUREMERCHANT), + luabind::value("LDONTreasure", LDON_TREASURE), + luabind::value("CorpseClass", CORPSE_CLASS), + luabind::value("TributeMaster", TRIBUTE_MASTER), + luabind::value("GuildTributeMaster", GUILD_TRIBUTE_MASTER), + luabind::value("NorrathsKeeperMerchant", NORRATHS_KEEPERS_MERCHANT), + luabind::value("DarkReignMerchant", DARK_REIGN_MERCHANT), + luabind::value("FellowshipMaster", FELLOWSHIP_MASTER), + luabind::value("AltCurrencyMerchant", ALT_CURRENCY_MERCHANT), + luabind::value("MercenaryMaster", MERCERNARY_MASTER) + ]; +} + #endif diff --git a/zone/lua_general.h b/zone/lua_general.h index eb117cfc6..1b39ea31a 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -3,12 +3,14 @@ #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(); #endif -#endif \ No newline at end of file +#endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 86c8f564c..475b73716 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2021,6 +2021,36 @@ int16 Lua_Mob::GetMeleeMinDamageMod_SE(uint16 skill) 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); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2372,7 +2402,13 @@ luabind::scope lua_register_mob() { .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("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); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index f83583ac3..9c84ada98 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -388,6 +388,12 @@ public: 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); }; #endif diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index 48dc29e66..9f352810e 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -51,6 +51,7 @@ void LuaMod::Init() 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; @@ -63,6 +64,7 @@ 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"]; @@ -73,6 +75,10 @@ void GetDamageHitInfo(luabind::adl::object &ret, DamageHitInfo &hit) { hit.base_damage = luabind::object_cast(base_damage); } + if (luabind::type(min_damage) == LUA_TNUMBER) { + hit.min_damage = luabind::object_cast(min_damage); + } + if (luabind::type(damage_done) == LUA_TNUMBER) { hit.damage_done = luabind::object_cast(damage_done); } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 8748494c7..bcd20f8b8 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1047,12 +1047,14 @@ 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_entity(), lua_register_encounter(), lua_register_mob(), diff --git a/zone/lua_ptr.h b/zone/lua_ptr.h index 11478f093..d337059ae 100644 --- a/zone/lua_ptr.h +++ b/zone/lua_ptr.h @@ -2,13 +2,21 @@ #define EQEMU_LUA_PTR_H #ifdef LUA_EQEMU -//TODO: Remove the error checking by a flag since this adds significant overhead to each c call +#ifndef EQEMU_UNSAFE_LUA #define Lua_Safe_Call_Void() if(!d_) { return; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Bool() if(!d_) { return false; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Int() if(!d_) { return 0; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Real() if(!d_) { return 0.0; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_String() if(!d_) { return ""; } NativeType *self = reinterpret_cast(d_) #define Lua_Safe_Call_Class(type) if(!d_) { return type(); } NativeType *self = reinterpret_cast(d_) +#else +#define Lua_Safe_Call_Void() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Bool() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Int() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Real() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_String() NativeType *self = reinterpret_cast(d_) +#define Lua_Safe_Call_Class(type) NativeType *self = reinterpret_cast(d_) +#endif template class Lua_Ptr diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index bf3f22586..94b63525c 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -1281,259 +1281,259 @@ int32 Lua_StatBonuses::GetReduceTradeskillFail(int idx) const { luabind::scope lua_register_stat_bonuses() { return luabind::class_("StatBonuses") .def(luabind::constructor<>()) - .def("GetAC", &Lua_StatBonuses::GetAC) - .def("GetHP", &Lua_StatBonuses::GetHP) - .def("GetHPRegen", &Lua_StatBonuses::GetHPRegen) - .def("GetMaxHP", &Lua_StatBonuses::GetMaxHP) - .def("GetManaRegen", &Lua_StatBonuses::GetManaRegen) - .def("GetEnduranceRegen", &Lua_StatBonuses::GetEnduranceRegen) - .def("GetMana", &Lua_StatBonuses::GetMana) - .def("GetEndurance", &Lua_StatBonuses::GetEndurance) - .def("GetATK", &Lua_StatBonuses::GetATK) - .def("GetSTR", &Lua_StatBonuses::GetSTR) - .def("GetSTRCapMod", &Lua_StatBonuses::GetSTRCapMod) - .def("GetHeroicSTR", &Lua_StatBonuses::GetHeroicSTR) - .def("GetSTA", &Lua_StatBonuses::GetSTA) - .def("GetSTACapMod", &Lua_StatBonuses::GetSTACapMod) - .def("GetHeroicSTA", &Lua_StatBonuses::GetHeroicSTA) - .def("GetDEX", &Lua_StatBonuses::GetDEX) - .def("GetDEXCapMod", &Lua_StatBonuses::GetDEXCapMod) - .def("GetHeroicDEX", &Lua_StatBonuses::GetHeroicDEX) - .def("GetAGI", &Lua_StatBonuses::GetAGI) - .def("GetAGICapMod", &Lua_StatBonuses::GetAGICapMod) - .def("GetHeroicAGI", &Lua_StatBonuses::GetHeroicAGI) - .def("GetINT", &Lua_StatBonuses::GetINT) - .def("GetINTCapMod", &Lua_StatBonuses::GetINTCapMod) - .def("GetHeroicINT", &Lua_StatBonuses::GetHeroicINT) - .def("GetWIS", &Lua_StatBonuses::GetWIS) - .def("GetWISCapMod", &Lua_StatBonuses::GetWISCapMod) - .def("GetHeroicWIS", &Lua_StatBonuses::GetHeroicWIS) - .def("GetCHA", &Lua_StatBonuses::GetCHA) - .def("GetCHACapMod", &Lua_StatBonuses::GetCHACapMod) - .def("GetHeroicCHA", &Lua_StatBonuses::GetHeroicCHA) - .def("GetMR", &Lua_StatBonuses::GetMR) - .def("GetMRCapMod", &Lua_StatBonuses::GetMRCapMod) - .def("GetHeroicMR", &Lua_StatBonuses::GetHeroicMR) - .def("GetFR", &Lua_StatBonuses::GetFR) - .def("GetFRCapMod", &Lua_StatBonuses::GetFRCapMod) - .def("GetHeroicFR", &Lua_StatBonuses::GetHeroicFR) - .def("GetCR", &Lua_StatBonuses::GetCR) - .def("GetCRCapMod", &Lua_StatBonuses::GetCRCapMod) - .def("GetHeroicCR", &Lua_StatBonuses::GetHeroicCR) - .def("GetPR", &Lua_StatBonuses::GetPR) - .def("GetPRCapMod", &Lua_StatBonuses::GetPRCapMod) - .def("GetHeroicPR", &Lua_StatBonuses::GetHeroicPR) - .def("GetDR", &Lua_StatBonuses::GetDR) - .def("GetDRCapMod", &Lua_StatBonuses::GetDRCapMod) - .def("GetHeroicDR", &Lua_StatBonuses::GetHeroicDR) - .def("GetCorrup", &Lua_StatBonuses::GetCorrup) - .def("GetCorrupCapMod", &Lua_StatBonuses::GetCorrupCapMod) - .def("GetHeroicCorrup", &Lua_StatBonuses::GetHeroicCorrup) - .def("GetDamageShieldSpellID", &Lua_StatBonuses::GetDamageShieldSpellID) - .def("GetDamageShield", &Lua_StatBonuses::GetDamageShield) - .def("GetDamageShieldType", &Lua_StatBonuses::GetDamageShieldType) - .def("GetSpellDamageShield", &Lua_StatBonuses::GetSpellDamageShield) - .def("GetSpellShield", &Lua_StatBonuses::GetSpellShield) - .def("GetReverseDamageShield", &Lua_StatBonuses::GetReverseDamageShield) - .def("GetReverseDamageShieldSpellID", &Lua_StatBonuses::GetReverseDamageShieldSpellID) - .def("GetReverseDamageShieldType", &Lua_StatBonuses::GetReverseDamageShieldType) - .def("Getmovementspeed", &Lua_StatBonuses::Getmovementspeed) - .def("Gethaste", &Lua_StatBonuses::Gethaste) - .def("Gethastetype2", &Lua_StatBonuses::Gethastetype2) - .def("Gethastetype3", &Lua_StatBonuses::Gethastetype3) - .def("Getinhibitmelee", &Lua_StatBonuses::Getinhibitmelee) - .def("GetAggroRange", &Lua_StatBonuses::GetAggroRange) - .def("GetAssistRange", &Lua_StatBonuses::GetAssistRange) - .def("Getskillmod", &Lua_StatBonuses::Getskillmod) - .def("Getskillmodmax", &Lua_StatBonuses::Getskillmodmax) - .def("Geteffective_casting_level", &Lua_StatBonuses::Geteffective_casting_level) - .def("Getreflect_chance", &Lua_StatBonuses::Getreflect_chance) - .def("GetsingingMod", &Lua_StatBonuses::GetsingingMod) - .def("GetAmplification", &Lua_StatBonuses::GetAmplification) - .def("GetbrassMod", &Lua_StatBonuses::GetbrassMod) - .def("GetpercussionMod", &Lua_StatBonuses::GetpercussionMod) - .def("GetwindMod", &Lua_StatBonuses::GetwindMod) - .def("GetstringedMod", &Lua_StatBonuses::GetstringedMod) - .def("GetsongModCap", &Lua_StatBonuses::GetsongModCap) - .def("Gethatemod", &Lua_StatBonuses::Gethatemod) - .def("GetEnduranceReduction", &Lua_StatBonuses::GetEnduranceReduction) - .def("GetStrikeThrough", &Lua_StatBonuses::GetStrikeThrough) - .def("GetMeleeMitigation", &Lua_StatBonuses::GetMeleeMitigation) - .def("GetMeleeMitigationEffect", &Lua_StatBonuses::GetMeleeMitigationEffect) - .def("GetCriticalHitChance", &Lua_StatBonuses::GetCriticalHitChance) - .def("GetCriticalSpellChance", &Lua_StatBonuses::GetCriticalSpellChance) - .def("GetSpellCritDmgIncrease", &Lua_StatBonuses::GetSpellCritDmgIncrease) - .def("GetSpellCritDmgIncNoStack", &Lua_StatBonuses::GetSpellCritDmgIncNoStack) - .def("GetDotCritDmgIncrease", &Lua_StatBonuses::GetDotCritDmgIncrease) - .def("GetCriticalHealChance", &Lua_StatBonuses::GetCriticalHealChance) - .def("GetCriticalHealOverTime", &Lua_StatBonuses::GetCriticalHealOverTime) - .def("GetCriticalDoTChance", &Lua_StatBonuses::GetCriticalDoTChance) - .def("GetCrippBlowChance", &Lua_StatBonuses::GetCrippBlowChance) - .def("GetAvoidMeleeChance", &Lua_StatBonuses::GetAvoidMeleeChance) - .def("GetAvoidMeleeChanceEffect", &Lua_StatBonuses::GetAvoidMeleeChanceEffect) - .def("GetRiposteChance", &Lua_StatBonuses::GetRiposteChance) - .def("GetDodgeChance", &Lua_StatBonuses::GetDodgeChance) - .def("GetParryChance", &Lua_StatBonuses::GetParryChance) - .def("GetDualWieldChance", &Lua_StatBonuses::GetDualWieldChance) - .def("GetDoubleAttackChance", &Lua_StatBonuses::GetDoubleAttackChance) - .def("GetTripleAttackChance", &Lua_StatBonuses::GetTripleAttackChance) - .def("GetDoubleRangedAttack", &Lua_StatBonuses::GetDoubleRangedAttack) - .def("GetResistSpellChance", &Lua_StatBonuses::GetResistSpellChance) - .def("GetResistFearChance", &Lua_StatBonuses::GetResistFearChance) - .def("GetFearless", &Lua_StatBonuses::GetFearless) - .def("GetIsFeared", &Lua_StatBonuses::GetIsFeared) - .def("GetIsBlind", &Lua_StatBonuses::GetIsBlind) - .def("GetStunResist", &Lua_StatBonuses::GetStunResist) - .def("GetMeleeSkillCheck", &Lua_StatBonuses::GetMeleeSkillCheck) - .def("GetMeleeSkillCheckSkill", &Lua_StatBonuses::GetMeleeSkillCheckSkill) - .def("GetHitChance", &Lua_StatBonuses::GetHitChance) - .def("GetHitChanceEffect", &Lua_StatBonuses::GetHitChanceEffect) - .def("GetDamageModifier", &Lua_StatBonuses::GetDamageModifier) - .def("GetDamageModifier2", &Lua_StatBonuses::GetDamageModifier2) - .def("GetMinDamageModifier", &Lua_StatBonuses::GetMinDamageModifier) - .def("GetProcChance", &Lua_StatBonuses::GetProcChance) - .def("GetProcChanceSPA", &Lua_StatBonuses::GetProcChanceSPA) - .def("GetExtraAttackChance", &Lua_StatBonuses::GetExtraAttackChance) - .def("GetDoTShielding", &Lua_StatBonuses::GetDoTShielding) - .def("GetFlurryChance", &Lua_StatBonuses::GetFlurryChance) - .def("GetHundredHands", &Lua_StatBonuses::GetHundredHands) - .def("GetMeleeLifetap", &Lua_StatBonuses::GetMeleeLifetap) - .def("GetVampirism", &Lua_StatBonuses::GetVampirism) - .def("GetHealRate", &Lua_StatBonuses::GetHealRate) - .def("GetMaxHPChange", &Lua_StatBonuses::GetMaxHPChange) - .def("GetHealAmt", &Lua_StatBonuses::GetHealAmt) - .def("GetSpellDmg", &Lua_StatBonuses::GetSpellDmg) - .def("GetClairvoyance", &Lua_StatBonuses::GetClairvoyance) - .def("GetDSMitigation", &Lua_StatBonuses::GetDSMitigation) - .def("GetDSMitigationOffHand", &Lua_StatBonuses::GetDSMitigationOffHand) - .def("GetTwoHandBluntBlock", &Lua_StatBonuses::GetTwoHandBluntBlock) - .def("GetItemManaRegenCap", &Lua_StatBonuses::GetItemManaRegenCap) - .def("GetGravityEffect", &Lua_StatBonuses::GetGravityEffect) - .def("GetAntiGate", &Lua_StatBonuses::GetAntiGate) - .def("GetMagicWeapon", &Lua_StatBonuses::GetMagicWeapon) - .def("GetIncreaseBlockChance", &Lua_StatBonuses::GetIncreaseBlockChance) - .def("GetPersistantCasting", &Lua_StatBonuses::GetPersistantCasting) - .def("GetXPRateMod", &Lua_StatBonuses::GetXPRateMod) - .def("GetBlockNextSpell", &Lua_StatBonuses::GetBlockNextSpell) - .def("GetImmuneToFlee", &Lua_StatBonuses::GetImmuneToFlee) - .def("GetVoiceGraft", &Lua_StatBonuses::GetVoiceGraft) - .def("GetSpellProcChance", &Lua_StatBonuses::GetSpellProcChance) - .def("GetCharmBreakChance", &Lua_StatBonuses::GetCharmBreakChance) - .def("GetSongRange", &Lua_StatBonuses::GetSongRange) - .def("GetHPToManaConvert", &Lua_StatBonuses::GetHPToManaConvert) - .def("GetNegateEffects", &Lua_StatBonuses::GetNegateEffects) - .def("GetTriggerMeleeThreshold", &Lua_StatBonuses::GetTriggerMeleeThreshold) - .def("GetTriggerSpellThreshold", &Lua_StatBonuses::GetTriggerSpellThreshold) - .def("GetShieldBlock", &Lua_StatBonuses::GetShieldBlock) - .def("GetBlockBehind", &Lua_StatBonuses::GetBlockBehind) - .def("GetCriticalRegenDecay", &Lua_StatBonuses::GetCriticalRegenDecay) - .def("GetCriticalHealDecay", &Lua_StatBonuses::GetCriticalHealDecay) - .def("GetCriticalDotDecay", &Lua_StatBonuses::GetCriticalDotDecay) - .def("GetDivineAura", &Lua_StatBonuses::GetDivineAura) - .def("GetDistanceRemoval", &Lua_StatBonuses::GetDistanceRemoval) - .def("GetFrenziedDevastation", &Lua_StatBonuses::GetFrenziedDevastation) - .def("GetNegateIfCombat", &Lua_StatBonuses::GetNegateIfCombat) - .def("GetScreech", &Lua_StatBonuses::GetScreech) - .def("GetAlterNPCLevel", &Lua_StatBonuses::GetAlterNPCLevel) - .def("GetBerserkSPA", &Lua_StatBonuses::GetBerserkSPA) - .def("GetMetabolism", &Lua_StatBonuses::GetMetabolism) - .def("GetSanctuary", &Lua_StatBonuses::GetSanctuary) - .def("GetFactionModPct", &Lua_StatBonuses::GetFactionModPct) - .def("GetPC_Pet_Flurry", &Lua_StatBonuses::GetPC_Pet_Flurry) - .def("GetPackrat", &Lua_StatBonuses::GetPackrat) - .def("GetBuffSlotIncrease", &Lua_StatBonuses::GetBuffSlotIncrease) - .def("GetDelayDeath", &Lua_StatBonuses::GetDelayDeath) - .def("GetBaseMovementSpeed", &Lua_StatBonuses::GetBaseMovementSpeed) - .def("GetIncreaseRunSpeedCap", &Lua_StatBonuses::GetIncreaseRunSpeedCap) - .def("GetDoubleSpecialAttack", &Lua_StatBonuses::GetDoubleSpecialAttack) - .def("GetFrontalStunResist", &Lua_StatBonuses::GetFrontalStunResist) - .def("GetBindWound", &Lua_StatBonuses::GetBindWound) - .def("GetMaxBindWound", &Lua_StatBonuses::GetMaxBindWound) - .def("GetChannelChanceSpells", &Lua_StatBonuses::GetChannelChanceSpells) - .def("GetChannelChanceItems", &Lua_StatBonuses::GetChannelChanceItems) - .def("GetSeeInvis", &Lua_StatBonuses::GetSeeInvis) - .def("GetTripleBackstab", &Lua_StatBonuses::GetTripleBackstab) - .def("GetFrontalBackstabMinDmg", &Lua_StatBonuses::GetFrontalBackstabMinDmg) - .def("GetFrontalBackstabChance", &Lua_StatBonuses::GetFrontalBackstabChance) - .def("GetConsumeProjectile", &Lua_StatBonuses::GetConsumeProjectile) - .def("GetForageAdditionalItems", &Lua_StatBonuses::GetForageAdditionalItems) - .def("GetSalvageChance", &Lua_StatBonuses::GetSalvageChance) - .def("GetArcheryDamageModifier", &Lua_StatBonuses::GetArcheryDamageModifier) - .def("GetSecondaryDmgInc", &Lua_StatBonuses::GetSecondaryDmgInc) - .def("GetGiveDoubleAttack", &Lua_StatBonuses::GetGiveDoubleAttack) - .def("GetPetCriticalHit", &Lua_StatBonuses::GetPetCriticalHit) - .def("GetPetAvoidance", &Lua_StatBonuses::GetPetAvoidance) - .def("GetCombatStability", &Lua_StatBonuses::GetCombatStability) - .def("GetDoubleRiposte", &Lua_StatBonuses::GetDoubleRiposte) - .def("GetAmbidexterity", &Lua_StatBonuses::GetAmbidexterity) - .def("GetPetMaxHP", &Lua_StatBonuses::GetPetMaxHP) - .def("GetPetFlurry", &Lua_StatBonuses::GetPetFlurry) - .def("GetMasteryofPast", &Lua_StatBonuses::GetMasteryofPast) - .def("GetGivePetGroupTarget", &Lua_StatBonuses::GetGivePetGroupTarget) - .def("GetRootBreakChance", &Lua_StatBonuses::GetRootBreakChance) - .def("GetUnfailingDivinity", &Lua_StatBonuses::GetUnfailingDivinity) - .def("GetItemHPRegenCap", &Lua_StatBonuses::GetItemHPRegenCap) - .def("GetOffhandRiposteFail", &Lua_StatBonuses::GetOffhandRiposteFail) - .def("GetItemATKCap", &Lua_StatBonuses::GetItemATKCap) - .def("GetShieldEquipDmgMod", &Lua_StatBonuses::GetShieldEquipDmgMod) - .def("GetTriggerOnValueAmount", &Lua_StatBonuses::GetTriggerOnValueAmount) - .def("GetStunBashChance", &Lua_StatBonuses::GetStunBashChance) - .def("GetIncreaseChanceMemwipe", &Lua_StatBonuses::GetIncreaseChanceMemwipe) - .def("GetCriticalMend", &Lua_StatBonuses::GetCriticalMend) - .def("GetImprovedReclaimEnergy", &Lua_StatBonuses::GetImprovedReclaimEnergy) - .def("GetPetMeleeMitigation", &Lua_StatBonuses::GetPetMeleeMitigation) - .def("GetIllusionPersistence", &Lua_StatBonuses::GetIllusionPersistence) - .def("Getextra_xtargets", &Lua_StatBonuses::Getextra_xtargets) - .def("GetShroudofStealth", &Lua_StatBonuses::GetShroudofStealth) - .def("GetReduceFallDamage", &Lua_StatBonuses::GetReduceFallDamage) - .def("GetTradeSkillMastery", &Lua_StatBonuses::GetTradeSkillMastery) - .def("GetNoBreakAESneak", &Lua_StatBonuses::GetNoBreakAESneak) - .def("GetFeignedCastOnChance", &Lua_StatBonuses::GetFeignedCastOnChance) - .def("GetDivineSaveChance", &Lua_StatBonuses::GetDivineSaveChance) - .def("GetDeathSave", &Lua_StatBonuses::GetDeathSave) - .def("GetAccuracy", &Lua_StatBonuses::GetAccuracy) - .def("GetSkillDmgTaken", &Lua_StatBonuses::GetSkillDmgTaken) - .def("GetSpellTriggers", &Lua_StatBonuses::GetSpellTriggers) - .def("GetSpellOnKill", &Lua_StatBonuses::GetSpellOnKill) - .def("GetSpellOnDeath", &Lua_StatBonuses::GetSpellOnDeath) - .def("GetCritDmgMob", &Lua_StatBonuses::GetCritDmgMob) - .def("GetSkillReuseTime", &Lua_StatBonuses::GetSkillReuseTime) - .def("GetSkillDamageAmount", &Lua_StatBonuses::GetSkillDamageAmount) - .def("GetHPPercCap", &Lua_StatBonuses::GetHPPercCap) - .def("GetManaPercCap", &Lua_StatBonuses::GetManaPercCap) - .def("GetEndPercCap", &Lua_StatBonuses::GetEndPercCap) - .def("GetFocusEffects", &Lua_StatBonuses::GetFocusEffects) - .def("GetFocusEffectsWorn", &Lua_StatBonuses::GetFocusEffectsWorn) - .def("GetSkillDamageAmount2", &Lua_StatBonuses::GetSkillDamageAmount2) - .def("GetNegateAttacks", &Lua_StatBonuses::GetNegateAttacks) - .def("GetMitigateMeleeRune", &Lua_StatBonuses::GetMitigateMeleeRune) - .def("GetMeleeThresholdGuard", &Lua_StatBonuses::GetMeleeThresholdGuard) - .def("GetSpellThresholdGuard", &Lua_StatBonuses::GetSpellThresholdGuard) - .def("GetMitigateSpellRune", &Lua_StatBonuses::GetMitigateSpellRune) - .def("GetMitigateDotRune", &Lua_StatBonuses::GetMitigateDotRune) - .def("GetManaAbsorbPercentDamage", &Lua_StatBonuses::GetManaAbsorbPercentDamage) - .def("GetImprovedTaunt", &Lua_StatBonuses::GetImprovedTaunt) - .def("GetRoot", &Lua_StatBonuses::GetRoot) - .def("GetAbsorbMagicAtt", &Lua_StatBonuses::GetAbsorbMagicAtt) - .def("GetMeleeRune", &Lua_StatBonuses::GetMeleeRune) - .def("GetAStacker", &Lua_StatBonuses::GetAStacker) - .def("GetBStacker", &Lua_StatBonuses::GetBStacker) - .def("GetCStacker", &Lua_StatBonuses::GetCStacker) - .def("GetDStacker", &Lua_StatBonuses::GetDStacker) - .def("GetLimitToSkill", &Lua_StatBonuses::GetLimitToSkill) - .def("GetSkillProc", &Lua_StatBonuses::GetSkillProc) - .def("GetSkillProcSuccess", &Lua_StatBonuses::GetSkillProcSuccess) - .def("GetPC_Pet_Rampage", &Lua_StatBonuses::GetPC_Pet_Rampage) - .def("GetSkillAttackProc", &Lua_StatBonuses::GetSkillAttackProc) - .def("GetSlayUndead", &Lua_StatBonuses::GetSlayUndead) - .def("GetGiveDoubleRiposte", &Lua_StatBonuses::GetGiveDoubleRiposte) - .def("GetRaiseSkillCap", &Lua_StatBonuses::GetRaiseSkillCap) - .def("GetSEResist", &Lua_StatBonuses::GetSEResist) - .def("GetFinishingBlow", &Lua_StatBonuses::GetFinishingBlow) - .def("GetFinishingBlowLvl", &Lua_StatBonuses::GetFinishingBlowLvl) - .def("GetHeadShot", &Lua_StatBonuses::GetHeadShot) - .def("GetHSLevel", &Lua_StatBonuses::GetHSLevel) - .def("GetAssassinate", &Lua_StatBonuses::GetAssassinate) - .def("GetAssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel) - .def("GetReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail); + .def("AC", &Lua_StatBonuses::GetAC) + .def("HP", &Lua_StatBonuses::GetHP) + .def("HPRegen", &Lua_StatBonuses::GetHPRegen) + .def("MaxHP", &Lua_StatBonuses::GetMaxHP) + .def("ManaRegen", &Lua_StatBonuses::GetManaRegen) + .def("EnduranceRegen", &Lua_StatBonuses::GetEnduranceRegen) + .def("Mana", &Lua_StatBonuses::GetMana) + .def("Endurance", &Lua_StatBonuses::GetEndurance) + .def("ATK", &Lua_StatBonuses::GetATK) + .def("STR", &Lua_StatBonuses::GetSTR) + .def("STRCapMod", &Lua_StatBonuses::GetSTRCapMod) + .def("HeroicSTR", &Lua_StatBonuses::GetHeroicSTR) + .def("STA", &Lua_StatBonuses::GetSTA) + .def("STACapMod", &Lua_StatBonuses::GetSTACapMod) + .def("HeroicSTA", &Lua_StatBonuses::GetHeroicSTA) + .def("DEX", &Lua_StatBonuses::GetDEX) + .def("DEXCapMod", &Lua_StatBonuses::GetDEXCapMod) + .def("HeroicDEX", &Lua_StatBonuses::GetHeroicDEX) + .def("AGI", &Lua_StatBonuses::GetAGI) + .def("AGICapMod", &Lua_StatBonuses::GetAGICapMod) + .def("HeroicAGI", &Lua_StatBonuses::GetHeroicAGI) + .def("INT", &Lua_StatBonuses::GetINT) + .def("INTCapMod", &Lua_StatBonuses::GetINTCapMod) + .def("HeroicINT", &Lua_StatBonuses::GetHeroicINT) + .def("WIS", &Lua_StatBonuses::GetWIS) + .def("WISCapMod", &Lua_StatBonuses::GetWISCapMod) + .def("HeroicWIS", &Lua_StatBonuses::GetHeroicWIS) + .def("CHA", &Lua_StatBonuses::GetCHA) + .def("CHACapMod", &Lua_StatBonuses::GetCHACapMod) + .def("HeroicCHA", &Lua_StatBonuses::GetHeroicCHA) + .def("MR", &Lua_StatBonuses::GetMR) + .def("MRCapMod", &Lua_StatBonuses::GetMRCapMod) + .def("HeroicMR", &Lua_StatBonuses::GetHeroicMR) + .def("FR", &Lua_StatBonuses::GetFR) + .def("FRCapMod", &Lua_StatBonuses::GetFRCapMod) + .def("HeroicFR", &Lua_StatBonuses::GetHeroicFR) + .def("CR", &Lua_StatBonuses::GetCR) + .def("CRCapMod", &Lua_StatBonuses::GetCRCapMod) + .def("HeroicCR", &Lua_StatBonuses::GetHeroicCR) + .def("PR", &Lua_StatBonuses::GetPR) + .def("PRCapMod", &Lua_StatBonuses::GetPRCapMod) + .def("HeroicPR", &Lua_StatBonuses::GetHeroicPR) + .def("DR", &Lua_StatBonuses::GetDR) + .def("DRCapMod", &Lua_StatBonuses::GetDRCapMod) + .def("HeroicDR", &Lua_StatBonuses::GetHeroicDR) + .def("Corrup", &Lua_StatBonuses::GetCorrup) + .def("CorrupCapMod", &Lua_StatBonuses::GetCorrupCapMod) + .def("HeroicCorrup", &Lua_StatBonuses::GetHeroicCorrup) + .def("DamageShieldSpellID", &Lua_StatBonuses::GetDamageShieldSpellID) + .def("DamageShield", &Lua_StatBonuses::GetDamageShield) + .def("DamageShieldType", &Lua_StatBonuses::GetDamageShieldType) + .def("SpellDamageShield", &Lua_StatBonuses::GetSpellDamageShield) + .def("SpellShield", &Lua_StatBonuses::GetSpellShield) + .def("ReverseDamageShield", &Lua_StatBonuses::GetReverseDamageShield) + .def("ReverseDamageShieldSpellID", &Lua_StatBonuses::GetReverseDamageShieldSpellID) + .def("ReverseDamageShieldType", &Lua_StatBonuses::GetReverseDamageShieldType) + .def("movementspeed", &Lua_StatBonuses::Getmovementspeed) + .def("haste", &Lua_StatBonuses::Gethaste) + .def("hastetype2", &Lua_StatBonuses::Gethastetype2) + .def("hastetype3", &Lua_StatBonuses::Gethastetype3) + .def("inhibitmelee", &Lua_StatBonuses::Getinhibitmelee) + .def("AggroRange", &Lua_StatBonuses::GetAggroRange) + .def("AssistRange", &Lua_StatBonuses::GetAssistRange) + .def("skillmod", &Lua_StatBonuses::Getskillmod) + .def("skillmodmax", &Lua_StatBonuses::Getskillmodmax) + .def("effective_casting_level", &Lua_StatBonuses::Geteffective_casting_level) + .def("reflect_chance", &Lua_StatBonuses::Getreflect_chance) + .def("singingMod", &Lua_StatBonuses::GetsingingMod) + .def("Amplification", &Lua_StatBonuses::GetAmplification) + .def("brassMod", &Lua_StatBonuses::GetbrassMod) + .def("percussionMod", &Lua_StatBonuses::GetpercussionMod) + .def("windMod", &Lua_StatBonuses::GetwindMod) + .def("stringedMod", &Lua_StatBonuses::GetstringedMod) + .def("songModCap", &Lua_StatBonuses::GetsongModCap) + .def("hatemod", &Lua_StatBonuses::Gethatemod) + .def("EnduranceReduction", &Lua_StatBonuses::GetEnduranceReduction) + .def("StrikeThrough", &Lua_StatBonuses::GetStrikeThrough) + .def("MeleeMitigation", &Lua_StatBonuses::GetMeleeMitigation) + .def("MeleeMitigationEffect", &Lua_StatBonuses::GetMeleeMitigationEffect) + .def("CriticalHitChance", &Lua_StatBonuses::GetCriticalHitChance) + .def("CriticalSpellChance", &Lua_StatBonuses::GetCriticalSpellChance) + .def("SpellCritDmgIncrease", &Lua_StatBonuses::GetSpellCritDmgIncrease) + .def("SpellCritDmgIncNoStack", &Lua_StatBonuses::GetSpellCritDmgIncNoStack) + .def("DotCritDmgIncrease", &Lua_StatBonuses::GetDotCritDmgIncrease) + .def("CriticalHealChance", &Lua_StatBonuses::GetCriticalHealChance) + .def("CriticalHealOverTime", &Lua_StatBonuses::GetCriticalHealOverTime) + .def("CriticalDoTChance", &Lua_StatBonuses::GetCriticalDoTChance) + .def("CrippBlowChance", &Lua_StatBonuses::GetCrippBlowChance) + .def("AvoidMeleeChance", &Lua_StatBonuses::GetAvoidMeleeChance) + .def("AvoidMeleeChanceEffect", &Lua_StatBonuses::GetAvoidMeleeChanceEffect) + .def("RiposteChance", &Lua_StatBonuses::GetRiposteChance) + .def("DodgeChance", &Lua_StatBonuses::GetDodgeChance) + .def("ParryChance", &Lua_StatBonuses::GetParryChance) + .def("DualWieldChance", &Lua_StatBonuses::GetDualWieldChance) + .def("DoubleAttackChance", &Lua_StatBonuses::GetDoubleAttackChance) + .def("TripleAttackChance", &Lua_StatBonuses::GetTripleAttackChance) + .def("DoubleRangedAttack", &Lua_StatBonuses::GetDoubleRangedAttack) + .def("ResistSpellChance", &Lua_StatBonuses::GetResistSpellChance) + .def("ResistFearChance", &Lua_StatBonuses::GetResistFearChance) + .def("Fearless", &Lua_StatBonuses::GetFearless) + .def("IsFeared", &Lua_StatBonuses::GetIsFeared) + .def("IsBlind", &Lua_StatBonuses::GetIsBlind) + .def("StunResist", &Lua_StatBonuses::GetStunResist) + .def("MeleeSkillCheck", &Lua_StatBonuses::GetMeleeSkillCheck) + .def("MeleeSkillCheckSkill", &Lua_StatBonuses::GetMeleeSkillCheckSkill) + .def("HitChance", &Lua_StatBonuses::GetHitChance) + .def("HitChanceEffect", &Lua_StatBonuses::GetHitChanceEffect) + .def("DamageModifier", &Lua_StatBonuses::GetDamageModifier) + .def("DamageModifier2", &Lua_StatBonuses::GetDamageModifier2) + .def("MinDamageModifier", &Lua_StatBonuses::GetMinDamageModifier) + .def("ProcChance", &Lua_StatBonuses::GetProcChance) + .def("ProcChanceSPA", &Lua_StatBonuses::GetProcChanceSPA) + .def("ExtraAttackChance", &Lua_StatBonuses::GetExtraAttackChance) + .def("DoTShielding", &Lua_StatBonuses::GetDoTShielding) + .def("FlurryChance", &Lua_StatBonuses::GetFlurryChance) + .def("HundredHands", &Lua_StatBonuses::GetHundredHands) + .def("MeleeLifetap", &Lua_StatBonuses::GetMeleeLifetap) + .def("Vampirism", &Lua_StatBonuses::GetVampirism) + .def("HealRate", &Lua_StatBonuses::GetHealRate) + .def("MaxHPChange", &Lua_StatBonuses::GetMaxHPChange) + .def("HealAmt", &Lua_StatBonuses::GetHealAmt) + .def("SpellDmg", &Lua_StatBonuses::GetSpellDmg) + .def("Clairvoyance", &Lua_StatBonuses::GetClairvoyance) + .def("DSMitigation", &Lua_StatBonuses::GetDSMitigation) + .def("DSMitigationOffHand", &Lua_StatBonuses::GetDSMitigationOffHand) + .def("TwoHandBluntBlock", &Lua_StatBonuses::GetTwoHandBluntBlock) + .def("ItemManaRegenCap", &Lua_StatBonuses::GetItemManaRegenCap) + .def("GravityEffect", &Lua_StatBonuses::GetGravityEffect) + .def("AntiGate", &Lua_StatBonuses::GetAntiGate) + .def("MagicWeapon", &Lua_StatBonuses::GetMagicWeapon) + .def("IncreaseBlockChance", &Lua_StatBonuses::GetIncreaseBlockChance) + .def("PersistantCasting", &Lua_StatBonuses::GetPersistantCasting) + .def("XPRateMod", &Lua_StatBonuses::GetXPRateMod) + .def("BlockNextSpell", &Lua_StatBonuses::GetBlockNextSpell) + .def("ImmuneToFlee", &Lua_StatBonuses::GetImmuneToFlee) + .def("VoiceGraft", &Lua_StatBonuses::GetVoiceGraft) + .def("SpellProcChance", &Lua_StatBonuses::GetSpellProcChance) + .def("CharmBreakChance", &Lua_StatBonuses::GetCharmBreakChance) + .def("SongRange", &Lua_StatBonuses::GetSongRange) + .def("HPToManaConvert", &Lua_StatBonuses::GetHPToManaConvert) + .def("NegateEffects", &Lua_StatBonuses::GetNegateEffects) + .def("TriggerMeleeThreshold", &Lua_StatBonuses::GetTriggerMeleeThreshold) + .def("TriggerSpellThreshold", &Lua_StatBonuses::GetTriggerSpellThreshold) + .def("ShieldBlock", &Lua_StatBonuses::GetShieldBlock) + .def("BlockBehind", &Lua_StatBonuses::GetBlockBehind) + .def("CriticalRegenDecay", &Lua_StatBonuses::GetCriticalRegenDecay) + .def("CriticalHealDecay", &Lua_StatBonuses::GetCriticalHealDecay) + .def("CriticalDotDecay", &Lua_StatBonuses::GetCriticalDotDecay) + .def("DivineAura", &Lua_StatBonuses::GetDivineAura) + .def("DistanceRemoval", &Lua_StatBonuses::GetDistanceRemoval) + .def("FrenziedDevastation", &Lua_StatBonuses::GetFrenziedDevastation) + .def("NegateIfCombat", &Lua_StatBonuses::GetNegateIfCombat) + .def("Screech", &Lua_StatBonuses::GetScreech) + .def("AlterNPCLevel", &Lua_StatBonuses::GetAlterNPCLevel) + .def("BerserkSPA", &Lua_StatBonuses::GetBerserkSPA) + .def("Metabolism", &Lua_StatBonuses::GetMetabolism) + .def("Sanctuary", &Lua_StatBonuses::GetSanctuary) + .def("FactionModPct", &Lua_StatBonuses::GetFactionModPct) + .def("PC_Pet_Flurry", &Lua_StatBonuses::GetPC_Pet_Flurry) + .def("Packrat", &Lua_StatBonuses::GetPackrat) + .def("BuffSlotIncrease", &Lua_StatBonuses::GetBuffSlotIncrease) + .def("DelayDeath", &Lua_StatBonuses::GetDelayDeath) + .def("BaseMovementSpeed", &Lua_StatBonuses::GetBaseMovementSpeed) + .def("IncreaseRunSpeedCap", &Lua_StatBonuses::GetIncreaseRunSpeedCap) + .def("DoubleSpecialAttack", &Lua_StatBonuses::GetDoubleSpecialAttack) + .def("FrontalStunResist", &Lua_StatBonuses::GetFrontalStunResist) + .def("BindWound", &Lua_StatBonuses::GetBindWound) + .def("MaxBindWound", &Lua_StatBonuses::GetMaxBindWound) + .def("ChannelChanceSpells", &Lua_StatBonuses::GetChannelChanceSpells) + .def("ChannelChanceItems", &Lua_StatBonuses::GetChannelChanceItems) + .def("SeeInvis", &Lua_StatBonuses::GetSeeInvis) + .def("TripleBackstab", &Lua_StatBonuses::GetTripleBackstab) + .def("FrontalBackstabMinDmg", &Lua_StatBonuses::GetFrontalBackstabMinDmg) + .def("FrontalBackstabChance", &Lua_StatBonuses::GetFrontalBackstabChance) + .def("ConsumeProjectile", &Lua_StatBonuses::GetConsumeProjectile) + .def("ForageAdditionalItems", &Lua_StatBonuses::GetForageAdditionalItems) + .def("SalvageChance", &Lua_StatBonuses::GetSalvageChance) + .def("ArcheryDamageModifier", &Lua_StatBonuses::GetArcheryDamageModifier) + .def("SecondaryDmgInc", &Lua_StatBonuses::GetSecondaryDmgInc) + .def("GiveDoubleAttack", &Lua_StatBonuses::GetGiveDoubleAttack) + .def("PetCriticalHit", &Lua_StatBonuses::GetPetCriticalHit) + .def("PetAvoidance", &Lua_StatBonuses::GetPetAvoidance) + .def("CombatStability", &Lua_StatBonuses::GetCombatStability) + .def("DoubleRiposte", &Lua_StatBonuses::GetDoubleRiposte) + .def("Ambidexterity", &Lua_StatBonuses::GetAmbidexterity) + .def("PetMaxHP", &Lua_StatBonuses::GetPetMaxHP) + .def("PetFlurry", &Lua_StatBonuses::GetPetFlurry) + .def("MasteryofPast", &Lua_StatBonuses::GetMasteryofPast) + .def("GivePetGroupTarget", &Lua_StatBonuses::GetGivePetGroupTarget) + .def("RootBreakChance", &Lua_StatBonuses::GetRootBreakChance) + .def("UnfailingDivinity", &Lua_StatBonuses::GetUnfailingDivinity) + .def("ItemHPRegenCap", &Lua_StatBonuses::GetItemHPRegenCap) + .def("OffhandRiposteFail", &Lua_StatBonuses::GetOffhandRiposteFail) + .def("ItemATKCap", &Lua_StatBonuses::GetItemATKCap) + .def("ShieldEquipDmgMod", &Lua_StatBonuses::GetShieldEquipDmgMod) + .def("TriggerOnValueAmount", &Lua_StatBonuses::GetTriggerOnValueAmount) + .def("StunBashChance", &Lua_StatBonuses::GetStunBashChance) + .def("IncreaseChanceMemwipe", &Lua_StatBonuses::GetIncreaseChanceMemwipe) + .def("CriticalMend", &Lua_StatBonuses::GetCriticalMend) + .def("ImprovedReclaimEnergy", &Lua_StatBonuses::GetImprovedReclaimEnergy) + .def("PetMeleeMitigation", &Lua_StatBonuses::GetPetMeleeMitigation) + .def("IllusionPersistence", &Lua_StatBonuses::GetIllusionPersistence) + .def("extra_xtargets", &Lua_StatBonuses::Getextra_xtargets) + .def("ShroudofStealth", &Lua_StatBonuses::GetShroudofStealth) + .def("ReduceFallDamage", &Lua_StatBonuses::GetReduceFallDamage) + .def("TradeSkillMastery", &Lua_StatBonuses::GetTradeSkillMastery) + .def("NoBreakAESneak", &Lua_StatBonuses::GetNoBreakAESneak) + .def("FeignedCastOnChance", &Lua_StatBonuses::GetFeignedCastOnChance) + .def("DivineSaveChance", &Lua_StatBonuses::GetDivineSaveChance) + .def("DeathSave", &Lua_StatBonuses::GetDeathSave) + .def("Accuracy", &Lua_StatBonuses::GetAccuracy) + .def("SkillDmgTaken", &Lua_StatBonuses::GetSkillDmgTaken) + .def("SpellTriggers", &Lua_StatBonuses::GetSpellTriggers) + .def("SpellOnKill", &Lua_StatBonuses::GetSpellOnKill) + .def("SpellOnDeath", &Lua_StatBonuses::GetSpellOnDeath) + .def("CritDmgMob", &Lua_StatBonuses::GetCritDmgMob) + .def("SkillReuseTime", &Lua_StatBonuses::GetSkillReuseTime) + .def("SkillDamageAmount", &Lua_StatBonuses::GetSkillDamageAmount) + .def("HPPercCap", &Lua_StatBonuses::GetHPPercCap) + .def("ManaPercCap", &Lua_StatBonuses::GetManaPercCap) + .def("EndPercCap", &Lua_StatBonuses::GetEndPercCap) + .def("FocusEffects", &Lua_StatBonuses::GetFocusEffects) + .def("FocusEffectsWorn", &Lua_StatBonuses::GetFocusEffectsWorn) + .def("SkillDamageAmount2", &Lua_StatBonuses::GetSkillDamageAmount2) + .def("NegateAttacks", &Lua_StatBonuses::GetNegateAttacks) + .def("MitigateMeleeRune", &Lua_StatBonuses::GetMitigateMeleeRune) + .def("MeleeThresholdGuard", &Lua_StatBonuses::GetMeleeThresholdGuard) + .def("SpellThresholdGuard", &Lua_StatBonuses::GetSpellThresholdGuard) + .def("MitigateSpellRune", &Lua_StatBonuses::GetMitigateSpellRune) + .def("MitigateDotRune", &Lua_StatBonuses::GetMitigateDotRune) + .def("ManaAbsorbPercentDamage", &Lua_StatBonuses::GetManaAbsorbPercentDamage) + .def("ImprovedTaunt", &Lua_StatBonuses::GetImprovedTaunt) + .def("Root", &Lua_StatBonuses::GetRoot) + .def("AbsorbMagicAtt", &Lua_StatBonuses::GetAbsorbMagicAtt) + .def("MeleeRune", &Lua_StatBonuses::GetMeleeRune) + .def("AStacker", &Lua_StatBonuses::GetAStacker) + .def("BStacker", &Lua_StatBonuses::GetBStacker) + .def("CStacker", &Lua_StatBonuses::GetCStacker) + .def("DStacker", &Lua_StatBonuses::GetDStacker) + .def("LimitToSkill", &Lua_StatBonuses::GetLimitToSkill) + .def("SkillProc", &Lua_StatBonuses::GetSkillProc) + .def("SkillProcSuccess", &Lua_StatBonuses::GetSkillProcSuccess) + .def("PC_Pet_Rampage", &Lua_StatBonuses::GetPC_Pet_Rampage) + .def("SkillAttackProc", &Lua_StatBonuses::GetSkillAttackProc) + .def("SlayUndead", &Lua_StatBonuses::GetSlayUndead) + .def("GiveDoubleRiposte", &Lua_StatBonuses::GetGiveDoubleRiposte) + .def("RaiseSkillCap", &Lua_StatBonuses::GetRaiseSkillCap) + .def("SEResist", &Lua_StatBonuses::GetSEResist) + .def("FinishingBlow", &Lua_StatBonuses::GetFinishingBlow) + .def("FinishingBlowLvl", &Lua_StatBonuses::GetFinishingBlowLvl) + .def("HeadShot", &Lua_StatBonuses::GetHeadShot) + .def("HSLevel", &Lua_StatBonuses::GetHSLevel) + .def("Assassinate", &Lua_StatBonuses::GetAssassinate) + .def("AssassinateLevel", &Lua_StatBonuses::GetAssassinateLevel) + .def("ReduceTradeskillFail", &Lua_StatBonuses::GetReduceTradeskillFail); } \ No newline at end of file diff --git a/zone/mob.h b/zone/mob.h index f280f5600..4ba87f2d7 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -233,7 +233,7 @@ public: inline bool SeeImprovedHide() const { return see_improved_hide; } bool IsInvisible(Mob* other = 0) const; void SetInvisible(uint8 state); - bool AttackAnimation(EQEmu::skills::SkillType &skillinuse, int Hand, const EQEmu::ItemInstance* weapon); + EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon); //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); @@ -1053,6 +1053,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 @@ -1199,8 +1201,6 @@ protected: virtual float GetDefensiveProcChances(float &ProcBonus, float &ProcChance, uint16 hand = EQEmu::inventory::slotPrimary, Mob *on = nullptr); virtual float GetSkillProcChances(uint16 ReuseTime, uint16 hand = 0); // hand = MainCharm? uint16 GetWeaponSpeedbyHand(uint16 hand); - int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); - int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); #ifdef BOTS virtual #endif diff --git a/zone/tune.cpp b/zone/tune.cpp index bbb56217e..36be51905 100644 --- a/zone/tune.cpp +++ b/zone/tune.cpp @@ -596,8 +596,7 @@ int32 Client::GetMeleeDamage(Mob* other, bool GetMinDamage) } } - EQEmu::skills::SkillType skillinuse; - AttackAnimation(skillinuse, Hand, weapon); + EQEmu::skills::SkillType skillinuse = AttackAnimation(Hand, weapon); int damage = 0; uint8 mylevel = GetLevel() ? GetLevel() : 1; @@ -665,16 +664,16 @@ void Mob::Tune_FindAccuaryByHitChance(Mob* defender, Mob *attacker, float hit_ch weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotPrimary, weapon); } else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotSecondary, weapon); else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotRange, weapon); } } } @@ -745,16 +744,16 @@ void Mob::Tune_FindAvoidanceByHitChance(Mob* defender, Mob *attacker, float hit_ weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotPrimary); if(weapon && weapon->IsWeapon()){ - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotPrimary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotPrimary, weapon); } else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotSecondary); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotSecondary, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotSecondary, weapon); else { weapon = attacker->CastToClient()->GetInv().GetItem(EQEmu::inventory::slotRange); if (weapon && weapon->IsWeapon()) - attacker->CastToClient()->AttackAnimation(skillinuse, EQEmu::inventory::slotRange, weapon); + skillinuse = attacker->CastToClient()->AttackAnimation(EQEmu::inventory::slotRange, weapon); } } } From 9277665f5f304f3b37ca843240ffc4ff4054d805 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 May 2017 15:03:14 -0400 Subject: [PATCH 047/218] Fix consumption Ahh not too sure why this is needed. We used the other field before and the client is still displaying correct item clicky cast times as well as food duration string ... Oh well --- zone/client.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 4ec1ba898..d35308d73 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8501,7 +8501,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a if (type == EQEmu::item::ItemTypeFood) { - int hchange = item->CastTime * cons_mod; + int hchange = item->CastTime_ * cons_mod; hchange = mod_food_value(item, hchange); if(hchange < 0) { return; } @@ -8518,7 +8518,7 @@ void Client::Consume(const EQEmu::ItemData *item, uint8 type, int16 slot, bool a } else { - int tchange = item->CastTime * cons_mod; + int tchange = item->CastTime_ * cons_mod; tchange = mod_drink_value(item, tchange); if(tchange < 0) { return; } From 5865948a8b9a2044def17a02e51ebb5c46615ff0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 17 May 2017 15:20:27 -0400 Subject: [PATCH 048/218] Fix ST_Pet item/AA casts Modern clients don't require the pet to be targeted --- zone/aa.cpp | 5 +++++ zone/client_packet.cpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/zone/aa.cpp b/zone/aa.cpp index e002dd4f2..2451416aa 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1202,6 +1202,11 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { Message_StringID(MT_SpellFailure, SNEAK_RESTRICT); return; } + // + // Modern clients don't require pet targeted for AA casts that are ST_Pet + if (spells[rank->spell].targettype == ST_Pet) + target_id = GetPetID(); + // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index bbd76183d..12250bdbd 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8606,6 +8606,10 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) return; } + // Modern clients don't require pet targeted for item clicks that are ST_Pet + if (spells[spell_id].targettype == ST_Pet) + target_id = GetPetID(); + Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); if (m_inv.SupportsClickCasting(slot_id) || ((item->ItemType == EQEmu::item::ItemTypePotion || item->PotionBelt) && m_inv.SupportsPotionBeltCasting(slot_id))) // sanity check From 5eba112b7aa76622421f21b86f153ff2f47ba92d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 May 2017 12:57:04 -0400 Subject: [PATCH 049/218] Fix Crash introduced in last patch --- zone/client_packet.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 12250bdbd..e9fad51c7 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8599,15 +8599,15 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) (IsAmnesiad() && IsDiscipline(spell_id)) || (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) || (inst->IsScaling() && inst->GetExp() <= 0) // charms don't have spells when less than 0 - ) ) + ) { SendSpellBarEnable(spell_id); return; } // Modern clients don't require pet targeted for item clicks that are ST_Pet - if (spells[spell_id].targettype == ST_Pet) + if (spell_id > 0 && spells[spell_id].targettype == ST_Pet) target_id = GetPetID(); Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); From 6bdcfaaa71522e51d339d185bcbad631ce93485b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 18 May 2017 12:59:23 -0400 Subject: [PATCH 050/218] Forgot ST_SummonedPet --- zone/aa.cpp | 2 +- zone/client_packet.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aa.cpp b/zone/aa.cpp index 2451416aa..51cb376da 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1204,7 +1204,7 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { } // // Modern clients don't require pet targeted for AA casts that are ST_Pet - if (spells[rank->spell].targettype == ST_Pet) + if (spells[rank->spell].targettype == ST_Pet || spells[rank->spell].targettype == ST_SummonedPet) target_id = GetPetID(); // Bards can cast instant cast AAs while they are casting another song diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e9fad51c7..361c67d40 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -8607,7 +8607,7 @@ void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) } // Modern clients don't require pet targeted for item clicks that are ST_Pet - if (spell_id > 0 && spells[spell_id].targettype == ST_Pet) + if (spell_id > 0 && (spells[spell_id].targettype == ST_Pet || spells[spell_id].targettype == ST_SummonedPet)) target_id = GetPetID(); Log(Logs::General, Logs::None, "OP ItemVerifyRequest: spell=%i, target=%i, inv=%i", spell_id, target_id, slot_id); From 7189994b78a6367c9f694412f508db25c1b92a13 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 19 May 2017 22:50:08 -0700 Subject: [PATCH 051/218] Many lua things many many things --- zone/attack.cpp | 37 ++-- zone/bonuses.cpp | 14 +- zone/client.cpp | 31 ++++ zone/client.h | 4 +- zone/common.h | 2 +- zone/entity.cpp | 19 ++ zone/entity.h | 3 +- zone/lua_client.cpp | 21 ++- zone/lua_client.h | 3 + zone/lua_entity.cpp | 12 ++ zone/lua_entity.h | 2 + zone/lua_entity_list.cpp | 29 +-- zone/lua_entity_list.h | 1 + zone/lua_general.cpp | 354 +++++++++++++++++++++++++++++++----- zone/lua_general.h | 4 + zone/lua_mob.cpp | 16 +- zone/lua_mob.h | 3 +- zone/lua_mod.cpp | 366 ++------------------------------------ zone/lua_mod.h | 23 +-- zone/lua_npc.cpp | 8 +- zone/lua_npc.h | 1 + zone/lua_parser.cpp | 69 +------ zone/lua_parser.h | 12 +- zone/lua_stat_bonuses.cpp | 6 +- zone/lua_stat_bonuses.h | 2 +- zone/mob.cpp | 9 +- zone/mob.h | 2 +- zone/special_attacks.cpp | 46 ----- 28 files changed, 500 insertions(+), 599 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 60b7ead7b..9a210236c 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1307,16 +1307,6 @@ void Mob::DoAttack(Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts) // IsFromSpell added to allow spell effects to use Attack. (Mainly for the Rampage AA right now.) bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { -#ifdef LUA_EQEMU - bool lua_ret = false; - bool ignoreDefault = false; - lua_ret = LuaParser::Instance()->ClientAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - if (ignoreDefault) { - return lua_ret; - } -#endif - if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to Client::Attack() for evaluation!"); @@ -1840,16 +1830,6 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk bool NPC::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts) { -#ifdef LUA_EQEMU - bool lua_ret = false; - bool ignoreDefault = false; - lua_ret = LuaParser::Instance()->NPCAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - if (ignoreDefault) { - return lua_ret; - } -#endif - if (!other) { SetTarget(nullptr); Log(Logs::General, Logs::Error, "A null Mob object was passed to NPC::Attack() for evaluation!"); @@ -4118,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; @@ -4139,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; @@ -4247,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, diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 7544ceb5f..232b74b2a 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1084,9 +1084,9 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) break; // base1 = effect value, base2 = skill restrictions(-1 for all) if (base2 == ALL_SKILLS) - newbon->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += base1; + newbon->CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] += base1; else - newbon->CritDmgMob[base2] += base1; + newbon->CritDmgMod[base2] += base1; break; } @@ -2441,9 +2441,9 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (base2 > EQEmu::skills::HIGHEST_SKILL) break; if(base2 == ALL_SKILLS) - new_bonus->CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; + new_bonus->CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] += effect_value; else - new_bonus->CritDmgMob[base2] += effect_value; + new_bonus->CritDmgMod[base2] += effect_value; break; } @@ -4203,9 +4203,9 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) { for (int e = 0; e < EQEmu::skills::HIGHEST_SKILL + 1; e++) { - spellbonuses.CritDmgMob[e] = effect_value; - aabonuses.CritDmgMob[e] = effect_value; - itembonuses.CritDmgMob[e] = effect_value; + spellbonuses.CritDmgMod[e] = effect_value; + aabonuses.CritDmgMod[e] = effect_value; + itembonuses.CritDmgMod[e] = effect_value; } break; } diff --git a/zone/client.cpp b/zone/client.cpp index 4ec1ba898..b25e4e18a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1255,6 +1255,37 @@ void Client::Message(uint32 type, const char* message, ...) { safe_delete_array(buffer); } +void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...) { + if (!FilteredMessageCheck(sender, filter)) + return; + + va_list argptr; + auto buffer = new char[4096]; + va_start(argptr, message); + vsnprintf(buffer, 4096, message, argptr); + va_end(argptr); + + size_t len = strlen(buffer); + + //client dosent like our packet all the time unless + //we make it really big, then it seems to not care that + //our header is malformed. + //len = 4096 - sizeof(SpecialMesg_Struct); + + uint32 len_packet = sizeof(SpecialMesg_Struct) + len; + auto app = new EQApplicationPacket(OP_SpecialMesg, len_packet); + SpecialMesg_Struct* sm = (SpecialMesg_Struct*)app->pBuffer; + sm->header[0] = 0x00; // Header used for #emote style messages.. + sm->header[1] = 0x00; // Play around with these to see other types + sm->header[2] = 0x00; + sm->msg_type = type; + memcpy(sm->message, buffer, len + 1); + + FastQueuePacket(&app); + + safe_delete_array(buffer); +} + void Client::QuestJournalledMessage(const char *npcname, const char* message) { // npcnames longer than 60 characters crash the client when they log back in diff --git a/zone/client.h b/zone/client.h index 19dc4c05b..89e0d9391 100644 --- a/zone/client.h +++ b/zone/client.h @@ -308,6 +308,7 @@ public: void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, const char* message, ...); void ChannelMessageSend(const char* from, const char* to, uint8 chan_num, uint8 language, uint8 lang_skill, const char* message, ...); void Message(uint32 type, const char* message, ...); + void FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, const char* message, ...); void QuestJournalledMessage(const char *npcname, const char* message); void VoiceMacroReceived(uint32 Type, char *Target, uint32 MacroNumber); void SendSound(); @@ -1260,6 +1261,8 @@ public: void CheckRegionTypeChanges(); + int32 CalcATK(); + protected: friend class Mob; void CalcItemBonuses(StatBonuses* newbon); @@ -1319,7 +1322,6 @@ private: void HandleTraderPriceUpdate(const EQApplicationPacket *app); - int32 CalcATK(); int32 CalcItemATKCap(); int32 CalcHaste(); diff --git a/zone/common.h b/zone/common.h index 7b63174d4..7294c87dc 100644 --- a/zone/common.h +++ b/zone/common.h @@ -408,7 +408,7 @@ struct StatBonuses { uint32 SpellTriggers[MAX_SPELL_TRIGGER]; // Innate/Spell/Item Spells that trigger when you cast uint32 SpellOnKill[MAX_SPELL_TRIGGER*3]; // Chance to proc after killing a mob uint32 SpellOnDeath[MAX_SPELL_TRIGGER*2]; // Chance to have effect cast when you die - int32 CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 + int32 CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 SkillReuseTime[EQEmu::skills::HIGHEST_SKILL + 1]; // Reduces skill timers int32 SkillDamageAmount[EQEmu::skills::HIGHEST_SKILL + 2]; // All Skills + -1 int32 TwoHandBluntBlock; // chance to block when wielding two hand blunt weapon diff --git a/zone/entity.cpp b/zone/entity.cpp index 37af35fdb..5a8e9fa5e 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2135,6 +2135,25 @@ void EntityList::MessageClose(Mob* sender, bool skipsender, float dist, uint32 t } } +void EntityList::FilteredMessageClose(Mob *sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char *message, ...) +{ + va_list argptr; + char buffer[4096]; + + va_start(argptr, message); + vsnprintf(buffer, 4095, message, argptr); + va_end(argptr); + + float dist2 = dist * dist; + + auto it = client_list.begin(); + while (it != client_list.end()) { + if (DistanceSquared(it->second->GetPosition(), sender->GetPosition()) <= dist2 && (!skipsender || it->second != sender)) + it->second->FilteredMessage(sender, type, filter, buffer); + ++it; + } +} + void EntityList::RemoveAllMobs() { auto it = mob_list.begin(); diff --git a/zone/entity.h b/zone/entity.h index 2f2237283..94078691a 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -79,6 +79,7 @@ public: virtual bool IsTrap() const { return false; } virtual bool IsBeacon() const { return false; } virtual bool IsEncounter() const { return false; } + virtual bool IsBot() const { return false; } virtual bool Process() { return false; } virtual bool Save() { return true; } @@ -113,7 +114,6 @@ public: bool CheckCoordLosNoZLeaps(float cur_x, float cur_y, float cur_z, float trg_x, float trg_y, float trg_z, float perwalk=1); #ifdef BOTS - virtual bool IsBot() const { return false; } Bot* CastToBot(); #endif @@ -315,6 +315,7 @@ public: void Message(uint32 to_guilddbid, uint32 type, const char* message, ...); void MessageStatus(uint32 to_guilddbid, int to_minstatus, uint32 type, const char* message, ...); void MessageClose(Mob* sender, bool skipsender, float dist, uint32 type, const char* message, ...); + void FilteredMessageClose(Mob* sender, bool skipsender, float dist, uint32 type, eqFilterType filter, const char* message, ...); void Message_StringID(Mob *sender, bool skipsender, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); void FilteredMessage_StringID(Mob *sender, bool skipsender, uint32 type, eqFilterType filter, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); void MessageClose_StringID(Mob *sender, bool skipsender, float dist, uint32 type, uint32 string_id, const char* message1=0,const char* message2=0,const char* message3=0,const char* message4=0,const char* message5=0,const char* message6=0,const char* message7=0,const char* message8=0,const char* message9=0); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 26acdd156..64bf2321c 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -1424,6 +1424,22 @@ bool Lua_Client::IsDead() { return self->IsDead(); } +int Lua_Client::CalcCurrentWeight() { + Lua_Safe_Call_Int(); + 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() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -1693,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("IsDead", &Lua_Client::IsDead); + .def("IsDead", &Lua_Client::IsDead) + .def("CalcCurrentWeight", &Lua_Client::CalcCurrentWeight) + .def("CalcATK", &Lua_Client::CalcATK) + .def("FilteredMessage", &Lua_Client::FilteredMessage); } luabind::scope lua_register_inventory_where() { diff --git a/zone/lua_client.h b/zone/lua_client.h index cd9206728..f29e3b46f 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -298,6 +298,9 @@ public: void QuestReward(Lua_Mob target, uint32 copper, uint32 silver, uint32 gold, uint32 platinum, uint32 itemid, uint32 exp, bool faction); void QuestReward(Lua_Mob target, luabind::adl::object reward); bool IsDead(); + int CalcCurrentWeight(); + int CalcATK(); + void FilteredMessage(Mob *sender, uint32 type, int filter, const char* message); }; #endif diff --git a/zone/lua_entity.cpp b/zone/lua_entity.cpp index ea233af4b..725e78f5e 100644 --- a/zone/lua_entity.cpp +++ b/zone/lua_entity.cpp @@ -67,6 +67,16 @@ bool Lua_Entity::IsBeacon() { return self->IsBeacon(); } +bool Lua_Entity::IsEncounter() { + Lua_Safe_Call_Bool(); + return self->IsEncounter(); +} + +bool Lua_Entity::IsBot() { + Lua_Safe_Call_Bool(); + return self->IsBot(); +} + int Lua_Entity::GetID() { Lua_Safe_Call_Bool(); return self->GetID(); @@ -124,6 +134,8 @@ luabind::scope lua_register_entity() { .def("IsDoor", &Lua_Entity::IsDoor) .def("IsTrap", &Lua_Entity::IsTrap) .def("IsBeacon", &Lua_Entity::IsBeacon) + .def("IsEncounter", &Lua_Entity::IsEncounter) + .def("IsBot", &Lua_Entity::IsBot) .def("GetID", &Lua_Entity::GetID) .def("CastToClient", &Lua_Entity::CastToClient) .def("CastToNPC", &Lua_Entity::CastToNPC) diff --git a/zone/lua_entity.h b/zone/lua_entity.h index 7e3254ff3..b45208581 100644 --- a/zone/lua_entity.h +++ b/zone/lua_entity.h @@ -44,6 +44,8 @@ public: bool IsDoor(); bool IsTrap(); bool IsBeacon(); + bool IsEncounter(); + bool IsBot(); int GetID(); Lua_Client CastToClient(); diff --git a/zone/lua_entity_list.cpp b/zone/lua_entity_list.cpp index 7626a709b..ef4057ed1 100644 --- a/zone/lua_entity_list.cpp +++ b/zone/lua_entity_list.cpp @@ -210,6 +210,12 @@ void Lua_EntityList::MessageClose(Lua_Mob sender, bool skip_sender, float dist, self->MessageClose(sender, skip_sender, dist, type, message); } +void Lua_EntityList::FilteredMessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, int filter, const char *message) +{ + Lua_Safe_Call_Void(); + self->FilteredMessageClose(sender, skip_sender, dist, type, (eqFilterType)filter, message); +} + void Lua_EntityList::RemoveFromTargets(Lua_Mob mob) { Lua_Safe_Call_Void(); self->RemoveFromTargets(mob); @@ -450,16 +456,17 @@ luabind::scope lua_register_entity_list() { .def("GetSpawnByID", (Lua_Spawn(Lua_EntityList::*)(uint32))&Lua_EntityList::GetSpawnByID) .def("ClearClientPetitionQueue", (void(Lua_EntityList::*)(void))&Lua_EntityList::ClearClientPetitionQueue) .def("CanAddHateForMob", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::CanAddHateForMob) - .def("Message", (void(Lua_EntityList::*)(uint32,uint32,const char*))&Lua_EntityList::Message) - .def("MessageStatus", (void(Lua_EntityList::*)(uint32,uint32,uint32,const char*))&Lua_EntityList::MessageStatus) - .def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob,bool,float,uint32,const char*))&Lua_EntityList::MessageClose) + .def("Message", (void(Lua_EntityList::*)(uint32, uint32, const char*))&Lua_EntityList::Message) + .def("MessageStatus", (void(Lua_EntityList::*)(uint32, uint32, uint32, const char*))&Lua_EntityList::MessageStatus) + .def("MessageClose", (void(Lua_EntityList::*)(Lua_Mob, bool, float, uint32, const char*))&Lua_EntityList::MessageClose) + .def("FilteredMessageClose", &Lua_EntityList::FilteredMessageClose) .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::RemoveFromTargets) - .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob,bool))&Lua_EntityList::RemoveFromTargets) - .def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob,Lua_Mob))&Lua_EntityList::ReplaceWithTarget) + .def("RemoveFromTargets", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromTargets) + .def("ReplaceWithTarget", (void(Lua_EntityList::*)(Lua_Mob, Lua_Mob))&Lua_EntityList::ReplaceWithTarget) .def("OpenDoorsNear", (void(Lua_EntityList::*)(Lua_NPC))&Lua_EntityList::OpenDoorsNear) .def("MakeNameUnique", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::MakeNameUnique) .def("RemoveNumbers", (std::string(Lua_EntityList::*)(const char*))&Lua_EntityList::RemoveNumbers) - .def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32,int))&Lua_EntityList::SignalMobsByNPCID) + .def("SignalMobsByNPCID", (void(Lua_EntityList::*)(uint32, int))&Lua_EntityList::SignalMobsByNPCID) .def("DeleteNPCCorpses", (int(Lua_EntityList::*)(void))&Lua_EntityList::DeleteNPCCorpses) .def("DeletePlayerCorpses", (int(Lua_EntityList::*)(void))&Lua_EntityList::DeletePlayerCorpses) .def("HalveAggro", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::HalveAggro) @@ -467,10 +474,10 @@ luabind::scope lua_register_entity_list() { .def("ClearFeignAggro", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::ClearFeignAggro) .def("Fighting", (bool(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::Fighting) .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob))&Lua_EntityList::RemoveFromHateLists) - .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob,bool))&Lua_EntityList::RemoveFromHateLists) - .def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob,bool,uint32,const char*))&Lua_EntityList::MessageGroup) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float))&Lua_EntityList::GetRandomClient) - .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float,float,float,float,Lua_Client))&Lua_EntityList::GetRandomClient) + .def("RemoveFromHateLists", (void(Lua_EntityList::*)(Lua_Mob, bool))&Lua_EntityList::RemoveFromHateLists) + .def("MessageGroup", (void(Lua_EntityList::*)(Lua_Mob, bool, uint32, const char*))&Lua_EntityList::MessageGroup) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float))&Lua_EntityList::GetRandomClient) + .def("GetRandomClient", (Lua_Client(Lua_EntityList::*)(float, float, float, float, Lua_Client))&Lua_EntityList::GetRandomClient) .def("GetMobList", (Lua_Mob_List(Lua_EntityList::*)(void))&Lua_EntityList::GetMobList) .def("GetClientList", (Lua_Client_List(Lua_EntityList::*)(void))&Lua_EntityList::GetClientList) .def("GetNPCList", (Lua_NPC_List(Lua_EntityList::*)(void))&Lua_EntityList::GetNPCList) @@ -479,7 +486,7 @@ luabind::scope lua_register_entity_list() { .def("GetDoorsList", (Lua_Doors_List(Lua_EntityList::*)(void))&Lua_EntityList::GetDoorsList) .def("GetSpawnList", (Lua_Spawn_List(Lua_EntityList::*)(void))&Lua_EntityList::GetSpawnList) .def("SignalAllClients", (void(Lua_EntityList::*)(int))&Lua_EntityList::SignalAllClients) - .def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob,int,int,const char*))&Lua_EntityList::ChannelMessage); + .def("ChannelMessage", (void(Lua_EntityList::*)(Lua_Mob, int, int, const char*))&Lua_EntityList::ChannelMessage); } luabind::scope lua_register_mob_list() { diff --git a/zone/lua_entity_list.h b/zone/lua_entity_list.h index 823499f24..17b00579e 100644 --- a/zone/lua_entity_list.h +++ b/zone/lua_entity_list.h @@ -80,6 +80,7 @@ public: void Message(uint32 guild_dbid, uint32 type, const char *message); void MessageStatus(uint32 guild_dbid, int min_status, uint32 type, const char *message); void MessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, const char *message); + void FilteredMessageClose(Lua_Mob sender, bool skip_sender, float dist, uint32 type, int filter, const char *message); void RemoveFromTargets(Lua_Mob mob); void RemoveFromTargets(Lua_Mob mob, bool RemoveFromXTargets); void ReplaceWithTarget(Lua_Mob target, Lua_Mob new_target); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index dd9eda5af..06e09f1a1 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -29,6 +29,10 @@ struct Materials { }; struct ClientVersions { }; struct Appearances { }; struct Classes { }; +struct Skills { }; +struct BodyTypes { }; +struct Filters { }; +struct MessageTypes { }; struct lua_registered_event { std::string encounter_name; @@ -1893,55 +1897,311 @@ luabind::scope lua_register_appearance() { } luabind::scope lua_register_classes() { - return luabind::class_("Classes") + return luabind::class_("Class") .enum_("constants") [ - luabind::value("Warrior", WARRIOR), - luabind::value("Cleric", CLERIC), - luabind::value("Paladin", PALADIN), - luabind::value("Ranger", RANGER), - luabind::value("ShadowKnight", SHADOWKNIGHT), - luabind::value("Druid", DRUID), - luabind::value("Monk", MONK), - luabind::value("Bard", BARD), - luabind::value("Rogue", ROGUE), - luabind::value("Shaman", SHAMAN), - luabind::value("Necromancer", NECROMANCER), - luabind::value("Wizard", WIZARD), - luabind::value("Magician", MAGICIAN), - luabind::value("Enchanter", ENCHANTER), - luabind::value("Beastlord", BEASTLORD), - luabind::value("Berserker", BERSERKER), - luabind::value("WarriorGM", WARRIORGM), - luabind::value("ClericGM", CLERICGM), - luabind::value("PaladinGM", PALADINGM), - luabind::value("RangerGM", RANGERGM), - luabind::value("ShadowKnightGM", SHADOWKNIGHTGM), - luabind::value("DruidGM", DRUIDGM), - luabind::value("MonkGM", MONKGM), - luabind::value("BardGM", BARDGM), - luabind::value("RogueGM", ROGUEGM), - luabind::value("ShamanGM", SHAMANGM), - luabind::value("NecromancerGM", NECROMANCERGM), - luabind::value("WizardGM", WIZARDGM), - luabind::value("MagicianGM", MAGICIANGM), - luabind::value("EnchanterGM", ENCHANTERGM), - luabind::value("BeastlordGM", BEASTLORDGM), - luabind::value("BerserkerGM", BERSERKERGM), - luabind::value("Banker", BANKER), - luabind::value("Merchant", MERCHANT), - luabind::value("DiscordMerchant", DISCORD_MERCHANT), - luabind::value("AdventureRecruiter", ADVENTURERECRUITER), - luabind::value("AdventureMerchant", ADVENTUREMERCHANT), - luabind::value("LDONTreasure", LDON_TREASURE), - luabind::value("CorpseClass", CORPSE_CLASS), - luabind::value("TributeMaster", TRIBUTE_MASTER), - luabind::value("GuildTributeMaster", GUILD_TRIBUTE_MASTER), - luabind::value("NorrathsKeeperMerchant", NORRATHS_KEEPERS_MERCHANT), - luabind::value("DarkReignMerchant", DARK_REIGN_MERCHANT), - luabind::value("FellowshipMaster", FELLOWSHIP_MASTER), - luabind::value("AltCurrencyMerchant", ALT_CURRENCY_MERCHANT), - luabind::value("MercenaryMaster", MERCERNARY_MASTER) + luabind::value("WARRIOR", WARRIOR), + luabind::value("CLERIC", CLERIC), + luabind::value("PALADIN", PALADIN), + luabind::value("RANGER", RANGER), + luabind::value("SHADOWKNIGHT", SHADOWKNIGHT), + luabind::value("DRUID", DRUID), + luabind::value("MONK", MONK), + luabind::value("BARD", BARD), + luabind::value("ROGUE", ROGUE), + luabind::value("SHAMAN", SHAMAN), + luabind::value("NECROMANCER", NECROMANCER), + luabind::value("WIZARD", WIZARD), + luabind::value("MAGICIAN", MAGICIAN), + luabind::value("ENCHANTER", ENCHANTER), + luabind::value("BEASTLORD", BEASTLORD), + luabind::value("BERSERKER", BERSERKER), + luabind::value("WARRIORGM", WARRIORGM), + luabind::value("CLERICGM", CLERICGM), + luabind::value("PALADINGM", PALADINGM), + luabind::value("RANGERGM", RANGERGM), + luabind::value("SHADOWKNIGHTGM", SHADOWKNIGHTGM), + luabind::value("DRUIDGM", DRUIDGM), + luabind::value("MONKGM", MONKGM), + luabind::value("BARDGM", BARDGM), + luabind::value("ROGUEGM", ROGUEGM), + luabind::value("SHAMANGM", SHAMANGM), + luabind::value("NECROMANCERGM", NECROMANCERGM), + luabind::value("WIZARDGM", WIZARDGM), + luabind::value("MAGICIANGM", MAGICIANGM), + luabind::value("ENCHANTERGM", ENCHANTERGM), + luabind::value("BEASTLORDGM", BEASTLORDGM), + luabind::value("BERSERKERGM", BERSERKERGM), + luabind::value("BANKER", BANKER), + luabind::value("MERCHANT", MERCHANT), + luabind::value("DISCORD_MERCHANT", DISCORD_MERCHANT), + luabind::value("ADVENTURERECRUITER", ADVENTURERECRUITER), + luabind::value("ADVENTUREMERCHANT", ADVENTUREMERCHANT), + luabind::value("LDON_TREASURE", LDON_TREASURE), + luabind::value("CORPSE_CLASS", CORPSE_CLASS), + luabind::value("TRIBUTE_MASTER", TRIBUTE_MASTER), + luabind::value("GUILD_TRIBUTE_MASTER", GUILD_TRIBUTE_MASTER), + luabind::value("NORRATHS_KEEPERS_MERCHANT", NORRATHS_KEEPERS_MERCHANT), + luabind::value("DARK_REIGN_MERCHANT", DARK_REIGN_MERCHANT), + luabind::value("FELLOWSHIP_MASTER", FELLOWSHIP_MASTER), + luabind::value("ALT_CURRENCY_MERCHANT", ALT_CURRENCY_MERCHANT), + luabind::value("MERCERNARY_MASTER", MERCERNARY_MASTER) + ]; +} + +luabind::scope lua_register_skills() { + return luabind::class_("Skill") + .enum_("constants") + [ + luabind::value("1HBlunt", EQEmu::skills::Skill1HBlunt), + luabind::value("1HSlashing", EQEmu::skills::Skill1HSlashing), + luabind::value("2HBlunt", EQEmu::skills::Skill2HBlunt), + luabind::value("2HSlashing", EQEmu::skills::Skill2HSlashing), + luabind::value("Abjuration", EQEmu::skills::SkillAbjuration), + luabind::value("Alteration", EQEmu::skills::SkillAlteration), + luabind::value("ApplyPoison", EQEmu::skills::SkillApplyPoison), + luabind::value("Archery", EQEmu::skills::SkillArchery), + luabind::value("Backstab", EQEmu::skills::SkillBackstab), + luabind::value("BindWound", EQEmu::skills::SkillBindWound), + luabind::value("Bash", EQEmu::skills::SkillBash), + luabind::value("Block", EQEmu::skills::SkillBlock), + luabind::value("BrassInstruments", EQEmu::skills::SkillBrassInstruments), + luabind::value("Channeling", EQEmu::skills::SkillChanneling), + luabind::value("Conjuration", EQEmu::skills::SkillConjuration), + luabind::value("Defense", EQEmu::skills::SkillDefense), + luabind::value("Disarm", EQEmu::skills::SkillDisarm), + luabind::value("DisarmTraps", EQEmu::skills::SkillDisarmTraps), + luabind::value("Divination", EQEmu::skills::SkillDivination), + luabind::value("Dodge", EQEmu::skills::SkillDodge), + luabind::value("DoubleAttack", EQEmu::skills::SkillDoubleAttack), + luabind::value("DragonPunch", EQEmu::skills::SkillDragonPunch), + luabind::value("TailRake", EQEmu::skills::SkillTailRake), + luabind::value("DualWield", EQEmu::skills::SkillDualWield), + luabind::value("EagleStrike", EQEmu::skills::SkillEagleStrike), + luabind::value("Evocation", EQEmu::skills::SkillEvocation), + luabind::value("FeignDeath", EQEmu::skills::SkillFeignDeath), + luabind::value("FlyingKick", EQEmu::skills::SkillFlyingKick), + luabind::value("Forage", EQEmu::skills::SkillForage), + luabind::value("HandtoHand", EQEmu::skills::SkillHandtoHand), + luabind::value("Hide", EQEmu::skills::SkillHide), + luabind::value("Kick", EQEmu::skills::SkillKick), + luabind::value("Meditate", EQEmu::skills::SkillMeditate), + luabind::value("Mend", EQEmu::skills::SkillMend), + luabind::value("Offense", EQEmu::skills::SkillOffense), + luabind::value("Parry", EQEmu::skills::SkillParry), + luabind::value("PickLock", EQEmu::skills::SkillPickLock), + luabind::value("1HPiercing", EQEmu::skills::Skill1HPiercing), + luabind::value("Riposte", EQEmu::skills::SkillRiposte), + luabind::value("RoundKick", EQEmu::skills::SkillRoundKick), + luabind::value("SafeFall", EQEmu::skills::SkillSafeFall), + luabind::value("SenseHeading", EQEmu::skills::SkillSenseHeading), + luabind::value("Singing", EQEmu::skills::SkillSinging), + luabind::value("Sneak", EQEmu::skills::SkillSneak), + luabind::value("SpecializeAbjure", EQEmu::skills::SkillSpecializeAbjure), + luabind::value("SpecializeAlteration", EQEmu::skills::SkillSpecializeAlteration), + luabind::value("SpecializeConjuration", EQEmu::skills::SkillSpecializeConjuration), + luabind::value("SpecializeDivination", EQEmu::skills::SkillSpecializeDivination), + luabind::value("SpecializeEvocation", EQEmu::skills::SkillSpecializeEvocation), + luabind::value("PickPockets", EQEmu::skills::SkillPickPockets), + luabind::value("StringedInstruments", EQEmu::skills::SkillStringedInstruments), + luabind::value("Swimming", EQEmu::skills::SkillSwimming), + luabind::value("Throwing", EQEmu::skills::SkillThrowing), + luabind::value("TigerClaw", EQEmu::skills::SkillTigerClaw), + luabind::value("Tracking", EQEmu::skills::SkillTracking), + luabind::value("WindInstruments", EQEmu::skills::SkillWindInstruments), + luabind::value("Fishing", EQEmu::skills::SkillFishing), + luabind::value("MakePoison", EQEmu::skills::SkillMakePoison), + luabind::value("Tinkering", EQEmu::skills::SkillTinkering), + luabind::value("Research", EQEmu::skills::SkillResearch), + luabind::value("Alchemy", EQEmu::skills::SkillAlchemy), + luabind::value("Baking", EQEmu::skills::SkillBaking), + luabind::value("Tailoring", EQEmu::skills::SkillTailoring), + luabind::value("SenseTraps", EQEmu::skills::SkillSenseTraps), + luabind::value("Blacksmithing", EQEmu::skills::SkillBlacksmithing), + luabind::value("Fletching", EQEmu::skills::SkillFletching), + luabind::value("Brewing", EQEmu::skills::SkillBrewing), + luabind::value("AlcoholTolerance", EQEmu::skills::SkillAlcoholTolerance), + luabind::value("Begging", EQEmu::skills::SkillBegging), + luabind::value("JewelryMaking", EQEmu::skills::SkillJewelryMaking), + luabind::value("Pottery", EQEmu::skills::SkillPottery), + luabind::value("PercussionInstruments", EQEmu::skills::SkillPercussionInstruments), + luabind::value("Intimidation", EQEmu::skills::SkillIntimidation), + luabind::value("Berserking", EQEmu::skills::SkillBerserking), + luabind::value("Taunt", EQEmu::skills::SkillTaunt), + luabind::value("Frenzy", EQEmu::skills::SkillFrenzy), + luabind::value("RemoveTraps", EQEmu::skills::SkillRemoveTraps), + luabind::value("TripleAttack", EQEmu::skills::SkillTripleAttack), + luabind::value("2HPiercing", EQEmu::skills::Skill2HPiercing), + luabind::value("HIGHEST_SKILL", EQEmu::skills::HIGHEST_SKILL) + ]; +} + +luabind::scope lua_register_bodytypes() { + return luabind::class_("BT") + .enum_("constants") + [ + luabind::value("Humanoid", 1), + luabind::value("Lycanthrope", 2), + luabind::value("Undead", 3), + luabind::value("Giant", 4), + luabind::value("Construct", 5), + luabind::value("Extraplanar", 6), + luabind::value("Magical", 7), + luabind::value("SummonedUndead", 8), + luabind::value("RaidGiant", 9), + luabind::value("NoTarget", 11), + luabind::value("Vampire", 12), + luabind::value("Atenha_Ra", 13), + luabind::value("Greater_Akheva", 14), + luabind::value("Khati_Sha", 15), + luabind::value("Seru", 16), + luabind::value("Draz_Nurakk", 18), + luabind::value("Zek", 19), + luabind::value("Luggald", 20), + luabind::value("Animal", 21), + luabind::value("Insect", 22), + luabind::value("Monster", 23), + luabind::value("Summoned", 24), + luabind::value("Plant", 25), + luabind::value("Dragon", 26), + luabind::value("Summoned2", 27), + luabind::value("Summoned3", 28), + luabind::value("VeliousDragon", 30), + luabind::value("Dragon3", 32), + luabind::value("Boxes", 33), + luabind::value("Muramite", 34), + luabind::value("NoTarget2", 60), + luabind::value("SwarmPet", 63), + luabind::value("InvisMan", 66), + luabind::value("Special", 67) + ]; +} + +luabind::scope lua_register_filters() { + return luabind::class_("Filter") + .enum_("constants") + [ + luabind::value("None", FilterNone), + luabind::value("GuildChat", FilterGuildChat), + luabind::value("Socials", FilterSocials), + luabind::value("GroupChat", FilterGroupChat), + luabind::value("Shouts", FilterShouts), + luabind::value("Auctions", FilterAuctions), + luabind::value("OOC", FilterOOC), + luabind::value("BadWords", FilterBadWords), + luabind::value("PCSpells", FilterPCSpells), + luabind::value("NPCSpells", FilterNPCSpells), + luabind::value("BardSongs", FilterBardSongs), + luabind::value("SpellCrits", FilterSpellCrits), + luabind::value("MeleeCrits", FilterMeleeCrits), + luabind::value("SpellDamage", FilterSpellDamage), + luabind::value("MyMisses", FilterMyMisses), + luabind::value("OthersMiss", FilterOthersMiss), + luabind::value("OthersHit", FilterOthersHit), + luabind::value("MissedMe", FilterMissedMe), + luabind::value("DamageShields", FilterDamageShields), + luabind::value("DOT", FilterDOT), + luabind::value("PetHits", FilterPetHits), + luabind::value("PetMisses", FilterPetMisses), + luabind::value("FocusEffects", FilterFocusEffects), + luabind::value("PetSpells", FilterPetSpells), + luabind::value("HealOverTime", FilterHealOverTime), + luabind::value("Unknown25", FilterUnknown25), + luabind::value("Unknown26", FilterUnknown26), + luabind::value("Unknown27", FilterUnknown27), + luabind::value("Unknown28", FilterUnknown28) + ]; +} + +luabind::scope lua_register_message_types() { + return luabind::class_("MT") + .enum_("constants") + [ + luabind::value("Say", MT_Say), + luabind::value("Tell", MT_Tell), + luabind::value("Group", MT_Group), + luabind::value("Guild", MT_Guild), + luabind::value("OOC", MT_OOC), + luabind::value("Auction", MT_Auction), + luabind::value("Shout", MT_Shout), + luabind::value("Emote", MT_Emote), + luabind::value("Spells", MT_Spells), + luabind::value("YouHitOther", MT_YouHitOther), + luabind::value("OtherHitsYou", MT_OtherHitsYou), + luabind::value("YouMissOther", MT_YouMissOther), + luabind::value("OtherMissesYou", MT_OtherMissesYou), + luabind::value("Broadcasts", MT_Broadcasts), + luabind::value("Skills", MT_Skills), + luabind::value("Disciplines", MT_Disciplines), + luabind::value("Unused1", MT_Unused1), + luabind::value("DefaultText", MT_DefaultText), + luabind::value("Unused2", MT_Unused2), + luabind::value("MerchantOffer", MT_MerchantOffer), + luabind::value("MerchantBuySell", MT_MerchantBuySell), + luabind::value("YourDeath", MT_YourDeath), + luabind::value("OtherDeath", MT_OtherDeath), + luabind::value("OtherHits", MT_OtherHits), + luabind::value("OtherMisses", MT_OtherMisses), + luabind::value("Who", MT_Who), + luabind::value("YellForHelp", MT_YellForHelp), + luabind::value("NonMelee", MT_NonMelee), + luabind::value("WornOff", MT_WornOff), + luabind::value("MoneySplit", MT_MoneySplit), + luabind::value("LootMessages", MT_LootMessages), + luabind::value("DiceRoll", MT_DiceRoll), + luabind::value("OtherSpells", MT_OtherSpells), + luabind::value("SpellFailure", MT_SpellFailure), + luabind::value("Chat", MT_Chat), + luabind::value("Channel1", MT_Channel1), + luabind::value("Channel2", MT_Channel2), + luabind::value("Channel3", MT_Channel3), + luabind::value("Channel4", MT_Channel4), + luabind::value("Channel5", MT_Channel5), + luabind::value("Channel6", MT_Channel6), + luabind::value("Channel7", MT_Channel7), + luabind::value("Channel8", MT_Channel8), + luabind::value("Channel9", MT_Channel9), + luabind::value("Channel10", MT_Channel10), + luabind::value("CritMelee", MT_CritMelee), + luabind::value("SpellCrits", MT_SpellCrits), + luabind::value("TooFarAway", MT_TooFarAway), + luabind::value("NPCRampage", MT_NPCRampage), + luabind::value("NPCFlurry", MT_NPCFlurry), + luabind::value("NPCEnrage", MT_NPCEnrage), + luabind::value("SayEcho", MT_SayEcho), + luabind::value("TellEcho", MT_TellEcho), + luabind::value("GroupEcho", MT_GroupEcho), + luabind::value("GuildEcho", MT_GuildEcho), + luabind::value("OOCEcho", MT_OOCEcho), + luabind::value("AuctionEcho", MT_AuctionEcho), + luabind::value("ShoutECho", MT_ShoutECho), + luabind::value("EmoteEcho", MT_EmoteEcho), + luabind::value("Chat1Echo", MT_Chat1Echo), + luabind::value("Chat2Echo", MT_Chat2Echo), + luabind::value("Chat3Echo", MT_Chat3Echo), + luabind::value("Chat4Echo", MT_Chat4Echo), + luabind::value("Chat5Echo", MT_Chat5Echo), + luabind::value("Chat6Echo", MT_Chat6Echo), + luabind::value("Chat7Echo", MT_Chat7Echo), + luabind::value("Chat8Echo", MT_Chat8Echo), + luabind::value("Chat9Echo", MT_Chat9Echo), + luabind::value("Chat10Echo", MT_Chat10Echo), + luabind::value("DoTDamage", MT_DoTDamage), + luabind::value("ItemLink", MT_ItemLink), + luabind::value("RaidSay", MT_RaidSay), + luabind::value("MyPet", MT_MyPet), + luabind::value("DS", MT_DS), + luabind::value("Leadership", MT_Leadership), + luabind::value("PetFlurry", MT_PetFlurry), + luabind::value("PetCrit", MT_PetCrit), + luabind::value("FocusEffect", MT_FocusEffect), + luabind::value("Experience", MT_Experience), + luabind::value("System", MT_System), + luabind::value("PetSpell", MT_PetSpell), + luabind::value("PetResponse", MT_PetResponse), + luabind::value("ItemSpeech", MT_ItemSpeech), + luabind::value("StrikeThrough", MT_StrikeThrough), + luabind::value("Stun", MT_Stun) ]; } diff --git a/zone/lua_general.h b/zone/lua_general.h index 1b39ea31a..62ec346f2 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -11,6 +11,10 @@ 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(); #endif #endif diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 475b73716..07fb17ac5 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2051,6 +2051,18 @@ bool Lua_Mob::TryFinishingBlow(Lua_Mob defender, int &damage) { 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(); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2408,7 +2420,9 @@ luabind::scope lua_register_mob() { .def("AttackAnimation", &Lua_Mob::AttackAnimation) .def("GetWeaponDamage", &Lua_Mob::GetWeaponDamage) .def("IsBerserk", &Lua_Mob::IsBerserk) - .def("TryFinishingBlow", &Lua_Mob::TryFinishingBlow); + .def("TryFinishingBlow", &Lua_Mob::TryFinishingBlow) + .def("GetBodyType", &Lua_Mob::GetBodyType) + .def("GetOrigBodyType", &Lua_Mob::GetOrigBodyType); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 9c84ada98..1da58c587 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -341,7 +341,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); @@ -394,6 +393,8 @@ public: int GetWeaponDamage(Lua_Mob against, Lua_ItemInst weapon); bool IsBerserk(); bool TryFinishingBlow(Lua_Mob defender, int &damage); + int GetBodyType(); + int GetOrigBodyType(); }; #endif diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index 9f352810e..f35992d94 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -34,18 +34,11 @@ void LuaMod::Init() { - m_has_client_attack = parser_->HasFunction("ClientAttack", package_name_); - m_has_npc_attack = parser_->HasFunction("NPCAttack", package_name_); - m_has_bot_attack = parser_->HasFunction("BotAttack", package_name_); 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_do_special_attack_damage = parser_->HasFunction("DoSpecialAttackDamage", package_name_); - m_has_do_ranged_attack_dmg = parser_->HasFunction("DoRangedAttackDmg", package_name_); - m_has_do_archery_attack_dmg = parser_->HasFunction("DoArcheryAttackDmg", package_name_); - m_has_do_throwing_attack_dmg = parser_->HasFunction("DoThrowingAttackDmg", package_name_); - m_has_do_melee_skill_attack_dmg = parser_->HasFunction("DoMeleeSkillAttackDmg", package_name_); + m_has_try_critical_hit = parser_->HasFunction("TryCriticalHit", package_name_); } void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) { @@ -182,114 +175,6 @@ void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) } } -bool LuaMod::ClientAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; - - if (!m_has_client_attack) { - return retval; - } - - retval = CommonAttack("ClientAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - - return retval; -} - -bool LuaMod::NPCAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; - - if (!m_has_npc_attack) { - return retval; - } - - retval = CommonAttack("NPCAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - - return retval; -} - -bool LuaMod::BotAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; - - if (!m_has_bot_attack) { - return retval; - } - - retval = CommonAttack("BotAttack", self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } - - return retval; -} - -bool LuaMod::CommonAttack(const std::string &fn, Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) { - bool retval = false; - - lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, fn.c_str()); - - 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; - e["Hand"] = Hand; - e["bRiposte"] = bRiposte; - e["IsStrikethrough"] = IsStrikethrough; - e["IsFromSpell"] = IsFromSpell; - - 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 retval; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - - auto returnValueObj = ret["ReturnValue"]; - if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { - retval = luabind::object_cast(returnValueObj); - } - - GetExtraAttackOptions(ret, opts); - } - - return retval; -} - void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); ignoreDefault = false; @@ -503,30 +388,28 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign return retval; } -void LuaMod::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault) -{ +//void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + +void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); ignoreDefault = false; try { - if (!m_has_do_special_attack_damage) { + if (!m_has_try_critical_hit) { return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, "DoSpecialAttackDamage"); + lua_getfield(L, -1, "TryCriticalHit"); Lua_Mob l_self(self); - Lua_Mob l_other(who); + Lua_Mob l_other(defender); luabind::adl::object e = luabind::newtable(L); e["self"] = l_self; e["other"] = l_other; - e["skill"] = (int)skill; - e["base_damage"] = base_damage; - e["min_damage"] = min_damage; - e["hate_override"] = hate_override; - e["ReuseTime"] = ReuseTime; + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); e.push(L); if (lua_pcall(L, 1, 1, 0)) { @@ -542,6 +425,9 @@ void LuaMod::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); } } catch (std::exception &ex) { @@ -554,231 +440,3 @@ void LuaMod::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType lua_pop(L, n); } } - -void LuaMod::DoRangedAttackDmg(Mob *self, Mob *other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - - try { - if (!m_has_do_ranged_attack_dmg) { - return; - } - - lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, "DoRangedAttackDmg"); - - 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; - e["Launch"] = Launch; - e["damage_mod"] = damage_mod; - e["chance_mod"] = chance_mod; - e["skill"] = (int)skill; - e["speed"] = speed; - e["IDFile"] = IDFile ? IDFile : ""; - - e.push(L); - - if (lua_pcall(L, 1, 1, 0)) { - std::string error = lua_tostring(L, -1); - parser_->AddError(error); - lua_pop(L, 1); - return; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - } - } - 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::DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - - try { - if (!m_has_do_archery_attack_dmg) { - return; - } - - lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, "DoArcheryAttackDmg"); - - Lua_Mob l_self(self); - Lua_Mob l_other(other); - Lua_ItemInst l_RangeWeapon(const_cast(RangeWeapon)); - Lua_ItemInst l_Ammo(const_cast(Ammo)); - Lua_Item l_AmmoItem(const_cast(AmmoItem)); - luabind::adl::object e = luabind::newtable(L); - e["self"] = l_self; - e["other"] = l_other; - e["RangeWeapon"] = l_RangeWeapon; - e["Ammo"] = l_Ammo; - e["weapon_damage"] = weapon_damage; - e["chance_mod"] = chance_mod; - e["focus"] = focus; - e["ReuseTime"] = ReuseTime; - e["range_id"] = range_id; - e["ammo_id"] = ammo_id; - e["AmmoItem"] = l_AmmoItem; - e["AmmoSlot"] = AmmoSlot; - e["speed"] = speed; - - e.push(L); - - if (lua_pcall(L, 1, 1, 0)) { - std::string error = lua_tostring(L, -1); - parser_->AddError(error); - lua_pop(L, 1); - return; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - } - } - 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::DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - - try { - if (!m_has_do_throwing_attack_dmg) { - return; - } - - lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, "DoThrowingAttackDmg"); - - Lua_Mob l_self(self); - Lua_Mob l_other(other); - Lua_ItemInst l_RangeWeapon(const_cast(RangeWeapon)); - Lua_Item l_AmmoItem(const_cast(AmmoItem)); - luabind::adl::object e = luabind::newtable(L); - e["self"] = l_self; - e["other"] = l_other; - e["RangeWeapon"] = l_RangeWeapon; - e["weapon_damage"] = weapon_damage; - e["chance_mod"] = chance_mod; - e["focus"] = focus; - e["ReuseTime"] = ReuseTime; - e["range_id"] = range_id; - e["AmmoItem"] = l_AmmoItem; - e["AmmoSlot"] = AmmoSlot; - e["speed"] = speed; - - e.push(L); - - if (lua_pcall(L, 1, 1, 0)) { - std::string error = lua_tostring(L, -1); - parser_->AddError(error); - lua_pop(L, 1); - return; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - } - } - 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::DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, - bool &ignoreDefault) -{ - int start = lua_gettop(L); - ignoreDefault = false; - - try { - if (!m_has_do_melee_skill_attack_dmg) { - return; - } - - lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); - lua_getfield(L, -1, "DoMeleeSkillAttackDmg"); - - 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; - e["weapon_damage"] = weapon_damage; - e["skillinuse"] = (int)skillinuse; - e["chance_mod"] = chance_mod; - e["focus"] = focus; - e["CanRiposte"] = CanRiposte; - e["ReuseTime"] = ReuseTime; - - e.push(L); - - if (lua_pcall(L, 1, 1, 0)) { - std::string error = lua_tostring(L, -1); - parser_->AddError(error); - lua_pop(L, 1); - return; - } - - if (lua_type(L, -1) == LUA_TTABLE) { - luabind::adl::object ret(luabind::from_stack(L, -1)); - auto IgnoreDefaultObj = ret["IgnoreDefault"]; - if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { - ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); - } - } - } - catch (std::exception &ex) { - parser_->AddError(ex.what()); - } - - int end = lua_gettop(L); - int n = end - start; - if (n > 0) { - lua_pop(L, n); - } -} \ No newline at end of file diff --git a/zone/lua_mod.h b/zone/lua_mod.h index 73792e25c..0ed017cdb 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -17,37 +17,20 @@ public: ~LuaMod() { } void Init(); - bool ClientAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); - bool NPCAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); - bool BotAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); - bool CommonAttack(const std::string &fn, Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); 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 DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault); - void DoRangedAttackDmg(Mob *self, Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault); - void DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault); - void DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault); - void DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, - bool &ignoreDefault); + void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); + private: LuaParser *parser_; lua_State *L; std::string package_name_; - bool m_has_client_attack; - bool m_has_npc_attack; - bool m_has_bot_attack; 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_do_special_attack_damage; - bool m_has_do_ranged_attack_dmg; - bool m_has_do_archery_attack_dmg; - bool m_has_do_throwing_attack_dmg; - bool m_has_do_melee_skill_attack_dmg; + bool m_has_try_critical_hit; }; diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 9ed705496..42f9fd556 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -498,6 +498,11 @@ uint8 Lua_NPC::GetMerchantProbability() { return self->GetMerchantProbability(); } +int Lua_NPC::GetRawAC() { + Lua_Safe_Call_Int(); + return self->GetRawAC(); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -598,7 +603,8 @@ 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); } #endif diff --git a/zone/lua_npc.h b/zone/lua_npc.h index e355c3e4d..8e36e29a6 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -125,6 +125,7 @@ public: void MerchantCloseShop(); void SetMerchantProbability(uint8 amt); uint8 GetMerchantProbability(); + int GetRawAC(); }; #endif diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index bcd20f8b8..4aa0e9165 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1055,6 +1055,10 @@ void LuaParser::MapFunctions(lua_State *L) { 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(), @@ -1282,36 +1286,6 @@ QuestEventID LuaParser::ConvertLuaEvent(QuestEventID evt) { #endif -bool LuaParser::ClientAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - bool retval = false; - for (auto &mod : mods_) { - retval = mod.ClientAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - } - - return retval; -} - -bool LuaParser::NPCAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - bool retval = false; - for (auto &mod : mods_) { - retval = mod.NPCAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - } - - return retval; -} - -bool LuaParser::BotAttack(Mob *self, Mob *other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault) -{ - bool retval = false; - for (auto &mod : mods_) { - retval = mod.BotAttack(self, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - } - - return retval; -} - void LuaParser::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { for (auto &mod : mods_) { @@ -1344,40 +1318,9 @@ bool LuaParser::CheckHitChance(Mob *self, Mob *other, DamageHitInfo &hit, bool & return retval; } -void LuaParser::DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault) +void LuaParser::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { for (auto &mod : mods_) { - mod.DoSpecialAttackDamage(self, who, skill, base_damage, min_damage, hate_override, ReuseTime, ignoreDefault); - } -} - -void LuaParser::DoRangedAttackDmg(Mob *self, Mob *other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault) -{ - for (auto &mod : mods_) { - mod.DoRangedAttackDmg(self, other, Launch, damage_mod, chance_mod, skill, speed, IDFile, ignoreDefault); - } -} - -void LuaParser::DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault) -{ - for (auto &mod : mods_) { - mod.DoArcheryAttackDmg(self, other, RangeWeapon, Ammo, weapon_damage, chance_mod, focus, ReuseTime, range_id, ammo_id, AmmoItem, AmmoSlot, speed, ignoreDefault); - } -} - -void LuaParser::DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault) -{ - for (auto &mod : mods_) { - mod.DoThrowingAttackDmg(self, other, RangeWeapon, AmmoItem, weapon_damage, chance_mod, focus, ReuseTime, range_id, AmmoSlot, speed, ignoreDefault); - } -} - -void LuaParser::DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, - int ReuseTime, bool &ignoreDefault) -{ - for (auto &mod : mods_) { - mod.DoMeleeSkillAttackDmg(self, other, weapon_damage, skillinuse, chance_mod, focus, CanRiposte, ReuseTime, ignoreDefault); + mod.TryCriticalHit(self, defender, hit, opts, ignoreDefault); } } diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 0d1f1256c..02519cab5 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -90,21 +90,11 @@ public: bool HasFunction(std::string function, std::string package_name); //Mod Extensions - bool ClientAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); - bool NPCAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); - bool BotAttack(Mob *self, Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, bool IsFromSpell, ExtraAttackOptions *opts, bool &ignoreDefault); 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 DoSpecialAttackDamage(Mob *self, Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime, bool &ignoreDefault); - void DoRangedAttackDmg(Mob *self, Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile, bool &ignoreDefault); - void DoArcheryAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemInstance *Ammo, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, uint32 ammo_id, const EQEmu::ItemData *AmmoItem, int AmmoSlot, float speed, bool &ignoreDefault); - void DoThrowingAttackDmg(Mob *self, Mob *other, const EQEmu::ItemInstance *RangeWeapon, const EQEmu::ItemData *AmmoItem, uint16 weapon_damage, int16 chance_mod, int16 focus, - int ReuseTime, uint32 range_id, int AmmoSlot, float speed, bool &ignoreDefault); - void DoMeleeSkillAttackDmg(Mob *self, Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime, - bool &ignoreDefault); + void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); private: LuaParser(); diff --git a/zone/lua_stat_bonuses.cpp b/zone/lua_stat_bonuses.cpp index 94b63525c..e1fb329cc 100644 --- a/zone/lua_stat_bonuses.cpp +++ b/zone/lua_stat_bonuses.cpp @@ -1078,9 +1078,9 @@ uint32 Lua_StatBonuses::GetSpellOnDeath(int idx) const { return self->SpellOnDeath[idx]; } -int32 Lua_StatBonuses::GetCritDmgMob(int idx) const { +int32 Lua_StatBonuses::GetCritDmgMod(int idx) const { Lua_Safe_Call_Int(); - return self->CritDmgMob[idx]; + return self->CritDmgMod[idx]; } int32 Lua_StatBonuses::GetSkillReuseTime(int idx) const { @@ -1496,7 +1496,7 @@ luabind::scope lua_register_stat_bonuses() { .def("SpellTriggers", &Lua_StatBonuses::GetSpellTriggers) .def("SpellOnKill", &Lua_StatBonuses::GetSpellOnKill) .def("SpellOnDeath", &Lua_StatBonuses::GetSpellOnDeath) - .def("CritDmgMob", &Lua_StatBonuses::GetCritDmgMob) + .def("CritDmgMod", &Lua_StatBonuses::GetCritDmgMod) .def("SkillReuseTime", &Lua_StatBonuses::GetSkillReuseTime) .def("SkillDamageAmount", &Lua_StatBonuses::GetSkillDamageAmount) .def("HPPercCap", &Lua_StatBonuses::GetHPPercCap) diff --git a/zone/lua_stat_bonuses.h b/zone/lua_stat_bonuses.h index 52aa53f8c..9ad04d681 100644 --- a/zone/lua_stat_bonuses.h +++ b/zone/lua_stat_bonuses.h @@ -240,7 +240,7 @@ public: uint32 GetSpellTriggers(int idx) const; uint32 GetSpellOnKill(int idx) const; uint32 GetSpellOnDeath(int idx) const; - int32 GetCritDmgMob(int idx) const; + int32 GetCritDmgMod(int idx) const; int32 GetSkillReuseTime(int idx) const; int32 GetSkillDamageAmount(int idx) const; int GetHPPercCap(int idx) const; diff --git a/zone/mob.cpp b/zone/mob.cpp index ae036398a..cec887797 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -4675,16 +4675,13 @@ bool Mob::TrySpellOnDeath() //in death because the heal will not register before the script kills you. } -int16 Mob::GetCritDmgMob(uint16 skill) +int16 Mob::GetCritDmgMod(uint16 skill) { int critDmg_mod = 0; // All skill dmg mod + Skill specific - critDmg_mod += itembonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMob[EQEmu::skills::HIGHEST_SKILL + 1] + - itembonuses.CritDmgMob[skill] + spellbonuses.CritDmgMob[skill] + aabonuses.CritDmgMob[skill]; - - if(critDmg_mod < -100) - critDmg_mod = -100; + critDmg_mod += itembonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + spellbonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + aabonuses.CritDmgMod[EQEmu::skills::HIGHEST_SKILL + 1] + + itembonuses.CritDmgMod[skill] + spellbonuses.CritDmgMod[skill] + aabonuses.CritDmgMod[skill]; return critDmg_mod; } diff --git a/zone/mob.h b/zone/mob.h index 619b12e5a..f2516b613 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -697,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(); diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index ed3f39074..57ea1c781 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -138,15 +138,6 @@ int Mob::GetBaseSkillDamage(EQEmu::skills::SkillType skill, Mob *target) void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 base_damage, int32 min_damage, int32 hate_override, int ReuseTime) { -#ifdef LUA_EQEMU - bool ignoreDefault = false; - LuaParser::Instance()->DoSpecialAttackDamage(this, who, skill, base_damage, min_damage, hate_override, ReuseTime, ignoreDefault); - - if (ignoreDefault) { - return; - } -#endif - // this really should go through the same code as normal melee damage to // pick up all the special behavior there @@ -768,16 +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) { -#ifdef LUA_EQEMU - bool ignoreDefault = false; - LuaParser::Instance()->DoArcheryAttackDmg(this, other, RangeWeapon, Ammo, weapon_damage, chance_mod, focus, ReuseTime, range_id, ammo_id, AmmoItem, AmmoSlot, speed, ignoreDefault); - - if (ignoreDefault) { - return; - } -#endif - - if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { @@ -1157,15 +1138,6 @@ void NPC::RangedAttack(Mob* other) void NPC::DoRangedAttackDmg(Mob* other, bool Launch, int16 damage_mod, int16 chance_mod, EQEmu::skills::SkillType skill, float speed, const char *IDFile) { -#ifdef LUA_EQEMU - bool ignoreDefault = false; - LuaParser::Instance()->DoRangedAttackDmg(this, other, Launch, damage_mod, chance_mod, skill, speed, IDFile, ignoreDefault); - - if (ignoreDefault) { - return; - } -#endif - if ((other == nullptr || (other->HasDied())) || HasDied() || @@ -1330,15 +1302,6 @@ void Mob::DoThrowingAttackDmg(Mob *other, const EQEmu::ItemInstance *RangeWeapon uint16 weapon_damage, int16 chance_mod, int16 focus, int ReuseTime, uint32 range_id, int AmmoSlot, float speed) { -#ifdef LUA_EQEMU - bool ignoreDefault = false; - LuaParser::Instance()->DoThrowingAttackDmg(this, other, RangeWeapon, AmmoItem, weapon_damage, chance_mod, focus, ReuseTime, range_id, AmmoSlot, speed, ignoreDefault); - - if (ignoreDefault) { - return; - } -#endif - if ((other == nullptr || ((IsClient() && CastToClient()->dead) || (other->IsClient() && other->CastToClient()->dead)) || HasDied() || (!IsAttackAllowed(other)) || (other->GetInvul() || other->GetSpecialAbility(IMMUNE_MELEE)))) { @@ -2123,15 +2086,6 @@ int Mob::TryAssassinate(Mob *defender, EQEmu::skills::SkillType skillInUse) void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills::SkillType skillinuse, int16 chance_mod, int16 focus, bool CanRiposte, int ReuseTime) { -#ifdef LUA_EQEMU - bool ignoreDefault = false; - LuaParser::Instance()->DoMeleeSkillAttackDmg(this, other, weapon_damage, skillinuse, chance_mod, focus, CanRiposte, ReuseTime, ignoreDefault); - - if (ignoreDefault) { - return; - } -#endif - if (!CanDoSpecialAttack(other)) return; From 962fcc2e8aa687a6383d96ca559d6e38b3e51661 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 20:34:15 -0400 Subject: [PATCH 052/218] Modernize Specialization mana savings No idea how it worked in the past, this matches live and our AAs assume we're on new system so fuck the old code. --- zone/effects.cpp | 56 ++++-------------------------------------------- 1 file changed, 4 insertions(+), 52 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 2537751aa..2a1e189ce 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -356,58 +356,10 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) cost -= mana_back; } - // This formula was derived from the following resource: - // http://www.eqsummoners.com/eq1/specialization-library.html - // WildcardX - float PercentManaReduction = 0; - float SpecializeSkill = GetSpecializeSkillValue(spell_id); - int SuccessChance = zone->random.Int(0, 100); - - float bonus = 1.0; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - bonus += 0.05; - break; - case 2: - bonus += 0.15; - break; - case 3: - bonus += 0.30; - break; - } - - bonus += 0.05f * GetAA(aaAdvancedSpellCastingMastery); - - if(SuccessChance <= (SpecializeSkill * 0.3 * bonus)) - { - PercentManaReduction = 1 + 0.05f * SpecializeSkill; - switch(GetAA(aaSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - - switch(GetAA(aaAdvancedSpellCastingMastery)) - { - case 1: - PercentManaReduction += 2.5; - break; - case 2: - PercentManaReduction += 5.0; - break; - case 3: - PercentManaReduction += 10.0; - break; - } - } + int spec = GetSpecializeSkillValue(spell_id); + int PercentManaReduction = 0; + if (spec) + PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); From 7781dc6ffee4dc89eee684209b7caf134f3b51a7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:04:43 -0400 Subject: [PATCH 053/218] Remove double RNG for mana pres This still may not be 100% correct, but it may give us the correct average savings, but for more work than we need to do, but I don't need to rewrite code! Yet. --- zone/effects.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 2a1e189ce..3b19047d8 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -363,11 +363,6 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); - if(focus_redux > 0) - { - PercentManaReduction += zone->random.Real(1, (double)focus_redux); - } - cost -= (cost * (PercentManaReduction / 100)); // Gift of Mana - reduces spell cost to 1 mana From b793f3d9cacdd1bb8ed203dc82918d9e5d27187b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:12:23 -0400 Subject: [PATCH 054/218] Whoops, lets make use of the calced focus effect --- zone/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 3b19047d8..a389a1336 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -361,7 +361,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) if (spec) PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. - int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); + PercentManaReduction += GetFocusEffect(focusManaCost, spell_id); cost -= (cost * (PercentManaReduction / 100)); From c69df293450b66edccf10aa47414f9fd6760db20 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 24 May 2017 22:15:54 -0400 Subject: [PATCH 055/218] Fixed some idiot's mistake --- zone/effects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index a389a1336..135eb3f95 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -361,7 +361,8 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) if (spec) PercentManaReduction = 1 + spec / 20; // there seems to be some non-obvious rounding here, let's truncate for now. - PercentManaReduction += GetFocusEffect(focusManaCost, spell_id); + int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); + PercentManaReduction += focus_redux; cost -= (cost * (PercentManaReduction / 100)); From fd6387c830804ebcf53cb68de99a0298e8512cba Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 25 May 2017 12:45:17 -0400 Subject: [PATCH 056/218] Fix mana pres math --- zone/effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 135eb3f95..8d8265e32 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -364,7 +364,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost) int16 focus_redux = GetFocusEffect(focusManaCost, spell_id); PercentManaReduction += focus_redux; - cost -= (cost * (PercentManaReduction / 100)); + cost -= cost * PercentManaReduction / 100; // Gift of Mana - reduces spell cost to 1 mana if(focus_redux >= 100) { From daced251018691ab66b20fa40826d840c2e71636 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 3 Jun 2017 16:16:05 -0700 Subject: [PATCH 057/218] Add Popup2 .. allows for more customization of the popup window. Using PlayMp3 with the SoundControl option for Popup2 enabled will allow you to adjust sound volume as well. --- common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 1 + common/patches/rof2.cpp | 1 + common/patches/rof2_structs.h | 2 +- common/patches/rof_structs.h | 2 +- common/patches/sod.cpp | 1 + common/patches/sod_structs.h | 2 +- common/patches/uf.cpp | 1 + common/patches/uf_structs.h | 2 +- zone/client.cpp | 40 +++++++++++++++++++++++++++++++++ zone/client.h | 1 + zone/perl_client.cpp | 42 +++++++++++++++++++++++++++++++++++ 12 files changed, 92 insertions(+), 4 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c84c4073a..c234e303a 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1695,6 +1695,7 @@ struct OnLevelMessage_Struct uint32 Duration; uint32 PopupID; uint32 NegativeID; + uint32 SoundControls; char ButtonName0[25]; char ButtonName1[25]; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index e342c5410..23e521a57 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1849,6 +1849,7 @@ namespace RoF eq->Text_Count = 4096; memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index e38fde6f1..5befaf08c 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -1927,6 +1927,7 @@ namespace RoF2 eq->Text_Count = 4096; memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 13befdad9..379941d51 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -2092,7 +2092,7 @@ struct OnLevelMessage_Struct { /*0000*/ uint32 ButtonName1_Count; /*0000*/ char ButtonName1[25]; /*0000*/ uint8 Buttons; -/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint8 SoundControls; // Something to do with audio controls /*0000*/ uint32 Duration; /*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 32c7c0d28..4c73c28d4 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -2122,7 +2122,7 @@ struct OnLevelMessage_Struct { /*0000*/ uint32 ButtonName1_Count; /*0000*/ char ButtonName1[25]; /*0000*/ uint8 Buttons; -/*0000*/ uint8 Unknown4275; // Something to do with audio controls +/*0000*/ uint8 SoundControls; // Something to do with audio controls /*0000*/ uint32 Duration; /*0000*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*0000*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index c68bfacef..f6d85f2bb 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1373,6 +1373,7 @@ namespace SoD memcpy(eq->Title, emu->Title, sizeof(eq->Title)); memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index fdcb03658..ed71d837b 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -1760,7 +1760,7 @@ struct OnLevelMessage_Struct { /*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively /*4249*/ char ButtonName1[25]; /*4274*/ uint8 Buttons; -/*4275*/ uint8 Unknown4275; // Something to do with audio controls +/*4275*/ uint8 SoundControls; // Something to do with audio controls /*4276*/ uint32 Duration; /*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index e2093aef0..b6d251953 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1607,6 +1607,7 @@ namespace UF memcpy(eq->Title, emu->Title, sizeof(eq->Title)); memcpy(eq->Text, emu->Text, sizeof(eq->Text)); OUT(Buttons); + OUT(SoundControls); OUT(Duration); OUT(PopupID); OUT(NegativeID); diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 560a9378d..5a9562117 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -1801,7 +1801,7 @@ struct OnLevelMessage_Struct { /*4224*/ char ButtonName0[25]; // If Buttons = 1, these two are the text for the left and right buttons respectively /*4249*/ char ButtonName1[25]; /*4274*/ uint8 Buttons; -/*4275*/ uint8 Unknown4275; // Something to do with audio controls +/*4275*/ uint8 SoundControls; // Something to do with audio controls /*4276*/ uint32 Duration; /*4280*/ uint32 PopupID; // If none zero, a response packet with 00 00 00 00 is returned on clicking the left button /*4284*/ uint32 NegativeID; // If none zero, a response packet with 01 00 00 00 is returned on clicking the right button diff --git a/zone/client.cpp b/zone/client.cpp index d35308d73..ad8482b46 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3929,6 +3929,46 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup safe_delete(outapp); } +void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Duration, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { + auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); + OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; + + if((strlen(Text) > (sizeof(olms->Text)-1)) || (strlen(Title) > (sizeof(olms->Title) - 1)) ) { + safe_delete(outapp); + return; + } + + if (ButtonName0 && ButtonName1 && ( (strlen(ButtonName0) > (sizeof(olms->ButtonName0) - 1)) || (strlen(ButtonName1) > (sizeof(olms->ButtonName1) - 1)) ) ) { + safe_delete(outapp); + return; + } + + strcpy(olms->Title, Title); + strcpy(olms->Text, Text); + + olms->Buttons = Buttons; + + if (ButtonName0 == NULL || ButtonName1 == NULL) { + sprintf(olms->ButtonName0, "%s", "Yes"); + sprintf(olms->ButtonName1, "%s", "No"); + } else { + strcpy(olms->ButtonName0, ButtonName0); + strcpy(olms->ButtonName1, ButtonName1); + } + + if(Duration > 0) + olms->Duration = Duration * 1000; + else + olms->Duration = 0xffffffff; + + olms->PopupID = PopupID; + olms->NegativeID = NegativeID; + olms->SoundControls = SoundControls; + + QueuePacket(outapp); + safe_delete(outapp); +} + void Client::SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...) { va_list argptr; char buffer[4096]; diff --git a/zone/client.h b/zone/client.h index 19dc4c05b..9ff541edc 100644 --- a/zone/client.h +++ b/zone/client.h @@ -945,6 +945,7 @@ public: inline bool HasSpellScribed(int spellid) { return (FindSpellBookSlotBySpellID(spellid) != -1 ? true : false); } uint16 GetMaxSkillAfterSpecializationRules(EQEmu::skills::SkillType skillid, uint16 maxSkill); void SendPopupToClient(const char *Title, const char *Text, uint32 PopupID = 0, uint32 Buttons = 0, uint32 Duration = 0); + void SendFullPopup(const char *Title, const char *Text, uint32 PopupID = 0, uint32 NegativeID = 0, uint32 Buttons = 0, uint32 Duration = 0, const char *ButtonName0 = 0, const char *ButtonName1 = 0, uint32 SoundControls = 0); void SendWindow(uint32 PopupID, uint32 NegativeID, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 Duration, int title_type, Client* target, const char *Title, const char *Text, ...); bool PendingTranslocate; time_t TranslocateTime; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 46746970c..77fb0877b 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6444,6 +6444,47 @@ XS(XS_Client_GetAccountAge) { XSRETURN(1); } +XS(XS_Client_Popup2); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_Popup2) +{ + dXSARGS; + if (items < 3 || items > 10) + Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls)"); + { + Client * THIS; + char* Title = (char *)SvPV_nolen(ST(1)); + char* Text = (char *)SvPV_nolen(ST(2)); + uint32 PopupID = 0; + uint32 NegativeID = 0; + uint32 Duration = 0; + uint32 Buttons = 0; + char* ButtonName0 = 0; + char* ButtonName1 = 0; + uint32 SoundControls = 0; + + if (sv_derived_from(ST(0), "Client")) { + IV tmp = SvIV((SV*)SvRV(ST(0))); + THIS = INT2PTR(Client *,tmp); + } + else + Perl_croak(aTHX_ "THIS is not of type Client"); + if(THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + if (items > 3) { PopupID = (uint32)SvUV(ST(3)); } + if (items > 4) { NegativeID = (uint32)SvUV(ST(4)); } + if (items > 5) { Duration = (uint32)SvUV(ST(5)); } + if (items > 6) { Buttons = (uint32)SvUV(ST(6)); } + if (items > 7) { ButtonName0 = (char *)SvPV_nolen(ST(7)); } + if (items > 8) { ButtonName1 = (char *)SvPV_nolen(ST(8)); } + if (items > 9) { SoundControls = (uint32)SvUV(ST(9)); } + + + THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls); + } + XSRETURN_EMPTY; +} + #ifdef __cplusplus extern "C" @@ -6698,6 +6739,7 @@ XS(boot_Client) newXSproto(strcpy(buf, "CalcEXP"), XS_Client_CalcEXP, file, "$"); newXSproto(strcpy(buf, "GetMoney"), XS_Client_GetMoney, file, "$$$"); newXSproto(strcpy(buf, "GetAccountAge"), XS_Client_GetAccountAge, file, "$"); + newXSproto(strcpy(buf, "Popup2"), XS_Client_Popup2, file, "$$$;$$$$$$$"); XSRETURN_YES; } From decaa1f7b66967bb293cd6ec2f733f29a11d5ba0 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Sat, 3 Jun 2017 16:35:30 -0700 Subject: [PATCH 058/218] Fix mismatch on Popup2 for Buttons / Duration (oops) $client->Popup2("Title", "Text", YesID, NoID, Buttons, Duration, Button0, Button1); YesID / NoID are the "popupid" for EVENT_POPUPRESPONSE depending on the players choice --- zone/client.cpp | 2 +- zone/perl_client.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index ad8482b46..5f35c6916 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -3929,7 +3929,7 @@ void Client::SendPopupToClient(const char *Title, const char *Text, uint32 Popup safe_delete(outapp); } -void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Duration, uint32 Buttons, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { +void Client::SendFullPopup(const char *Title, const char *Text, uint32 PopupID, uint32 NegativeID, uint32 Buttons, uint32 Duration, const char *ButtonName0, const char *ButtonName1, uint32 SoundControls) { auto outapp = new EQApplicationPacket(OP_OnLevelMessage, sizeof(OnLevelMessage_Struct)); OnLevelMessage_Struct *olms = (OnLevelMessage_Struct *)outapp->pBuffer; diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 77fb0877b..622551ce0 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -6449,15 +6449,15 @@ XS(XS_Client_Popup2) { dXSARGS; if (items < 3 || items > 10) - Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls)"); + Perl_croak(aTHX_ "Usage: Client::SendFullPopup(THIS, Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls)"); { Client * THIS; char* Title = (char *)SvPV_nolen(ST(1)); char* Text = (char *)SvPV_nolen(ST(2)); uint32 PopupID = 0; uint32 NegativeID = 0; - uint32 Duration = 0; uint32 Buttons = 0; + uint32 Duration = 0; char* ButtonName0 = 0; char* ButtonName1 = 0; uint32 SoundControls = 0; @@ -6473,14 +6473,14 @@ XS(XS_Client_Popup2) if (items > 3) { PopupID = (uint32)SvUV(ST(3)); } if (items > 4) { NegativeID = (uint32)SvUV(ST(4)); } - if (items > 5) { Duration = (uint32)SvUV(ST(5)); } - if (items > 6) { Buttons = (uint32)SvUV(ST(6)); } + if (items > 5) { Buttons = (uint32)SvUV(ST(5)); } + if (items > 6) { Duration = (uint32)SvUV(ST(6)); } if (items > 7) { ButtonName0 = (char *)SvPV_nolen(ST(7)); } if (items > 8) { ButtonName1 = (char *)SvPV_nolen(ST(8)); } if (items > 9) { SoundControls = (uint32)SvUV(ST(9)); } - THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Duration, Buttons, ButtonName0, ButtonName1, SoundControls); + THIS->SendFullPopup(Title, Text, PopupID, NegativeID, Buttons, Duration, ButtonName0, ButtonName1, SoundControls); } XSRETURN_EMPTY; } From c25a5fa0ba22b5904fbb34c105913e5191f6b6d4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 8 Jun 2017 00:54:22 -0400 Subject: [PATCH 059/218] AC/ACv2 negative affects don't affect stacking fixes #622 Unsure if these are the only SPAs that should act this way, but this resolves the issues we were seeing --- zone/spells.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/zone/spells.cpp b/zone/spells.cpp index 2be0a0bce..ef0553526 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3059,6 +3059,12 @@ int Mob::CheckStackConflict(uint16 spellid1, int caster_level1, uint16 spellid2, if (IsEffectIgnoredInStacking(effect1)) continue; + // negative AC affects are skipped. Ex. Sun's Corona and Glacier Breath should stack + // There may be more SPAs we need to add here .... + // The client does just check base rather than calculating the affect change value. + if ((effect1 == SE_ArmorClass || effect1 == SE_ACv2) && sp2.base[i] < 0) + continue; + /* If target is a npc and caster1 and caster2 exist If Caster1 isn't the same as Caster2 and the effect is a DoT then ignore it. From d6890ad76d86382f83569cabc03b5c923c1aba0f Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 8 Jun 2017 19:55:25 -0700 Subject: [PATCH 060/218] More changes --- zone/attack.cpp | 2 +- zone/lua_general.cpp | 2 +- zone/lua_npc.cpp | 9 ++++++++- zone/lua_npc.h | 1 + 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 9a210236c..2b5fb4a34 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4301,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); } diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 06e09f1a1..a07db54fb 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1691,7 +1691,7 @@ luabind::scope lua_register_random() { luabind::def("Int", &random_int), luabind::def("Real", &random_real), luabind::def("Roll", &random_roll_int), - luabind::def("Roll", &random_roll_real), + luabind::def("RollReal", &random_roll_real), luabind::def("Roll0", &random_roll0) ]; } diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index 42f9fd556..50ff597f6 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -503,6 +503,12 @@ int Lua_NPC::GetRawAC() { return self->GetRawAC(); } +int Lua_NPC::GetAvoidanceRating() +{ + Lua_Safe_Call_Int(); + return self->GetAvoidanceRating(); +} + luabind::scope lua_register_npc() { return luabind::class_("NPC") .def(luabind::constructor<>()) @@ -604,7 +610,8 @@ luabind::scope lua_register_npc() { .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("GetRawAC", (int(Lua_NPC::*)(void))&Lua_NPC::GetRawAC); + .def("GetRawAC", (int(Lua_NPC::*)(void))&Lua_NPC::GetRawAC) + .def("GetAvoidanceRating", &Lua_NPC::GetAvoidanceRating); } #endif diff --git a/zone/lua_npc.h b/zone/lua_npc.h index 8e36e29a6..d3d673641 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -126,6 +126,7 @@ public: void SetMerchantProbability(uint8 amt); uint8 GetMerchantProbability(); int GetRawAC(); + int GetAvoidanceRating(); }; #endif From c83810be363aa9ac63457ba0efd6e05d5df12ba5 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 8 Jun 2017 20:11:20 -0700 Subject: [PATCH 061/218] Add combat mod example implementation --- .gitignore | 2 + utils/mods/legacy_combat.lua | 732 +++++++++++++++++++++++++++++++++++ utils/mods/load_order.txt | 1 + 3 files changed, 735 insertions(+) create mode 100644 utils/mods/legacy_combat.lua create mode 100644 utils/mods/load_order.txt diff --git a/.gitignore b/.gitignore index 52dbcb224..805c783a4 100644 --- a/.gitignore +++ b/.gitignore @@ -33,5 +33,7 @@ Build_32/ build_32/ Build_64/ build_64/ +x64/ +x86/ log/ logs/ diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua new file mode 100644 index 000000000..a0e936d7f --- /dev/null +++ b/utils/mods/legacy_combat.lua @@ -0,0 +1,732 @@ +SoftcapFactor = 1.88; +MonkACBonusWeight = 15; +NPCACFactor = 2.25; +OldACSoftcapRules = false; +ClothACSoftcap = 75; +LeatherACSoftcap = 100; +MonkACSoftcap = 120; +ChainACSoftcap = 200; +PlateACSoftcap = 300; +AAMitigationACFactor = 3.0; +WarriorACSoftcapReturn = 0.45; +KnightACSoftcapReturn = 0.33; +LowPlateChainACSoftcapReturn = 0.23; +LowChainLeatherACSoftcapReturn = 0.17; +CasterACSoftcapReturn = 0.06; +MiscACSoftcapReturn = 0.3; +WarACSoftcapReturn = 0.3448; +ClrRngMnkBrdACSoftcapReturn = 0.3030; +PalShdACSoftcapReturn = 0.3226; +DruNecWizEncMagACSoftcapReturn = 0.2000; +RogShmBstBerACSoftcapReturn = 0.2500; +SoftcapFactor = 1.88; +ACthac0Factor = 0.55; +ACthac20Factor = 0.55; + +MeleeBaseCritChance = 0.0; +ClientBaseCritChance = 0.0; +BerserkBaseCritChance = 6.0; +WarBerBaseCritChance = 3.0; +RogueCritThrowingChance = 25; +RogueDeadlyStrikeChance = 80; +RogueDeadlyStrikeMod = 2; + +BaseHitChance = 69.0; +NPCBonusHitChance = 26.0; +HitFalloffMinor = 5.0; +HitFalloffModerate = 7.0; +HitFalloffMajor = 50.0; +HitBonusPerLevel = 1.2; +AgiHitFactor = 0.01; +WeaponSkillFalloff = 0.33; +ArcheryHitPenalty = 0.25; + +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, 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, 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(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 diff --git a/utils/mods/load_order.txt b/utils/mods/load_order.txt new file mode 100644 index 000000000..979674adb --- /dev/null +++ b/utils/mods/load_order.txt @@ -0,0 +1 @@ +legacy_combat.lua From 7c377e8904f5a8d7de1fdd0477dd950dafa8e6cf Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 10 Jun 2017 11:25:09 -0400 Subject: [PATCH 062/218] Fix typo on database call in #object. Fix issue with fishing.. Search needs to search from my z for full line length not for only the diff between my feet and the possible water location. --- zone/command.cpp | 6 +++--- zone/forage.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zone/command.cpp b/zone/command.cpp index afaa493ea..bef50e184 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -8746,9 +8746,9 @@ void command_object(Client *c, const Seperator *sep) // Verify no other objects already in this spot (accidental double-click of Hotkey?) query = StringFormat( "SELECT COUNT(*) FROM object WHERE zoneid = %u " - "AND version=%u AND (posx BETWEEN %.1f AND %.1f) " - "AND (posy BETWEEN %.1f AND %.1f) " - "AND (posz BETWEEN %.1f AND %.1f)", + "AND version=%u AND (xpos BETWEEN %.1f AND %.1f) " + "AND (ypos BETWEEN %.1f AND %.1f) " + "AND (zpos BETWEEN %.1f AND %.1f)", zone->GetZoneID(), zone->GetInstanceVersion(), od.x - 0.2f, od.x + 0.2f, // Yes, we're actually using a bounding box instead of a radius. od.y - 0.2f, od.y + 0.2f, // Much less processing power used this way. diff --git a/zone/forage.cpp b/zone/forage.cpp index 5d21d599f..be93d39ae 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -196,7 +196,7 @@ bool Client::CanFish() { float step_size = RuleR(Watermap, FishingLineStepSize); - for(float i = 0.0f; i < len; i += step_size) { + for(float i = 0.0f; i < LineLength; i += step_size) { glm::vec3 dest(rodPosition.x, rodPosition.y, m_Position.z - i); bool in_lava = zone->watermap->InLava(dest); From 31d8336b4b21baa7af95c6f7d060a24ef62703a6 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 10 Jun 2017 15:12:31 -0700 Subject: [PATCH 063/218] Fix acceptmessages, added exp hooks to luamods --- common/net/console_server.cpp | 17 +++ common/net/console_server.h | 3 +- common/net/console_server_connection.cpp | 49 +++++++ common/net/console_server_connection.h | 3 + utils/mods/classic_wow_experience.lua | 159 ++++++++++++++++++++++ world/net.cpp | 4 +- world/zoneserver.cpp | 39 +++++- world/zoneserver.h | 4 +- zone/aa.cpp | 2 +- zone/attack.cpp | 2 +- zone/client.h | 4 +- zone/client_packet.cpp | 3 +- zone/exp.cpp | 54 +++++++- zone/lua_mod.cpp | 163 ++++++++++++++++++++++- zone/lua_mod.h | 7 +- zone/lua_parser.cpp | 34 +++++ zone/lua_parser.h | 3 + 17 files changed, 530 insertions(+), 20 deletions(-) create mode 100644 utils/mods/classic_wow_experience.lua diff --git a/common/net/console_server.cpp b/common/net/console_server.cpp index d8f08b05d..ab420bd42 100644 --- a/common/net/console_server.cpp +++ b/common/net/console_server.cpp @@ -25,6 +25,23 @@ void EQ::Net::ConsoleServer::RegisterLogin(ConsoleServerLoginCallback fn) m_login = fn; } +EQ::Net::ConsoleServerConnection *EQ::Net::ConsoleServer::FindByAccountName(const std::string &acct_name) { + for (auto &iter : m_connections) { + if (iter.second->UserName().compare(acct_name) == 0) { + return iter.second.get(); + } + } + + return nullptr; +} + + +void EQ::Net::ConsoleServer::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell) { + for (auto &iter : m_connections) { + iter.second->SendChannelMessage(scm, onTell); + } +} + void EQ::Net::ConsoleServer::ConnectionDisconnected(ConsoleServerConnection *c) { auto iter = m_connections.find(c->GetUUID()); diff --git a/common/net/console_server.h b/common/net/console_server.h index 5a0c48f8e..d28f43844 100644 --- a/common/net/console_server.h +++ b/common/net/console_server.h @@ -25,7 +25,8 @@ namespace EQ void RegisterCall(const std::string& command, int status_required, const std::string& help_definition, ConsoleServerCallback fn); void RegisterLogin(ConsoleServerLoginCallback fn); - + ConsoleServerConnection *FindByAccountName(const std::string &acct_name); + void SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell); private: void ConnectionDisconnected(ConsoleServerConnection *c); void ProcessCommand(ConsoleServerConnection *c, const std::string& cmd); diff --git a/common/net/console_server_connection.cpp b/common/net/console_server_connection.cpp index 8764f09b6..249817818 100644 --- a/common/net/console_server_connection.cpp +++ b/common/net/console_server_connection.cpp @@ -2,6 +2,8 @@ #include "../common/util/uuid.h" #include "../common/net/packet.h" #include "../common/eqemu_logsys.h" +#include "../common/servertalk.h" +#include "../common/rulesys.h" EQ::Net::ConsoleServerConnection::ConsoleServerConnection(ConsoleServer *parent, std::shared_ptr connection) { @@ -107,6 +109,53 @@ void EQ::Net::ConsoleServerConnection::QueueMessage(const std::string &msg) } } +bool EQ::Net::ConsoleServerConnection::SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell) { + if (!m_accept_messages) { + return false; + } + + switch (scm->chan_num) { + if (RuleB(Chat, ServerWideAuction)) { + case 4: { + QueueMessage(fmt::format("{0} auctions, '{1}'", scm->from, scm->message)); + break; + } + } + + if (RuleB(Chat, ServerWideOOC)) { + case 5: { + QueueMessage(fmt::format("{0} says ooc, '{1}'", scm->from, scm->message)); + break; + } + } + + case 6: { + QueueMessage(fmt::format("{0} BROADCASTS, '{1}'", scm->from, scm->message)); + break; + } + + case 7: { + QueueMessage(fmt::format("[{0}] tells you, '{1}'", scm->from, scm->message)); + if (onTell) { + onTell(); + } + + break; + } + + case 11: { + QueueMessage(fmt::format("{0} GMSAYS, '{1}'", scm->from, scm->message)); + break; + } + + default: { + return false; + } + } + + return true; +} + void EQ::Net::ConsoleServerConnection::OnRead(TCPConnection *c, const unsigned char *data, size_t sz) { for (size_t i = 0; i < sz; ++i) { diff --git a/common/net/console_server_connection.h b/common/net/console_server_connection.h index d826ba07b..a49700841 100644 --- a/common/net/console_server_connection.h +++ b/common/net/console_server_connection.h @@ -4,6 +4,8 @@ #include #include +struct ServerChannelMessage_Struct; + namespace EQ { namespace Net @@ -42,6 +44,7 @@ namespace EQ bool AcceptMessages() const { return m_accept_messages; } void SetAcceptMessages(bool v) { m_accept_messages = v; } void QueueMessage(const std::string &msg); + bool SendChannelMessage(const ServerChannelMessage_Struct* scm, std::function onTell); private: void OnRead(TCPConnection* c, const unsigned char* data, size_t sz); void OnDisconnect(TCPConnection* c); diff --git a/utils/mods/classic_wow_experience.lua b/utils/mods/classic_wow_experience.lua new file mode 100644 index 000000000..cde740ff6 --- /dev/null +++ b/utils/mods/classic_wow_experience.lua @@ -0,0 +1,159 @@ +--Mod file to demo changing the experience tables +--In this case I used some old wow tables (roughly it's not 100%) + +function GetRequiredAAExperience(e) + e.level = 51; + return GetEXPForLevel(e); +end + +function GetExperienceForKill(e) + local ML = e.other:GetLevel(); + local CL = e.self:GetLevel(); + + if(ML > CL) then + local lmod = (ML - CL) * 0.05; + if(lmod > 1.0) then + lmod = 1.0; + end + e.ReturnValue = BaseXP(ML) * (1 + lmod); + elseif(ML < CL) then + local lmod = (CL - ML) * 0.05; + if(lmod > 1.0) then + lmod = 1.0; + end + e.ReturnValue = BaseXP(ML) * (1 - lmod); + else + e.ReturnValue = BaseXP(ML); + end + + e.IgnoreDefault = true; + return e; +end + +function BaseXP(L) + local base = L * 5; + + if(L < 60) then + base = base + 45; + elseif(L < 70) then + base = base + 235; + elseif(L < 80) then + base = base + 580; + else + base = base + 1875; + end + + return base; +end + +function GetEXPForLevel(e) + local exp_table = { + 0, + 400, + 900, + 1400, + 2100, + 2800, + 3600, + 4500, + 5400, + 6500, + 7600, + 8700, + 9800, + 11000, + 12300, + 13600, + 15000, + 16400, + 17800, + 19300, + 20800, + 22400, + 24000, + 25500, + 27200, + 28900, + 30500, + 32200, + 33900, + 36300, + 38800, + 41600, + 44600, + 48000, + 51400, + 55000, + 58700, + 62400, + 66200, + 70200, + 74300, + 78500, + 82800, + 87100, + 91600, + 96300, + 101000, + 105800, + 110700, + 115700, + 120900, + 126100, + 131500, + 137000, + 142500, + 148200, + 154000, + 159900, + 165800, + 172000, + 290000, + 317000, + 349000, + 386000, + 428000, + 475000, + 527000, + 585000, + 648000, + 717000, + 1523800, + 1539000, + 1555700, + 1571800, + 1587900, + 1604200, + 1620700, + 1637400, + 1653900, + 1670800, + 1670800, + 1670800, + 2121500, + 2669000, + 3469000, + 4583000, + 13000000, + 15080000, + 22600000, + 27300000, + 32800000 + }; + + if(e.level < 1) then + e.ReturnValue = 0; + e.IgnoreDefault = true; + return e; + end + + if(e.level > 91) then + e.ReturnValue = exp_table[91]; + e.IgnoreDefault = true; + return e; + end + + e.ReturnValue = exp_table[e.level]; + e.IgnoreDefault = true; + return e; +end diff --git a/world/net.cpp b/world/net.cpp index df3749829..09511c3f2 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -392,12 +392,12 @@ int main(int argc, char** argv) { server_connection->Listen(server_opts); Log(Logs::General, Logs::World_Server, "Server (TCP) listener started."); - server_connection->OnConnectionIdentified("Zone", [](std::shared_ptr connection) { + server_connection->OnConnectionIdentified("Zone", [&console](std::shared_ptr connection) { LogF(Logs::General, Logs::World_Server, "New Zone Server connection from {2} at {0}:{1}", connection->Handle()->RemoteIP(), connection->Handle()->RemotePort(), connection->GetUUID()); numzones++; - zoneserver_list.Add(new ZoneServer(connection)); + zoneserver_list.Add(new ZoneServer(connection, console.get())); }); server_connection->OnConnectionRemoved("Zone", [](std::shared_ptr connection) { diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index a3fc7da7f..01cca7557 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -46,7 +46,7 @@ extern UCSConnection UCSLink; extern QueryServConnection QSLink; void CatchSignal(int sig_num); -ZoneServer::ZoneServer(std::shared_ptr connection) +ZoneServer::ZoneServer(std::shared_ptr connection, EQ::Net::ConsoleServer *console) : tcpc(connection), zone_boot_timer(5000) { /* Set Process tracking variable defaults */ @@ -73,6 +73,8 @@ ZoneServer::ZoneServer(std::shared_ptr conn zone_boot_timer.Disable(); } })); + + this->console = console; } ZoneServer::~ZoneServer() { @@ -412,6 +414,27 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { break; } if (scm->chan_num == 7 || scm->chan_num == 14) { + if (scm->deliverto[0] == '*') { + + if (console) { + auto con = console->FindByAccountName(&scm->deliverto[1]); + if (((!con) || (!con->SendChannelMessage(scm, [&scm]() { + auto pack = new ServerPacket(ServerOP_ChannelMessage, + sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); + memcpy(pack->pBuffer, scm, pack->size); + ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer; + strcpy(scm2->deliverto, scm2->from); + scm2->noreply = true; + client_list.SendPacket(scm->from, pack); + safe_delete(pack); + }))) && (!scm->noreply)) + { + zoneserver_list.SendEmoteMessage(scm->from, 0, 0, 0, "%s is not online at this time.", scm->to); + } + } + break; + } + ClientListEntry* cle = client_list.FindCharacter(scm->deliverto); if (cle == 0 || cle->Online() < CLE_Status_Zoning || (cle->TellsOff() && ((cle->Anon() == 1 && scm->fromadmin < cle->Admin()) || scm->fromadmin < 80))) { @@ -462,6 +485,20 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { cle->Server()->SendPacket(pack); } else { + if (scm->chan_num == 5 || scm->chan_num == 6 || scm->chan_num == 11) { + if (console) { + console->SendChannelMessage(scm, [&scm]() { + auto pack = new ServerPacket(ServerOP_ChannelMessage, + sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1); + memcpy(pack->pBuffer, scm, pack->size); + ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*)pack->pBuffer; + strcpy(scm2->deliverto, scm2->from); + scm2->noreply = true; + client_list.SendPacket(scm->from, pack); + safe_delete(pack); + }); + } + } zoneserver_list.SendPacket(pack); } break; diff --git a/world/zoneserver.h b/world/zoneserver.h index a6bbc8373..1f9e9516c 100644 --- a/world/zoneserver.h +++ b/world/zoneserver.h @@ -22,6 +22,7 @@ #include "../net/servertalk_server.h" #include "../event/timer.h" #include "../timer.h" +#include "console.h" #include #include @@ -31,7 +32,7 @@ class ServerPacket; class ZoneServer : public WorldTCPConnection { public: - ZoneServer(std::shared_ptr connection); + ZoneServer(std::shared_ptr connection, EQ::Net::ConsoleServer *console); ~ZoneServer(); virtual inline bool IsZoneServer() { return true; } @@ -97,6 +98,7 @@ private: uint32 zone_os_process_id; std::string launcher_name; //the launcher which started us std::string launched_name; //the name of the zone we launched. + EQ::Net::ConsoleServer *console; }; #endif diff --git a/zone/aa.cpp b/zone/aa.cpp index 51cb376da..31ad9c162 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -916,7 +916,7 @@ void Client::SendAlternateAdvancementRank(int aa_id, int level) { void Client::SendAlternateAdvancementStats() { auto outapp = new EQApplicationPacket(OP_AAExpUpdate, sizeof(AltAdvStats_Struct)); AltAdvStats_Struct *aps = (AltAdvStats_Struct *)outapp->pBuffer; - aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)max_AAXP); + aps->experience = (uint32)(((float)330.0f * (float)m_pp.expAA) / (float)GetRequiredAAExperience()); aps->unspent = m_pp.aapoints; aps->percentage = m_epp.perAA; QueuePacket(outapp); diff --git a/zone/attack.cpp b/zone/attack.cpp index 2b5fb4a34..1f7738119 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2222,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) { diff --git a/zone/client.h b/zone/client.h index 0f0f90873..50f36ba72 100644 --- a/zone/client.h +++ b/zone/client.h @@ -571,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); @@ -796,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); @@ -1493,7 +1494,6 @@ private: uint32 tribute_master_id; - uint32 max_AAXP; bool npcflag; uint8 npclevel; bool feigned; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 361c67d40..9249f5266 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1355,8 +1355,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) /* Set Total Seconds Played */ TotalSecondsPlayed = m_pp.timePlayedMin * 60; - /* Set Max AA XP */ - max_AAXP = RuleI(AA, ExpPerPoint); + /* If we can maintain intoxication across zones, check for it */ if (!RuleB(Character, MaintainIntoxicationAcrossZones)) m_pp.intoxication = 0; diff --git a/zone/exp.cpp b/zone/exp.cpp index 044a102e0..fe2cfd543 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -28,6 +28,7 @@ #include "queryserv.h" #include "quest_parser_collection.h" +#include "lua_parser.h" #include "string_ids.h" #ifdef BOTS @@ -153,6 +154,26 @@ uint32 Client::CalcEXP(uint8 conlevel) { return in_add_exp; } +uint32 Client::GetExperienceForKill(Mob *against) +{ +#ifdef LUA_EQEMU + uint32 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->GetExperienceForKill(this, against, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + + if (against && against->IsNPC()) { + uint32 level = (uint32)against->GetLevel(); + return EXP_FORMULA; + } + + return 0; +} + void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { this->EVENT_ITEM_ScriptStopReturn(); @@ -339,8 +360,8 @@ void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { void Client::SetEXP(uint32 set_exp, uint32 set_aaxp, bool isrezzexp) { Log(Logs::Detail, Logs::None, "Attempting to Set Exp for %s (XP: %u, AAXP: %u, Rez: %s)", this->GetCleanName(), set_exp, set_aaxp, isrezzexp ? "true" : "false"); - //max_AAXP = GetEXPForLevel(52) - GetEXPForLevel(51); //GetEXPForLevel() doesn't depend on class/race, just level, so it shouldn't change between Clients - max_AAXP = RuleI(AA, ExpPerPoint); //this may be redundant since we're doing this in Client::FinishConnState2() + + auto max_AAXP = GetRequiredAAExperience(); if (max_AAXP == 0 || GetEXPForLevel(GetLevel()) == 0xFFFFFFFF) { Message(13, "Error in Client::SetEXP. EXP not set."); return; // Must be invalid class/race @@ -460,14 +481,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 +591,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 +683,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 +961,17 @@ uint32 Client::GetCharMaxLevelFromQGlobal() { return false; } + +uint32 Client::GetRequiredAAExperience() { +#ifdef LUA_EQEMU + uint32 lua_ret = 0; + bool ignoreDefault = false; + lua_ret = LuaParser::Instance()->GetRequiredAAExperience(this, ignoreDefault); + + if (ignoreDefault) { + return lua_ret; + } +#endif + + return RuleI(AA, ExpPerPoint); +} diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index f35992d94..1a97945a5 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -39,6 +39,9 @@ void LuaMod::Init() 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_); } void PutDamageHitInfo(lua_State *L, luabind::adl::object &e, DamageHitInfo &hit) { @@ -388,8 +391,6 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign return retval; } -//void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); - void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); ignoreDefault = false; @@ -440,3 +441,161 @@ void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraA lua_pop(L, n); } } + +uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + uint32 retval = 0; + + try { + if (!m_has_get_required_aa_experience) { + return retval; + } + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + retval = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { + int start = lua_gettop(L); + ignoreDefault = false; + uint32 retval = 0; + + try { + if (!m_has_get_exp_for_level) { + return retval; + } + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + retval = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} + +uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + uint32 retval = 0; + + try { + if (!m_has_get_experience_for_kill) { + return retval; + } + + 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 retval; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + auto returnValueObj = ret["ReturnValue"]; + if (luabind::type(returnValueObj) == LUA_TNUMBER) { + retval = luabind::object_cast(returnValueObj); + } + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } + + return retval; +} diff --git a/zone/lua_mod.h b/zone/lua_mod.h index 0ed017cdb..bef40bbcc 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -22,7 +22,9 @@ public: 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); - + uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); + uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); + uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault); private: LuaParser *parser_; lua_State *L; @@ -33,4 +35,7 @@ private: bool m_has_avoid_damage; bool m_has_check_hit_chance; bool m_has_try_critical_hit; + bool m_has_get_required_aa_experience; + bool m_has_get_exp_for_level; + bool m_has_get_experience_for_kill; }; diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 4aa0e9165..f77ccb4da 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -959,6 +959,13 @@ void LuaParser::ReloadQuests() { if (load_order) { char file_name[256] = { 0 }; while (fgets(file_name, 256, load_order) != nullptr) { + for (int i = 0; i < 256; ++i) { + if (file_name[i] == '\n') { + file_name[i] = 0; + break; + } + } + LoadScript("mods/" + std::string(file_name), file_name); mods_.push_back(LuaMod(L, this, file_name)); } @@ -1324,3 +1331,30 @@ void LuaParser::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, Ext mod.TryCriticalHit(self, defender, hit, opts, ignoreDefault); } } + +uint32 LuaParser::GetRequiredAAExperience(Client *self, bool &ignoreDefault) +{ + uint32 retval = false; + for (auto &mod : mods_) { + retval = mod.GetRequiredAAExperience(self, ignoreDefault); + } + return retval; +} + +uint32 LuaParser::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) +{ + uint32 retval = false; + for (auto &mod : mods_) { + retval = mod.GetEXPForLevel(self, level, ignoreDefault); + } + return retval; +} + +uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) +{ + uint32 retval = false; + for (auto &mod : mods_) { + retval = mod.GetExperienceForKill(self, against, ignoreDefault); + } + return retval; +} diff --git a/zone/lua_parser.h b/zone/lua_parser.h index 02519cab5..f99553ccc 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -95,6 +95,9 @@ public: 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); + uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); + uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); + uint32 GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault); private: LuaParser(); From 6575d106de2a228438e65c900769750c93f4ada2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 10 Jun 2017 19:17:05 -0700 Subject: [PATCH 064/218] Fix bug in critical hit for pets --- utils/mods/legacy_combat.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index a0e936d7f..6ce193c7d 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -363,7 +363,7 @@ function TryPetCriticalHit(self, defender, hit) end local CritPetChance = owner:GetAABonuses():PetCriticalHit() + owner:GetItemBonuses():PetCriticalHit() + owner:GetSpellBonuses():PetCriticalHit(); - local CritChanceBonus = GetCriticalChanceBonus(self, skill); + local CritChanceBonus = GetCriticalChanceBonus(self, hit.skill); if (CritPetChance or critChance) then critChance = critChance + CritPetChance; @@ -375,7 +375,7 @@ function TryPetCriticalHit(self, defender, hit) if(Random.RollReal(critChance)) then local entity_list = eq.get_entity_list(); - critMod = critMod + GetCritDmgMob(self, skill) * 2; + 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)', From d64f2e40c5c8017a182bae51bd13d7e36c2b64b4 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sun, 4 Jun 2017 19:57:21 -0400 Subject: [PATCH 065/218] Implement EVENT_USE_SKILL in Perl/Lua. - Exports skill_id and skill_level in Perl/Lua whenever a skill is used (bash, kick, taunt, etc.) --- zone/client.cpp | 4 +++- zone/embparser.cpp | 7 +++++++ zone/event_codes.h | 1 + zone/lua_general.cpp | 3 ++- zone/lua_parser.cpp | 4 +++- zone/lua_parser_events.cpp | 9 +++++++++ zone/lua_parser_events.h | 2 ++ 7 files changed, 27 insertions(+), 3 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 5f35c6916..741b41e72 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2337,7 +2337,9 @@ bool Client::CheckIncreaseSkill(EQEmu::skills::SkillType skillid, Mob *against_w return false; int skillval = GetRawSkill(skillid); int maxskill = GetMaxSkillAfterSpecializationRules(skillid, MaxSkill(skillid)); - + char buffer[24] = { 0 }; + snprintf(buffer, 23, "%d %d", skillid, skillval); + parse->EventPlayer(EVENT_USE_SKILL, this, buffer, 0); if(against_who) { if(against_who->GetSpecialAbility(IMMUNE_AGGRO) || against_who->IsClient() || diff --git a/zone/embparser.cpp b/zone/embparser.cpp index f76c2ea6a..80f6ace11 100644 --- a/zone/embparser.cpp +++ b/zone/embparser.cpp @@ -117,6 +117,7 @@ const char *QuestEventSubroutines[_LargestEventID] = { "EVENT_TICK", "EVENT_SPAWN_ZONE", "EVENT_DEATH_ZONE", + "EVENT_USE_SKILL", }; PerlembParser::PerlembParser() : perl(nullptr) { @@ -1441,6 +1442,12 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID ExportVar(package_name.c_str(), "killed_npc_id", sep.arg[4]); break; } + case EVENT_USE_SKILL:{ + Seperator sep(data); + ExportVar(package_name.c_str(), "skill_id", sep.arg[0]); + ExportVar(package_name.c_str(), "skill_level", sep.arg[1]); + break; + } default: { break; diff --git a/zone/event_codes.h b/zone/event_codes.h index 1b0e18505..bb623f041 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -85,6 +85,7 @@ typedef enum { EVENT_TICK, EVENT_SPAWN_ZONE, EVENT_DEATH_ZONE, + EVENT_USE_SKILL, _LargestEventID } QuestEventID; diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index bc6205c85..1d71fd2f3 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -1738,7 +1738,8 @@ luabind::scope lua_register_events() { luabind::value("unhandled_opcode", static_cast(EVENT_UNHANDLED_OPCODE)), luabind::value("tick", static_cast(EVENT_TICK)), luabind::value("spawn_zone", static_cast(EVENT_SPAWN_ZONE)), - luabind::value("death_zone", static_cast(EVENT_DEATH_ZONE)) + luabind::value("death_zone", static_cast(EVENT_DEATH_ZONE)), + luabind::value("use_skill", static_cast(EVENT_USE_SKILL)) ]; } diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 92f0adbea..edd4d71db 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -120,7 +120,8 @@ const char *LuaEvents[_LargestEventID] = { "event_unhandled_opcode", "event_tick", "event_spawn_zone", - "event_death_zone" + "event_death_zone", + "event_use_skill" }; extern Zone *zone; @@ -202,6 +203,7 @@ LuaParser::LuaParser() { PlayerArgumentDispatch[EVENT_LEAVE_AREA] = handle_player_area; PlayerArgumentDispatch[EVENT_RESPAWN] = handle_player_respawn; PlayerArgumentDispatch[EVENT_UNHANDLED_OPCODE] = handle_player_packet; + PlayerArgumentDispatch[EVENT_USE_SKILL] = handle_player_use_skill; ItemArgumentDispatch[EVENT_ITEM_CLICK] = handle_item_click; ItemArgumentDispatch[EVENT_ITEM_CLICK_CAST] = handle_item_click; diff --git a/zone/lua_parser_events.cpp b/zone/lua_parser_events.cpp index f01af5a6d..e70c5de9f 100644 --- a/zone/lua_parser_events.cpp +++ b/zone/lua_parser_events.cpp @@ -505,6 +505,15 @@ void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std std::vector *extra_pointers) { } +void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers) { + Seperator sep(data.c_str()); + lua_pushinteger(L, std::stoi(sep.arg[0])); + lua_setfield(L, -2, "skill_id"); + + lua_pushinteger(L, std::stoi(sep.arg[1])); + lua_setfield(L, -2, "skill_level"); +} + //Item void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, std::vector *extra_pointers) { diff --git a/zone/lua_parser_events.h b/zone/lua_parser_events.h index 42315ed0b..44ba9b72f 100644 --- a/zone/lua_parser_events.h +++ b/zone/lua_parser_events.h @@ -95,6 +95,8 @@ void handle_player_packet(QuestInterface *parse, lua_State* L, Client* client, s std::vector *extra_pointers); void handle_player_null(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, std::vector *extra_pointers); +void handle_player_use_skill(QuestInterface *parse, lua_State* L, Client* client, std::string data, uint32 extra_data, + std::vector *extra_pointers); //Item void handle_item_click(QuestInterface *parse, lua_State* L, Client* client, EQEmu::ItemInstance* item, Mob *mob, std::string data, uint32 extra_data, From 995a4527da59c2c0cd236a8f42685c69d6cbbe73 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 10 Jun 2017 22:23:27 -0700 Subject: [PATCH 066/218] Some changes to directory code to help it compile on newer gcc compilers --- common/util/directory.cpp | 21 ++++++++++++++------- common/util/directory.h | 5 ++--- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/common/util/directory.cpp b/common/util/directory.cpp index 557a7a006..9bc075bbe 100644 --- a/common/util/directory.cpp +++ b/common/util/directory.cpp @@ -6,28 +6,35 @@ #include #endif +struct EQ::Directory::impl { + DIR *m_dir; +}; + EQ::Directory::Directory(const std::string &path) { - m_dir = opendir(path.c_str()); + m_impl = new impl; + m_impl->m_dir = opendir(path.c_str()); } EQ::Directory::~Directory() { - if (m_dir) { - closedir(m_dir); + if (m_impl->m_dir) { + closedir(m_impl->m_dir); } + + delete m_impl; } bool EQ::Directory::Exists() { - return m_dir != nullptr; + return m_impl->m_dir != nullptr; } void EQ::Directory::GetFiles(std::vector& files) { - if (m_dir) { + if (m_impl->m_dir) { struct dirent *ent; - while ((ent = readdir(m_dir)) != nullptr) { + while ((ent = readdir(m_impl->m_dir)) != nullptr) { switch (ent->d_type) { case DT_REG: files.push_back(ent->d_name); @@ -37,6 +44,6 @@ void EQ::Directory::GetFiles(std::vector& files) } } - rewinddir(m_dir); + rewinddir(m_impl->m_dir); } } diff --git a/common/util/directory.h b/common/util/directory.h index aa4cc9ecb..d5f7441b2 100644 --- a/common/util/directory.h +++ b/common/util/directory.h @@ -3,8 +3,6 @@ #include #include -struct DIR; - namespace EQ { class Directory { @@ -15,6 +13,7 @@ namespace EQ { bool Exists(); void GetFiles(std::vector &files); private: - DIR *m_dir; + struct impl; + impl *m_impl; }; } From b4837011ea92889e3e774461e34af96e3fc3488a Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 11 Jun 2017 16:13:03 -0700 Subject: [PATCH 067/218] Actually fix load order line ending bug --- zone/lua_parser.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index f77ccb4da..431d7cd29 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -960,7 +960,8 @@ void LuaParser::ReloadQuests() { char file_name[256] = { 0 }; while (fgets(file_name, 256, load_order) != nullptr) { for (int i = 0; i < 256; ++i) { - if (file_name[i] == '\n') { + auto c = file_name[i]; + if (c == '\n' || c == '\r' || c == ' ') { file_name[i] = 0; break; } From 59ddf507e60c4f8ddb9a7cf0fdda20ddce85ddf6 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 12 Jun 2017 08:41:37 -0700 Subject: [PATCH 068/218] Add CrossZoneSetEntityVariableByClientName --- common/servertalk.h | 7 +++++++ world/zoneserver.cpp | 1 + zone/embparser_api.cpp | 19 +++++++++++++++++++ zone/questmgr.cpp | 14 ++++++++++++++ zone/questmgr.h | 1 + zone/worldserver.cpp | 9 +++++++++ 6 files changed, 51 insertions(+) diff --git a/common/servertalk.h b/common/servertalk.h index fa3f10aad..f5965cd74 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -189,6 +189,7 @@ #define ServerOP_ReloadWorld 0x4009 #define ServerOP_ReloadLogs 0x4010 #define ServerOP_ReloadPerlExportSettings 0x4011 +#define ServerOP_CZSetEntityVariableByClientName 0x4012 /* Query Server OP Codes */ #define ServerOP_QSPlayerLogTrades 0x5010 #define ServerOP_QSPlayerLogHandins 0x5011 @@ -1263,6 +1264,12 @@ struct CZSetEntVarByNPCTypeID_Struct { char m_var[256]; }; +struct CZSetEntVarByClientName_Struct { + char CharName[64]; + char id[256]; + char m_var[256]; +}; + struct ReloadWorld_Struct{ uint32 Option; }; diff --git a/world/zoneserver.cpp b/world/zoneserver.cpp index a3fc7da7f..d9c32a15f 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -1248,6 +1248,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { case ServerOP_CZSignalNPC: case ServerOP_CZSetEntityVariableByNPCTypeID: case ServerOP_CZSignalClient: + case ServerOP_CZSetEntityVariableByClientName: case ServerOP_WWMarquee: case ServerOP_DepopAllPlayersCorpses: case ServerOP_DepopPlayerCorpse: diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index d74282211..b440fdd3b 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3599,6 +3599,24 @@ XS(XS__crosszonesetentityvariablebynpctypeid) XSRETURN_EMPTY; } +XS(XS__crosszonesetentityvariablebyclientname); +XS(XS__crosszonesetentityvariablebyclientname) +{ + dXSARGS; + + if (items != 3) + Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebyclientname(clientname, id, m_var)"); + + if (items == 3) { + const char *clientname = (const char *)SvPV_nolen(ST(0)); + const char *id = (const char *)SvPV_nolen(ST(1)); + const char *m_var = (const char *)SvPV_nolen(ST(2)); + quest_manager.CrossZoneSetEntityVariableByClientName(clientname, id, m_var); + } + + XSRETURN_EMPTY; +} + XS(XS__crosszonesignalnpcbynpctypeid); XS(XS__crosszonesignalnpcbynpctypeid) { @@ -3766,6 +3784,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "createguild"), XS__createguild, file); newXS(strcpy(buf, "crosszonemessageplayerbyname"), XS__crosszonemessageplayerbyname, file); newXS(strcpy(buf, "crosszonesetentityvariablebynpctypeid"), XS__crosszonesetentityvariablebynpctypeid, file); + newXS(strcpy(buf, "crosszonesetentityvariablebyclientname"), XS__crosszonesetentityvariablebyclientname, file); newXS(strcpy(buf, "crosszonesignalclientbycharid"), XS__crosszonesignalclientbycharid, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 8c52460d6..34c1d2bc3 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3004,6 +3004,20 @@ void QuestManager::CrossZoneMessagePlayerByName(uint32 Type, const char *CharNam safe_delete(pack); } +void QuestManager::CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var){ + uint32 message_len = strlen(id) + 1; + uint32 message_len2 = strlen(m_var) + 1; + uint32 message_len3 = strlen(CharName) + 1; + auto pack = new ServerPacket(ServerOP_CZSetEntityVariableByClientName, + sizeof(CZSetEntVarByClientName_Struct) + message_len + message_len2 + message_len3); + CZSetEntVarByClientName_Struct* CZ = (CZSetEntVarByClientName_Struct*)pack->pBuffer; + strn0cpy(CZ->CharName, CharName, 64); + strn0cpy(CZ->id, id, 256); + strn0cpy(CZ->m_var, m_var, 256); + worldserver.SendPacket(pack); + safe_delete(pack); +} + void QuestManager::CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var){ uint32 message_len = strlen(id) + 1; uint32 message_len2 = strlen(m_var) + 1; diff --git a/zone/questmgr.h b/zone/questmgr.h index a878de71e..0c846c013 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -255,6 +255,7 @@ public: void CrossZoneSignalNPCByNPCTypeID(uint32 npctype_id, uint32 data); void CrossZoneSignalPlayerByName(const char *CharName, uint32 data); void CrossZoneSetEntityVariableByNPCTypeID(uint32 npctype_id, const char *id, const char *m_var); + void CrossZoneSetEntityVariableByClientName(const char *CharName, const char *id, const char *m_var); void CrossZoneMessagePlayerByName(uint32 Type, const char *CharName, const char *Message); void WorldWideMarquee(uint32 Type, uint32 Priority, uint32 FadeIn, uint32 FadeOut, uint32 Duration, const char *Message); bool EnableRecipe(uint32 recipe_id); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index b0ea2ea5d..99f748d51 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1857,6 +1857,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } break; } + case ServerOP_CZSetEntityVariableByClientName: + { + CZSetEntVarByClientName_Struct* CZCS = (CZSetEntVarByClientName_Struct*)pack->pBuffer; + Client* client = entity_list.GetClientByName(CZCS->CharName); + if (client != 0) { + client->SetEntityVariable(CZCS->id, CZCS->m_var); + } + break; + } case ServerOP_WWMarquee: { WWMarquee_Struct* WWMS = (WWMarquee_Struct*)pack->pBuffer; From d62219d0add364d25d60fa5af90338ab63e39826 Mon Sep 17 00:00:00 2001 From: Natedog2012 Date: Mon, 12 Jun 2017 10:22:09 -0700 Subject: [PATCH 069/218] Add CrossZoneSetEntityVariableByClientName to lua as well --- zone/lua_general.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index 1d71fd2f3..c635f8b2a 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -892,6 +892,10 @@ void lua_cross_zone_message_player_by_name(uint32 type, const char *player, cons quest_manager.CrossZoneMessagePlayerByName(type, player, message); } +void lua_cross_zone_set_entity_variable_by_client_name(const char *player, const char *id, const char *m_var) { + quest_manager.CrossZoneSetEntityVariableByClientName(player, id, m_var); +} + void lua_world_wide_marquee(uint32 type, uint32 priority, uint32 fadein, uint32 fadeout, uint32 duration, const char *message) { quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message); } @@ -1617,6 +1621,7 @@ luabind::scope lua_register_general() { luabind::def("cross_zone_signal_client_by_char_id", &lua_cross_zone_signal_client_by_char_id), luabind::def("cross_zone_signal_client_by_name", &lua_cross_zone_signal_client_by_name), luabind::def("cross_zone_message_player_by_name", &lua_cross_zone_message_player_by_name), + luabind::def("cross_zone_set_entity_variable_by_client_name", &lua_cross_zone_set_entity_variable_by_client_name), luabind::def("world_wide_marquee", &lua_world_wide_marquee), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_NPC,Lua_Client))&lua_get_qglobals), luabind::def("get_qglobals", (luabind::adl::object(*)(lua_State*,Lua_Client))&lua_get_qglobals), From b29f70ad3f8f52988395ca661318730d10f7cba4 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 12 Jun 2017 13:01:01 -0700 Subject: [PATCH 070/218] Add mod hook for CommonOutgoingHitSuccess --- utils/mods/legacy_combat.lua | 7 +++-- zone/attack.cpp | 9 ++++++ zone/lua_mod.cpp | 53 ++++++++++++++++++++++++++++++++++++ zone/lua_mod.h | 2 ++ zone/lua_parser.cpp | 7 +++++ zone/lua_parser.h | 1 + 6 files changed, 76 insertions(+), 3 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 6ce193c7d..a27435be9 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -1,7 +1,7 @@ SoftcapFactor = 1.88; MonkACBonusWeight = 15; NPCACFactor = 2.25; -OldACSoftcapRules = false; +OldACSoftcapRules = true; ClothACSoftcap = 75; LeatherACSoftcap = 100; MonkACSoftcap = 120; @@ -40,6 +40,7 @@ HitBonusPerLevel = 1.2; AgiHitFactor = 0.01; WeaponSkillFalloff = 0.33; ArcheryHitPenalty = 0.25; +UseOldDamageIntervalRules = true; function MeleeMitigation(e) e.IgnoreDefault = true; @@ -575,13 +576,13 @@ end function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_rating, attack_rating) if (not attacker:IsNPC() or UseOldDamageIntervalRules) then - return MobGetMeleeMitDmg(attacker, damage, min_damage, mitigation_rating, attack_rating); + 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; + local spellMeleeMit = (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100.0; if (defender:GetClass() == Class.WARRIOR) then spellMeleeMit = spellMeleeMit + 0.05; end diff --git a/zone/attack.cpp b/zone/attack.cpp index 1f7738119..388a959c2 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -4926,6 +4926,15 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac if (!defender) return; +#ifdef LUA_EQEMU + bool ignoreDefault = false; + LuaParser::Instance()->CommonOutgoingHitSuccess(this, defender, hit, opts, ignoreDefault); + + if (ignoreDefault) { + return; + } +#endif + // BER weren't parsing the halving if (hit.skill == EQEmu::skills::SkillArchery || (hit.skill == EQEmu::skills::SkillThrowing && GetClass() != BERSERKER)) diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index 1a97945a5..ba675c767 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -42,6 +42,7 @@ void LuaMod::Init() 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) { @@ -391,6 +392,58 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign return retval; } +void LuaMod::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) +{ + int start = lua_gettop(L); + ignoreDefault = false; + + try { + if (!m_has_common_outgoing_hit_success) { + return; + } + + lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); + lua_getfield(L, -1, "CommonOutgoingHitSuccess"); + + Lua_Mob l_self(self); + Lua_Mob l_other(other); + luabind::adl::object e = luabind::newtable(L); + e["self"] = l_self; + e["other"] = l_other; + + PutDamageHitInfo(L, e, hit); + PutExtraAttackOptions(L, e, opts); + e.push(L); + + if (lua_pcall(L, 1, 1, 0)) { + std::string error = lua_tostring(L, -1); + parser_->AddError(error); + lua_pop(L, 1); + return; + } + + if (lua_type(L, -1) == LUA_TTABLE) { + luabind::adl::object ret(luabind::from_stack(L, -1)); + auto IgnoreDefaultObj = ret["IgnoreDefault"]; + if (luabind::type(IgnoreDefaultObj) == LUA_TBOOLEAN) { + ignoreDefault = ignoreDefault || luabind::object_cast(IgnoreDefaultObj); + } + + GetDamageHitInfo(ret, hit); + GetExtraAttackOptions(ret, opts); + } + } + catch (std::exception &ex) { + parser_->AddError(ex.what()); + } + + int end = lua_gettop(L); + int n = end - start; + if (n > 0) { + lua_pop(L, n); + } +} + void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); ignoreDefault = false; diff --git a/zone/lua_mod.h b/zone/lua_mod.h index bef40bbcc..04f991f05 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -21,6 +21,7 @@ public: 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 CommonOutgoingHitSuccess(Mob *self, Mob* other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); void TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault); uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); @@ -34,6 +35,7 @@ private: 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; diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 431d7cd29..8f2eda66d 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1333,6 +1333,13 @@ void LuaParser::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, Ext } } +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 = false; diff --git a/zone/lua_parser.h b/zone/lua_parser.h index f99553ccc..eb57faa96 100644 --- a/zone/lua_parser.h +++ b/zone/lua_parser.h @@ -95,6 +95,7 @@ public: 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); From 0a0d4fbb70804b812a264cc98582b4eaa4d9e327 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 12 Jun 2017 16:57:35 -0400 Subject: [PATCH 071/218] SE_SpellResistReduction should be RNG I think before there was an implied 1 to base now it's base to base2 --- zone/spell_effects.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index e04a136e6..151823701 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5024,8 +5024,19 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_SpellResistReduction: - if (type == focusResistRate && focus_spell.base[i] > value) - value = focus_spell.base[i]; + if (type == focusResistRate) { + if (best_focus) { + if (focus_spell.base2 != 0) { + value = focus_spell.base2[i]; + } else { + value = focus_spell.base[i]; + } + } else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { + value = focus_spell.base[i]; + } else { + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + } break; case SE_SpellHateMod: @@ -5319,7 +5330,7 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance - if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage || type == focusImprovedDamage2)) + if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage || type == focusImprovedDamage2 || type == focusResistRate)) rand_effectiveness = true; //Check if item focus effect exists for the client. From f79f54920d70150c8221f0aee71cbfc02c7b9570 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 12 Jun 2017 14:14:39 -0700 Subject: [PATCH 072/218] Export needed fns --- zone/lua_mob.cpp | 23 ++++++++++++++++++++++- zone/lua_mob.h | 3 +++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 07fb17ac5..b6e87fd20 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -1726,6 +1726,18 @@ int Lua_Mob::GetSkillDmgTaken(int skill) { return self->GetSkillDmgTaken(static_cast(skill)); } +int Lua_Mob::GetFcDamageAmtIncoming(Lua_Mob caster, uint32 spell_id, bool use_skill, uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetFcDamageAmtIncoming(caster, spell_id, use_skill, skill); +} + +int Lua_Mob::GetSkillDmgAmt(uint16 skill) +{ + Lua_Safe_Call_Int(); + return self->GetSkillDmgAmt(skill); +} + void Lua_Mob::SetAllowBeneficial(bool value) { Lua_Safe_Call_Void(); self->SetAllowBeneficial(value); @@ -2063,6 +2075,12 @@ int Lua_Mob::GetOrigBodyType() return (int)self->GetOrigBodyType(); } +void Lua_Mob::CheckNumHitsRemaining(int type, int32 buff_slot, uint16 spell_id) +{ + Lua_Safe_Call_Void(); + self->CheckNumHitsRemaining((NumHit)type, buff_slot, spell_id); +} + luabind::scope lua_register_mob() { return luabind::class_("Mob") .def(luabind::constructor<>()) @@ -2359,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", (int(Lua_Mob::*)(int))&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) @@ -2422,7 +2442,8 @@ luabind::scope lua_register_mob() { .def("IsBerserk", &Lua_Mob::IsBerserk) .def("TryFinishingBlow", &Lua_Mob::TryFinishingBlow) .def("GetBodyType", &Lua_Mob::GetBodyType) - .def("GetOrigBodyType", &Lua_Mob::GetOrigBodyType); + .def("GetOrigBodyType", &Lua_Mob::GetOrigBodyType) + .def("CheckNumHitsRemaining", &Lua_Mob::CheckNumHitsRemaining); } luabind::scope lua_register_special_abilities() { diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 1da58c587..c54deb6bc 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -331,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); @@ -395,6 +397,7 @@ public: bool TryFinishingBlow(Lua_Mob defender, int &damage); int GetBodyType(); int GetOrigBodyType(); + void CheckNumHitsRemaining(int type, int32 buff_slot, uint16 spell_id); }; #endif From 233ce5cf03c4fbf0cca9674531211ef9595521bd Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 12 Jun 2017 16:37:25 -0700 Subject: [PATCH 073/218] Fix for bad signature on this func --- zone/lua_mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index b6e87fd20..18651edea 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2377,7 +2377,7 @@ 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", (int(Lua_Mob::*)(int))&Lua_Mob::GetFcDamageAmtIncoming) + .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) From b5a81fbd07ed1f6de23bf41273db740834e0fea4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 13 Jun 2017 14:00:09 -0400 Subject: [PATCH 074/218] Fix life burn Need to investigate more, but reuse --- zone/spell_effects.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 151823701..808a803f7 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -277,12 +277,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove caster->SetMana(0); } else if (spell_id == 2755 && caster) //Lifeburn { - dmg = caster->GetHP()*-15/10; - caster->SetHP(1); - if(caster->IsClient()){ - caster->CastToClient()->SetFeigned(true); - caster->SendAppearancePacket(AT_Anim, 115); - } + dmg = -1 * caster->GetHP(); // just your current HP or should it be Max HP? + caster->SetHP(dmg / 4); // 2003 patch notes say ~ 1/4 HP. Should this be 1/4 your current HP or do 3/4 max HP dmg? Can it kill you? } //do any AAs apply to these spells? From 0c5c6587e5f80748574f1a26410107aa14443dca Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 13 Jun 2017 21:30:34 -0400 Subject: [PATCH 075/218] Fix resist focus issue --- zone/spell_effects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 808a803f7..ccb412860 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5022,7 +5022,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_SpellResistReduction: if (type == focusResistRate) { if (best_focus) { - if (focus_spell.base2 != 0) { + if (focus_spell.base2[i] != 0) { value = focus_spell.base2[i]; } else { value = focus_spell.base[i]; From 35c194e2eb81626363f8a67579ac6bead1d4f1cf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 13 Jun 2017 21:33:42 -0400 Subject: [PATCH 076/218] Fix SE_FcSpellVulnerability --- zone/mob.cpp | 4 +++- zone/spell_effects.cpp | 14 ++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index ae036398a..91fe108ac 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3829,7 +3829,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, SE_FcSpellVulnerability))){ - int32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id); + int32 focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[i].spellid, spell_id, true); if (!focus) continue; @@ -3847,6 +3847,8 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) } } + tmp_focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[tmp_focus].spellid, spell_id); + if (tmp_focus < -99) tmp_focus = -99; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index ccb412860..7cddf0057 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5078,8 +5078,18 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo break; case SE_FcSpellVulnerability: - if (type == focusSpellVulnerability) - value = focus_spell.base[i]; + if (type == focusSpellVulnerability) { + if (best_focus) { + if (focus_spell.base2[i] != 0) + value = focus_spell.base2[i]; + else + value = focus_spell.base[i]; + } else if (focus_spell.base2[i] == 0 || focus_spell.base[i] == focus_spell.base2[i]) { + value = focus_spell.base[i]; + } else { + value = zone->random.Int(focus_spell.base[i], focus_spell.base2[i]); + } + } break; case SE_FcTwincast: From 4e15364d42bc2c36fc5b712e45383442b93c0e75 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 13 Jun 2017 21:48:02 -0400 Subject: [PATCH 077/218] Fix auto completing to wrong thing ... --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 91fe108ac..5ac331c01 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3847,7 +3847,7 @@ int32 Mob::GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining) } } - tmp_focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[tmp_focus].spellid, spell_id); + tmp_focus = caster->CalcFocusEffect(focusSpellVulnerability, buffs[tmp_buffslot].spellid, spell_id); if (tmp_focus < -99) tmp_focus = -99; From 8df8d7c3f66d4cbfa1c47f6e041b4623912cffa8 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 16 Jun 2017 23:12:54 -0700 Subject: [PATCH 078/218] Bugs in mod return values fixed --- utils/mods/legacy_combat.lua | 33 +++++++++++++++---- zone/exp.cpp | 12 ++++--- zone/lua_mod.cpp | 63 ++++++++++++------------------------ zone/lua_mod.h | 10 +++--- zone/lua_parser.cpp | 16 ++++----- 5 files changed, 67 insertions(+), 67 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index a27435be9..90f07a742 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -50,7 +50,7 @@ function MeleeMitigation(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); + e.hit = DoMeleeMitigation(e.self, e.other, e.hit, e.opts); return e; end @@ -582,9 +582,9 @@ function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation 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; + local spellMeleeMit = (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100.0; if (defender:GetClass() == Class.WARRIOR) then - spellMeleeMit = spellMeleeMit + 0.05; + spellMeleeMit = spellMeleeMit - 0.05; end dmg_bonus = dmg_bonus - (dmg_bonus * (defender:GetItemBonuses():MeleeMitigation() / 100.0)); @@ -652,12 +652,12 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra elseif (d > 20.0) then d = 20.0; end - - local interval = (damage - min_damage) / 20.0; - damage = damage - (math.floor(d) * interval); + 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); + damage = damage + (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100); + return damage; end @@ -731,3 +731,22 @@ function ApplyDamageTable(e) e.IgnoreDefault = true; return e; end + +function CommonOutgoingHitSuccess(e) + e = ApplyMeleeDamageBonus(e); + e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * e.other:GetSkillDmgTaken(e.hit.skill) / 100) + (e.self:GetSkillDmgAmt(e.hit.skill) + e.other:GetFcDamageAmtIncoming(e.self, 0, true, e.hit.skill)); + e = TryCriticalHit(e); + e.self:CheckNumHitsRemaining(5, -1, 65535); + e.IgnoreDefault = true; + return e; +end + +function ApplyMeleeDamageBonus(e) + local dmgbonusmod = e.self:GetMeleeDamageMod_SE(e.hit.skill); + if (opts) then + dmgbonusmod = dmgbonusmod + e.opts.melee_damage_bonus_flat; + end + + e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100); + return e; +end \ No newline at end of file diff --git a/zone/exp.cpp b/zone/exp.cpp index fe2cfd543..7d9a02fa8 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -398,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); } } diff --git a/zone/lua_mod.cpp b/zone/lua_mod.cpp index ba675c767..a891fb064 100644 --- a/zone/lua_mod.cpp +++ b/zone/lua_mod.cpp @@ -181,7 +181,6 @@ void GetExtraAttackOptions(luabind::adl::object &ret, ExtraAttackOptions *opts) void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; try { if (!m_has_melee_mitigation) { @@ -233,7 +232,6 @@ void LuaMod::MeleeMitigation(Mob *self, Mob *attacker, DamageHitInfo &hit, Extra void LuaMod::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; try { if (!m_has_apply_damage_table) { @@ -278,14 +276,12 @@ void LuaMod::ApplyDamageTable(Mob *self, DamageHitInfo &hit, bool &ignoreDefault } } -bool LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignoreDefault) { +void LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; try { if (!m_has_avoid_damage) { - return retval; + return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); @@ -304,7 +300,7 @@ bool LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignore std::string error = lua_tostring(L, -1); parser_->AddError(error); lua_pop(L, 1); - return retval; + return; } if (lua_type(L, -1) == LUA_TTABLE) { @@ -316,7 +312,7 @@ bool LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignore auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { - retval = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); } GetDamageHitInfo(ret, hit); @@ -331,18 +327,14 @@ bool LuaMod::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool &ignore if (n > 0) { lua_pop(L, n); } - - return retval; } -bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ignoreDefault) { +void LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; - bool retval = false; try { if (!m_has_check_hit_chance) { - return retval; + return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); @@ -361,7 +353,7 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign std::string error = lua_tostring(L, -1); parser_->AddError(error); lua_pop(L, 1); - return retval; + return; } if (lua_type(L, -1) == LUA_TTABLE) { @@ -373,7 +365,7 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TBOOLEAN) { - retval = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); } GetDamageHitInfo(ret, hit); @@ -388,14 +380,11 @@ bool LuaMod::CheckHitChance(Mob *self, Mob* other, DamageHitInfo &hit, bool &ign if (n > 0) { lua_pop(L, n); } - - return retval; } void LuaMod::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; try { if (!m_has_common_outgoing_hit_success) { @@ -446,7 +435,6 @@ void LuaMod::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &hit, void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraAttackOptions *opts, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; try { if (!m_has_try_critical_hit) { @@ -495,15 +483,13 @@ void LuaMod::TryCriticalHit(Mob *self, Mob *defender, DamageHitInfo &hit, ExtraA } } -uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault) +void LuaMod::GetRequiredAAExperience(Client *self, uint32 &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; - uint32 retval = 0; try { if (!m_has_get_required_aa_experience) { - return retval; + return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); @@ -518,7 +504,7 @@ uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault) std::string error = lua_tostring(L, -1); parser_->AddError(error); lua_pop(L, 1); - return retval; + return; } if (lua_type(L, -1) == LUA_TTABLE) { @@ -530,7 +516,7 @@ uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault) auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TNUMBER) { - retval = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); } } } @@ -543,18 +529,14 @@ uint32 LuaMod::GetRequiredAAExperience(Client *self, bool &ignoreDefault) if (n > 0) { lua_pop(L, n); } - - return retval; } -uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { +void LuaMod::GetEXPForLevel(Client *self, uint16 level, uint32 &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; - uint32 retval = 0; try { if (!m_has_get_exp_for_level) { - return retval; + return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); @@ -570,7 +552,7 @@ uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { std::string error = lua_tostring(L, -1); parser_->AddError(error); lua_pop(L, 1); - return retval; + return; } if (lua_type(L, -1) == LUA_TTABLE) { @@ -582,7 +564,7 @@ uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TNUMBER) { - retval = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); } } } @@ -595,19 +577,16 @@ uint32 LuaMod::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { if (n > 0) { lua_pop(L, n); } - - return retval; } -uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) +void LuaMod::GetExperienceForKill(Client *self, Mob *against, uint32 &returnValue, bool &ignoreDefault) { int start = lua_gettop(L); - ignoreDefault = false; uint32 retval = 0; try { if (!m_has_get_experience_for_kill) { - return retval; + return; } lua_getfield(L, LUA_REGISTRYINDEX, package_name_.c_str()); @@ -624,7 +603,7 @@ uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefa std::string error = lua_tostring(L, -1); parser_->AddError(error); lua_pop(L, 1); - return retval; + return; } if (lua_type(L, -1) == LUA_TTABLE) { @@ -636,7 +615,7 @@ uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefa auto returnValueObj = ret["ReturnValue"]; if (luabind::type(returnValueObj) == LUA_TNUMBER) { - retval = luabind::object_cast(returnValueObj); + returnValue = luabind::object_cast(returnValueObj); } } } @@ -649,6 +628,4 @@ uint32 LuaMod::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefa if (n > 0) { lua_pop(L, n); } - - return retval; } diff --git a/zone/lua_mod.h b/zone/lua_mod.h index 04f991f05..defc5edab 100644 --- a/zone/lua_mod.h +++ b/zone/lua_mod.h @@ -19,13 +19,13 @@ public: 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 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); - uint32 GetRequiredAAExperience(Client *self, bool &ignoreDefault); - uint32 GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault); - uint32 GetExperienceForKill(Client *self, Mob *against, 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; diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index 8f2eda66d..c315c54a1 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1312,7 +1312,7 @@ bool LuaParser::AvoidDamage(Mob *self, Mob *other, DamageHitInfo &hit, bool & ig { bool retval = false; for (auto &mod : mods_) { - retval = mod.AvoidDamage(self, other, hit, ignoreDefault); + mod.AvoidDamage(self, other, hit, retval, ignoreDefault); } return retval; } @@ -1321,7 +1321,7 @@ bool LuaParser::CheckHitChance(Mob *self, Mob *other, DamageHitInfo &hit, bool & { bool retval = false; for (auto &mod : mods_) { - retval = mod.CheckHitChance(self, other, hit, ignoreDefault); + mod.CheckHitChance(self, other, hit, retval, ignoreDefault); } return retval; } @@ -1342,27 +1342,27 @@ void LuaParser::CommonOutgoingHitSuccess(Mob *self, Mob *other, DamageHitInfo &h uint32 LuaParser::GetRequiredAAExperience(Client *self, bool &ignoreDefault) { - uint32 retval = false; + uint32 retval = 0; for (auto &mod : mods_) { - retval = mod.GetRequiredAAExperience(self, ignoreDefault); + mod.GetRequiredAAExperience(self, retval, ignoreDefault); } return retval; } uint32 LuaParser::GetEXPForLevel(Client *self, uint16 level, bool &ignoreDefault) { - uint32 retval = false; + uint32 retval = 0; for (auto &mod : mods_) { - retval = mod.GetEXPForLevel(self, level, ignoreDefault); + mod.GetEXPForLevel(self, level, retval, ignoreDefault); } return retval; } uint32 LuaParser::GetExperienceForKill(Client *self, Mob *against, bool &ignoreDefault) { - uint32 retval = false; + uint32 retval = 0; for (auto &mod : mods_) { - retval = mod.GetExperienceForKill(self, against, ignoreDefault); + mod.GetExperienceForKill(self, against, retval, ignoreDefault); } return retval; } From 70b3a7ba84540b0bd11b032ab5f517356430c5ec Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 17 Jun 2017 12:46:57 -0700 Subject: [PATCH 079/218] Invert only spell bonus migitation --- utils/mods/legacy_combat.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 90f07a742..09ce616ed 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -656,7 +656,7 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra 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); + damage = damage - (damage * (-defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100); return damage; end From 16cbf9bbf12c14df5666a0a28f8418c42331c7a2 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 17 Jun 2017 16:41:32 -0700 Subject: [PATCH 080/218] Allow rule access from lua, double checked and fixed up the spell mitigation stuff --- utils/mods/legacy_combat.lua | 78 ++++++++++++++++++------------------ zone/lua_general.cpp | 56 ++++++++++++++++++++++++++ zone/lua_general.h | 4 ++ zone/lua_parser.cpp | 6 ++- 4 files changed, 104 insertions(+), 40 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 09ce616ed..297b81b98 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -1,27 +1,27 @@ -SoftcapFactor = 1.88; -MonkACBonusWeight = 15; -NPCACFactor = 2.25; -OldACSoftcapRules = true; -ClothACSoftcap = 75; -LeatherACSoftcap = 100; -MonkACSoftcap = 120; -ChainACSoftcap = 200; -PlateACSoftcap = 300; -AAMitigationACFactor = 3.0; -WarriorACSoftcapReturn = 0.45; -KnightACSoftcapReturn = 0.33; -LowPlateChainACSoftcapReturn = 0.23; -LowChainLeatherACSoftcapReturn = 0.17; -CasterACSoftcapReturn = 0.06; -MiscACSoftcapReturn = 0.3; -WarACSoftcapReturn = 0.3448; -ClrRngMnkBrdACSoftcapReturn = 0.3030; -PalShdACSoftcapReturn = 0.3226; -DruNecWizEncMagACSoftcapReturn = 0.2000; -RogShmBstBerACSoftcapReturn = 0.2500; -SoftcapFactor = 1.88; -ACthac0Factor = 0.55; -ACthac20Factor = 0.55; +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; @@ -31,16 +31,16 @@ RogueCritThrowingChance = 25; RogueDeadlyStrikeChance = 80; RogueDeadlyStrikeMod = 2; -BaseHitChance = 69.0; -NPCBonusHitChance = 26.0; -HitFalloffMinor = 5.0; -HitFalloffModerate = 7.0; -HitFalloffMajor = 50.0; -HitBonusPerLevel = 1.2; -AgiHitFactor = 0.01; -WeaponSkillFalloff = 0.33; -ArcheryHitPenalty = 0.25; -UseOldDamageIntervalRules = true; +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; @@ -582,13 +582,13 @@ function ClientGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation 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; + 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); + dmg_interval = dmg_interval + (dmg_interval * spellMeleeMit); local mit_roll = Random.Real(0, mitigation_rating); local atk_roll = Random.Real(0, attack_rating); @@ -655,8 +655,8 @@ function MobGetMeleeMitDmg(defender, attacker, damage, min_damage, mitigation_ra 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); + damage = damage - (min_damage * defender:GetItemBonuses():MeleeMitigation() / 100); + damage = damage + (damage * (defender:GetSpellBonuses():MeleeMitigationEffect() + defender:GetItemBonuses():MeleeMitigationEffect() + defender:GetAABonuses():MeleeMitigationEffect()) / 100); return damage; end diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index a07db54fb..7e3f0520d 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -10,6 +10,7 @@ #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" @@ -33,6 +34,7 @@ struct Skills { }; struct BodyTypes { }; struct Filters { }; struct MessageTypes { }; +struct Rule { }; struct lua_registered_event { std::string encounter_name; @@ -1485,6 +1487,18 @@ 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") [ @@ -2205,4 +2219,46 @@ luabind::scope lua_register_message_types() { ]; } +luabind::scope lua_register_rules_const() { + return luabind::class_("Rule") + .enum_("constants") + [ +#define RULE_INT(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Int__##rule), +#include "../common/ruletypes.h" + luabind::value("_IntRuleCount", RuleManager::_IntRuleCount), +#undef RULE_INT +#define RULE_REAL(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Real__##rule), +#include "../common/ruletypes.h" + luabind::value("_RealRuleCount", RuleManager::_RealRuleCount), +#undef RULE_REAL +#define RULE_BOOL(cat, rule, default_value) \ + luabind::value(#rule, RuleManager::Bool__##rule), +#include "../common/ruletypes.h" + luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount) + ]; +} + +luabind::scope lua_register_rulei() { + return luabind::namespace_("RuleI") + [ + luabind::def("Get", &get_rulei) + ]; +} + +luabind::scope lua_register_ruler() { + return luabind::namespace_("RuleR") + [ + luabind::def("Get", &get_ruler) + ]; +} + +luabind::scope lua_register_ruleb() { + return luabind::namespace_("RuleB") + [ + luabind::def("Get", &get_ruleb) + ]; +} + #endif diff --git a/zone/lua_general.h b/zone/lua_general.h index 62ec346f2..4c8b7f8d2 100644 --- a/zone/lua_general.h +++ b/zone/lua_general.h @@ -15,6 +15,10 @@ 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 diff --git a/zone/lua_parser.cpp b/zone/lua_parser.cpp index c315c54a1..296c766b5 100644 --- a/zone/lua_parser.cpp +++ b/zone/lua_parser.cpp @@ -1096,7 +1096,11 @@ void LuaParser::MapFunctions(lua_State *L) { lua_register_object(), lua_register_packet(), lua_register_packet_opcodes(), - lua_register_stat_bonuses() + lua_register_stat_bonuses(), + lua_register_rules_const(), + lua_register_rulei(), + lua_register_ruler(), + lua_register_ruleb() ]; } catch(std::exception &ex) { From b0cef869b5edeeae5ff90602911b6f5c7ca67a4b Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 17 Jun 2017 19:40:54 -0700 Subject: [PATCH 081/218] Fix bot compile --- zone/bot.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 12cc040bd..fbed35a06 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3857,17 +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) { -#ifdef LUA_EQEMU - bool lua_ret = false; - bool ignoreDefault = false; - lua_ret = LuaParser::Instance()->BotAttack(this, other, Hand, bRiposte, IsStrikethrough, IsFromSpell, opts, ignoreDefault); - - if (ignoreDefault) { - return lua_ret; - } -#endif - +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!"); From d0e612b5fff82594dad7b594da7fbc5888fadacb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 20 Jun 2017 02:31:29 -0500 Subject: [PATCH 082/218] Fix some lua calls/variables in legacy_combat.lua --- utils/mods/legacy_combat.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 297b81b98..9ba9eb3b0 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -42,6 +42,7 @@ WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff); ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty); UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules); + function MeleeMitigation(e) e.IgnoreDefault = true; @@ -376,7 +377,7 @@ function TryPetCriticalHit(self, defender, hit) if(Random.RollReal(critChance)) then local entity_list = eq.get_entity_list(); - critMod = critMod + GetCritDmgMob(self, hit.skill) * 2; + critMod = critMod + GetCritDmgMod(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)', @@ -719,7 +720,7 @@ function GetDamageTable(attacker, skill) if attacker:GetClass() == 7 then local monkDamageTableBonus = 20; - return (dmg_table[GetLevel() - 50] * (100 + monkDamageTableBonus) / 100); + return (dmg_table[attacker:GetLevel() - 50] * (100 + monkDamageTableBonus) / 100); else return dmg_table[attacker:GetLevel() - 50]; end From 1cabb091e73647130fe76c23b1c09109266bf5fe Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 22 Jun 2017 22:26:12 -0700 Subject: [PATCH 083/218] Added packet buffering for dbg connections to avoid connections sending a ton of packets at once --- common/net/daybreak_connection.cpp | 77 +++++++++++++++++++++++------- common/net/daybreak_connection.h | 21 ++++++-- 2 files changed, 77 insertions(+), 21 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 19b5ee5d1..501cf30c0 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -365,7 +365,8 @@ void EQ::Net::DaybreakConnection::Process() FlushBuffer(); } - ProcessQueue(); + ProcessInboundQueue(); + ProcessOutboundQueue(); } catch (std::exception ex) { LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what()); @@ -440,7 +441,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) } } -void EQ::Net::DaybreakConnection::ProcessQueue() +void EQ::Net::DaybreakConnection::ProcessInboundQueue() { for (int i = 0; i < 4; ++i) { auto stream = &m_streams[i]; @@ -459,6 +460,31 @@ void EQ::Net::DaybreakConnection::ProcessQueue() } } +void EQ::Net::DaybreakConnection::ProcessOutboundQueue() +{ + for (int i = 0; i < 4; ++i) { + auto stream = &m_streams[i]; + + if (stream->outstanding_bytes == 0) { + continue; + } + + while (!stream->buffered_packets.empty()) { + auto &buff = stream->buffered_packets.front(); + + if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || + stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { + break; + } + + stream->outstanding_bytes += buff.sent.packet.Length(); + stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); + InternalSend(buff.sent.packet); + stream->buffered_packets.pop_front(); + } + } +} + void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) { auto s = &m_streams[stream]; @@ -1019,7 +1045,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto now = Clock::now(); auto s = &m_streams[stream]; - for (auto &entry : s->sent_packets) { + for (auto &entry : s->outstanding_packets) { auto time_since_last_send = std::chrono::duration_cast(now - entry.second.last_sent); if (entry.second.times_resent == 0) { if ((size_t)time_since_last_send.count() > m_resend_delay) { @@ -1051,8 +1077,8 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto now = Clock::now(); auto s = &m_streams[stream]; - auto iter = s->sent_packets.begin(); - while (iter != s->sent_packets.end()) { + auto iter = s->outstanding_packets.begin(); + while (iter != s->outstanding_packets.end()) { auto order = CompareSequence(seq, iter->first); if (order != SequenceFuture) { @@ -1063,7 +1089,8 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - iter = s->sent_packets.erase(iter); + s->outstanding_bytes -= iter->second.packet.Length(); + iter = s->outstanding_packets.erase(iter); } else { ++iter; @@ -1075,8 +1102,8 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) { auto now = Clock::now(); auto s = &m_streams[stream]; - auto iter = s->sent_packets.find(seq); - if (iter != s->sent_packets.end()) { + auto iter = s->outstanding_packets.find(seq); + if (iter != s->outstanding_packets.end()) { uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); @@ -1084,10 +1111,30 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - s->sent_packets.erase(iter); + s->outstanding_bytes -= iter->second.packet.Length(); + s->outstanding_packets.erase(iter); } } +void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent) +{ + auto s = &m_streams[stream]; + //If we can send the packet then send it + //else buffer it to be sent when we can send it + if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { + //Would go over one of the limits, buffer this packet. + DaybreakBufferedPacket bp; + bp.sent = std::move(sent); + bp.seq = seq; + s->buffered_packets.push_back(bp); + return; + } + + s->outstanding_bytes += sent.packet.Length(); + s->outstanding_packets.insert(std::make_pair(seq, sent)); + InternalSend(sent.packet); +} + void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) { DaybreakReliableHeader ack; @@ -1293,11 +1340,9 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); + BufferPacket(stream_id, stream->sequence_out, sent); stream->sequence_out++; - InternalBufferedSend(first_packet); - while (used < length) { auto left = length - used; DynamicPacket packet; @@ -1321,10 +1366,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); + BufferPacket(stream_id, stream->sequence_out, sent); stream->sequence_out++; - - InternalBufferedSend(packet); } } else { @@ -1341,10 +1384,8 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); + BufferPacket(stream_id, stream->sequence_out, sent); stream->sequence_out++; - - InternalBufferedSend(packet); } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 2d99153e9..2c318793f 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include namespace EQ @@ -145,6 +145,12 @@ namespace EQ size_t times_resent; }; + struct DaybreakBufferedPacket + { + uint16_t seq; + DaybreakSentPacket sent; + }; + struct DaybreakStream { DaybreakStream() { @@ -152,17 +158,20 @@ namespace EQ sequence_out = 0; fragment_current_bytes = 0; fragment_total_bytes = 0; + outstanding_bytes = 0; } uint16_t sequence_in; uint16_t sequence_out; std::unordered_map packet_queue; + std::deque buffered_packets; DynamicPacket fragment_packet; uint32_t fragment_current_bytes; uint32_t fragment_total_bytes; - std::unordered_map sent_packets; + std::unordered_map outstanding_packets; + size_t outstanding_bytes; }; DaybreakStream m_streams[4]; @@ -170,7 +179,8 @@ namespace EQ void Process(); void ProcessPacket(Packet &p); - void ProcessQueue(); + void ProcessInboundQueue(); + void ProcessOutboundQueue(); void RemoveFromQueue(int stream, uint16_t seq); void AddToQueue(int stream, uint16_t seq, const Packet &p); void ProcessDecodedPacket(const Packet &p); @@ -186,6 +196,7 @@ namespace EQ void ProcessResend(int stream); void Ack(int stream, uint16_t seq); void OutOfOrderAck(int stream, uint16_t seq); + void BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent); void SendConnect(); void SendKeepAlive(); @@ -225,6 +236,8 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; + max_outstanding_packets = 200; + max_outstanding_bytes = 200 * 512; } size_t max_packet_size; @@ -247,6 +260,8 @@ namespace EQ size_t connection_close_time; DaybreakEncodeType encode_passes[2]; int port; + size_t max_outstanding_packets; + size_t max_outstanding_bytes; }; class DaybreakConnectionManager From a7c239b8014605ec1b7d43c5d35dbaa4b9a39b9b Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 23 Jun 2017 21:52:28 -0700 Subject: [PATCH 084/218] Some changes to the outbound queue and default settings --- common/net/daybreak_connection.cpp | 3 ++- common/net/daybreak_connection.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 501cf30c0..d07023d05 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -366,7 +366,6 @@ void EQ::Net::DaybreakConnection::Process() } ProcessInboundQueue(); - ProcessOutboundQueue(); } catch (std::exception ex) { LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what()); @@ -1091,6 +1090,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) s->outstanding_bytes -= iter->second.packet.Length(); iter = s->outstanding_packets.erase(iter); + ProcessOutboundQueue(); } else { ++iter; @@ -1113,6 +1113,7 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) s->outstanding_bytes -= iter->second.packet.Length(); s->outstanding_packets.erase(iter); + ProcessOutboundQueue(); } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 2c318793f..8f0b932a3 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -236,7 +236,7 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_packets = 200; + max_outstanding_packets = 300; max_outstanding_bytes = 200 * 512; } From 627859ba73ab5ced0e760faa3a37a02c06b2fa74 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 24 Jun 2017 14:58:40 -0400 Subject: [PATCH 085/218] Merchants don't change heading --- zone/client_process.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 130c10c9d..583ad627b 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -985,8 +985,6 @@ void Client::BulkSendMerchantInventory(int merchant_id, int npcid) { Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName(), handyitem->Name); else Message_StringID(10, GENERIC_STRINGID_SAY, merch->GetCleanName(), handy_id, this->GetName()); - - merch->CastToNPC()->FaceTarget(this->CastToMob()); } // safe_delete_array(cpi); From f164833b00cd01d480576dfdfc6203a4c8602553 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 24 Jun 2017 15:07:58 -0400 Subject: [PATCH 086/218] Adventure Merchants don't change heading either --- zone/client_packet.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 9249f5266..2ca3a1ed4 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -2075,7 +2075,6 @@ void Client::Handle_OP_AdventureMerchantRequest(const EQApplicationPacket *app) return; merchantid = tmp->CastToNPC()->MerchantType; - tmp->CastToNPC()->FaceTarget(this->CastToMob()); const EQEmu::ItemData *item = nullptr; std::list merlist = zone->merchanttable[merchantid]; From 357be65a69e05121210ac0a2daa89c4a90d69ad4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 24 Jun 2017 20:07:01 -0500 Subject: [PATCH 087/218] Speed up saylink retrieval x 1,000 - helpful for dialogues, plugins with many saylinks --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../sql/git/required/2017_06_24_saylink_index.sql | 2 ++ zone/questmgr.cpp | 14 ++++---------- 4 files changed, 8 insertions(+), 11 deletions(-) create mode 100644 utils/sql/git/required/2017_06_24_saylink_index.sql diff --git a/common/version.h b/common/version.h index 411493356..40efffa5a 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9110 +#define CURRENT_BINARY_DATABASE_VERSION 9111 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index b4dce6c86..fc97ffc1b 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -364,6 +364,7 @@ 9108|2017_04_07_ignore_despawn.sql|SHOW COLUMNS FROM `npc_types` LIKE 'ignore_despawn'|empty| 9109|2017_04_08_doors_disable_timer.sql|SHOW COLUMNS FROM `doors` LIKE 'disable_timer'|empty| 9110|2017_04_10_graveyard.sql|show index from graveyard WHERE key_name = 'zone_id_nonunique'|empty| +9111|2017_06_24_saylink_index.sql|SHOW INDEX FROM `saylink` WHERE `key_name` = 'phrase_index'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_06_24_saylink_index.sql b/utils/sql/git/required/2017_06_24_saylink_index.sql new file mode 100644 index 000000000..3dfb5c9ef --- /dev/null +++ b/utils/sql/git/required/2017_06_24_saylink_index.sql @@ -0,0 +1,2 @@ +ALTER TABLE `saylink` +ADD INDEX `phrase_index` (`phrase`) USING BTREE ; \ No newline at end of file diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 34c1d2bc3..757098c57 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2743,20 +2743,14 @@ const char* QuestManager::saylink(char* Phrase, bool silent, const char* LinkNam if (results.RowCount() >= 1) { for (auto row = results.begin();row != results.end(); ++row) sayid = atoi(row[0]); - } else { // Add a new saylink entry to the database and query it again for the new sayid number + } else { std::string insert_query = StringFormat("INSERT INTO `saylink` (`phrase`) VALUES ('%s')", escaped_string); results = database.QueryDatabase(insert_query); if (!results.Success()) { Log(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str()); - } else { - results = database.QueryDatabase(query); - if (results.Success()) { - if (results.RowCount() >= 1) - for(auto row = results.begin(); row != results.end(); ++row) - sayid = atoi(row[0]); - } else { - Log(Logs::General, Logs::Error, "Error in saylink phrase queries", results.ErrorMessage().c_str()); - } + } + else { + sayid = results.LastInsertedID(); } } } From 6cc774faf4146e4ff4ba05d94224d49adc1ab26e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 24 Jun 2017 20:10:12 -0500 Subject: [PATCH 088/218] Adjust netcode variables proven to be stable for players --- common/net/daybreak_connection.cpp | 8 ++++---- common/net/daybreak_connection.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index d07023d05..82a7e2d12 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -277,7 +277,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_encode_passes[1] = owner->m_options.encode_passes[1]; m_hold_time = Clock::now(); m_buffered_packets_length = 0; - m_rolling_ping = 900; + m_rolling_ping = 500; 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 = 900; + m_rolling_ping = 500; 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; @@ -1051,7 +1051,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 300; + m_rolling_ping += 100; } } else { @@ -1065,7 +1065,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 300; + m_rolling_ping += 100; } } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 8f0b932a3..b4faf2438 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -217,10 +217,10 @@ namespace EQ DaybreakConnectionManagerOptions() { max_connection_count = 0; keepalive_delay_ms = 9000; - resend_delay_ms = 300; + resend_delay_ms = 150; resend_delay_factor = 1.5; - resend_delay_min = 350; - resend_delay_max = 8000; + resend_delay_min = 150; + resend_delay_max = 1000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; From 5fac13075b7acbd685821c1c12494a1d0df321b9 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 24 Jun 2017 18:29:18 -0700 Subject: [PATCH 089/218] Up resend delay max a few seconds --- common/net/daybreak_connection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index b4faf2438..2ec7f200f 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -220,7 +220,7 @@ namespace EQ resend_delay_ms = 150; resend_delay_factor = 1.5; resend_delay_min = 150; - resend_delay_max = 1000; + resend_delay_max = 4000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; From 1c8dea909e3fbbdd77c757868db2240278de811c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 24 Jun 2017 21:11:46 -0500 Subject: [PATCH 090/218] New rules made by developers are now automatically created when world boots up, this keeps from having to issue schema SQL updates every time rules are added. - Whenever a rule isn't present in the database, it will be automatically created - utils/sql/git/required/2017_06_24_rule_values_expand.sql required for avoid floating point value inserts --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2017_06_24_rule_values_expand.sql | 2 ++ world/net.cpp | 2 ++ 4 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 utils/sql/git/required/2017_06_24_rule_values_expand.sql diff --git a/common/version.h b/common/version.h index 40efffa5a..2391862a1 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9111 +#define CURRENT_BINARY_DATABASE_VERSION 9112 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index fc97ffc1b..5586b9848 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -365,6 +365,7 @@ 9109|2017_04_08_doors_disable_timer.sql|SHOW COLUMNS FROM `doors` LIKE 'disable_timer'|empty| 9110|2017_04_10_graveyard.sql|show index from graveyard WHERE key_name = 'zone_id_nonunique'|empty| 9111|2017_06_24_saylink_index.sql|SHOW INDEX FROM `saylink` WHERE `key_name` = 'phrase_index'|empty| +9112|2017_06_24_rule_values_expand.sql|SHOW COLUMNS FROM rule_values WHERE Field = 'rule_value' and Type = 'varchar(30)'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_06_24_rule_values_expand.sql b/utils/sql/git/required/2017_06_24_rule_values_expand.sql new file mode 100644 index 000000000..2d4720007 --- /dev/null +++ b/utils/sql/git/required/2017_06_24_rule_values_expand.sql @@ -0,0 +1,2 @@ +ALTER TABLE `rule_values` +MODIFY COLUMN `rule_value` varchar(30) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `rule_name`; diff --git a/world/net.cpp b/world/net.cpp index 09511c3f2..599f01c8f 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -332,6 +332,8 @@ int main(int argc, char** argv) { database.ClearMerchantTemp(); } + RuleManager::Instance()->SaveRules(&database); + Log(Logs::General, Logs::World_Server, "Loading EQ time of day.."); TimeOfDay_Struct eqTime; time_t realtime; From 497170c4533ba9d8017122eec39deab9cb2b81c6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 25 Jun 2017 16:30:37 -0400 Subject: [PATCH 091/218] Optimize Entity::AESpell Probably could use more work, but quick testing had this method taking the least amount of time in various situations --- zone/effects.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 8d8265e32..e7933a833 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -703,6 +703,10 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ float min_range2 = spells[spell_id].min_range * spells[spell_id].min_range; float dist_targ = 0; + const auto &position = spells[spell_id].targettype == ST_Ring ? caster->GetTargetRingLocation() : static_cast(center->GetPosition()); + glm::vec2 min = { position.x - dist, position.y - dist }; + glm::vec2 max = { position.x + dist, position.y + dist }; + bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); int MAX_TARGETS_ALLOWED = 4; @@ -732,13 +736,10 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ continue; if (spells[spell_id].pcnpc_only_flag == 2 && (curmob->IsClient() || curmob->IsMerc())) continue; + if (!IsWithinAxisAlignedBox(static_cast(curmob->GetPosition()), min, max)) + continue; - if (spells[spell_id].targettype == ST_Ring) { - dist_targ = DistanceSquared(static_cast(curmob->GetPosition()), caster->GetTargetRingLocation()); - } - else if (center) { - dist_targ = DistanceSquared(curmob->GetPosition(), center->GetPosition()); - } + dist_targ = DistanceSquared(curmob->GetPosition(), position); if (dist_targ > dist2) //make sure they are in range continue; @@ -761,9 +762,7 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ if (bad) { if (!caster->IsAttackAllowed(curmob, true)) continue; - if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob)) - continue; - if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize())) + if (!spells[spell_id].npc_no_los && !caster->CheckLosFN(position.x, position.y, position.z, curmob->GetSize())) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // This does not check faction for beneficial AE buffs..only agro and attackable. From 3e1b75b81484ebc3137dc878e32e1cff16382d97 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 25 Jun 2017 18:18:27 -0400 Subject: [PATCH 092/218] Fix Rain target limit (massive nerf) Added rule Spells:OldRainTargets, set to true if you don't want the nerf --- common/ruletypes.h | 1 + zone/beacon.cpp | 7 +++++-- zone/beacon.h | 1 + zone/effects.cpp | 14 ++++++++++---- zone/entity.h | 2 +- 5 files changed, 18 insertions(+), 7 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index e9599e09b..11a55c423 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -397,6 +397,7 @@ RULE_BOOL(Spells, FlatItemExtraSpellAmt, false) // allow SpellDmg stat to affect RULE_BOOL(Spells, IgnoreSpellDmgLvlRestriction, false) // ignore the 5 level spread on applying SpellDmg RULE_BOOL(Spells, AllowItemTGB, false) // TGB doesn't work with items on live, custom servers want it though RULE_BOOL(Spells, NPCInnateProcOverride, true) // NPC innate procs override the target type to single target. +RULE_BOOL(Spells, OldRainTargets, false) // use old incorrectly implemented max targets for rains RULE_CATEGORY_END() RULE_CATEGORY(Combat) diff --git a/zone/beacon.cpp b/zone/beacon.cpp index 27f86fce7..e5ea9f38f 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -68,6 +68,7 @@ Beacon::Beacon(Mob *at_mob, int lifetime) resist_adjust = 0; spell_iterations = 0; caster_id = 0; + max_targets = 4; // default if(lifetime) remove_timer.Start(); @@ -93,10 +94,10 @@ bool Beacon::Process() ) { Mob *caster = entity_list.GetMob(caster_id); - if(caster && spell_iterations--) + if(caster && spell_iterations-- && max_targets) { bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()); //NPC AE spells do not affect the NPC caster - entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust); + entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust, &max_targets); } else { @@ -126,6 +127,8 @@ void Beacon::AELocationSpell(Mob *caster, uint16 cast_spell_id, int16 resist_adj this->resist_adjust = resist_adjust; spell_iterations = spells[spell_id].AEDuration / 2500; spell_iterations = spell_iterations < 1 ? 1 : spell_iterations; // at least 1 + if (spells[spell_id].aemaxtargets) + max_targets = spells[spell_id].aemaxtargets; spell_timer.Start(2500); spell_timer.Trigger(); } diff --git a/zone/beacon.h b/zone/beacon.h index b79ed318c..c22189dfd 100644 --- a/zone/beacon.h +++ b/zone/beacon.h @@ -56,6 +56,7 @@ protected: int16 resist_adjust; int spell_iterations; Timer spell_timer; + int max_targets; uint16 caster_id; private: diff --git a/zone/effects.cpp b/zone/effects.cpp index e7933a833..0585f3c50 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -694,7 +694,7 @@ void EntityList::AETaunt(Client* taunter, float range, int32 bonus_hate) // causes caster to hit every mob within dist range of center with // spell_id. // NPC spells will only affect other NPCs with compatible faction -void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust) +void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster, int16 resist_adjust, int *max_targets) { Mob *curmob = nullptr; @@ -709,9 +709,13 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ bool bad = IsDetrimentalSpell(spell_id); bool isnpc = caster->IsNPC(); - int MAX_TARGETS_ALLOWED = 4; - if (spells[spell_id].aemaxtargets) + if (RuleB(Spells, OldRainTargets)) + max_targets = nullptr; // ignore it! + + int MAX_TARGETS_ALLOWED = max_targets ? *max_targets : 4; + + if (!max_targets && spells[spell_id].aemaxtargets) MAX_TARGETS_ALLOWED = spells[spell_id].aemaxtargets; int iCounter = 0; @@ -789,8 +793,10 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ } if (!isnpc || spells[spell_id].aemaxtargets) //npcs are not target limited (unless casting a spell with a target limit)... - iCounter++; + iCounter++; // should really pull out the MAX_TARGETS_ALLOWED calc so we can break early ... } + if (max_targets) + *max_targets = *max_targets - std::min(iCounter, *max_targets); // could be higher than the count } void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster) diff --git a/zone/entity.h b/zone/entity.h index 94078691a..e2224d05d 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -357,7 +357,7 @@ public: void AEAttack(Mob *attacker, float dist, int Hand = EQEmu::inventory::slotPrimary, int count = 0, bool IsFromSpell = false); void AETaunt(Client *caster, float range=0, int32 bonus_hate=0); - void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0); + void AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true, int16 resist_adjust = 0, int *max_targets = nullptr); void MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); void AEBardPulse(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster = true); From c0f53647b8b7c8e354af224edc238eab1f6dd443 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 25 Jun 2017 20:37:37 -0500 Subject: [PATCH 093/218] Revert 5fac13075b7acbd685821c1c12494a1d0df321b9 until we don't creep client resend up to 4 seconds so quickly, this causes issues in higher traffic amounts and takes longer for clients to recover than needed --- common/net/daybreak_connection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 2ec7f200f..b4faf2438 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -220,7 +220,7 @@ namespace EQ resend_delay_ms = 150; resend_delay_factor = 1.5; resend_delay_min = 150; - resend_delay_max = 4000; + resend_delay_max = 1000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; From 4f7b8e0934469d53323d8799bcc20188cc007a4b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 26 Jun 2017 00:12:56 -0500 Subject: [PATCH 094/218] Add Critical Hit range (default 80) to legacy_combat.lua and fix a variable in Pet Criticals --- utils/mods/legacy_combat.lua | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/utils/mods/legacy_combat.lua b/utils/mods/legacy_combat.lua index 9ba9eb3b0..9ab70cf4d 100644 --- a/utils/mods/legacy_combat.lua +++ b/utils/mods/legacy_combat.lua @@ -42,6 +42,7 @@ WeaponSkillFalloff = RuleR.Get(Rule.WeaponSkillFalloff); ArcheryHitPenalty = RuleR.Get(Rule.ArcheryHitPenalty); UseOldDamageIntervalRules = RuleB.Get(Rule.UseOldDamageIntervalRules); +CriticalMessageRange = RuleI.Get(Rule.CriticalDamage); function MeleeMitigation(e) e.IgnoreDefault = true; @@ -238,9 +239,9 @@ function TryCriticalHit(e) 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)); + entity_list:FilteredMessageClose(self, false, CriticalMessageRange, 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)); + entity_list:FilteredMessageClose(self, false, CriticalMessageRange, MT.CritMelee, Filter.MeleeCrits, string.format('%s\'s holy blade cleanses his target! (%d)', self:GetCleanName(), e.hit.damage_done)); end return e; @@ -326,15 +327,15 @@ function TryCriticalHit(e) 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)); + entity_list:FilteredMessageClose(self, false, CriticalMessageRange, 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)); + entity_list:FilteredMessageClose(self, false, CriticalMessageRange, 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)); + entity_list:FilteredMessageClose(self, false, CriticalMessageRange, MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a critical hit! (%d)', self:GetCleanName(), e.hit.damage_done)); end end end @@ -379,9 +380,9 @@ function TryPetCriticalHit(self, defender, hit) local entity_list = eq.get_entity_list(); critMod = critMod + GetCritDmgMod(self, hit.skill) * 2; hit.damage_done = (hit.damage_done * critMod) / 100; - entity_list:FilteredMessageClose(this, false, 200, + entity_list:FilteredMessageClose(this, false, CriticalMessageRange, MT.CritMelee, Filter.MeleeCrits, string.format('%s scores a critical hit! (%d)', - self:GetCleanName(), hit.damage_done)); + self:GetCleanName(), e.hit.damage_done)); end end @@ -750,4 +751,4 @@ function ApplyMeleeDamageBonus(e) e.hit.damage_done = e.hit.damage_done + (e.hit.damage_done * dmgbonusmod / 100); return e; -end \ No newline at end of file +end From b09792812aa7496ae16aa3ccfbff632282f6ea8b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 26 Jun 2017 15:00:47 -0400 Subject: [PATCH 095/218] Final AESpell optimization pass --- zone/effects.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 0585f3c50..7dfc4e617 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -713,10 +713,15 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ if (RuleB(Spells, OldRainTargets)) max_targets = nullptr; // ignore it! - int MAX_TARGETS_ALLOWED = max_targets ? *max_targets : 4; - - if (!max_targets && spells[spell_id].aemaxtargets) - MAX_TARGETS_ALLOWED = spells[spell_id].aemaxtargets; + // if we have a passed in value, use it, otherwise default to data + // detrimental Target AEs have a default value of 4 for PCs and unlimited for NPCs + int max_targets_allowed = 0; // unlimited + if (max_targets) // rains pass this in since they need to preserve the count through waves + max_targets_allowed = *max_targets; + else if (spells[spell_id].aemaxtargets) + max_targets_allowed = spells[spell_id].aemaxtargets; + else if (IsTargetableAESpell(spell_id) && bad && !isnpc) + max_targets_allowed = 4; int iCounter = 0; @@ -779,24 +784,17 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ } curmob->CalcSpellPowerDistanceMod(spell_id, dist_targ); + caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); - //if we get here... cast the spell. - if (IsTargetableAESpell(spell_id) && bad) { - if (iCounter < MAX_TARGETS_ALLOWED) { - caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); - } - } else { - if (spells[spell_id].aemaxtargets && iCounter < spells[spell_id].aemaxtargets) - caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); - if (!spells[spell_id].aemaxtargets) - caster->SpellOnTarget(spell_id, curmob, false, true, resist_adjust); + if (max_targets_allowed) { // if we have a limit, increment count + iCounter++; + if (iCounter >= max_targets_allowed) // we done + break; } - - if (!isnpc || spells[spell_id].aemaxtargets) //npcs are not target limited (unless casting a spell with a target limit)... - iCounter++; // should really pull out the MAX_TARGETS_ALLOWED calc so we can break early ... } - if (max_targets) - *max_targets = *max_targets - std::min(iCounter, *max_targets); // could be higher than the count + + if (max_targets && max_targets_allowed) + *max_targets = *max_targets - iCounter; } void EntityList::MassGroupBuff(Mob *caster, Mob *center, uint16 spell_id, bool affect_caster) From 592bbd31804a7b03f0e685059476620941994683 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 27 Jun 2017 20:38:46 -0400 Subject: [PATCH 096/218] Target AEs don't always hit target --- zone/spells.cpp | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index ef0553526..5504422e0 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2237,21 +2237,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui // special ae duration spell ae_center->CastToBeacon()->AELocationSpell(this, spell_id, resist_adjust); } else { - // regular PB AE or targeted AE spell - spell_target is null if PB - if(spell_target) // this must be an AETarget spell - { - bool cast_on_target = true; - if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && spell_target->IsPetOwnerClient()) - cast_on_target = false; - if (spells[spell_id].targettype == ST_AreaClientOnly && !spell_target->IsClient()) - cast_on_target = false; - if (spells[spell_id].targettype == ST_AreaNPCOnly && !spell_target->IsNPC()) - cast_on_target = false; - - // affect the target too - if (cast_on_target) - SpellOnTarget(spell_id, spell_target, false, true, resist_adjust); - } + // unsure if we actually need this? Need to find some spell examples if(ae_center && ae_center == this && IsBeneficialSpell(spell_id)) SpellOnTarget(spell_id, this); From 539fa8b2628ed97b75638ea4f1eae0c23fa5f303 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jun 2017 02:38:20 -0500 Subject: [PATCH 097/218] Fixed issues with Z correctness when NPCs are pathing on normal grids Fixed issues with Z correctness when NPCs are engaged with players following NPC corpses should fall into the ground far less --- changelog.txt | 45 +++++++++------ common/ruletypes.h | 1 + zone/attack.cpp | 7 +++ zone/mob.cpp | 4 +- zone/mob.h | 3 + zone/mob_ai.cpp | 3 + zone/waypoints.cpp | 141 +++++++++++++-------------------------------- 7 files changed, 85 insertions(+), 119 deletions(-) diff --git a/changelog.txt b/changelog.txt index 8edf925b0..0614ff4a8 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,25 +1,36 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 6/28/2017 == +Akkadius: Fixed issues with Z correctness when NPCs are pathing on normal grids +Akkadius: Fixed issues with Z correctness when NPCs are engaged with players following +Akkadius: NPC corpses should fall into the ground far less + +== 6/25/2017 == +Akkadius: New rules made by developers are now automatically created when world boots up, this keeps + from having to issue schema SQL updates every time rules are added. + - Whenever a rule isn't present in the database, it will be automatically created +Akkadius: Sped up saylink retrieval x1000 helpful for dialogues, plugins with many saylinks + == 4/16/2017 == KLS: Merge eqstream branch - -UDP client stack completely rewritten should both have better throughput and recover better (peq has had far fewer reports of desyncs). - -TCP Server to Server connection stack completely rewritten. - -Server connections reconnect much more reliably and quickly now. - -Now supports optional packet encryption via libsodium (https://download.libsodium.org/doc/). - -Protocol behind the tcp connections has changed (see breaking changes section). - -API significantly changed and should be easier to write new servers or handlers for. - -Telnet console connection has been separated out from the current port (see breaking changes section). - -Because of changes to the TCP stack, lsreconnect and echo have been disabled. - -The server tic rate has been changed to be approx 30 fps from 500+ fps. - -Changed how missiles and movement were calculated slightly to account for this (Missiles in particular are not perfect but close enough). + - UDP client stack completely rewritten should both have better throughput and recover better (peq has had far fewer reports of desyncs). + - TCP Server to Server connection stack completely rewritten. + - Server connections reconnect much more reliably and quickly now. + - Now supports optional packet encryption via libsodium (https://download.libsodium.org/doc/). + - Protocol behind the tcp connections has changed (see breaking changes section). + - API significantly changed and should be easier to write new servers or handlers for. + - Telnet console connection has been separated out from the current port (see breaking changes section). + - Because of changes to the TCP stack, lsreconnect and echo have been disabled. + - The server tic rate has been changed to be approx 30 fps from 500+ fps. + - Changed how missiles and movement were calculated slightly to account for this (Missiles in particular are not perfect but close enough). - -Breaking changes: - -Users who use the cmake install feature should be aware that the install directory is now %cmake_install_dir%/bin instead of just %cmake_install_dir%/ - -To support new features such as encryption the underlying protocol had to change... however some servers such as the public login server will be slow to change so we've included a compatibility layer for legacy login connections: - -You should add 1 to the login section of your configuration file when connecting to a server that is using the old protocol. - -The central eqemu login server uses the old protocol and probably will for the forseeable future so if your server is connecting to it be sure to add that tag to your configuration file in that section. - -Telnet no longer uses the same port as the Server to Server connection and because of this the tcp tag no longer has any effect on telnet connections. - -To enable telnet you need to add a telnet tag in the world section of configuration such as: + - Breaking changes: + - Users who use the cmake install feature should be aware that the install directory is now %cmake_install_dir%/bin instead of just %cmake_install_dir%/ + - To support new features such as encryption the underlying protocol had to change... however some servers such as the public login server will be slow to change so we've included a compatibility layer for legacy login connections: + - You should add 1 to the login section of your configuration file when connecting to a server that is using the old protocol. + - The central eqemu login server uses the old protocol and probably will for the forseeable future so if your server is connecting to it be sure to add that tag to your configuration file in that section. + - Telnet no longer uses the same port as the Server to Server connection and because of this the tcp tag no longer has any effect on telnet connections. + - To enable telnet you need to add a telnet tag in the world section of configuration such as: == 4/1/2017 == diff --git a/common/ruletypes.h b/common/ruletypes.h index 11a55c423..945c2625a 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -274,6 +274,7 @@ RULE_BOOL(Map, FixPathingZWhenLoading, true) //increases zone boot times a bit RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, accomplishes the same thing but does it at each waypoint instead of once at boot time. RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints. RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well. +RULE_BOOL(Map, FixZWhenMoving, true) // Automatically fix NPC Z coordinates when moving/pathing/engaged (Far less CPU intensive than its predecessor) RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply. RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. diff --git a/zone/attack.cpp b/zone/attack.cpp index 388a959c2..28ff607dc 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2388,6 +2388,13 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil entity_list.UnMarkNPC(GetID()); entity_list.RemoveNPC(GetID()); + + /* Fix Z on Corpse Creation */ + glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); + float new_z = zone->zonemap->FindBestZ(dest, nullptr); + corpse->SetFlyMode(1); + corpse->GMMove(m_Position.x, m_Position.y, new_z + 5, m_Position.w); + this->SetID(0); if (killer != 0 && emoteid != 0) diff --git a/zone/mob.cpp b/zone/mob.cpp index 64ada4b71..c411f6a3c 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -112,7 +112,9 @@ Mob::Mob(const char* in_name, m_Position(position), tmHidden(-1), mitigation_ac(0), - m_specialattacks(eSpecialAttacks::None) + m_specialattacks(eSpecialAttacks::None), + fix_z_timer(1000), + fix_z_timer_engaged(100) { targeted = 0; tar_ndx=0; diff --git a/zone/mob.h b/zone/mob.h index f2516b613..a8bf043c6 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -913,6 +913,7 @@ public: float GetGroundZ(float new_x, float new_y, float z_offset=0.0); void SendTo(float new_x, float new_y, float new_z); void SendToFixZ(float new_x, float new_y, float new_z); + void FixZ(); void NPCSpecialAttacks(const char* parse, int permtag, bool reset = true, bool remove = false); inline uint32 DontHealMeBefore() const { return pDontHealMeBefore; } inline uint32 DontBuffMeBefore() const { return pDontBuffMeBefore; } @@ -1373,6 +1374,8 @@ protected: bool flee_mode; Timer flee_timer; + Timer fix_z_timer; + Timer fix_z_timer_engaged; bool pAIControlled; bool roamer; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index fd0ec5d81..405382033 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -991,6 +991,9 @@ void Mob::AI_Process() { if (engaged) { + if (moving && fix_z_timer_engaged.Check()) + this->FixZ(); + if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); // we are prevented from getting here if we are blind and don't have a target in range diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 64f674cde..6ceee481e 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -513,39 +513,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.y = new_y; m_Position.z = new_z; - uint8 NPCFlyMode = 0; - - if (IsNPC()) { - if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2) - NPCFlyMode = 1; - } - - //fix up pathing Z - if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) - { - if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) - { - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - - float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; - - if ((newz > -2000) && - std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check. - { - if ((std::abs(x - m_Position.x) < 0.5) && - (std::abs(y - m_Position.y) < 0.5)) { - if (std::abs(z - m_Position.z) <= - RuleR(Map, FixPathingZMaxDeltaMoving)) - m_Position.z = z; - else - m_Position.z = newz + 1; - } - else - m_Position.z = newz + 1; - } - } - } + if(fix_z_timer.Check()) + this->FixZ(); tar_ndx++; return true; @@ -651,37 +620,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.w = CalculateHeadingToTarget(x, y); } - uint8 NPCFlyMode = 0; - - if (IsNPC()) { - if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2) - NPCFlyMode = 1; - } - - //fix up pathing Z - if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) { - - if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) - { - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - - float newz = zone->zonemap->FindBestZ(dest, nullptr); - - if ((newz > -2000) && - std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check. - { - if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) { - if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving)) - m_Position.z = z; - else - m_Position.z = newz + 1; - } - else - m_Position.z = newz + 1; - } - } - } + if (fix_z_timer.Check()) + this->FixZ(); SetMoving(true); moved = true; @@ -769,39 +709,8 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ Log(Logs::Detail, Logs::AI, "Next position (%.3f, %.3f, %.3f)", m_Position.x, m_Position.y, m_Position.z); } - uint8 NPCFlyMode = 0; - - if (IsNPC()) { - if (CastToNPC()->GetFlyMode() == 1 || CastToNPC()->GetFlyMode() == 2) - NPCFlyMode = 1; - } - - //fix up pathing Z - if (!NPCFlyMode && checkZ && zone->HasMap() && RuleB(Map, FixPathingZWhenMoving)) - { - if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) - { - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - - float newz = zone->zonemap->FindBestZ(dest, nullptr) + 2.0f; - - Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z); - - if ((newz > -2000) && - std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) // Sanity check. - { - if (std::abs(x - m_Position.x) < 0.5 && std::abs(y - m_Position.y) < 0.5) { - if (std::abs(z - m_Position.z) <= RuleR(Map, FixPathingZMaxDeltaMoving)) - m_Position.z = z; - else - m_Position.z = newz + 1; - } - else - m_Position.z = newz + 1; - } - } - } + if (fix_z_timer.Check()) + this->FixZ(); //OP_MobUpdate if ((old_test_vector != test_vector) || tar_ndx>20) { //send update @@ -943,9 +852,6 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) { m_Position.y = new_y; m_Position.z = new_z + 0.1; - //fix up pathing Z, this shouldent be needed IF our waypoints - //are corrected instead - if (zone->HasMap() && RuleB(Map, FixPathingZOnSendTo)) { if (!RuleB(Watermap, CheckForWaterOnSendTo) || !zone->HasWaterMap() || @@ -955,7 +861,7 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) { float newz = zone->zonemap->FindBestZ(dest, nullptr); - Log(Logs::Detail, Logs::AI, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z); + Log(Logs::Moderate, Logs::Pathing, "BestZ returned %4.3f at %4.3f, %4.3f, %4.3f", newz, m_Position.x, m_Position.y, m_Position.z); if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaSendTo)) // Sanity check. m_Position.z = newz + 1; @@ -963,6 +869,39 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) { } } +void Mob::FixZ() { + BenchTimer timer; + timer.reset(); + + if (zone->HasMap() && RuleB(Map, FixZWhenMoving) && (flymode != 1 && flymode != 2)) + { + if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || + (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) + { + glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); + + float new_z = zone->zonemap->FindBestZ(dest, nullptr); + + auto duration = timer.elapsed(); + + Log( + Logs::Moderate, + Logs::Pathing, + "Mob::FixZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf", + this->GetCleanName(), + new_z, + m_Position.x, + m_Position.y, + m_Position.z, + duration + ); + + if ((new_z > -2000) && std::abs(new_z - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) + m_Position.z = new_z + 1; + } + } +} + int ZoneDatabase::GetHighestGrid(uint32 zoneid) { std::string query = StringFormat("SELECT COALESCE(MAX(id), 0) FROM grid WHERE zoneid = %i", zoneid); From cbbd01b39148fd1c6be13779fcf5074cb0880378 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 28 Jun 2017 13:27:37 -0400 Subject: [PATCH 098/218] Quick fix for NPC attack skill issue --- zone/attack.cpp | 5 ++--- zone/mob.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 28ff607dc..c210e37dc 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -53,9 +53,8 @@ extern WorldServer worldserver; extern EntityList entity_list; extern Zone* zone; -EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon) +EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills:SkillType skillinuse) { - EQEmu::skills::SkillType skillinuse = EQEmu::skills::Skill1HBlunt; // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { @@ -1924,7 +1923,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); - my_hit.skill = AttackAnimation(Hand, &weapon_inst); + my_hit.skill = AttackAnimation(Hand, &weapon_inst, my_hit.skill); //basically "if not immune" then do the attack if (weapon_damage > 0) { diff --git a/zone/mob.h b/zone/mob.h index a8bf043c6..109cd3656 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -233,7 +233,7 @@ public: inline bool SeeImprovedHide() const { return see_improved_hide; } bool IsInvisible(Mob* other = 0) const; void SetInvisible(uint8 state); - EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon); + EQEmu::skills::SkillType AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse = EQEmu::skills::Skill1HBlunt); //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); From 09ccd23d0bc8a82b7840e14fd281dbf163884fc3 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 28 Jun 2017 13:30:20 -0400 Subject: [PATCH 099/218] Fix syntax issue --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index c210e37dc..04cb65c9a 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -53,7 +53,7 @@ extern WorldServer worldserver; extern EntityList entity_list; extern Zone* zone; -EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills:SkillType skillinuse) +EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse) { // Determine animation int type = 0; From 4d2825d8179d9cd0b690316b400df16051c256df Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jun 2017 16:43:38 -0500 Subject: [PATCH 100/218] Make sure we also fix Z when mobs flee up/down stairs --- zone/mob_ai.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 405382033..07f89ca63 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -743,6 +743,10 @@ void Client::AI_Process() if(RuleB(Combat, EnableFearPathing)){ if(currently_fleeing) { + + if (fix_z_timer_engaged.Check()) + this->FixZ(); + if(IsRooted()) { //make sure everybody knows were not moving, for appearance sake if(IsMoving()) @@ -782,6 +786,7 @@ void Client::AI_Process() } return; } + } } From e0237ce5269425a9e2abdc8e7c5d7d9f1b18535b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 28 Jun 2017 19:58:06 -0400 Subject: [PATCH 101/218] Quick fix for AE LOS issue --- zone/effects.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 7dfc4e617..95eb44ac8 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -771,7 +771,9 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ if (bad) { if (!caster->IsAttackAllowed(curmob, true)) continue; - if (!spells[spell_id].npc_no_los && !caster->CheckLosFN(position.x, position.y, position.z, curmob->GetSize())) + if (center && !spells[spell_id].npc_no_los && !center->CheckLosFN(curmob)) + continue; + if (!center && !spells[spell_id].npc_no_los && !caster->CheckLosFN(caster->GetTargetRingX(), caster->GetTargetRingY(), caster->GetTargetRingZ(), curmob->GetSize())) continue; } else { // check to stop casting beneficial ae buffs (to wit: bard songs) on enemies... // This does not check faction for beneficial AE buffs..only agro and attackable. From 5a9744b429094fcbe791f293949f2e8e39568be5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jun 2017 21:23:02 -0500 Subject: [PATCH 102/218] Add a fail-safe for dynamic zone shutdown timers --- zone/net.cpp | 3 +++ zone/zone.cpp | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/zone/net.cpp b/zone/net.cpp index f51d50bb4..eafdde807 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -541,6 +541,9 @@ int main(int argc, char** argv) { if (previous_loaded && !current_loaded) { process_timer.Stop(); process_timer.Start(1000, true); + + uint32 shutdown_timer = database.getZoneShutDownDelay(zone->GetZoneID(), zone->GetInstanceVersion()); + zone->StartShutdownTimer(shutdown_timer); } else if (!previous_loaded && current_loaded) { process_timer.Stop(); diff --git a/zone/zone.cpp b/zone/zone.cpp index 086754d55..6a0754dea 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1414,11 +1414,11 @@ bool Zone::HasWeather() void Zone::StartShutdownTimer(uint32 set_time) { if (set_time > autoshutdown_timer.GetRemainingTime()) { - if (set_time == (RuleI(Zone, AutoShutdownDelay))) - { + if (set_time == (RuleI(Zone, AutoShutdownDelay))) { set_time = database.getZoneShutDownDelay(GetZoneID(), GetInstanceVersion()); } - autoshutdown_timer.Start(set_time, false); + autoshutdown_timer.SetTimer(set_time); + Log(Logs::General, Logs::Zone_Server, "Zone::StartShutdownTimer set to %u", set_time); } } From 9b1a449fbaa5a9aee5173fda93b269787c827647 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 28 Jun 2017 21:44:31 -0500 Subject: [PATCH 103/218] Fix Z when following during pull, not when engaged and stationary or moving slightly --- zone/mob_ai.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 07f89ca63..20d22c42f 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -996,8 +996,11 @@ void Mob::AI_Process() { if (engaged) { + /* Fix Z when following during pull, not when engaged and stationary */ if (moving && fix_z_timer_engaged.Check()) - this->FixZ(); + if(this->GetTarget()) + if(DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) + this->FixZ(); if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); From 5c6f6848084770ae7822197af7664a57d30b28ef Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 29 Jun 2017 14:13:55 -0700 Subject: [PATCH 104/218] Some work on congestion avoidance now uses a sliding congestion window instead of a static one --- common/net/daybreak_connection.cpp | 78 ++++++++++++++++++++++++------ common/net/daybreak_connection.h | 11 ++--- 2 files changed, 68 insertions(+), 21 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 82a7e2d12..57f83e9d1 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -283,6 +283,9 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[0] = 0; m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); + m_outstanding_bytes = 0; + m_cwnd = m_max_packet_size; + m_ssthresh = m_owner->m_options.max_outstanding_bytes; } //new connection made as client @@ -306,6 +309,9 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[0] = 0; m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); + m_outstanding_bytes = 0; + m_cwnd = m_max_packet_size; + m_ssthresh = m_owner->m_options.max_outstanding_bytes; } EQ::Net::DaybreakConnection::~DaybreakConnection() @@ -463,20 +469,16 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() { for (int i = 0; i < 4; ++i) { auto stream = &m_streams[i]; - - if (stream->outstanding_bytes == 0) { - continue; - } while (!stream->buffered_packets.empty()) { auto &buff = stream->buffered_packets.front(); - if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || - stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { + if (m_outstanding_bytes + buff.sent.packet.Length() >= m_cwnd) { break; } - stream->outstanding_bytes += buff.sent.packet.Length(); + LogF(Logs::Detail, Logs::Netcode, "Sending buffered packet {0} on stream {1}", buff.seq, i); + m_outstanding_bytes += buff.sent.packet.Length(); stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); InternalSend(buff.sent.packet); stream->buffered_packets.pop_front(); @@ -1051,7 +1053,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + + LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size"); + m_ssthresh = m_cwnd / 2; + m_cwnd = m_cwnd / 2; } } else { @@ -1065,7 +1070,10 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) InternalBufferedSend(entry.second.packet); entry.second.last_sent = now; entry.second.times_resent++; - m_rolling_ping += 100; + + LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size"); + m_ssthresh = m_cwnd / 2; + m_cwnd = m_cwnd / 2; } } } @@ -1086,10 +1094,29 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; + m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; - s->outstanding_bytes -= iter->second.packet.Length(); + m_outstanding_bytes -= iter->second.packet.Length(); iter = s->outstanding_packets.erase(iter); + if (m_cwnd < m_ssthresh) { + //Still in slow start mode + m_cwnd *= 2; + if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { + m_cwnd = m_owner->m_options.max_outstanding_bytes; + } + + LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); + } + else { + m_cwnd += m_max_packet_size; + + if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { + m_cwnd = m_owner->m_options.max_outstanding_bytes; + } + + LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); + } + ProcessOutboundQueue(); } else { @@ -1111,8 +1138,28 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - s->outstanding_bytes -= iter->second.packet.Length(); + m_outstanding_bytes -= iter->second.packet.Length(); s->outstanding_packets.erase(iter); + + if (m_cwnd < m_ssthresh) { + //Still in slow start mode + m_cwnd *= 2; + if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { + m_cwnd = m_owner->m_options.max_outstanding_bytes; + } + + LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); + } + else { + m_cwnd += m_max_packet_size; + + if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { + m_cwnd = m_owner->m_options.max_outstanding_bytes; + } + + LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); + } + ProcessOutboundQueue(); } } @@ -1122,16 +1169,17 @@ void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, Daybrea auto s = &m_streams[stream]; //If we can send the packet then send it //else buffer it to be sent when we can send it - if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { + if (m_outstanding_bytes + sent.packet.Length() > m_cwnd) { //Would go over one of the limits, buffer this packet. DaybreakBufferedPacket bp; bp.sent = std::move(sent); bp.seq = seq; s->buffered_packets.push_back(bp); + LogF(Logs::Detail, Logs::Netcode, "Buffering packet {0} on stream {1}", seq, stream); return; } - s->outstanding_bytes += sent.packet.Length(); + m_outstanding_bytes += sent.packet.Length(); s->outstanding_packets.insert(std::make_pair(seq, sent)); InternalSend(sent.packet); } @@ -1438,4 +1486,4 @@ EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t exp } return SequencePast; -} \ No newline at end of file +} diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 2ec7f200f..c337ed262 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -136,7 +136,10 @@ namespace EQ size_t m_resend_delay; size_t m_rolling_ping; Timestamp m_close_time; - + size_t m_outstanding_bytes; + size_t m_cwnd; + size_t m_ssthresh; + struct DaybreakSentPacket { DynamicPacket packet; @@ -158,7 +161,6 @@ namespace EQ sequence_out = 0; fragment_current_bytes = 0; fragment_total_bytes = 0; - outstanding_bytes = 0; } uint16_t sequence_in; @@ -171,7 +173,6 @@ namespace EQ uint32_t fragment_total_bytes; std::unordered_map outstanding_packets; - size_t outstanding_bytes; }; DaybreakStream m_streams[4]; @@ -236,8 +237,7 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_packets = 300; - max_outstanding_bytes = 200 * 512; + max_outstanding_bytes = 65535; } size_t max_packet_size; @@ -260,7 +260,6 @@ namespace EQ size_t connection_close_time; DaybreakEncodeType encode_passes[2]; int port; - size_t max_outstanding_packets; size_t max_outstanding_bytes; }; From 62531621660aa2f10f012921d079d966ac4bd974 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 29 Jun 2017 14:15:11 -0700 Subject: [PATCH 105/218] Change settings --- common/net/daybreak_connection.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 21ef8ffa6..9cf96b8f7 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -220,8 +220,8 @@ namespace EQ keepalive_delay_ms = 9000; resend_delay_ms = 150; resend_delay_factor = 1.5; - resend_delay_min = 150; - resend_delay_max = 1000; + resend_delay_min = 500; + resend_delay_max = 4000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; From 21ef83bcbecfd8e738f1ce3087d6e0cd1ba92241 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 30 Jun 2017 13:50:23 -0400 Subject: [PATCH 106/218] Fix /invite xtarget raid issue --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index cecd22b45..85956ea08 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4242,7 +4242,7 @@ bool Client::GroupFollow(Client* inviter) { RemoveAutoXTargets(); } - SetXTargetAutoMgr(GetXTargetAutoMgr()); + SetXTargetAutoMgr(raid->GetXTargetAutoMgr()); if (!GetXTargetAutoMgr()->empty()) SetDirtyAutoHaters(); From 8d680b22222f39ae1fec3434824434d3fd182ae7 Mon Sep 17 00:00:00 2001 From: KimLS Date: Fri, 30 Jun 2017 22:40:05 -0700 Subject: [PATCH 107/218] Some changes --- common/net/daybreak_connection.cpp | 16 +++++++++------- common/net/daybreak_connection.h | 4 ++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 57f83e9d1..2c8f59903 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -1089,18 +1089,19 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto order = CompareSequence(seq, iter->first); if (order != SequenceFuture) { - uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); + uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.first_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; + bool filled_window = m_outstanding_bytes >= m_cwnd; m_outstanding_bytes -= iter->second.packet.Length(); iter = s->outstanding_packets.erase(iter); if (m_cwnd < m_ssthresh) { //Still in slow start mode - m_cwnd *= 2; + m_cwnd += m_max_packet_size; if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { m_cwnd = m_owner->m_options.max_outstanding_bytes; } @@ -1108,7 +1109,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); } else { - m_cwnd += m_max_packet_size; + m_cwnd += std::max((size_t)1UL, (m_max_packet_size * m_max_packet_size) / m_cwnd); if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { m_cwnd = m_owner->m_options.max_outstanding_bytes; @@ -1131,19 +1132,20 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) auto s = &m_streams[stream]; auto iter = s->outstanding_packets.find(seq); if (iter != s->outstanding_packets.end()) { - uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); + uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.first_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; + m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; + bool filled_window = m_outstanding_bytes >= m_cwnd; m_outstanding_bytes -= iter->second.packet.Length(); s->outstanding_packets.erase(iter); if (m_cwnd < m_ssthresh) { //Still in slow start mode - m_cwnd *= 2; + m_cwnd += m_max_packet_size; if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { m_cwnd = m_owner->m_options.max_outstanding_bytes; } @@ -1151,7 +1153,7 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); } else { - m_cwnd += m_max_packet_size; + m_cwnd += std::max((size_t)1UL, (m_max_packet_size * m_max_packet_size) / m_cwnd); if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { m_cwnd = m_owner->m_options.max_outstanding_bytes; diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 9cf96b8f7..722b82c49 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -219,7 +219,7 @@ namespace EQ max_connection_count = 0; keepalive_delay_ms = 9000; resend_delay_ms = 150; - resend_delay_factor = 1.5; + resend_delay_factor = 1.25; resend_delay_min = 500; resend_delay_max = 4000; connect_delay_ms = 500; @@ -237,7 +237,7 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_bytes = 65535; + max_outstanding_bytes = 204800; } size_t max_packet_size; From 1f39a0cb3e1c52134f074fd6e5ae0cf2995e00f7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 1 Jul 2017 03:07:45 -0500 Subject: [PATCH 108/218] Fix some NPC and Corpse falling through the ground issues --- common/ruletypes.h | 1 + zone/attack.cpp | 8 +++++++- zone/bonuses.cpp | 8 ++++++++ zone/mob.cpp | 4 +++- zone/mob.h | 2 ++ zone/waypoints.cpp | 26 ++++++++++++++++++++++---- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index 945c2625a..b97c061bd 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -275,6 +275,7 @@ RULE_BOOL(Map, FixPathingZAtWaypoints, false) //alternative to `WhenLoading`, ac RULE_BOOL(Map, FixPathingZWhenMoving, false) //very CPU intensive, but helps hopping with widely spaced waypoints. RULE_BOOL(Map, FixPathingZOnSendTo, false) //try to repair Z coords in the SendTo routine as well. RULE_BOOL(Map, FixZWhenMoving, true) // Automatically fix NPC Z coordinates when moving/pathing/engaged (Far less CPU intensive than its predecessor) +RULE_BOOL(Map, MobZVisualDebug, false) // Displays spell effects determining whether or not NPC is hitting Best Z calcs (blue for hit, red for miss) RULE_REAL(Map, FixPathingZMaxDeltaMoving, 20) //at runtime while pathing: max change in Z to allow the BestZ code to apply. RULE_REAL(Map, FixPathingZMaxDeltaWaypoint, 20) //at runtime at each waypoint: max change in Z to allow the BestZ code to apply. RULE_REAL(Map, FixPathingZMaxDeltaSendTo, 20) //at runtime in SendTo: max change in Z to allow the BestZ code to apply. diff --git a/zone/attack.cpp b/zone/attack.cpp index 04cb65c9a..b681745e7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2392,7 +2392,13 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); float new_z = zone->zonemap->FindBestZ(dest, nullptr); corpse->SetFlyMode(1); - corpse->GMMove(m_Position.x, m_Position.y, new_z + 5, m_Position.w); + float size = GetSize(); + if (size > 10) + size = 10; + + new_z += size / 2; + + corpse->GMMove(m_Position.x, m_Position.y, new_z, m_Position.w); this->SetID(0); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 232b74b2a..22a323a81 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -48,6 +48,14 @@ void Mob::CalcBonuses() SetAttackTimer(); CalcAC(); + /* Fast walking NPC's are prone to disappear into walls/hills + We set this here because NPC's can cast spells to change walkspeed/runspeed + */ + float get_walk_speed = static_cast(0.025f * this->GetWalkspeed()); + if (get_walk_speed >= 0.9 && this->fix_z_timer.GetDuration() != 100) { + this->fix_z_timer.SetTimer(100); + } + rooted = FindType(SE_Root); } diff --git a/zone/mob.cpp b/zone/mob.cpp index c411f6a3c..7e04221c3 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -113,7 +113,7 @@ Mob::Mob(const char* in_name, tmHidden(-1), mitigation_ac(0), m_specialattacks(eSpecialAttacks::None), - fix_z_timer(1000), + fix_z_timer(300), fix_z_timer_engaged(100) { targeted = 0; @@ -121,6 +121,8 @@ Mob::Mob(const char* in_name, tar_vector=0; currently_fleeing = false; + last_z = 0; + AI_Init(); SetMoving(false); moved=false; diff --git a/zone/mob.h b/zone/mob.h index 109cd3656..bb07679c8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1067,6 +1067,8 @@ public: int GetWeaponDamage(Mob *against, const EQEmu::ItemData *weapon_item); int GetWeaponDamage(Mob *against, const EQEmu::ItemInstance *weapon_item, uint32 *hate = nullptr); + float last_z; + // Bots HealRotation methods #ifdef BOTS bool IsHealRotationTarget() { return (m_target_of_heal_rotation.use_count() && m_target_of_heal_rotation.get()); } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 6ceee481e..2271bced0 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -870,6 +870,7 @@ void Mob::SendToFixZ(float new_x, float new_y, float new_z) { } void Mob::FixZ() { + BenchTimer timer; timer.reset(); @@ -878,9 +879,8 @@ void Mob::FixZ() { if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) { - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - float new_z = zone->zonemap->FindBestZ(dest, nullptr); + float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 10); auto duration = timer.elapsed(); @@ -896,8 +896,26 @@ void Mob::FixZ() { duration ); - if ((new_z > -2000) && std::abs(new_z - dest.z) < RuleR(Map, FixPathingZMaxDeltaMoving)) - m_Position.z = new_z + 1; + float size = GetSize(); + if (size > 10) + size = 10; + + new_z += size / 2; + + if ((new_z > -2000) && std::abs(m_Position.z - new_z) < 35) { + if (RuleB(Map, MobZVisualDebug)) + this->SendAppearanceEffect(78, 0, 0, 0, 0); + + m_Position.z = new_z; + } + else { + if (RuleB(Map, MobZVisualDebug)) + this->SendAppearanceEffect(103, 0, 0, 0, 0); + + Log(Logs::General, Logs::Debug, "%s is failing to find Z %f", this->GetCleanName(), std::abs(m_Position.z - new_z)); + } + + last_z = m_Position.z; } } } From eddc9c9baf70265cbe280736f6fc7d86499f7e50 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 1 Jul 2017 13:46:39 -0700 Subject: [PATCH 109/218] Only increase cwnd when full, fiddled with formulas --- common/net/daybreak_connection.cpp | 119 +++++++++++++---------------- common/net/daybreak_connection.h | 3 + 2 files changed, 55 insertions(+), 67 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 2c8f59903..ab4790447 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -486,6 +486,44 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() } } +bool EQ::Net::DaybreakConnection::CongestionWindowFull() const +{ + for (int i = 0; i < 4; ++i) { + auto stream = &m_streams[i]; + + if (!stream->buffered_packets.empty()) { + //We had to buffer packets and we only do that if the window was full + return true; + } + } + + return false; +} + +void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() +{ + if (!CongestionWindowFull()) { + return; + } + + if (m_cwnd < m_ssthresh) { + m_cwnd += m_cwnd; + } + else { + m_cwnd += m_max_packet_size; + } + + m_cwnd = EQEmu::Clamp(m_cwnd, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); + LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); +} + +void EQ::Net::DaybreakConnection::ReduceCongestionWindow() +{ + m_cwnd = EQEmu::Clamp(m_cwnd / 2, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); + m_ssthresh = m_cwnd; + LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); +} + void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) { auto s = &m_streams[stream]; @@ -1048,33 +1086,17 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto s = &m_streams[stream]; for (auto &entry : s->outstanding_packets) { auto time_since_last_send = std::chrono::duration_cast(now - entry.second.last_sent); - if (entry.second.times_resent == 0) { - if ((size_t)time_since_last_send.count() > m_resend_delay) { - InternalBufferedSend(entry.second.packet); - entry.second.last_sent = now; - entry.second.times_resent++; - - LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size"); - m_ssthresh = m_cwnd / 2; - m_cwnd = m_cwnd / 2; - } + auto time_since_first_sent = std::chrono::duration_cast(now - entry.second.first_sent); + if (time_since_first_sent.count() >= m_owner->m_options.resend_timeout) { + Close(); + return; } - else { - auto time_since_first_sent = std::chrono::duration_cast(now - entry.second.first_sent); - if (time_since_first_sent.count() >= m_owner->m_options.resend_timeout) { - Close(); - return; - } - if ((size_t)time_since_last_send.count() > m_resend_delay) { - InternalBufferedSend(entry.second.packet); - entry.second.last_sent = now; - entry.second.times_resent++; - - LogF(Logs::Detail, Logs::Netcode, "Congestion detected, reducing window size"); - m_ssthresh = m_cwnd / 2; - m_cwnd = m_cwnd / 2; - } + if ((size_t)time_since_last_send.count() > m_resend_delay) { + InternalBufferedSend(entry.second.packet); + entry.second.last_sent = now; + entry.second.times_resent++; + ReduceCongestionWindow(); } } } @@ -1089,35 +1111,17 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto order = CompareSequence(seq, iter->first); if (order != SequenceFuture) { - uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.first_sent).count(); + uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; - bool filled_window = m_outstanding_bytes >= m_cwnd; m_outstanding_bytes -= iter->second.packet.Length(); iter = s->outstanding_packets.erase(iter); - if (m_cwnd < m_ssthresh) { - //Still in slow start mode - m_cwnd += m_max_packet_size; - if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { - m_cwnd = m_owner->m_options.max_outstanding_bytes; - } - - LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); - } - else { - m_cwnd += std::max((size_t)1UL, (m_max_packet_size * m_max_packet_size) / m_cwnd); - - if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { - m_cwnd = m_owner->m_options.max_outstanding_bytes; - } - - LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); - } + IncreaseCongestionWindow(); ProcessOutboundQueue(); } else { @@ -1132,36 +1136,17 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) auto s = &m_streams[stream]; auto iter = s->outstanding_packets.find(seq); if (iter != s->outstanding_packets.end()) { - uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.first_sent).count(); + uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; + m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - bool filled_window = m_outstanding_bytes >= m_cwnd; m_outstanding_bytes -= iter->second.packet.Length(); s->outstanding_packets.erase(iter); - if (m_cwnd < m_ssthresh) { - //Still in slow start mode - m_cwnd += m_max_packet_size; - if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { - m_cwnd = m_owner->m_options.max_outstanding_bytes; - } - - LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); - } - else { - m_cwnd += std::max((size_t)1UL, (m_max_packet_size * m_max_packet_size) / m_cwnd); - - if (m_cwnd > m_owner->m_options.max_outstanding_bytes) { - m_cwnd = m_owner->m_options.max_outstanding_bytes; - } - - LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); - } - + IncreaseCongestionWindow(); ProcessOutboundQueue(); } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 722b82c49..b190e7900 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -182,6 +182,9 @@ namespace EQ void ProcessPacket(Packet &p); void ProcessInboundQueue(); void ProcessOutboundQueue(); + bool CongestionWindowFull() const; + void IncreaseCongestionWindow(); + void ReduceCongestionWindow(); void RemoveFromQueue(int stream, uint16_t seq); void AddToQueue(int stream, uint16_t seq, const Packet &p); void ProcessDecodedPacket(const Packet &p); From c3c60b331a60fc9add9c0369897d5d57a9bc2c52 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 1 Jul 2017 15:57:41 -0500 Subject: [PATCH 110/218] Resolve issues with NPC's hopping to the ceiling in small corridors Improved grounding issues with NPC's during combat Improved scenarios where NPC's need to be dragged out of the ground - they should correct themselves far more consistently - Scenarios where an NPC is coming up from the bottom floor, or from the top floor, they will correct much better - A video of these tests can be found here: https://www.youtube.com/watch?v=HtC7bVNM7ZQ&feature=youtu.be --- changelog.txt | 7 +++++++ zone/mob.h | 1 + zone/mob_ai.cpp | 11 +++++++++-- zone/waypoints.cpp | 4 ++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index 0614ff4a8..b561c34ab 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,12 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/1/2017 == +Akkadius: Resolve issues with NPC's hopping to the ceiling in small corridors +Akkadius: Improved grounding issues with NPC's during combat +Akkadius: Improved scenarios where NPC's need to be dragged out of the ground - they should correct themselves far more consistently + - Scenarios where an NPC is coming up from the bottom floor, or from the top floor, they will correct much better + - A video of these tests can be found here: https://www.youtube.com/watch?v=HtC7bVNM7ZQ&feature=youtu.be + == 6/28/2017 == Akkadius: Fixed issues with Z correctness when NPCs are pathing on normal grids Akkadius: Fixed issues with Z correctness when NPCs are engaged with players following diff --git a/zone/mob.h b/zone/mob.h index bb07679c8..aa4b3fb29 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -492,6 +492,7 @@ public: inline const float GetTarVZ() const { return m_TargetV.z; } inline const float GetTarVector() const { return tar_vector; } inline const uint8 GetTarNDX() const { return tar_ndx; } + inline const int8 GetFlyMode() const { return flymode; } bool IsBoat() const; //Group diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 20d22c42f..58d685df4 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -998,9 +998,16 @@ void Mob::AI_Process() { /* Fix Z when following during pull, not when engaged and stationary */ if (moving && fix_z_timer_engaged.Check()) - if(this->GetTarget()) - if(DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) + if (this->GetTarget()) { + /* If we are engaged, moving and following client, let's look for best Z more often */ + if (DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) { this->FixZ(); + } + /* If we are close to client and our Z differences aren't big, match the client */ + else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) < 20){ + this->m_Position.z = this->GetTarget()->GetZ(); + } + } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 2271bced0..c034c1578 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -879,8 +879,8 @@ void Mob::FixZ() { if (!RuleB(Watermap, CheckForWaterWhenMoving) || !zone->HasWaterMap() || (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_Position)))) { - - float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 10); + /* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors */ + float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 5); auto duration = timer.elapsed(); From aed1959dbec91b0d4d60174bc90101011b949ed3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 3 Jul 2017 01:53:41 -0500 Subject: [PATCH 111/218] Fix issues with underground NPC corpses - add command #fixcorpses to fix nearby NPC corpses of the player (this should be a seldom need) --- zone/attack.cpp | 12 ------------ zone/command.cpp | 6 ++++++ zone/command.h | 1 + zone/entity.cpp | 16 ++++++++++++++++ zone/entity.h | 1 + 5 files changed, 24 insertions(+), 12 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index b681745e7..819623148 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -2388,18 +2388,6 @@ bool NPC::Death(Mob* killer_mob, int32 damage, uint16 spell, EQEmu::skills::Skil entity_list.UnMarkNPC(GetID()); entity_list.RemoveNPC(GetID()); - /* Fix Z on Corpse Creation */ - glm::vec3 dest(m_Position.x, m_Position.y, m_Position.z); - float new_z = zone->zonemap->FindBestZ(dest, nullptr); - corpse->SetFlyMode(1); - float size = GetSize(); - if (size > 10) - size = 10; - - new_z += size / 2; - - corpse->GMMove(m_Position.x, m_Position.y, new_z, m_Position.w); - this->SetID(0); if (killer != 0 && emoteid != 0) diff --git a/zone/command.cpp b/zone/command.cpp index a80a0481e..b6c79e235 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -173,6 +173,7 @@ int command_init(void) command_add("checklos", "- Check for line of sight to your target", 50, command_checklos) || command_add("clearinvsnapshots", "[use rule] - Clear inventory snapshot history (true - elapsed entries, false - all entries)", 200, command_clearinvsnapshots) || command_add("corpse", "- Manipulate corpses, use with no arguments for help", 50, command_corpse) || + command_add("corpsefix", "Attempts to bring corpses from underneath the ground within close proximity of the player", 0, command_corpsefix) || command_add("crashtest", "- Crash the zoneserver", 255, command_crashtest) || command_add("cvs", "- Summary of client versions currently online.", 200, command_cvs) || command_add("damage", "[amount] - Damage your target", 100, command_damage) || @@ -2977,6 +2978,11 @@ void command_reloadqst(Client *c, const Seperator *sep) } +void command_corpsefix(Client *c, const Seperator *sep) +{ + entity_list.CorpseFix(c); +} + void command_reloadworld(Client *c, const Seperator *sep) { c->Message(0, "Reloading quest cache and repopping zones worldwide."); diff --git a/zone/command.h b/zone/command.h index 987adf674..0a850fbca 100644 --- a/zone/command.h +++ b/zone/command.h @@ -72,6 +72,7 @@ void command_checklos(Client *c, const Seperator *sep); void command_clearinvsnapshots(Client *c, const Seperator *sep); void command_connectworldserver(Client *c, const Seperator *sep); void command_corpse(Client *c, const Seperator *sep); +void command_corpsefix(Client *c, const Seperator *sep); void command_crashtest(Client *c, const Seperator *sep); void command_cvs(Client *c, const Seperator *sep); void command_d1(Client *c, const Seperator *sep); diff --git a/zone/entity.cpp b/zone/entity.cpp index 5a8e9fa5e..35d67a5d3 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2845,6 +2845,22 @@ int32 EntityList::DeleteNPCCorpses() return x; } +void EntityList::CorpseFix(Client* c) +{ + + auto it = corpse_list.begin(); + while (it != corpse_list.end()) { + Corpse* corpse = it->second; + if (corpse->IsNPCCorpse()) { + if (DistanceNoZ(c->GetPosition(), corpse->GetPosition()) < 100) { + c->Message(15, "Attempting to fix %s", it->second->GetCleanName()); + corpse->GMMove(corpse->GetX(), corpse->GetY(), c->GetZ() + 2, 0); + } + } + ++it; + } +} + // returns the number of corpses deleted. A negative number indicates an error code. int32 EntityList::DeletePlayerCorpses() { diff --git a/zone/entity.h b/zone/entity.h index e2224d05d..7752e97b1 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -386,6 +386,7 @@ public: void FindPathsToAllNPCs(); int32 DeleteNPCCorpses(); int32 DeletePlayerCorpses(); + void CorpseFix(Client* c); void WriteEntityIDs(); void HalveAggro(Mob* who); void DoubleAggro(Mob* who); From 83605831ec9141975845eee75fa22a8947a6394d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 3 Jul 2017 14:27:11 -0500 Subject: [PATCH 112/218] Remove some of the legacy Z adjust functions conflicting with newer changes --- zone/waypoints.cpp | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c034c1578..419735a69 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -212,22 +212,6 @@ void NPC::UpdateWaypoint(int wp_index) cur_wp_pause = cur->pause; Log(Logs::Detail, Logs::AI, "Next waypoint %d: (%.3f, %.3f, %.3f, %.3f)", wp_index, m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z, m_CurrentWayPoint.w); - //fix up pathing Z - if (zone->HasMap() && RuleB(Map, FixPathingZAtWaypoints) && !IsBoat()) - { - - if (!RuleB(Watermap, CheckForWaterAtWaypoints) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(glm::vec3(m_CurrentWayPoint)))) - { - glm::vec3 dest(m_CurrentWayPoint.x, m_CurrentWayPoint.y, m_CurrentWayPoint.z); - - float newz = zone->zonemap->FindBestZ(dest, nullptr); - - if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaWaypoint)) - m_CurrentWayPoint.z = newz + 1; - } - } - } void NPC::CalculateNewWaypoint() @@ -780,20 +764,6 @@ void NPC::AssignWaypoints(int32 grid) newwp.y = atof(row[1]); newwp.z = atof(row[2]); - if (zone->HasMap() && RuleB(Map, FixPathingZWhenLoading)) - { - auto positon = glm::vec3(newwp.x, newwp.y, newwp.z); - if (!RuleB(Watermap, CheckWaypointsInWaterWhenLoading) || !zone->HasWaterMap() || - (zone->HasWaterMap() && !zone->watermap->InWater(positon))) - { - glm::vec3 dest(newwp.x, newwp.y, newwp.z); - float newz = zone->zonemap->FindBestZ(dest, nullptr); - - if ((newz > -2000) && std::abs(newz - dest.z) < RuleR(Map, FixPathingZMaxDeltaLoading)) - newwp.z = newz + 1; - } - } - newwp.pause = atoi(row[3]); newwp.heading = atof(row[4]); Waypoints.push_back(newwp); From d11e2410bf444b0cb4feed06398f24c73601ed7a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 3 Jul 2017 17:46:16 -0400 Subject: [PATCH 113/218] Don't need the center check anymore --- zone/effects.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/effects.cpp b/zone/effects.cpp index 95eb44ac8..adc7b16b2 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -730,8 +730,6 @@ void EntityList::AESpell(Mob *caster, Mob *center, uint16 spell_id, bool affect_ // test to fix possible cause of random zone crashes..external methods accessing client properties before they're initialized if (curmob->IsClient() && !curmob->CastToClient()->ClientFinishedLoading()) continue; - if (curmob == center) //do not affect center - continue; if (curmob == caster && !affect_caster) //watch for caster too continue; if (spells[spell_id].targettype == ST_TargetAENoPlayersPets && curmob->IsPetOwnerClient()) From cfd2f8776ed58c8c8c32435759f0b28c3c808c31 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 3 Jul 2017 19:36:35 -0500 Subject: [PATCH 114/218] More Z fixes --- zone/waypoints.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 419735a69..9d272472f 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -866,12 +866,6 @@ void Mob::FixZ() { duration ); - float size = GetSize(); - if (size > 10) - size = 10; - - new_z += size / 2; - if ((new_z > -2000) && std::abs(m_Position.z - new_z) < 35) { if (RuleB(Map, MobZVisualDebug)) this->SendAppearanceEffect(78, 0, 0, 0, 0); From 3dcc2edcebbdf23bf42404c2750e6e0cc2037dae Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 3 Jul 2017 19:55:28 -0500 Subject: [PATCH 115/218] Add rule Spells:ReflectMessagesClose - Live functionality is for reflect messages to show to players within close proximity, false shows just player reflecting --- common/ruletypes.h | 1 + zone/spells.cpp | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index b97c061bd..c5fc1b9ce 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -350,6 +350,7 @@ RULE_INT(Spells, MaxTotalSlotsNPC, 60) // default to Tit's limit RULE_INT(Spells, MaxTotalSlotsPET, 30) // default to Tit's limit RULE_BOOL (Spells, EnableBlockedBuffs, true) RULE_INT(Spells, ReflectType, 3) //0 = disabled, 1 = single target player spells only, 2 = all player spells, 3 = all single target spells, 4 = all spells +RULE_BOOL(Spells, ReflectMessagesClose, true) // Live functionality is for Reflect messages to show to players within close proximity, false shows just player reflecting RULE_INT(Spells, VirusSpreadDistance, 30) // The distance a viral spell will jump to its next victim RULE_BOOL(Spells, LiveLikeFocusEffects, true) // Determines whether specific healing, dmg and mana reduction focuses are randomized RULE_INT(Spells, BaseImmunityLevel, 55) // The level that targets start to be immune to stun, fear and mez spells with a max level of 0. diff --git a/zone/spells.cpp b/zone/spells.cpp index 5504422e0..65626d43b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3804,8 +3804,22 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r break; } if (reflect_chance) { - entity_list.MessageClose_StringID(this, false, RuleI(Range, SpellMessages), MT_Spells, - SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName()); + + if (RuleB(Spells, ReflectMessagesClose)) { + entity_list.MessageClose_StringID( + this, /* Sender */ + false, /* Skip Sender */ + RuleI(Range, SpellMessages), /* Range */ + MT_Spells, /* Type */ + SPELL_REFLECT, /* String ID */ + GetCleanName(), /* Message 1 */ + spelltar->GetCleanName() /* Message 2 */ + ); + } + else { + Message_StringID(MT_Spells, SPELL_REFLECT, GetCleanName(), spelltar->GetCleanName()); + } + CheckNumHitsRemaining(NumHit::ReflectSpell); // caster actually appears to change // ex. During OMM fight you click your reflect mask and you get the recourse from the reflected From c6bb4a647076e5bb4d54588855cbdf6d63d4566d Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 3 Jul 2017 21:31:25 -0700 Subject: [PATCH 116/218] Some tweaks --- common/net/daybreak_connection.cpp | 25 ++++--------------------- common/net/daybreak_connection.h | 7 +++---- 2 files changed, 7 insertions(+), 25 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index ab4790447..c8e8b1a6d 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -486,31 +486,14 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() } } -bool EQ::Net::DaybreakConnection::CongestionWindowFull() const -{ - for (int i = 0; i < 4; ++i) { - auto stream = &m_streams[i]; - - if (!stream->buffered_packets.empty()) { - //We had to buffer packets and we only do that if the window was full - return true; - } - } - - return false; -} - void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() { - if (!CongestionWindowFull()) { - return; - } - if (m_cwnd < m_ssthresh) { - m_cwnd += m_cwnd; + m_cwnd += m_max_packet_size; } else { - m_cwnd += m_max_packet_size; + size_t denom = std::max(m_cwnd, (size_t)1U); + m_cwnd += std::max((size_t)(m_max_packet_size * m_max_packet_size / denom), (size_t)1U); } m_cwnd = EQEmu::Clamp(m_cwnd, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); @@ -519,7 +502,7 @@ void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() void EQ::Net::DaybreakConnection::ReduceCongestionWindow() { - m_cwnd = EQEmu::Clamp(m_cwnd / 2, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); + m_cwnd = EQEmu::Clamp((size_t)m_max_packet_size, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); m_ssthresh = m_cwnd; LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index b190e7900..8cdbcb33a 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -182,7 +182,6 @@ namespace EQ void ProcessPacket(Packet &p); void ProcessInboundQueue(); void ProcessOutboundQueue(); - bool CongestionWindowFull() const; void IncreaseCongestionWindow(); void ReduceCongestionWindow(); void RemoveFromQueue(int stream, uint16_t seq); @@ -224,7 +223,7 @@ namespace EQ resend_delay_ms = 150; resend_delay_factor = 1.25; resend_delay_min = 500; - resend_delay_max = 4000; + resend_delay_max = 5000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -234,13 +233,13 @@ namespace EQ encode_passes[1] = DaybreakEncodeType::EncodeNone; port = 0; hold_size = 448; - hold_length_ms = 10; + hold_length_ms = 40; simulated_in_packet_loss = 0; simulated_out_packet_loss = 0; tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_bytes = 204800; + max_outstanding_bytes = 48000; } size_t max_packet_size; From eff800019617487f3c9a1e526bf445fcfa03f6d5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 4 Jul 2017 13:01:34 -0400 Subject: [PATCH 117/218] Fix PB AE --- zone/beacon.cpp | 4 +++- zone/spells.cpp | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/zone/beacon.cpp b/zone/beacon.cpp index e5ea9f38f..36075dca5 100644 --- a/zone/beacon.cpp +++ b/zone/beacon.cpp @@ -96,7 +96,9 @@ bool Beacon::Process() Mob *caster = entity_list.GetMob(caster_id); if(caster && spell_iterations-- && max_targets) { - bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()); //NPC AE spells do not affect the NPC caster + // NPCs should never be affected by an AE they cast. PB AEs shouldn't affect caster either + // I don't think any other cases that get here matter + bool affect_caster = (!caster->IsNPC() && !caster->IsAIControlled()) && spells[spell_id].targettype != ST_AECaster; entity_list.AESpell(caster, this, spell_id, affect_caster, resist_adjust, &max_targets); } else diff --git a/zone/spells.cpp b/zone/spells.cpp index 65626d43b..58121a760 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -2241,7 +2241,9 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, CastingSlot slot, ui if(ae_center && ae_center == this && IsBeneficialSpell(spell_id)) SpellOnTarget(spell_id, this); - bool affect_caster = !IsNPC(); //NPC AE spells do not affect the NPC caster + // NPCs should never be affected by an AE they cast. PB AEs shouldn't affect caster either + // I don't think any other cases that get here matter + bool affect_caster = !IsNPC() && spells[spell_id].targettype != ST_AECaster; if (spells[spell_id].targettype == ST_AETargetHateList) hate_list.SpellCast(this, spell_id, spells[spell_id].aoerange, ae_center); From 10b01e62dfa95d859b2f3dc02e88cc1ff25a3459 Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 4 Jul 2017 12:45:23 -0700 Subject: [PATCH 118/218] More tweaks --- common/net/daybreak_connection.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index c8e8b1a6d..73b3b7b9b 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -284,7 +284,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); m_outstanding_bytes = 0; - m_cwnd = m_max_packet_size; + m_cwnd = m_max_packet_size * 4; m_ssthresh = m_owner->m_options.max_outstanding_bytes; } @@ -310,7 +310,7 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); m_outstanding_bytes = 0; - m_cwnd = m_max_packet_size; + m_cwnd = m_max_packet_size * 4; m_ssthresh = m_owner->m_options.max_outstanding_bytes; } @@ -502,8 +502,9 @@ void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() void EQ::Net::DaybreakConnection::ReduceCongestionWindow() { - m_cwnd = EQEmu::Clamp((size_t)m_max_packet_size, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); - m_ssthresh = m_cwnd; + m_ssthresh = EQEmu::ClampLower(m_cwnd / 2, (size_t)(8 * m_max_packet_size)); + m_cwnd = (size_t)m_max_packet_size * 4; + LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); } From 49505a7a45b83457705f6d033ce8461f4eacbc1d Mon Sep 17 00:00:00 2001 From: KimLS Date: Tue, 4 Jul 2017 21:03:49 -0700 Subject: [PATCH 119/218] Bug fix plus tweak to reset cwnd when no longer needed --- common/net/daybreak_connection.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 73b3b7b9b..cac63451c 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -140,8 +140,9 @@ void EQ::Net::DaybreakConnectionManager::Process() if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) { connection->SendConnect(); } + + break; } - break; case StatusConnected: { if (m_options.keepalive_delay_ms != 0) { auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); @@ -372,6 +373,11 @@ void EQ::Net::DaybreakConnection::Process() } ProcessInboundQueue(); + + if (m_outstanding_bytes == 0) { + m_cwnd = 4 * m_max_packet_size; + m_ssthresh = m_owner->m_options.max_outstanding_bytes; + } } catch (std::exception ex) { LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what()); @@ -480,7 +486,7 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() LogF(Logs::Detail, Logs::Netcode, "Sending buffered packet {0} on stream {1}", buff.seq, i); m_outstanding_bytes += buff.sent.packet.Length(); stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); - InternalSend(buff.sent.packet); + InternalBufferedSend(buff.sent.packet); stream->buffered_packets.pop_front(); } } @@ -502,7 +508,7 @@ void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() void EQ::Net::DaybreakConnection::ReduceCongestionWindow() { - m_ssthresh = EQEmu::ClampLower(m_cwnd / 2, (size_t)(8 * m_max_packet_size)); + m_ssthresh = std::max((size_t)m_cwnd / 2, (size_t)m_max_packet_size * 2); m_cwnd = (size_t)m_max_packet_size * 4; LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); From 4a84c311b26b4e1e38d1295acf1e1c085f9116aa Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 5 Jul 2017 18:26:50 -0400 Subject: [PATCH 120/218] Change to allow pets to use better of db/oocregen if oocregen is turned on in the rule_set. --- zone/npc.cpp | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index de4ad4e7c..269f3fb84 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -615,37 +615,54 @@ bool NPC::Process() if (currently_fleeing) ProcessFlee(); - uint32 bonus = 0; + uint32 sitting_bonus = 0; + uint32 petbonus = 0; + uint32 bestregen = 0; + int32 dbregen = GetNPCHPRegen(); if (GetAppearance() == eaSitting) - bonus += 3; + sitting_bonus += 3; int32 OOCRegen = 0; if (oocregen > 0) { //should pull from Mob class OOCRegen += GetMaxHP() * oocregen / 100; } - //Lieka Edit:Fixing NPC regen.NPCs should regen to full during a set duration, not based on their HPs.Increase NPC's HPs by % of total HPs / tick. + + //Lieka Edit:Fixing NPC regen.NPCs should regen to full during + // a set duration, not based on their HPs.Increase NPC's HPs by + // % of total HPs / tick. + // + // Noudess Edit: If oocregen set in db, apply to pets as well. + // This allows the obscene #s for pets in the db to be tweaked + // while maintaining a decent ooc regen. + + bestregen = std::max(dbregen,OOCRegen); + if ((GetHP() < GetMaxHP()) && !IsPet()) { - if (!IsEngaged()) {//NPC out of combat - if (GetNPCHPRegen() > OOCRegen) - SetHP(GetHP() + GetNPCHPRegen()); - else - SetHP(GetHP() + OOCRegen); - } + if (!IsEngaged()) + SetHP(GetHP() + bestregen + sitting_bonus); else - SetHP(GetHP() + GetNPCHPRegen()); + SetHP(GetHP() + dbregen); } else if (GetHP() < GetMaxHP() && GetOwnerID() != 0) { - if (!IsEngaged()) //pet - SetHP(GetHP() + GetNPCHPRegen() + bonus + (GetLevel() / 5)); + if (!IsEngaged()) { + if (oocregen > 0) { + petbonus = std::max(OOCRegen,dbregen); + } + else { + petbonus = dbregen + (GetLevel() / 5); + } + + SetHP(GetHP() + sitting_bonus + petbonus); + } else - SetHP(GetHP() + GetNPCHPRegen() + bonus); + SetHP(GetHP() + dbregen); } else - SetHP(GetHP() + GetNPCHPRegen()); + SetHP(GetHP() + dbregen + sitting_bonus); if (GetMana() < GetMaxMana()) { - SetMana(GetMana() + mana_regen + bonus); + SetMana(GetMana() + mana_regen + sitting_bonus); } From 94b5684b421b7a59207709ea382a417381509463 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 5 Jul 2017 18:59:43 -0500 Subject: [PATCH 121/218] Fix fighting on hill issues --- zone/mob_ai.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 58d685df4..dd814df12 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1003,10 +1003,6 @@ void Mob::AI_Process() { if (DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) { this->FixZ(); } - /* If we are close to client and our Z differences aren't big, match the client */ - else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) < 20){ - this->m_Position.z = this->GetTarget()->GetZ(); - } } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) From 5542107f02581537b08c8a512514a8770faa496b Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Wed, 5 Jul 2017 21:26:10 -0400 Subject: [PATCH 122/218] Remove names --- zone/npc.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/npc.cpp b/zone/npc.cpp index 269f3fb84..97dd647ec 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -628,11 +628,11 @@ bool NPC::Process() OOCRegen += GetMaxHP() * oocregen / 100; } - //Lieka Edit:Fixing NPC regen.NPCs should regen to full during + // Fixing NPC regen.NPCs should regen to full during // a set duration, not based on their HPs.Increase NPC's HPs by // % of total HPs / tick. // - // Noudess Edit: If oocregen set in db, apply to pets as well. + // If oocregen set in db, apply to pets as well. // This allows the obscene #s for pets in the db to be tweaked // while maintaining a decent ooc regen. From a7c0e82c9ebbde140ab83e2b7358e11eef51166b Mon Sep 17 00:00:00 2001 From: KimLS Date: Wed, 5 Jul 2017 20:24:39 -0700 Subject: [PATCH 123/218] Tweaks and bug fixes --- common/net/daybreak_connection.cpp | 46 +++++++++++++++++++----------- common/net/daybreak_connection.h | 5 +++- 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index cac63451c..34f325434 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -285,7 +285,8 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); m_outstanding_bytes = 0; - m_cwnd = m_max_packet_size * 4; + m_outstanding_packets = 0; + m_cwnd = m_max_packet_size; m_ssthresh = m_owner->m_options.max_outstanding_bytes; } @@ -311,7 +312,8 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); m_outstanding_bytes = 0; - m_cwnd = m_max_packet_size * 4; + m_outstanding_packets = 0; + m_cwnd = m_max_packet_size; m_ssthresh = m_owner->m_options.max_outstanding_bytes; } @@ -373,11 +375,6 @@ void EQ::Net::DaybreakConnection::Process() } ProcessInboundQueue(); - - if (m_outstanding_bytes == 0) { - m_cwnd = 4 * m_max_packet_size; - m_ssthresh = m_owner->m_options.max_outstanding_bytes; - } } catch (std::exception ex) { LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what()); @@ -479,12 +476,17 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() while (!stream->buffered_packets.empty()) { auto &buff = stream->buffered_packets.front(); + if (m_outstanding_packets + 1 >= m_owner->m_options.max_outstanding_packets) { + break; + } + if (m_outstanding_bytes + buff.sent.packet.Length() >= m_cwnd) { break; } LogF(Logs::Detail, Logs::Netcode, "Sending buffered packet {0} on stream {1}", buff.seq, i); m_outstanding_bytes += buff.sent.packet.Length(); + m_outstanding_packets++; stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); InternalBufferedSend(buff.sent.packet); stream->buffered_packets.pop_front(); @@ -495,11 +497,11 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() { if (m_cwnd < m_ssthresh) { - m_cwnd += m_max_packet_size; + m_cwnd *= 2; } else { size_t denom = std::max(m_cwnd, (size_t)1U); - m_cwnd += std::max((size_t)(m_max_packet_size * m_max_packet_size / denom), (size_t)1U); + m_cwnd += m_max_packet_size; } m_cwnd = EQEmu::Clamp(m_cwnd, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); @@ -509,7 +511,7 @@ void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() void EQ::Net::DaybreakConnection::ReduceCongestionWindow() { m_ssthresh = std::max((size_t)m_cwnd / 2, (size_t)m_max_packet_size * 2); - m_cwnd = (size_t)m_max_packet_size * 4; + m_cwnd = m_ssthresh; LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); } @@ -1097,6 +1099,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto now = Clock::now(); auto s = &m_streams[stream]; auto iter = s->outstanding_packets.begin(); + bool success = false; while (iter != s->outstanding_packets.end()) { auto order = CompareSequence(seq, iter->first); @@ -1109,15 +1112,19 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; m_outstanding_bytes -= iter->second.packet.Length(); + m_outstanding_packets--; iter = s->outstanding_packets.erase(iter); - - IncreaseCongestionWindow(); - ProcessOutboundQueue(); + success = true; } else { ++iter; } } + + if (success) { + IncreaseCongestionWindow(); + ProcessOutboundQueue(); + } } void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) @@ -1134,6 +1141,7 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; m_outstanding_bytes -= iter->second.packet.Length(); + m_outstanding_packets--; s->outstanding_packets.erase(iter); IncreaseCongestionWindow(); @@ -1144,9 +1152,8 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent) { auto s = &m_streams[stream]; - //If we can send the packet then send it - //else buffer it to be sent when we can send it - if (m_outstanding_bytes + sent.packet.Length() > m_cwnd) { + if (m_outstanding_bytes + sent.packet.Length() > m_cwnd || + m_outstanding_packets + 1 > m_owner->m_options.max_outstanding_packets) { //Would go over one of the limits, buffer this packet. DaybreakBufferedPacket bp; bp.sent = std::move(sent); @@ -1157,8 +1164,9 @@ void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, Daybrea } m_outstanding_bytes += sent.packet.Length(); + m_outstanding_packets++; s->outstanding_packets.insert(std::make_pair(seq, sent)); - InternalSend(sent.packet); + InternalBufferedSend(sent.packet); } void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) @@ -1212,6 +1220,10 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) FlushBuffer(); } + if (m_buffered_packets_length == 0) { + m_hold_time = Clock::now(); + } + DynamicPacket copy; copy.PutPacket(0, p); m_buffered_packets.push_back(copy); diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 8cdbcb33a..0e4b5b9b8 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -137,6 +137,7 @@ namespace EQ size_t m_rolling_ping; Timestamp m_close_time; size_t m_outstanding_bytes; + size_t m_outstanding_packets; size_t m_cwnd; size_t m_ssthresh; @@ -239,7 +240,8 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_bytes = 48000; + max_outstanding_bytes = 204800; + max_outstanding_packets = 400; } size_t max_packet_size; @@ -263,6 +265,7 @@ namespace EQ DaybreakEncodeType encode_passes[2]; int port; size_t max_outstanding_bytes; + size_t max_outstanding_packets; }; class DaybreakConnectionManager From f8b56371127af9a36a2dcb4f79da9da96c68d526 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 6 Jul 2017 10:13:33 -0500 Subject: [PATCH 124/218] Fix close combat positioning issues --- zone/mob_ai.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index dd814df12..d777c5f44 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1003,6 +1003,10 @@ void Mob::AI_Process() { if (DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) { this->FixZ(); } + /* If we are close to client and our Z differences aren't big, match the client */ + else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) <= 5) { + this->m_Position.z = this->GetTarget()->GetZ(); + } } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) From 786e03b0acc1dc5bd904ba5b03112d431de21fa0 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 6 Jul 2017 10:33:03 -0500 Subject: [PATCH 125/218] One more check --- zone/mob_ai.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index d777c5f44..6b3be34d8 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1004,7 +1004,7 @@ void Mob::AI_Process() { this->FixZ(); } /* If we are close to client and our Z differences aren't big, match the client */ - else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) <= 5) { + else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) <= 5 && this->GetTarget()->IsClient()) { this->m_Position.z = this->GetTarget()->GetZ(); } } From 3878bd0c76ea49f017011f3cb36af3df09a1aa7a Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 6 Jul 2017 17:25:00 -0700 Subject: [PATCH 126/218] Move to an older implementation --- common/net/daybreak_connection.cpp | 115 ++++++++++------------------- common/net/daybreak_connection.h | 26 +++---- 2 files changed, 50 insertions(+), 91 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 34f325434..f3329a976 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -140,9 +140,8 @@ void EQ::Net::DaybreakConnectionManager::Process() if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) { connection->SendConnect(); } - - break; } + break; case StatusConnected: { if (m_options.keepalive_delay_ms != 0) { auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); @@ -284,10 +283,6 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[0] = 0; m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); - m_outstanding_bytes = 0; - m_outstanding_packets = 0; - m_cwnd = m_max_packet_size; - m_ssthresh = m_owner->m_options.max_outstanding_bytes; } //new connection made as client @@ -311,10 +306,6 @@ EQ::Net::DaybreakConnection::DaybreakConnection(DaybreakConnectionManager *owner m_combined[0] = 0; m_combined[1] = OP_Combined; m_last_session_stats = Clock::now(); - m_outstanding_bytes = 0; - m_outstanding_packets = 0; - m_cwnd = m_max_packet_size; - m_ssthresh = m_owner->m_options.max_outstanding_bytes; } EQ::Net::DaybreakConnection::~DaybreakConnection() @@ -473,49 +464,26 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() for (int i = 0; i < 4; ++i) { auto stream = &m_streams[i]; + if (stream->outstanding_bytes == 0) { + continue; + } + while (!stream->buffered_packets.empty()) { auto &buff = stream->buffered_packets.front(); - if (m_outstanding_packets + 1 >= m_owner->m_options.max_outstanding_packets) { + if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || + stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { break; } - if (m_outstanding_bytes + buff.sent.packet.Length() >= m_cwnd) { - break; - } - - LogF(Logs::Detail, Logs::Netcode, "Sending buffered packet {0} on stream {1}", buff.seq, i); - m_outstanding_bytes += buff.sent.packet.Length(); - m_outstanding_packets++; + stream->outstanding_bytes += buff.sent.packet.Length(); stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); - InternalBufferedSend(buff.sent.packet); + InternalSend(buff.sent.packet); stream->buffered_packets.pop_front(); } } } -void EQ::Net::DaybreakConnection::IncreaseCongestionWindow() -{ - if (m_cwnd < m_ssthresh) { - m_cwnd *= 2; - } - else { - size_t denom = std::max(m_cwnd, (size_t)1U); - m_cwnd += m_max_packet_size; - } - - m_cwnd = EQEmu::Clamp(m_cwnd, (size_t)m_max_packet_size, m_owner->m_options.max_outstanding_bytes); - LogF(Logs::Detail, Logs::Netcode, "Increasing cwnd size new size is {0}", m_cwnd); -} - -void EQ::Net::DaybreakConnection::ReduceCongestionWindow() -{ - m_ssthresh = std::max((size_t)m_cwnd / 2, (size_t)m_max_packet_size * 2); - m_cwnd = m_ssthresh; - - LogF(Logs::Detail, Logs::Netcode, "Reducing cwnd size new size is {0}", m_cwnd); -} - void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) { auto s = &m_streams[stream]; @@ -1078,17 +1046,27 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto s = &m_streams[stream]; for (auto &entry : s->outstanding_packets) { auto time_since_last_send = std::chrono::duration_cast(now - entry.second.last_sent); - auto time_since_first_sent = std::chrono::duration_cast(now - entry.second.first_sent); - if (time_since_first_sent.count() >= m_owner->m_options.resend_timeout) { - Close(); - return; + if (entry.second.times_resent == 0) { + if ((size_t)time_since_last_send.count() > m_resend_delay) { + InternalBufferedSend(entry.second.packet); + entry.second.last_sent = now; + entry.second.times_resent++; + m_rolling_ping += 100; + } } + else { + auto time_since_first_sent = std::chrono::duration_cast(now - entry.second.first_sent); + if (time_since_first_sent.count() >= m_owner->m_options.resend_timeout) { + Close(); + return; + } - if ((size_t)time_since_last_send.count() > m_resend_delay) { - InternalBufferedSend(entry.second.packet); - entry.second.last_sent = now; - entry.second.times_resent++; - ReduceCongestionWindow(); + if ((size_t)time_since_last_send.count() > m_resend_delay) { + InternalBufferedSend(entry.second.packet); + entry.second.last_sent = now; + entry.second.times_resent++; + m_rolling_ping += 100; + } } } } @@ -1099,32 +1077,25 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto now = Clock::now(); auto s = &m_streams[stream]; auto iter = s->outstanding_packets.begin(); - bool success = false; while (iter != s->outstanding_packets.end()) { auto order = CompareSequence(seq, iter->first); - if (order != SequenceFuture) { + if (order != SequenceFuture) { uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); m_stats.min_ping = std::min(m_stats.min_ping, round_time); m_stats.last_ping = round_time; - m_rolling_ping = (m_rolling_ping * 4 + round_time) / 5; + m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - m_outstanding_bytes -= iter->second.packet.Length(); - m_outstanding_packets--; + s->outstanding_bytes -= iter->second.packet.Length(); iter = s->outstanding_packets.erase(iter); - success = true; + ProcessOutboundQueue(); } else { ++iter; } } - - if (success) { - IncreaseCongestionWindow(); - ProcessOutboundQueue(); - } } void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) @@ -1140,11 +1111,8 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - m_outstanding_bytes -= iter->second.packet.Length(); - m_outstanding_packets--; + s->outstanding_bytes -= iter->second.packet.Length(); s->outstanding_packets.erase(iter); - - IncreaseCongestionWindow(); ProcessOutboundQueue(); } } @@ -1152,21 +1120,20 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent) { auto s = &m_streams[stream]; - if (m_outstanding_bytes + sent.packet.Length() > m_cwnd || - m_outstanding_packets + 1 > m_owner->m_options.max_outstanding_packets) { + //If we can send the packet then send it + //else buffer it to be sent when we can send it + if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { //Would go over one of the limits, buffer this packet. DaybreakBufferedPacket bp; bp.sent = std::move(sent); bp.seq = seq; s->buffered_packets.push_back(bp); - LogF(Logs::Detail, Logs::Netcode, "Buffering packet {0} on stream {1}", seq, stream); return; } - m_outstanding_bytes += sent.packet.Length(); - m_outstanding_packets++; + s->outstanding_bytes += sent.packet.Length(); s->outstanding_packets.insert(std::make_pair(seq, sent)); - InternalBufferedSend(sent.packet); + InternalSend(sent.packet); } void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) @@ -1220,10 +1187,6 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) FlushBuffer(); } - if (m_buffered_packets_length == 0) { - m_hold_time = Clock::now(); - } - DynamicPacket copy; copy.PutPacket(0, p); m_buffered_packets.push_back(copy); @@ -1475,4 +1438,4 @@ EQ::Net::SequenceOrder EQ::Net::DaybreakConnection::CompareSequence(uint16_t exp } return SequencePast; -} +} \ No newline at end of file diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index 0e4b5b9b8..ffda5cbae 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -136,11 +136,7 @@ namespace EQ size_t m_resend_delay; size_t m_rolling_ping; Timestamp m_close_time; - size_t m_outstanding_bytes; - size_t m_outstanding_packets; - size_t m_cwnd; - size_t m_ssthresh; - + struct DaybreakSentPacket { DynamicPacket packet; @@ -162,6 +158,7 @@ namespace EQ sequence_out = 0; fragment_current_bytes = 0; fragment_total_bytes = 0; + outstanding_bytes = 0; } uint16_t sequence_in; @@ -174,6 +171,7 @@ namespace EQ uint32_t fragment_total_bytes; std::unordered_map outstanding_packets; + size_t outstanding_bytes; }; DaybreakStream m_streams[4]; @@ -183,8 +181,6 @@ namespace EQ void ProcessPacket(Packet &p); void ProcessInboundQueue(); void ProcessOutboundQueue(); - void IncreaseCongestionWindow(); - void ReduceCongestionWindow(); void RemoveFromQueue(int stream, uint16_t seq); void AddToQueue(int stream, uint16_t seq, const Packet &p); void ProcessDecodedPacket(const Packet &p); @@ -222,9 +218,9 @@ namespace EQ max_connection_count = 0; keepalive_delay_ms = 9000; resend_delay_ms = 150; - resend_delay_factor = 1.25; - resend_delay_min = 500; - resend_delay_max = 5000; + resend_delay_factor = 1.5; + resend_delay_min = 150; + resend_delay_max = 1000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -234,14 +230,14 @@ namespace EQ encode_passes[1] = DaybreakEncodeType::EncodeNone; port = 0; hold_size = 448; - hold_length_ms = 40; + hold_length_ms = 10; simulated_in_packet_loss = 0; simulated_out_packet_loss = 0; tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_bytes = 204800; - max_outstanding_packets = 400; + max_outstanding_packets = 300; + max_outstanding_bytes = 200 * 512; } size_t max_packet_size; @@ -264,8 +260,8 @@ namespace EQ size_t connection_close_time; DaybreakEncodeType encode_passes[2]; int port; - size_t max_outstanding_bytes; size_t max_outstanding_packets; + size_t max_outstanding_bytes; }; class DaybreakConnectionManager @@ -302,4 +298,4 @@ namespace EQ friend class DaybreakConnection; }; } -} +} \ No newline at end of file From 7300776a856d8076b9c91a1e215fb7dc99d38199 Mon Sep 17 00:00:00 2001 From: KimLS Date: Thu, 6 Jul 2017 18:03:19 -0700 Subject: [PATCH 127/218] Fix for bug where packets were not combining when sent inside cwnd, altered some settings --- common/net/daybreak_connection.cpp | 10 +++++++--- common/net/daybreak_connection.h | 10 +++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index f3329a976..de21485d3 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -141,7 +141,7 @@ void EQ::Net::DaybreakConnectionManager::Process() connection->SendConnect(); } } - break; + break; case StatusConnected: { if (m_options.keepalive_delay_ms != 0) { auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); @@ -478,7 +478,7 @@ void EQ::Net::DaybreakConnection::ProcessOutboundQueue() stream->outstanding_bytes += buff.sent.packet.Length(); stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); - InternalSend(buff.sent.packet); + InternalBufferedSend(buff.sent.packet); stream->buffered_packets.pop_front(); } } @@ -1133,7 +1133,7 @@ void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, Daybrea s->outstanding_bytes += sent.packet.Length(); s->outstanding_packets.insert(std::make_pair(seq, sent)); - InternalSend(sent.packet); + InternalBufferedSend(sent.packet); } void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) @@ -1187,6 +1187,10 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) FlushBuffer(); } + if (m_buffered_packets.size() == 0) { + m_hold_time = Clock::now(); + } + DynamicPacket copy; copy.PutPacket(0, p); m_buffered_packets.push_back(copy); diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index ffda5cbae..bbd0c7d93 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -219,8 +219,8 @@ namespace EQ keepalive_delay_ms = 9000; resend_delay_ms = 150; resend_delay_factor = 1.5; - resend_delay_min = 150; - resend_delay_max = 1000; + resend_delay_min = 300; + resend_delay_max = 3000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -230,14 +230,14 @@ namespace EQ encode_passes[1] = DaybreakEncodeType::EncodeNone; port = 0; hold_size = 448; - hold_length_ms = 10; + hold_length_ms = 50; simulated_in_packet_loss = 0; simulated_out_packet_loss = 0; tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_packets = 300; - max_outstanding_bytes = 200 * 512; + max_outstanding_packets = 400; + max_outstanding_bytes = 400 * 512; } size_t max_packet_size; From 0c532236a532a0e4621203d734877971a8a6bc3f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 7 Jul 2017 14:59:01 -0500 Subject: [PATCH 128/218] Fix Server -> Client packet logging --- common/eq_stream_proxy.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/common/eq_stream_proxy.cpp b/common/eq_stream_proxy.cpp index 7fb4c9432..6a3cc6ced 100644 --- a/common/eq_stream_proxy.cpp +++ b/common/eq_stream_proxy.cpp @@ -2,6 +2,8 @@ #include "global_define.h" #include "eq_stream_proxy.h" #include "struct_strategy.h" +#include "eqemu_logsys.h" +#include "opcodemgr.h" EQStreamProxy::EQStreamProxy(std::shared_ptr &stream, const StructStrategy *structs, OpcodeManager **opcodes) @@ -39,6 +41,11 @@ void EQStreamProxy::QueuePacket(const EQApplicationPacket *p, bool ack_req) { if(p == nullptr) return; + if (p->GetOpcode() != OP_SpecialMesg) { + Log(Logs::General, Logs::Server_Client_Packet, "[%s - 0x%04x] [Size: %u]", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size()); + Log(Logs::General, Logs::Server_Client_Packet_With_Dump, "[%s - 0x%04x] [Size: %u] %s", OpcodeManager::EmuToName(p->GetOpcode()), p->GetOpcode(), p->Size(), DumpPacketToString(p).c_str()); + } + EQApplicationPacket *newp = p->Copy(); FastQueuePacket(&newp, ack_req); } From aae1d2f049132d5c2d0575682ce22070a392218a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 8 Jul 2017 22:17:39 -0500 Subject: [PATCH 129/218] Better Z compensation on hills, while engaged and NPC's quickly recover if they go underground --- zone/mob_ai.cpp | 12 +++++++----- zone/waypoints.cpp | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 6b3be34d8..633dde297 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -997,17 +997,19 @@ void Mob::AI_Process() { if (engaged) { /* Fix Z when following during pull, not when engaged and stationary */ - if (moving && fix_z_timer_engaged.Check()) + if (moving && fix_z_timer_engaged.Check()) { if (this->GetTarget()) { /* If we are engaged, moving and following client, let's look for best Z more often */ - if (DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()) > 50) { + float target_distance = DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()); + if (target_distance >= 50) { this->FixZ(); } - /* If we are close to client and our Z differences aren't big, match the client */ - else if (std::abs(this->GetZ() - this->GetTarget()->GetZ()) <= 5 && this->GetTarget()->IsClient()) { - this->m_Position.z = this->GetTarget()->GetZ(); + else if (!this->CheckLosFN(this->GetTarget())) { + Mob* target = this->GetTarget(); + this->GMMove(target->GetX(), target->GetY(), target->GetZ(), target->GetHeading()); } } + } if (!(m_PlayerState & static_cast(PlayerState::Aggressive))) SendAddPlayerState(PlayerState::Aggressive); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 9d272472f..fbbce67b9 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -497,7 +497,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.y = new_y; m_Position.z = new_z; - if(fix_z_timer.Check()) + if(fix_z_timer.Check() && !this->IsEngaged()) this->FixZ(); tar_ndx++; @@ -604,7 +604,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.w = CalculateHeadingToTarget(x, y); } - if (fix_z_timer.Check()) + if (fix_z_timer.Check() && !this->IsEngaged()) this->FixZ(); SetMoving(true); From 127f51e7587b0d354f0f326f8661a640baf313e2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 9 Jul 2017 02:51:01 -0500 Subject: [PATCH 130/218] Massive reductions in unnecessary network traffic especially during high spam combat fights - HP Updates now only send to others when HP percentage changes (0-100%) - HP Updates were sending excessively even during idle zones when HP wasn't changing at all - Attack animations now only send once per second versus up to a hundred times a second per Mob/Client - 17,000 OP_ClientUpdate packets per second have been observed in combat scenarios, some of the major culprits have been throttled without affecting what the client should see - Before and After packet differences under similar load/tests (Packets per second) - 7,000 - 8,000 OP_Animation pps After: 600-800 pps - 13,0000 - 17,000 OP_MobHealth pps After: 1-10 pps - 15,0000 - 20,000 OP_ClientUpdate pps After: 500-1,000 pps - Packet reports from a 46 client test here: https://gist.github.com/Akkadius/28b7ad2fdd82bdd15ea737c68f404346 - Servers who use Marquee HP updates will also recieve far less packet spam as they will only be sent when HP changes --- changelog.txt | 15 +++++++++++++++ common/eqemu_logsys.h | 5 ++++- zone/attack.cpp | 12 ++++++++---- zone/client.cpp | 2 +- zone/mob.cpp | 20 +++++++++++++++++++- zone/mob.h | 4 ++++ 6 files changed, 51 insertions(+), 7 deletions(-) diff --git a/changelog.txt b/changelog.txt index b561c34ab..29747ba45 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,20 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/9/2017 == +Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights + - HP Updates now only send to others when HP percentage changes (0-100%) + - HP Updates were sending excessively even during idle zones when HP wasn't changing at all + - Attack animations now only send once per second versus up to a hundred times a second per Mob/Client + - 17,000 OP_ClientUpdate packets per second have been observed in combat scenarios, some of the major culprits have been + throttled without affecting what the client should see + - Before and After packet differences under similar load/tests (Packets per second) + - 7,000 - 8,000 OP_Animation pps After: 600-800 pps + - 13,0000 - 17,000 OP_MobHealth pps After: 1-10 pps + - 15,0000 - 20,000 OP_ClientUpdate pps After: 500-1,000 pps + - Packet reports from a 46 client test here: + https://gist.github.com/Akkadius/28b7ad2fdd82bdd15ea737c68f404346 + - Servers who use Marquee HP updates will also recieve far less packet spam as they will only be sent when HP changes + == 7/1/2017 == Akkadius: Resolve issues with NPC's hopping to the ceiling in small corridors Akkadius: Improved grounding issues with NPC's during combat diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index ed821831a..7ae5a0296 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -86,6 +86,7 @@ enum LogCategory { Login_Server, Client_Login, Headless_Client, + HP_Update, MaxCategoryID /* Don't Remove this*/ }; @@ -135,7 +136,9 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = { "Packet :: Server -> Client (Dump)", "Packet :: Client -> Server (Dump)", "Login Server", - "Client Login" + "Client Login", + "Headless Client", + "HP Update" }; } diff --git a/zone/attack.cpp b/zone/attack.cpp index 819623148..ddd8c04ce 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -137,7 +137,10 @@ EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstanc if (Hand == EQEmu::inventory::slotSecondary) // DW anim type = animDualWield; - DoAnim(type, 0, false); + if (attack_anim_timer.Check()) { + DoAnim(type, 0, false); + } + return skillinuse; } @@ -3397,8 +3400,6 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const SetHP(GetHP() - damage); - if (IsClient() && RuleB(Character, MarqueeHPUpdates)) - this->CastToClient()->SendHPUpdateMarquee(); if (HasDied()) { bool IsSaved = false; @@ -3549,8 +3550,11 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const if (zone->zonemap && zone->zonemap->CheckLoS(glm::vec3(m_Position), new_pos)) { // If we have LoS on the new loc it should be reachable. if (IsNPC()) { // Is this adequate? + Teleport(new_pos); - SendPosUpdate(); + if (position_update_melee_push_timer.Check()) { + SendPosUpdate(); + } } } else { diff --git a/zone/client.cpp b/zone/client.cpp index 85956ea08..2df13f25b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -8745,7 +8745,7 @@ void Client::SendHPUpdateMarquee(){ return; /* Health Update Marquee Display: Custom*/ - uint32 health_percentage = (uint32)(this->cur_hp * 100 / this->max_hp); + int8 health_percentage = (int8)(this->cur_hp * 100 / this->max_hp); if (health_percentage == 100) return; diff --git a/zone/mob.cpp b/zone/mob.cpp index 7e04221c3..e795cf040 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -114,7 +114,9 @@ Mob::Mob(const char* in_name, mitigation_ac(0), m_specialattacks(eSpecialAttacks::None), fix_z_timer(300), - fix_z_timer_engaged(100) + fix_z_timer_engaged(100), + attack_anim_timer(1000), + position_update_melee_push_timer(1000) { targeted = 0; tar_ndx=0; @@ -123,6 +125,8 @@ Mob::Mob(const char* in_name, last_z = 0; + last_hp = 100; + AI_Init(); SetMoving(false); moved=false; @@ -1299,6 +1303,20 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) // sends hp update of this mob to people who might care void Mob::SendHPUpdate(bool skip_self) { + + int8 current_hp = (max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp)); + + Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp, last_hp); + if (current_hp == last_hp) { + Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update"); + ResetHPUpdateTimer(); + return; + } + else { + Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: HP Changed - Send update"); + last_hp = current_hp; + } + EQApplicationPacket hp_app; Group *group = nullptr; diff --git a/zone/mob.h b/zone/mob.h index aa4b3fb29..1d692d977 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1379,6 +1379,8 @@ protected: Timer flee_timer; Timer fix_z_timer; Timer fix_z_timer_engaged; + Timer attack_anim_timer; + Timer position_update_melee_push_timer; bool pAIControlled; bool roamer; @@ -1387,6 +1389,8 @@ protected: int wandertype; int pausetype; + int8 last_hp; + int cur_wp; glm::vec4 m_CurrentWayPoint; int cur_wp_pause; From ccdeb4d385218bf53ba34be6fefdacb961088cf8 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 9 Jul 2017 17:35:08 -0500 Subject: [PATCH 131/218] Fix HP update issues, rework logic for more accurate and responsive HP updates --- changelog.txt | 1 + common/ruletypes.h | 1 - zone/client.cpp | 7 ++- zone/client.h | 1 + zone/mob.cpp | 143 +++++++++++++++++++++++++-------------------- zone/mob.h | 3 +- 6 files changed, 87 insertions(+), 69 deletions(-) diff --git a/changelog.txt b/changelog.txt index 29747ba45..3ab8093cc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,7 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- == 7/9/2017 == +Akkadius: Fix HP update issues, rework logic for more accurate HP updates Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights - HP Updates now only send to others when HP percentage changes (0-100%) - HP Updates were sending excessively even during idle zones when HP wasn't changing at all diff --git a/common/ruletypes.h b/common/ruletypes.h index c5fc1b9ce..aac46003d 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -134,7 +134,6 @@ RULE_INT(Character, TradeskillUpMakePoison, 2) // Make Poison skillup rate adjus RULE_INT(Character, TradeskillUpPottery, 4) // Pottery skillup rate adjust. Lower is faster. RULE_INT(Character, TradeskillUpResearch, 1) // Research skillup rate adjust. Lower is faster. RULE_INT(Character, TradeskillUpTinkering, 2) // Tinkering skillup rate adjust. Lower is faster. -RULE_BOOL(Character, SpamHPUpdates, false) // if your server has stupid amounts of HP that causes client display issues, turn this on! RULE_BOOL(Character, MarqueeHPUpdates, false) // Will show Health % in center of screen < 100% RULE_INT(Character, IksarCommonTongue, 95) // 95 By default (live-like?) RULE_INT(Character, OgreCommonTongue, 95) // 95 By default (live-like?) diff --git a/zone/client.cpp b/zone/client.cpp index 2df13f25b..73221e279 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -158,7 +158,8 @@ Client::Client(EQStreamInterface* ieqs) m_AutoAttackTargetLocation(0.0f, 0.0f, 0.0f), last_region_type(RegionTypeUnsupported), m_dirtyautohaters(false), - npc_close_scan_timer(6000) + npc_close_scan_timer(6000), + hp_self_update_throttle_timer(500) { for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; @@ -8745,8 +8746,8 @@ void Client::SendHPUpdateMarquee(){ return; /* Health Update Marquee Display: Custom*/ - int8 health_percentage = (int8)(this->cur_hp * 100 / this->max_hp); - if (health_percentage == 100) + uint8 health_percentage = (uint8)(this->cur_hp * 100 / this->max_hp); + if (health_percentage >= 100) return; std::string health_update_notification = StringFormat("Health: %u%%", health_percentage); diff --git a/zone/client.h b/zone/client.h index 50f36ba72..879e6622a 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1485,6 +1485,7 @@ private: Timer helm_toggle_timer; Timer aggro_meter_timer; Timer npc_close_scan_timer; + Timer hp_self_update_throttle_timer; glm::vec3 m_Proximity; diff --git a/zone/mob.cpp b/zone/mob.cpp index e795cf040..dfc7a38bd 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -125,7 +125,7 @@ Mob::Mob(const char* in_name, last_z = 0; - last_hp = 100; + AI_Init(); SetMoving(false); @@ -180,6 +180,8 @@ Mob::Mob(const char* in_name, fearspeed = ((float)base_fearspeed) * 0.025f; } + last_hp_percent = 0; + last_hp = 0; current_speed = base_runspeed; @@ -1303,123 +1305,136 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) // sends hp update of this mob to people who might care void Mob::SendHPUpdate(bool skip_self) { + + /* If our HP is different from last HP update call - let's update ourself */ + if (IsClient() && cur_hp != last_hp) { + /* This is to prevent excessive packet sending under trains/fast combat */ + if (this->CastToClient()->hp_self_update_throttle_timer.Check()) { + Log(Logs::General, Logs::HP_Update, + "Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s", + this->GetCleanName(), + cur_hp, + last_hp, + (skip_self ? "true" : "false") + ); - int8 current_hp = (max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp)); + if (!skip_self || this->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::UF) { + auto client_packet = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct)); + SpawnHPUpdate_Struct* hp_packet_client = (SpawnHPUpdate_Struct*)client_packet->pBuffer; - Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp, last_hp); - if (current_hp == last_hp) { + hp_packet_client->cur_hp = CastToClient()->GetHP() - itembonuses.HP; + hp_packet_client->spawn_id = GetID(); + hp_packet_client->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; + + CastToClient()->QueuePacket(client_packet); + + safe_delete(client_packet); + + ResetHPUpdateTimer(); + } + } + } + + /* Used to check if HP has changed to update self next round */ + last_hp = cur_hp; + + int8 current_hp_percent = (max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp)); + + Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp_percent, last_hp_percent); + + if (current_hp_percent == last_hp_percent) { Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update"); ResetHPUpdateTimer(); + return; } else { + + if (IsClient() && RuleB(Character, MarqueeHPUpdates)) + this->CastToClient()->SendHPUpdateMarquee(); + Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: HP Changed - Send update"); - last_hp = current_hp; + + last_hp_percent = current_hp_percent; } EQApplicationPacket hp_app; Group *group = nullptr; - // destructor will free the pBuffer CreateHPPacket(&hp_app); - // send to people who have us targeted + /* Update those who have use targeted */ entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients); + + /* Update those who have us on x-target */ entity_list.QueueClientsByXTarget(this, &hp_app, false); + + /* Update groups using Group LAA health name tag counter */ entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); - // send to group - if(IsGrouped()) - { + /* Update group */ + if(IsGrouped()) { group = entity_list.GetGroupByMob(this); if(group) //not sure why this might be null, but it happens group->SendHPPacketsFrom(this); } + /* Update Raid */ if(IsClient()){ - Raid *r = entity_list.GetRaidByClient(CastToClient()); - if(r){ - r->SendHPPacketsFrom(this); - } + Raid *raid = entity_list.GetRaidByClient(CastToClient()); + if (raid) + raid->SendHPPacketsFrom(this); } - // send to master - if(GetOwner() && GetOwner()->IsClient()) - { + /* Pet - Update master - group and raid if exists */ + if(GetOwner() && GetOwner()->IsClient()) { GetOwner()->CastToClient()->QueuePacket(&hp_app, false); group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); + if(group) group->SendHPPacketsFrom(this); - Raid *r = entity_list.GetRaidByClient(GetOwner()->CastToClient()); - if(r) - r->SendHPPacketsFrom(this); + + Raid *raid = entity_list.GetRaidByClient(GetOwner()->CastToClient()); + if(raid) + raid->SendHPPacketsFrom(this); } - // send to pet - if(GetPet() && GetPet()->IsClient()) - { + /* Send to pet */ + if(GetPet() && GetPet()->IsClient()) { GetPet()->CastToClient()->QueuePacket(&hp_app, false); } - // Update the damage state of destructible objects - if(IsNPC() && IsDestructibleObject()) - { - if (GetHPRatio() > 74) - { - if (GetAppearance() != eaStanding) - { - SendAppearancePacket(AT_DamageState, eaStanding); - _appearance = eaStanding; + /* Destructible objects */ + if (IsNPC() && IsDestructibleObject()) { + if (GetHPRatio() > 74) { + if (GetAppearance() != eaStanding) { + SendAppearancePacket(AT_DamageState, eaStanding); + _appearance = eaStanding; } } - else if (GetHPRatio() > 49) - { - if (GetAppearance() != eaSitting) - { + else if (GetHPRatio() > 49) { + if (GetAppearance() != eaSitting) { SendAppearancePacket(AT_DamageState, eaSitting); _appearance = eaSitting; } } - else if (GetHPRatio() > 24) - { - if (GetAppearance() != eaCrouching) - { + else if (GetHPRatio() > 24) { + if (GetAppearance() != eaCrouching) { SendAppearancePacket(AT_DamageState, eaCrouching); _appearance = eaCrouching; } } - else if (GetHPRatio() > 0) - { - if (GetAppearance() != eaDead) - { + else if (GetHPRatio() > 0) { + if (GetAppearance() != eaDead) { SendAppearancePacket(AT_DamageState, eaDead); _appearance = eaDead; } } - else if (GetAppearance() != eaLooting) - { + else if (GetAppearance() != eaLooting) { SendAppearancePacket(AT_DamageState, eaLooting); _appearance = eaLooting; } } - - bool dospam = RuleB(Character, SpamHPUpdates); - // send to self - we need the actual hps here - if(IsClient() && (!skip_self || dospam)) { - - if (RuleB(Character, MarqueeHPUpdates)) - this->CastToClient()->SendHPUpdateMarquee(); - - auto hp_app2 = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct)); - SpawnHPUpdate_Struct* ds = (SpawnHPUpdate_Struct*)hp_app2->pBuffer; - ds->cur_hp = CastToClient()->GetHP() - itembonuses.HP; - ds->spawn_id = GetID(); - ds->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; - CastToClient()->QueuePacket(hp_app2); - safe_delete(hp_app2); - } - if (!dospam) - ResetHPUpdateTimer(); // delay the timer } // this one just warps the mob to the current location diff --git a/zone/mob.h b/zone/mob.h index 1d692d977..c1a300569 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1389,7 +1389,8 @@ protected: int wandertype; int pausetype; - int8 last_hp; + int8 last_hp_percent; + int32 last_hp; int cur_wp; glm::vec4 m_CurrentWayPoint; From c6c6d00badbbf089d02c92a75ddb6b7c9edc2dcb Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 10:42:07 -0500 Subject: [PATCH 132/218] #path process file_name.path will actually push to the maps/ directory by default now --- zone/pathing.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 417ee3af2..25d996eac 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -1454,7 +1454,10 @@ void PathManager::NodeInfo(Client *c) void PathManager::DumpPath(std::string filename) { std::ofstream o_file; - o_file.open(filename.c_str(), std::ios_base::binary | std::ios_base::trunc | std::ios_base::out); + + std::string file_to_write = StringFormat("%s%s", Config->MapDir.c_str(), filename.c_str()); + + o_file.open(file_to_write.c_str(), std::ios_base::binary | std::ios_base::trunc | std::ios_base::out); o_file.write("EQEMUPATH", 9); o_file.write((const char*)&Head, sizeof(Head)); o_file.write((const char*)PathNodes, (sizeof(PathNode)*Head.PathNodeCount)); From 122e71f4a35e7f5efdd442db8201907c5cddf0d1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 20:40:32 -0500 Subject: [PATCH 133/218] Fix HP/Mana/Endurance updates for group/raids when entering-leaving zone and when initially being added to group/raid --- zone/client_packet.cpp | 9 +++++++ zone/groups.cpp | 22 +++++++++++------ zone/raids.cpp | 55 ++++++++++++++++++++++++------------------ 3 files changed, 55 insertions(+), 31 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 2ca3a1ed4..daf2e5f97 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -583,8 +583,17 @@ void Client::CompleteConnect() if (raid->IsLocked()) raid->SendRaidLockTo(this); + + raid->SendHPPacketsTo(this); } } + else { + Group *group_update = nullptr; + group_update = this->GetGroup(); + if (group_update) + group_update->SendHPPacketsTo(this); + } + //bulk raid send in here eventually diff --git a/zone/groups.cpp b/zone/groups.cpp index 6216de4ac..28b4abd6a 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -338,6 +338,13 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte database.SetGroupID(NewMemberName, GetID(), owner->CharacterID(), true); } } + + Group* group = newmember->CastToClient()->GetGroup(); + if (group) { + group->SendHPPacketsTo(newmember); + group->SendHPPacketsFrom(newmember); + } + } else { @@ -389,26 +396,25 @@ void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) // first joins a group, but otherwise there shouldn't be a need to call it void Group::SendHPPacketsTo(Mob *member) { - if(member && member->IsClient()) - { + if(member && member->IsClient()) { EQApplicationPacket hpapp; EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) - { - if(members[i] && members[i] != member) - { + for (uint32 i = 0; i < MAX_GROUP_MEMBERS; i++) { + if(members[i] && members[i] != member) { members[i]->CreateHPPacket(&hpapp); member->CastToClient()->QueuePacket(&hpapp, false); safe_delete_array(hpapp.pBuffer); hpapp.size = 0; - if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + + if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; mmus->spawn_id = members[i]->GetID(); mmus->mana = members[i]->GetManaPercent(); member->CastToClient()->QueuePacket(&outapp, false); + MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; outapp.SetOpcode(OP_MobEnduranceUpdate); meus->endurance = members[i]->GetEndurancePercent(); diff --git a/zone/raids.cpp b/zone/raids.cpp index c9d4ee6c5..d32ad4def 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -145,6 +145,13 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo } } + Group *group_update = nullptr; + group_update = c->GetGroup(); + if (group_update) { + group_update->SendHPPacketsTo(c); + group_update->SendHPPacketsFrom(c); + } + auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); ServerRaidGeneralAction_Struct *rga = (ServerRaidGeneralAction_Struct*)pack->pBuffer; rga->rid = GetID(); @@ -1539,35 +1546,37 @@ void Raid::MemberZoned(Client *c) group_mentor[gid].mentoree = nullptr; } -void Raid::SendHPPacketsTo(Client *c) +void Raid::SendHPPacketsTo(Client *client) { - if(!c) + if(!client) return; - uint32 gid = this->GetGroup(c); - EQApplicationPacket hpapp; + uint32 group_id = this->GetGroup(client); + + EQApplicationPacket hp_packet; EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(members[x].member) - { - if((members[x].member != c) && (members[x].GroupNumber == gid)) - { - members[x].member->CreateHPPacket(&hpapp); - c->QueuePacket(&hpapp, false); - safe_delete_array(hpapp.pBuffer); - hpapp.size = 0; - if (c->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + + for(int x = 0; x < MAX_RAID_MEMBERS; x++) { + if(members[x].member) { + if((members[x].member != client) && (members[x].GroupNumber == group_id)) { + + members[x].member->CreateHPPacket(&hp_packet); + client->QueuePacket(&hp_packet, false); + safe_delete_array(hp_packet.pBuffer); + + hp_packet.size = 0; + if (client->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = members[x].member->GetID(); - mmus->mana = members[x].member->GetManaPercent(); - c->QueuePacket(&outapp, false); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = members[x].member->GetID(); + mana_update->mana = members[x].member->GetManaPercent(); + client->QueuePacket(&outapp, false); + outapp.SetOpcode(OP_MobEnduranceUpdate); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - meus->endurance = members[x].member->GetEndurancePercent(); - c->QueuePacket(&outapp, false); + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->endurance = members[x].member->GetEndurancePercent(); + client->QueuePacket(&outapp, false); } } } From 62e4169e504d47d285ababeef35d726e1c06e9f2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 20:41:56 -0500 Subject: [PATCH 134/218] More animation packet reductions, DoAnim is called in many other places in combat than just AttackAnimation --- zone/attack.cpp | 7 ++++--- zone/mob.cpp | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index ddd8c04ce..d04bbf0d7 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -55,6 +55,9 @@ extern Zone* zone; EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse) { + if (!attack_anim_timer.Check()) + return skillinuse; + // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { @@ -137,9 +140,7 @@ EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstanc if (Hand == EQEmu::inventory::slotSecondary) // DW anim type = animDualWield; - if (attack_anim_timer.Check()) { - DoAnim(type, 0, false); - } + DoAnim(type, 0, false); return skillinuse; } diff --git a/zone/mob.cpp b/zone/mob.cpp index dfc7a38bd..830ac9a61 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1568,6 +1568,9 @@ void Mob::ShowStats(Client* client) } void Mob::DoAnim(const int animnum, int type, bool ackreq, eqFilterType filter) { + if (!attack_anim_timer.Check()) + return; + auto outapp = new EQApplicationPacket(OP_Animation, sizeof(Animation_Struct)); Animation_Struct* anim = (Animation_Struct*)outapp->pBuffer; anim->spawnid = GetID(); From a41c690a6245803d4602d07847985483b293b7f3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 22:27:03 -0500 Subject: [PATCH 135/218] Another animation adjustment --- zone/attack.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index d04bbf0d7..ee1384b44 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -55,9 +55,6 @@ extern Zone* zone; EQEmu::skills::SkillType Mob::AttackAnimation(int Hand, const EQEmu::ItemInstance* weapon, EQEmu::skills::SkillType skillinuse) { - if (!attack_anim_timer.Check()) - return skillinuse; - // Determine animation int type = 0; if (weapon && weapon->IsClassCommon()) { From dceb79ad696adac4fadd14839a879fe1f647e409 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 22:57:58 -0500 Subject: [PATCH 136/218] Only send mana/endurance updates to self when they actually change --- zone/client.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 73221e279..03e113ed0 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1833,13 +1833,13 @@ void Client::SendManaUpdatePacket() { if (!Connected()) return; - if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { - SendManaUpdate(); - SendEnduranceUpdate(); - } - if (last_reported_mana != cur_mana || last_reported_endur != cur_end) { + if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + SendManaUpdate(); + SendEnduranceUpdate(); + } + auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; manachange->new_mana = cur_mana; From ec00daa5be0ffbfc61623abc5bc1235f95f7da4d Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jul 2017 23:03:40 -0500 Subject: [PATCH 137/218] Mob position updates now completely only send to 600 units range defined by Range:MobPositionUpdates Client updates nearby clients more often because they will disappear after 10 seconds without a position update to the client This results in a massive reduction in unnecessary traffic as we only update clients of their relevance around them This also resembles live-like packet sending behavior of positions --- common/ruletypes.h | 1 - zone/client_packet.cpp | 8 +++---- zone/client_process.cpp | 32 +++++++++++++++++-------- zone/entity.cpp | 45 ++++++++++++++++++++-------------- zone/entity.h | 2 +- zone/mob.cpp | 53 +++++++++++++++-------------------------- zone/mob.h | 1 - 7 files changed, 73 insertions(+), 69 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index aac46003d..397f1a832 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -234,7 +234,6 @@ RULE_BOOL(World, StartZoneSameAsBindOnCreation, true) //Should the start zone AL RULE_CATEGORY_END() RULE_CATEGORY(Zone) -RULE_INT(Zone, NPCPositonUpdateTicCount, 32) //ms between intervals of sending a position update to the entire zone. RULE_INT(Zone, ClientLinkdeadMS, 180000) //the time a client remains link dead on the server after a sudden disconnection RULE_INT(Zone, GraveyardTimeMS, 1200000) //ms time until a player corpse is moved to a zone's graveyard, if one is specified for the zone RULE_BOOL(Zone, EnableShadowrest, 1) // enables or disables the shadowrest zone feature for player corpses. Default is turned on. diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index daf2e5f97..e4891b999 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -588,10 +588,10 @@ void Client::CompleteConnect() } } else { - Group *group_update = nullptr; - group_update = this->GetGroup(); - if (group_update) - group_update->SendHPPacketsTo(this); + Group *group = nullptr; + group = this->GetGroup(); + if (group) + group->SendHPPacketsTo(this); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 583ad627b..a5ced5d1a 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -256,17 +256,29 @@ bool Client::Process() { close_npcs.clear(); - auto &npc_list = entity_list.GetNPCList(); + auto &mob_list = entity_list.GetMobList(); + float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan)); + float client_update_range = (RuleI(Range, MobPositionUpdates) * RuleI(Range, MobPositionUpdates)); - float scan_range = RuleI(Range, ClientNPCScan); - for (auto itr = npc_list.begin(); itr != npc_list.end(); ++itr) { - NPC* npc = itr->second; - float distance = DistanceNoZ(m_Position, npc->GetPosition()); - if(distance <= scan_range) { - close_npcs.insert(std::pair(npc, distance)); + for (auto itr = mob_list.begin(); itr != mob_list.end(); ++itr) { + Mob* mob = itr->second; + float distance = DistanceSquared(m_Position, mob->GetPosition()); + if (mob->IsNPC()) { + if (distance <= scan_range) { + close_npcs.insert(std::pair(mob->CastToNPC(), distance)); + } + else if (mob->GetAggroRange() > scan_range) { + close_npcs.insert(std::pair(mob->CastToNPC(), distance)); + } } - else if (npc->GetAggroRange() > scan_range) { - close_npcs.insert(std::pair(npc, distance)); + + /* Clients need to be kept up to date for position updates more often otherwise they disappear */ + if (mob->IsClient() && this != mob && distance <= client_update_range) { + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; + mob->MakeSpawnUpdateNoDelta(spawn_update); + this->FastQueuePacket(&app, false); + safe_delete(app); } } } @@ -455,7 +467,7 @@ bool Client::Process() { // Send a position packet every 8 seconds - if not done, other clients // see this char disappear after 10-12 seconds of inactivity if (position_timer_counter >= 36) { // Approx. 4 ticks per second - entity_list.SendPositionUpdates(this, pLastUpdateWZ, 500, GetTarget(), true); + entity_list.SendPositionUpdates(this, pLastUpdateWZ, RuleI(Range, MobPositionUpdates), GetTarget(), true); pLastUpdate = Timer::GetCurrentTime(); pLastUpdateWZ = pLastUpdate; position_timer_counter = 0; diff --git a/zone/entity.cpp b/zone/entity.cpp index 35d67a5d3..eee89ce0f 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2634,10 +2634,9 @@ void EntityList::RemoveDebuffs(Mob *caster) // Currently, a new packet is sent per entity. // @todo: Come back and use FLAG_COMBINED to pack // all updates into one packet. -void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, - float range, Entity *alwayssend, bool iSendEvenIfNotChanged) +void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float update_range, Entity *always_send, bool iSendEvenIfNotChanged) { - range = range * range; + update_range = (update_range * update_range); EQApplicationPacket *outapp = 0; PlayerPositionUpdateServer_Struct *ppu = 0; @@ -2645,27 +2644,37 @@ void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, auto it = mob_list.begin(); while (it != mob_list.end()) { - if (outapp == 0) { - outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; - } + mob = it->second; - if (mob && !mob->IsCorpse() && (it->second != client) + + if ( + mob && !mob->IsCorpse() + && (it->second != client) && (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate)) - && (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client))) { + && (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client)) + ) { + if ( + update_range == 0 + || (it->second == always_send) + || mob->IsClient() + || (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= update_range) + ) { + if (mob && mob->IsClient() && mob->GetID() > 0) { + client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); - //bool Grouped = client->HasGroup() && mob->IsClient() && (client->GetGroup() == mob->CastToClient()->GetGroup()); + if (outapp == 0) { + outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; + } - //if (range == 0 || (iterator.GetData() == alwayssend) || Grouped || (mob->DistNoRootNoZ(*client) <= range)) { - if (range == 0 || (it->second == alwayssend) || mob->IsClient() || (DistanceSquared(mob->GetPosition(), client->GetPosition()) <= range)) { - mob->MakeSpawnUpdate(ppu); - } - if(mob && mob->IsClient() && mob->GetID()>0) { - client->QueuePacket(outapp, false, Client::CLIENT_CONNECTED); + mob->MakeSpawnUpdate(ppu); + + safe_delete(outapp); + outapp = 0; + } } } - safe_delete(outapp); - outapp = 0; + ++it; } diff --git a/zone/entity.h b/zone/entity.h index 7752e97b1..16249547b 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -370,7 +370,7 @@ public: Mob* FindDefenseNPC(uint32 npcid); void OpenDoorsNear(NPC* opener); void UpdateWho(bool iSendFullUpdate = false); - void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float range = 0, Entity* alwayssend = 0, bool iSendEvenIfNotChanged = false); + void SendPositionUpdates(Client* client, uint32 cLastUpdate = 0, float update_range = 0, Entity* always_send = 0, bool iSendEvenIfNotChanged = false); char* MakeNameUnique(char* name); static char* RemoveNumbers(char* name); void SignalMobsByNPCID(uint32 npc_type, int signal_id); diff --git a/zone/mob.cpp b/zone/mob.cpp index 830ac9a61..256fd7df7 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -131,7 +131,6 @@ Mob::Mob(const char* in_name, SetMoving(false); moved=false; m_RewindLocation = glm::vec3(); - move_tic_count = 0; _egnode = nullptr; name[0]=0; @@ -1443,8 +1442,7 @@ void Mob::SendPosition() auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); - move_tic_count = 0; - entity_list.QueueClients(this, app, true); + entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); safe_delete(app); } @@ -1456,45 +1454,32 @@ void Mob::SendPosUpdate(uint8 iSendToSelf) { if (iSendToSelf == 2) { if (IsClient()) { - CastToClient()->FastQueuePacket(&app,false); + CastToClient()->FastQueuePacket(&app, false); } } - else - { - if(move_tic_count == RuleI(Zone, NPCPositonUpdateTicCount)) - { - entity_list.QueueClients(this, app, (iSendToSelf == 0), false); - move_tic_count = 0; - } - else if(move_tic_count % 2 == 0) - { - entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false); - move_tic_count++; - } - else { - move_tic_count++; - } + else { + entity_list.QueueCloseClients(this, app, (iSendToSelf == 0), RuleI(Range, MobPositionUpdates), nullptr, false); } safe_delete(app); } // this is for SendPosition() -void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu){ - memset(spu,0xff,sizeof(PlayerPositionUpdateServer_Struct)); - spu->spawn_id = GetID(); - spu->x_pos = FloatToEQ19(m_Position.x); - spu->y_pos = FloatToEQ19(m_Position.y); - spu->z_pos = FloatToEQ19(m_Position.z); - spu->delta_x = NewFloatToEQ13(0); - spu->delta_y = NewFloatToEQ13(0); - spu->delta_z = NewFloatToEQ13(0); - spu->heading = FloatToEQ19(m_Position.w); - spu->animation = 0; +void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) { + memset(spu, 0xff, sizeof(PlayerPositionUpdateServer_Struct)); + spu->spawn_id = GetID(); + spu->x_pos = FloatToEQ19(m_Position.x); + spu->y_pos = FloatToEQ19(m_Position.y); + spu->z_pos = FloatToEQ19(m_Position.z); + spu->delta_x = NewFloatToEQ13(0); + spu->delta_y = NewFloatToEQ13(0); + spu->delta_z = NewFloatToEQ13(0); + spu->heading = FloatToEQ19(m_Position.w); + spu->animation = 0; spu->delta_heading = NewFloatToEQ13(0); - spu->padding0002 =0; - spu->padding0006 =7; - spu->padding0014 =0x7f; - spu->padding0018 =0x5df27; + spu->padding0002 = 0; + spu->padding0006 = 7; + spu->padding0014 = 0x7f; + spu->padding0018 = 0x5df27; } diff --git a/zone/mob.h b/zone/mob.h index c1a300569..27ea48d4f 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1373,7 +1373,6 @@ protected: void ClearItemFactionBonuses(); void CalculateFearPosition(); - uint32 move_tic_count; bool flee_mode; Timer flee_timer; From 59a2f0cdde4986aac63ab0a0cff06fac24dcb9e3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jul 2017 01:58:47 -0500 Subject: [PATCH 138/218] Refactor close_npcs to close_mobs for future implementations --- zone/client.cpp | 2 +- zone/client.h | 2 +- zone/client_process.cpp | 17 ++++++++++------- zone/entity.cpp | 7 +++---- zone/entity.h | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 03e113ed0..986c2b582 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -358,7 +358,7 @@ Client::~Client() { m_tradeskill_object = nullptr; } - close_npcs.clear(); + close_mobs.clear(); if(IsDueling() && GetDuelTarget() != 0) { Entity* entity = entity_list.GetID(GetDuelTarget()); diff --git a/zone/client.h b/zone/client.h index 879e6622a..7bd02c46c 100644 --- a/zone/client.h +++ b/zone/client.h @@ -222,7 +222,7 @@ public: Client(EQStreamInterface * ieqs); ~Client(); - std::unordered_map close_npcs; + std::unordered_map close_mobs; bool is_client_moving; //abstract virtual function implementations required by base abstract class diff --git a/zone/client_process.cpp b/zone/client_process.cpp index a5ced5d1a..08cb9a325 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -254,7 +254,7 @@ bool Client::Process() { /* Build a close range list of NPC's */ if (npc_close_scan_timer.Check()) { - close_npcs.clear(); + close_mobs.clear(); auto &mob_list = entity_list.GetMobList(); float scan_range = (RuleI(Range, ClientNPCScan) * RuleI(Range, ClientNPCScan)); @@ -265,10 +265,10 @@ bool Client::Process() { float distance = DistanceSquared(m_Position, mob->GetPosition()); if (mob->IsNPC()) { if (distance <= scan_range) { - close_npcs.insert(std::pair(mob->CastToNPC(), distance)); + close_mobs.insert(std::pair(mob, distance)); } else if (mob->GetAggroRange() > scan_range) { - close_npcs.insert(std::pair(mob->CastToNPC(), distance)); + close_mobs.insert(std::pair(mob, distance)); } } @@ -631,11 +631,14 @@ bool Client::Process() { // only if client is not feigned if (zone->CanDoCombat() && ret && !GetFeigned() && client_scan_npc_aggro_timer.Check()) { int npc_scan_count = 0; - for (auto it = close_npcs.begin(); it != close_npcs.end(); ++it) { - NPC *npc = it->first; + for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) { + Mob *mob = it->first; - if (npc->CheckWillAggro(this) && !npc->CheckAggro(this)) { - npc->AddToHateList(this, 25); + if (mob->IsClient()) + continue; + + if (mob->CheckWillAggro(this) && !mob->CheckAggro(this)) { + mob->AddToHateList(this, 25); } npc_scan_count++; } diff --git a/zone/entity.cpp b/zone/entity.cpp index eee89ce0f..2a3429f02 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2323,10 +2323,9 @@ bool EntityList::RemoveNPC(uint16 delete_id) // make sure its proximity is removed RemoveProximity(delete_id); // remove from client close lists - RemoveNPCFromClientCloseLists(npc); + RemoveMobFromClientCloseLists(npc->CastToMob()); // remove from the list npc_list.erase(it); - // remove from limit list if needed if (npc_limit_list.count(delete_id)) @@ -2336,11 +2335,11 @@ bool EntityList::RemoveNPC(uint16 delete_id) return false; } -bool EntityList::RemoveNPCFromClientCloseLists(NPC *npc) +bool EntityList::RemoveMobFromClientCloseLists(Mob *mob) { auto it = client_list.begin(); while (it != client_list.end()) { - it->second->close_npcs.erase(npc); + it->second->close_mobs.erase(mob); ++it; } return false; diff --git a/zone/entity.h b/zone/entity.h index 16249547b..036e0c419 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -279,7 +279,7 @@ public: bool RemoveTrap(uint16 delete_id); bool RemoveObject(uint16 delete_id); bool RemoveProximity(uint16 delete_npc_id); - bool RemoveNPCFromClientCloseLists(NPC *npc); + bool RemoveMobFromClientCloseLists(Mob *mob); void RemoveAllMobs(); void RemoveAllClients(); void RemoveAllNPCs(); From d9a1cf8c7b9bde228fad35735b0f42bba8d0bde5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jul 2017 02:08:00 -0500 Subject: [PATCH 139/218] Safeguard to npc aggro scanning --- zone/client_process.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 08cb9a325..a346b7ce3 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -634,6 +634,9 @@ bool Client::Process() { for (auto it = close_mobs.begin(); it != close_mobs.end(); ++it) { Mob *mob = it->first; + if (!mob) + continue; + if (mob->IsClient()) continue; From d47daa28578e4dac247d64b76586939274066eee Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jul 2017 02:42:06 -0500 Subject: [PATCH 140/218] Pointer removals --- zone/entity.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/zone/entity.cpp b/zone/entity.cpp index 2a3429f02..52eb41165 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -2282,6 +2282,9 @@ bool EntityList::RemoveMob(uint16 delete_id) auto it = mob_list.find(delete_id); if (it != mob_list.end()) { + + RemoveMobFromClientCloseLists(it->second); + if (npc_list.count(delete_id)) entity_list.RemoveNPC(delete_id); else if (client_list.count(delete_id)) @@ -2304,6 +2307,8 @@ bool EntityList::RemoveMob(Mob *delete_mob) auto it = mob_list.begin(); while (it != mob_list.end()) { if (it->second == delete_mob) { + RemoveMobFromClientCloseLists(it->second); + safe_delete(it->second); if (!corpse_list.count(it->first)) free_ids.push(it->first); From 855796448cb1405f8b1910132a172af4620d25d5 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jul 2017 17:54:46 -0500 Subject: [PATCH 141/218] Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes Raid/Group Mana/Endurance updates should now update real-time once again Fixed an issue with clients looking like they are 'skipping' when they are moving in view of another client Fixed an issue with NPC's who are ghosted in plain view of a client when they are not really there --- changelog.txt | 6 ++ zone/bot.cpp | 12 ++-- zone/client.cpp | 129 +++++++++++++++++++++++----------------- zone/client.h | 13 ++-- zone/client_mods.cpp | 16 ++--- zone/client_packet.cpp | 4 +- zone/client_process.cpp | 8 +-- zone/command.cpp | 2 +- zone/groups.cpp | 71 +++++++++++++++++----- zone/groups.h | 6 +- zone/merc.cpp | 10 ++-- zone/mob.cpp | 36 +++++++---- zone/mob.h | 10 ++-- zone/npc.cpp | 2 +- zone/perl_groups.cpp | 2 +- zone/raids.cpp | 104 ++++++++++++++++++++++++-------- zone/raids.h | 6 +- zone/worldserver.cpp | 2 +- 18 files changed, 289 insertions(+), 150 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3ab8093cc..51011d64b 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 7/11/2017 == +Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes +Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again +Akkadius: Fixed an issue with clients looking like they are 'skipping' when they are moving in view of another client +Akkadius: Fixed an issue with NPC's who are ghosted in plain view of a client when they are not really there + == 7/9/2017 == Akkadius: Fix HP update issues, rework logic for more accurate HP updates Akkadius: Massive reductions in unnecessary network traffic especially during high spam combat fights diff --git a/zone/bot.cpp b/zone/bot.cpp index fbed35a06..129cdb9b3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -84,7 +84,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm GenerateBaseStats(); // Calculate HitPoints Last As It Uses Base Stats cur_hp = GenerateBaseHitPoints(); - cur_mana = GenerateBaseManaPoints(); + current_mana = GenerateBaseManaPoints(); cur_end = CalcBaseEndurance(); hp_regen = CalcHPRegen(); mana_regen = CalcManaRegen(); @@ -129,7 +129,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to _baseRace = npcTypeData.race; _baseGender = npcTypeData.gender; cur_hp = npcTypeData.cur_hp; - cur_mana = npcTypeData.Mana; + current_mana = npcTypeData.Mana; RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; @@ -206,8 +206,8 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SpellOnTarget(756, this); // Rezz effects } - if(cur_mana > max_mana) - cur_mana = max_mana; + if(current_mana > max_mana) + current_mana = max_mana; cur_end = max_end; } @@ -5557,8 +5557,8 @@ int32 Bot::CalcMaxMana() { } } - if(cur_mana > max_mana) - cur_mana = max_mana; + if(current_mana > max_mana) + current_mana = max_mana; else if(max_mana < 0) max_mana = 0; diff --git a/zone/client.cpp b/zone/client.cpp index 986c2b582..0bcbb4ec2 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -161,8 +161,10 @@ Client::Client(EQStreamInterface* ieqs) npc_close_scan_timer(6000), hp_self_update_throttle_timer(500) { + for(int cf=0; cf < _FilterCount; cf++) ClientFilters[cf] = FilterShow; + character_id = 0; conn_state = NoPacketsReceived; client_data_loaded = false; @@ -191,7 +193,9 @@ Client::Client(EQStreamInterface* ieqs) strcpy(account_name, ""); tellsoff = false; last_reported_mana = 0; - last_reported_endur = 0; + last_reported_endurance = 0; + last_reported_endurance_percent = 0; + last_reported_mana_percent = 0; gmhideme = false; AFK = false; LFG = false; @@ -269,7 +273,7 @@ Client::Client(EQStreamInterface* ieqs) RestRegenMana = 0; RestRegenEndurance = 0; XPRate = 100; - cur_end = 0; + current_endurance = 0; m_TimeSinceLastPositionCheck = 0; m_DistanceSinceLastPositionCheck = 0.0f; @@ -287,7 +291,7 @@ Client::Client(EQStreamInterface* ieqs) HideCorpseMode = HideCorpseNone; PendingGuildInvitation = false; - cur_end = 0; + current_endurance = 0; InitializeBuffSlots(); @@ -599,8 +603,8 @@ bool Client::Save(uint8 iCommitNow) { m_pp.cur_hp = GetHP(); } - m_pp.mana = cur_mana; - m_pp.endurance = cur_end; + m_pp.mana = current_mana; + m_pp.endurance = current_endurance; /* Save Character Currency */ database.SaveCharacterCurrency(CharacterID(), &m_pp); @@ -1820,20 +1824,20 @@ const int32& Client::SetMana(int32 amount) { amount = 0; if (amount > GetMaxMana()) amount = GetMaxMana(); - if (amount != cur_mana) + if (amount != current_mana) update = true; - cur_mana = amount; + current_mana = amount; if (update) Mob::SetMana(amount); - SendManaUpdatePacket(); - return cur_mana; + CheckManaEndUpdate(); + return current_mana; } -void Client::SendManaUpdatePacket() { +void Client::CheckManaEndUpdate() { if (!Connected()) return; - if (last_reported_mana != cur_mana || last_reported_endur != cur_end) { + if (last_reported_mana != current_mana || last_reported_endurance != current_endurance) { if (ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { SendManaUpdate(); @@ -1841,46 +1845,65 @@ void Client::SendManaUpdatePacket() { } auto outapp = new EQApplicationPacket(OP_ManaChange, sizeof(ManaChange_Struct)); - ManaChange_Struct* manachange = (ManaChange_Struct*)outapp->pBuffer; - manachange->new_mana = cur_mana; - manachange->stamina = cur_end; - manachange->spell_id = casting_spell_id; - manachange->keepcasting = 1; + ManaChange_Struct* mana_change = (ManaChange_Struct*)outapp->pBuffer; + mana_change->new_mana = current_mana; + mana_change->stamina = current_endurance; + mana_change->spell_id = casting_spell_id; + mana_change->keepcasting = 1; outapp->priority = 6; QueuePacket(outapp); safe_delete(outapp); - Group *g = GetGroup(); + /* Let others know when our mana percent has changed */ + if (this->GetManaPercent() != last_reported_mana_percent) { + Group *group = this->GetGroup(); + Raid *raid = this->GetRaid(); - if(g) - { - outapp = new EQApplicationPacket(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - auto outapp2 = - new EQApplicationPacket(OP_MobEnduranceUpdate, sizeof(MobEnduranceUpdate_Struct)); + if (raid) { + raid->SendManaPacketFrom(this); + } + else if (group) { + group->SendManaPacketFrom(this); + } - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp->pBuffer; - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp2->pBuffer; + auto mana_packet = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); + ManaUpdate_Struct* mana_update = (ManaUpdate_Struct*)mana_packet->pBuffer; + mana_update->cur_mana = GetMana(); + mana_update->max_mana = GetMaxMana(); + mana_update->spawn_id = GetID(); + QueuePacket(mana_packet); + entity_list.QueueClientsByXTarget(this, mana_packet, false); + safe_delete(mana_packet); - mmus->spawn_id = meus->spawn_id = GetID(); - - mmus->mana = GetManaPercent(); - meus->endurance = GetEndurancePercent(); - - - for(int i = 0; i < MAX_GROUP_MEMBERS; ++i) - if (g->members[i] && g->members[i]->IsClient() && (g->members[i] != this) && (g->members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD)) - { - g->members[i]->CastToClient()->QueuePacket(outapp); - g->members[i]->CastToClient()->QueuePacket(outapp2); - } - - safe_delete(outapp); - safe_delete(outapp2); + last_reported_mana_percent = this->GetManaPercent(); } + /* Let others know when our endurance percent has changed */ + if (this->GetEndurancePercent() != last_reported_endurance_percent) { + Group *group = this->GetGroup(); + Raid *raid = this->GetRaid(); - last_reported_mana = cur_mana; - last_reported_endur = cur_end; + if (raid) { + raid->SendEndurancePacketFrom(this); + } + else if (group) { + group->SendEndurancePacketFrom(this); + } + + auto endurance_packet = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); + EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)endurance_packet->pBuffer; + endurance_update->cur_end = GetEndurance(); + endurance_update->max_end = GetMaxEndurance(); + endurance_update->spawn_id = GetID(); + QueuePacket(endurance_packet); + entity_list.QueueClientsByXTarget(this, endurance_packet, false); + safe_delete(endurance_packet); + + last_reported_endurance_percent = this->GetEndurancePercent(); + } + + last_reported_mana = current_mana; + last_reported_endurance = current_endurance; } } @@ -1888,12 +1911,11 @@ void Client::SendManaUpdatePacket() { void Client::SendManaUpdate() { auto mana_app = new EQApplicationPacket(OP_ManaUpdate, sizeof(ManaUpdate_Struct)); - ManaUpdate_Struct* mus = (ManaUpdate_Struct*)mana_app->pBuffer; - mus->cur_mana = GetMana(); - mus->max_mana = GetMaxMana(); - mus->spawn_id = GetID(); + ManaUpdate_Struct* mana_update = (ManaUpdate_Struct*)mana_app->pBuffer; + mana_update->cur_mana = GetMana(); + mana_update->max_mana = GetMaxMana(); + mana_update->spawn_id = GetID(); QueuePacket(mana_app); - entity_list.QueueClientsByXTarget(this, mana_app, false); safe_delete(mana_app); } @@ -1901,12 +1923,11 @@ void Client::SendManaUpdate() void Client::SendEnduranceUpdate() { auto end_app = new EQApplicationPacket(OP_EnduranceUpdate, sizeof(EnduranceUpdate_Struct)); - EnduranceUpdate_Struct* eus = (EnduranceUpdate_Struct*)end_app->pBuffer; - eus->cur_end = GetEndurance(); - eus->max_end = GetMaxEndurance(); - eus->spawn_id = GetID(); + EnduranceUpdate_Struct* endurance_update = (EnduranceUpdate_Struct*)end_app->pBuffer; + endurance_update->cur_end = GetEndurance(); + endurance_update->max_end = GetMaxEndurance(); + endurance_update->spawn_id = GetID(); QueuePacket(end_app); - entity_list.QueueClientsByXTarget(this, end_app, false); safe_delete(end_app); } @@ -3769,8 +3790,8 @@ void Client::SetEndurance(int32 newEnd) newEnd = GetMaxEndurance(); } - cur_end = newEnd; - SendManaUpdatePacket(); + current_endurance = newEnd; + CheckManaEndUpdate(); } void Client::SacrificeConfirm(Client *caster) @@ -4376,7 +4397,7 @@ bool Client::GroupFollow(Client* inviter) { } database.RefreshGroupFromDB(this); - group->SendHPPacketsTo(this); + group->SendHPManaEndPacketsTo(this); //send updates to clients out of zone... group->SendGroupJoinOOZ(this); return true; diff --git a/zone/client.h b/zone/client.h index 7bd02c46c..ff617f009 100644 --- a/zone/client.h +++ b/zone/client.h @@ -540,11 +540,11 @@ public: void CalcMaxEndurance(); //This calculates the maximum endurance we can have int32 CalcBaseEndurance(); //Calculates Base End int32 CalcEnduranceRegen(); //Calculates endurance regen used in DoEnduranceRegen() - int32 GetEndurance() const {return cur_end;} //This gets our current endurance + int32 GetEndurance() const {return current_endurance;} //This gets our current endurance int32 GetMaxEndurance() const {return max_end;} //This gets our endurance from the last CalcMaxEndurance() call int32 CalcEnduranceRegenCap(); int32 CalcHPRegenCap(); - inline uint8 GetEndurancePercent() { return (uint8)((float)cur_end / (float)max_end * 100.0f); } + inline uint8 GetEndurancePercent() { return (uint8)((float)current_endurance / (float)max_end * 100.0f); } void SetEndurance(int32 newEnd); //This sets the current endurance to the new value void DoEnduranceRegen(); //This Regenerates endurance void DoEnduranceUpkeep(); //does the endurance upkeep @@ -661,7 +661,7 @@ public: void RefreshGuildInfo(); - void SendManaUpdatePacket(); + void CheckManaEndUpdate(); void SendManaUpdate(); void SendEnduranceUpdate(); uint8 GetFace() const { return m_pp.face; } @@ -1411,7 +1411,7 @@ private: int Haste; //precalced value int32 max_end; - int32 cur_end; + int32 current_endurance; PlayerProfile_Struct m_pp; ExtendedProfile_Struct m_epp; @@ -1502,7 +1502,10 @@ private: bool tgb; bool instalog; int32 last_reported_mana; - int32 last_reported_endur; + int32 last_reported_endurance; + + int8 last_reported_mana_percent; + int8 last_reported_endurance_percent; unsigned int AggroCount; // How many mobs are aggro on us. diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index ad6a8e7a2..6db0437c5 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -1046,14 +1046,14 @@ int32 Client::CalcMaxMana() if (max_mana < 0) { max_mana = 0; } - if (cur_mana > max_mana) { - cur_mana = max_mana; + if (current_mana > max_mana) { + current_mana = max_mana; } int mana_perc_cap = spellbonuses.ManaPercCap[0]; if (mana_perc_cap) { int curMana_cap = (max_mana * mana_perc_cap) / 100; - if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) { - cur_mana = curMana_cap; + if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) { + current_mana = curMana_cap; } } Log(Logs::Detail, Logs::Spells, "Client::CalcMaxMana() called for %s - returning %d", GetName(), max_mana); @@ -2034,14 +2034,14 @@ void Client::CalcMaxEndurance() if (max_end < 0) { max_end = 0; } - if (cur_end > max_end) { - cur_end = max_end; + if (current_endurance > max_end) { + current_endurance = max_end; } int end_perc_cap = spellbonuses.EndPercCap[0]; if (end_perc_cap) { int curEnd_cap = (max_end * end_perc_cap) / 100; - if (cur_end > curEnd_cap || (spellbonuses.EndPercCap[1] && cur_end > spellbonuses.EndPercCap[1])) { - cur_end = curEnd_cap; + if (current_endurance > curEnd_cap || (spellbonuses.EndPercCap[1] && current_endurance > spellbonuses.EndPercCap[1])) { + current_endurance = curEnd_cap; } } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index e4891b999..5e1bcc8ca 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -584,14 +584,14 @@ void Client::CompleteConnect() if (raid->IsLocked()) raid->SendRaidLockTo(this); - raid->SendHPPacketsTo(this); + raid->SendHPManaEndPacketsTo(this); } } else { Group *group = nullptr; group = this->GetGroup(); if (group) - group->SendHPPacketsTo(this); + group->SendHPManaEndPacketsTo(this); } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index a346b7ce3..2bf1d5818 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -135,7 +135,7 @@ bool Client::Process() { SendHPUpdate(); if (mana_timer.Check()) - SendManaUpdatePacket(); + CheckManaEndUpdate(); if (dead && dead_timer.Check()) { database.MoveCharacterToZone(GetName(), database.GetZoneName(m_pp.binds[0].zoneId)); @@ -273,10 +273,10 @@ bool Client::Process() { } /* Clients need to be kept up to date for position updates more often otherwise they disappear */ - if (mob->IsClient() && this != mob && distance <= client_update_range) { + if (mob->IsClient() && this != mob && !mob->IsMoving() && distance <= client_update_range) { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - mob->MakeSpawnUpdateNoDelta(spawn_update); + mob->MakeSpawnUpdate(spawn_update); this->FastQueuePacket(&app, false); safe_delete(app); } @@ -1832,7 +1832,7 @@ void Client::DoManaRegen() { return; SetMana(GetMana() + CalcManaRegen() + RestRegenMana); - SendManaUpdatePacket(); + CheckManaEndUpdate(); } diff --git a/zone/command.cpp b/zone/command.cpp index b6c79e235..cbcdf6bb3 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -7197,7 +7197,7 @@ void command_ginfo(Client *c, const Seperator *sep) void command_hp(Client *c, const Seperator *sep) { c->SendHPUpdate(); - c->SendManaUpdatePacket(); + c->CheckManaEndUpdate(); } void command_aggro(Client *c, const Seperator *sep) diff --git a/zone/groups.cpp b/zone/groups.cpp index 28b4abd6a..c6fa6a978 100644 --- a/zone/groups.cpp +++ b/zone/groups.cpp @@ -341,7 +341,7 @@ bool Group::AddMember(Mob* newmember, const char *NewMemberName, uint32 Characte Group* group = newmember->CastToClient()->GetGroup(); if (group) { - group->SendHPPacketsTo(newmember); + group->SendHPManaEndPacketsTo(newmember); group->SendHPPacketsFrom(newmember); } @@ -394,7 +394,7 @@ void Group::QueuePacket(const EQApplicationPacket *app, bool ack_req) // Sends the rest of the group's hps to member. this is useful when someone // first joins a group, but otherwise there shouldn't be a need to call it -void Group::SendHPPacketsTo(Mob *member) +void Group::SendHPManaEndPacketsTo(Mob *member) { if(member && member->IsClient()) { EQApplicationPacket hpapp; @@ -410,14 +410,14 @@ void Group::SendHPPacketsTo(Mob *member) if (member->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = members[i]->GetID(); - mmus->mana = members[i]->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = members[i]->GetID(); + mana_update->mana = members[i]->GetManaPercent(); member->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = members[i]->GetEndurancePercent(); + endurance_update->endurance = members[i]->GetEndurancePercent(); member->CastToClient()->QueuePacket(&outapp, false); } } @@ -436,19 +436,58 @@ void Group::SendHPPacketsFrom(Mob *member) uint32 i; for(i = 0; i < MAX_GROUP_MEMBERS; i++) { - if(members[i] && members[i] != member && members[i]->IsClient()) - { + if(members[i] && members[i] != member && members[i]->IsClient()) { members[i]->CastToClient()->QueuePacket(&hp_app); - if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = member->GetID(); - mmus->mana = member->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = member->GetID(); + mana_update->mana = member->GetManaPercent(); members[i]->CastToClient()->QueuePacket(&outapp, false); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; outapp.SetOpcode(OP_MobEnduranceUpdate); - meus->endurance = member->GetEndurancePercent(); + endurance_update->endurance = member->GetEndurancePercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + } + } + } +} + +void Group::SendManaPacketFrom(Mob *member) +{ + if (!member) + return; + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i] != member && members[i]->IsClient()) { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = member->GetID(); + mana_update->mana = member->GetManaPercent(); + members[i]->CastToClient()->QueuePacket(&outapp, false); + } + } + } +} + +void Group::SendEndurancePacketFrom(Mob* member) +{ + if (!member) + return; + + EQApplicationPacket outapp(OP_MobEnduranceUpdate, sizeof(MobManaUpdate_Struct)); + + uint32 i; + for (i = 0; i < MAX_GROUP_MEMBERS; i++) { + if (members[i] && members[i] != member && members[i]->IsClient()) { + if (members[i]->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->spawn_id = member->GetID(); + endurance_update->endurance = member->GetEndurancePercent(); members[i]->CastToClient()->QueuePacket(&outapp, false); } } diff --git a/zone/groups.h b/zone/groups.h index 6de364d93..79fb0d8b6 100644 --- a/zone/groups.h +++ b/zone/groups.h @@ -80,8 +80,10 @@ public: inline void SetLeader(Mob* newleader){ leader=newleader; }; inline Mob* GetLeader() { return leader; }; const char* GetLeaderName() { return membername[0]; }; - void SendHPPacketsTo(Mob* newmember); - void SendHPPacketsFrom(Mob* newmember); + void SendHPManaEndPacketsTo(Mob* newmember); + void SendHPPacketsFrom(Mob* member); + void SendManaPacketFrom(Mob* member); + void SendEndurancePacketFrom(Mob* member); bool UpdatePlayer(Mob* update); void MemberZoned(Mob* removemob); inline bool IsLeader(Mob* leadertest) { return leadertest==leader; }; diff --git a/zone/merc.cpp b/zone/merc.cpp index 90d287152..2b1ef7098 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -906,15 +906,15 @@ int32 Merc::CalcMaxMana() max_mana = 0; } - if (cur_mana > max_mana) { - cur_mana = max_mana; + if (current_mana > max_mana) { + current_mana = max_mana; } int mana_perc_cap = spellbonuses.ManaPercCap[0]; if(mana_perc_cap) { int curMana_cap = (max_mana * mana_perc_cap) / 100; - if (cur_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && cur_mana > spellbonuses.ManaPercCap[1])) - cur_mana = curMana_cap; + if (current_mana > curMana_cap || (spellbonuses.ManaPercCap[1] && current_mana > spellbonuses.ManaPercCap[1])) + current_mana = curMana_cap; } #if EQDEBUG >= 11 @@ -4987,7 +4987,7 @@ void Merc::ScaleStats(int scalepercent, bool setmax) { max_mana = (int)((float)base_mana * scalerate); base_mana = max_mana; if (setmax) - cur_mana = max_mana; + current_mana = max_mana; } if (base_end) diff --git a/zone/mob.cpp b/zone/mob.cpp index 256fd7df7..eebb9798f 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -125,7 +125,7 @@ Mob::Mob(const char* in_name, last_z = 0; - + last_major_update_position = m_Position; AI_Init(); SetMoving(false); @@ -249,7 +249,7 @@ Mob::Mob(const char* in_name, bEnraged = false; shield_target = nullptr; - cur_mana = 0; + current_mana = 0; max_mana = 0; hp_regen = in_hp_regen; mana_regen = in_mana_regen; @@ -1357,24 +1357,24 @@ void Mob::SendHPUpdate(bool skip_self) last_hp_percent = current_hp_percent; } - EQApplicationPacket hp_app; + EQApplicationPacket hp_packet; Group *group = nullptr; - CreateHPPacket(&hp_app); + CreateHPPacket(&hp_packet); /* Update those who have use targeted */ - entity_list.QueueClientsByTarget(this, &hp_app, false, 0, false, true, EQEmu::versions::bit_AllClients); + entity_list.QueueClientsByTarget(this, &hp_packet, false, 0, false, true, EQEmu::versions::bit_AllClients); /* Update those who have us on x-target */ - entity_list.QueueClientsByXTarget(this, &hp_app, false); + entity_list.QueueClientsByXTarget(this, &hp_packet, false); /* Update groups using Group LAA health name tag counter */ - entity_list.QueueToGroupsForNPCHealthAA(this, &hp_app); + entity_list.QueueToGroupsForNPCHealthAA(this, &hp_packet); /* Update group */ if(IsGrouped()) { group = entity_list.GetGroupByMob(this); - if(group) //not sure why this might be null, but it happens + if(group) group->SendHPPacketsFrom(this); } @@ -1387,7 +1387,7 @@ void Mob::SendHPUpdate(bool skip_self) /* Pet - Update master - group and raid if exists */ if(GetOwner() && GetOwner()->IsClient()) { - GetOwner()->CastToClient()->QueuePacket(&hp_app, false); + GetOwner()->CastToClient()->QueuePacket(&hp_packet, false); group = entity_list.GetGroupByClient(GetOwner()->CastToClient()); if(group) @@ -1400,7 +1400,7 @@ void Mob::SendHPUpdate(bool skip_self) /* Send to pet */ if(GetPet() && GetPet()->IsClient()) { - GetPet()->CastToClient()->QueuePacket(&hp_app, false); + GetPet()->CastToClient()->QueuePacket(&hp_packet, false); } /* Destructible objects */ @@ -1439,10 +1439,20 @@ void Mob::SendHPUpdate(bool skip_self) // this one just warps the mob to the current location void Mob::SendPosition() { + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); - entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); + + /* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ + if (DistanceNoZ(last_major_update_position, m_Position) > 100) { + entity_list.QueueClients(this, app, true, true); + last_major_update_position = m_Position; + } + else { + entity_list.QueueCloseClients(this, app, true, RuleI(Range, MobPositionUpdates), nullptr, false); + } + safe_delete(app); } @@ -2270,13 +2280,13 @@ const int32& Mob::SetMana(int32 amount) { CalcMaxMana(); int32 mmana = GetMaxMana(); - cur_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); + current_mana = amount < 0 ? 0 : (amount > mmana ? mmana : amount); /* if(IsClient()) LogFile->write(EQEMuLog::Debug, "Setting mana for %s to %d (%4.1f%%)", GetName(), amount, GetManaRatio()); */ - return cur_mana; + return current_mana; } diff --git a/zone/mob.h b/zone/mob.h index 27ea48d4f..5292aff00 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -466,14 +466,14 @@ public: inline int32 GetMaxHP() const { return max_hp; } virtual int32 CalcMaxHP(); inline int32 GetMaxMana() const { return max_mana; } - inline int32 GetMana() const { return cur_mana; } + inline int32 GetMana() const { return current_mana; } virtual int32 GetEndurance() const { return 0; } virtual void SetEndurance(int32 newEnd) { return; } int32 GetItemHPBonuses(); int32 GetSpellHPBonuses(); virtual const int32& SetMana(int32 amount); inline float GetManaRatio() const { return max_mana == 0 ? 100 : - ((static_cast(cur_mana) / max_mana) * 100); } + ((static_cast(current_mana) / max_mana) * 100); } virtual int32 CalcMaxMana(); uint32 GetNPCTypeID() const { return npctype_id; } void SetNPCTypeID(uint32 npctypeid) { npctype_id = npctypeid; } @@ -998,7 +998,7 @@ public: Timer GetAttackTimer() { return attack_timer; } Timer GetAttackDWTimer() { return attack_dw_timer; } inline bool IsFindable() { return findable; } - inline uint8 GetManaPercent() { return (uint8)((float)cur_mana / (float)max_mana * 100.0f); } + inline uint8 GetManaPercent() { return (uint8)((float)current_mana / (float)max_mana * 100.0f); } virtual uint8 GetEndurancePercent() { return 0; } inline virtual bool IsBlockedBuff(int16 SpellID) { return false; } @@ -1145,7 +1145,7 @@ protected: int32 cur_hp; int32 max_hp; int32 base_hp; - int32 cur_mana; + int32 current_mana; int32 max_mana; int32 hp_regen; int32 mana_regen; @@ -1184,6 +1184,8 @@ protected: uint8 orig_level; uint32 npctype_id; glm::vec4 m_Position; + /* Used to determine when an NPC has traversed so many units - to send a zone wide pos update */ + glm::vec4 last_major_update_position; uint16 animation; float base_size; float size; diff --git a/zone/npc.cpp b/zone/npc.cpp index 97dd647ec..8ddd9b2e3 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1990,7 +1990,7 @@ void NPC::ModifyNPCStat(const char *identifier, const char *newValue) else if(id == "int" || id == "_int") { INT = atoi(val.c_str()); CalcMaxMana(); return; } else if(id == "cha") { CHA = atoi(val.c_str()); return; } else if(id == "max_hp") { base_hp = atoi(val.c_str()); CalcMaxHP(); if (cur_hp > max_hp) { cur_hp = max_hp; } return; } - else if(id == "max_mana") { npc_mana = atoi(val.c_str()); CalcMaxMana(); if (cur_mana > max_mana){ cur_mana = max_mana; } return; } + else if(id == "max_mana") { npc_mana = atoi(val.c_str()); CalcMaxMana(); if (current_mana > max_mana){ current_mana = max_mana; } return; } else if(id == "mr") { MR = atoi(val.c_str()); return; } else if(id == "fr") { FR = atoi(val.c_str()); return; } else if(id == "cr") { CR = atoi(val.c_str()); return; } diff --git a/zone/perl_groups.cpp b/zone/perl_groups.cpp index cdbffdd1c..e264b7d7a 100644 --- a/zone/perl_groups.cpp +++ b/zone/perl_groups.cpp @@ -389,7 +389,7 @@ XS(XS_Group_SendHPPacketsTo) if(newmember == nullptr) Perl_croak(aTHX_ "newmember is nullptr, avoiding crash."); - THIS->SendHPPacketsTo(newmember); + THIS->SendHPManaEndPacketsTo(newmember); } XSRETURN_EMPTY; } diff --git a/zone/raids.cpp b/zone/raids.cpp index d32ad4def..baf2d71b0 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -145,11 +145,11 @@ void Raid::AddMember(Client *c, uint32 group, bool rleader, bool groupleader, bo } } - Group *group_update = nullptr; - group_update = c->GetGroup(); - if (group_update) { - group_update->SendHPPacketsTo(c); - group_update->SendHPPacketsFrom(c); + Raid *raid_update = nullptr; + raid_update = c->GetRaid(); + if (raid_update) { + raid_update->SendHPManaEndPacketsTo(c); + raid_update->SendHPPacketsFrom(c); } auto pack = new ServerPacket(ServerOP_RaidAdd, sizeof(ServerRaidGeneralAction_Struct)); @@ -1546,7 +1546,7 @@ void Raid::MemberZoned(Client *c) group_mentor[gid].mentoree = nullptr; } -void Raid::SendHPPacketsTo(Client *client) +void Raid::SendHPManaEndPacketsTo(Client *client) { if(!client) return; @@ -1583,35 +1583,89 @@ void Raid::SendHPPacketsTo(Client *client) } } -void Raid::SendHPPacketsFrom(Mob *m) +void Raid::SendHPPacketsFrom(Mob *mob) { - if(!m) + if(!mob) return; - uint32 gid = 0; - if(m->IsClient()) - gid = this->GetGroup(m->CastToClient()); + uint32 group_id = 0; + + if(mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + EQApplicationPacket hpapp; EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); - m->CreateHPPacket(&hpapp); - for(int x = 0; x < MAX_RAID_MEMBERS; x++) - { - if(members[x].member) - { - if(!m->IsClient() || ((members[x].member != m->CastToClient()) && (members[x].GroupNumber == gid))) - { + mob->CreateHPPacket(&hpapp); + + for(int x = 0; x < MAX_RAID_MEMBERS; x++) { + if(members[x].member) { + if(!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { members[x].member->QueuePacket(&hpapp, false); - if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) - { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { outapp.SetOpcode(OP_MobManaUpdate); - MobManaUpdate_Struct *mmus = (MobManaUpdate_Struct *)outapp.pBuffer; - mmus->spawn_id = m->GetID(); - mmus->mana = m->GetManaPercent(); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = mob->GetID(); + mana_update->mana = mob->GetManaPercent(); members[x].member->QueuePacket(&outapp, false); + outapp.SetOpcode(OP_MobEnduranceUpdate); - MobEnduranceUpdate_Struct *meus = (MobEnduranceUpdate_Struct *)outapp.pBuffer; - meus->endurance = m->GetEndurancePercent(); + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->endurance = mob->GetEndurancePercent(); + members[x].member->QueuePacket(&outapp, false); + } + } + } + } +} + +void Raid::SendManaPacketFrom(Mob *mob) +{ + if (!mob) + return; + + uint32 group_id = 0; + + if (mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (members[x].member) { + if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobManaUpdate); + MobManaUpdate_Struct *mana_update = (MobManaUpdate_Struct *)outapp.pBuffer; + mana_update->spawn_id = mob->GetID(); + mana_update->mana = mob->GetManaPercent(); + members[x].member->QueuePacket(&outapp, false); + } + } + } + } +} + +void Raid::SendEndurancePacketFrom(Mob *mob) +{ + if (!mob) + return; + + uint32 group_id = 0; + + if (mob->IsClient()) + group_id = this->GetGroup(mob->CastToClient()); + + EQApplicationPacket outapp(OP_MobManaUpdate, sizeof(MobManaUpdate_Struct)); + + for (int x = 0; x < MAX_RAID_MEMBERS; x++) { + if (members[x].member) { + if (!mob->IsClient() || ((members[x].member != mob->CastToClient()) && (members[x].GroupNumber == group_id))) { + if (members[x].member->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + outapp.SetOpcode(OP_MobEnduranceUpdate); + MobEnduranceUpdate_Struct *endurance_update = (MobEnduranceUpdate_Struct *)outapp.pBuffer; + endurance_update->spawn_id = mob->GetID(); + endurance_update->endurance = mob->GetEndurancePercent(); members[x].member->QueuePacket(&outapp, false); } } diff --git a/zone/raids.h b/zone/raids.h index 9e681153c..232a0057f 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -172,8 +172,10 @@ public: bool LearnMembers(); void VerifyRaid(); void MemberZoned(Client *c); - void SendHPPacketsTo(Client *c); - void SendHPPacketsFrom(Mob *m); + void SendHPManaEndPacketsTo(Client *c); + void SendHPPacketsFrom(Mob *mob); + void SendManaPacketFrom(Mob *mob); + void SendEndurancePacketFrom(Mob *mob); void RaidSay(const char *msg, Client *c); void RaidGroupSay(const char *msg, Client *c); diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 99f748d51..18730bb55 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -989,7 +989,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) } database.RefreshGroupFromDB(client); - group->SendHPPacketsTo(client); + group->SendHPManaEndPacketsTo(client); // If the group leader is not set, pull the group leader information from the database. if (!group->GetLeader()) From 45b29aedf302b4fb19c11d4de84b702c1ca4d808 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 12 Jul 2017 21:49:30 -0500 Subject: [PATCH 142/218] Bring back netcode to robust commit 34549a4 - proven and tested by PEQ and EZ as solid/stable with all of recent packet fixes --- common/net/daybreak_connection.cpp | 154 ++++++++++------------------- common/net/daybreak_connection.h | 28 ++---- 2 files changed, 60 insertions(+), 122 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index de21485d3..1213b65eb 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -141,7 +141,7 @@ void EQ::Net::DaybreakConnectionManager::Process() connection->SendConnect(); } } - break; + break; case StatusConnected: { if (m_options.keepalive_delay_ms != 0) { auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); @@ -151,10 +151,10 @@ void EQ::Net::DaybreakConnectionManager::Process() } } case StatusDisconnecting: - connection->Process(); - break; + connection->Process(); + break; default: - break; + break; } iter++; @@ -172,10 +172,10 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend() { case StatusConnected: case StatusDisconnecting: - connection->ProcessResend(); - break; + connection->ProcessResend(); + break; default: - break; + break; } iter++; @@ -365,7 +365,7 @@ void EQ::Net::DaybreakConnection::Process() FlushBuffer(); } - ProcessInboundQueue(); + ProcessQueue(); } catch (std::exception ex) { LogF(Logs::Detail, Logs::Netcode, "Error processing connection: {0}", ex.what()); @@ -407,13 +407,13 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { case EncodeCompression: - Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; + Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; default: - break; + break; } } @@ -425,10 +425,10 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; default: - break; + break; } } @@ -440,7 +440,7 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) } } -void EQ::Net::DaybreakConnection::ProcessInboundQueue() +void EQ::Net::DaybreakConnection::ProcessQueue() { for (int i = 0; i < 4; ++i) { auto stream = &m_streams[i]; @@ -459,31 +459,6 @@ void EQ::Net::DaybreakConnection::ProcessInboundQueue() } } -void EQ::Net::DaybreakConnection::ProcessOutboundQueue() -{ - for (int i = 0; i < 4; ++i) { - auto stream = &m_streams[i]; - - if (stream->outstanding_bytes == 0) { - continue; - } - - while (!stream->buffered_packets.empty()) { - auto &buff = stream->buffered_packets.front(); - - if (stream->outstanding_bytes + buff.sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || - stream->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { - break; - } - - stream->outstanding_bytes += buff.sent.packet.Length(); - stream->outstanding_packets.insert(std::make_pair(buff.seq, buff.sent)); - InternalBufferedSend(buff.sent.packet); - stream->buffered_packets.pop_front(); - } - } -} - void EQ::Net::DaybreakConnection::RemoveFromQueue(int stream, uint16_t seq) { auto s = &m_streams[stream]; @@ -779,10 +754,10 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) break; } case OP_SessionStatResponse: - break; + break; default: - LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1)); - break; + LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1)); + break; } } else { @@ -808,15 +783,15 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p) int actual = 0; switch (m_crc_bytes) { case 2: - actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff; - calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff; - break; + actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff; + calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff; + break; case 4: - actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]); - calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key); - break; + actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]); + calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key); + break; default: - return false; + return false; } if (actual == calculated) { @@ -835,13 +810,13 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p) int calculated = 0; switch (m_crc_bytes) { case 2: - calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff; - p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated)); - break; + calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff; + p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated)); + break; case 4: - calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key); - p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated)); - break; + calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key); + p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated)); + break; } } @@ -1044,7 +1019,7 @@ void EQ::Net::DaybreakConnection::ProcessResend(int stream) auto now = Clock::now(); auto s = &m_streams[stream]; - for (auto &entry : s->outstanding_packets) { + for (auto &entry : s->sent_packets) { auto time_since_last_send = std::chrono::duration_cast(now - entry.second.last_sent); if (entry.second.times_resent == 0) { if ((size_t)time_since_last_send.count() > m_resend_delay) { @@ -1076,8 +1051,8 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) auto now = Clock::now(); auto s = &m_streams[stream]; - auto iter = s->outstanding_packets.begin(); - while (iter != s->outstanding_packets.end()) { + auto iter = s->sent_packets.begin(); + while (iter != s->sent_packets.end()) { auto order = CompareSequence(seq, iter->first); if (order != SequenceFuture) { @@ -1088,9 +1063,7 @@ void EQ::Net::DaybreakConnection::Ack(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - s->outstanding_bytes -= iter->second.packet.Length(); - iter = s->outstanding_packets.erase(iter); - ProcessOutboundQueue(); + iter = s->sent_packets.erase(iter); } else { ++iter; @@ -1102,8 +1075,8 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) { auto now = Clock::now(); auto s = &m_streams[stream]; - auto iter = s->outstanding_packets.find(seq); - if (iter != s->outstanding_packets.end()) { + auto iter = s->sent_packets.find(seq); + if (iter != s->sent_packets.end()) { uint64_t round_time = (uint64_t)std::chrono::duration_cast(now - iter->second.last_sent).count(); m_stats.max_ping = std::max(m_stats.max_ping, round_time); @@ -1111,31 +1084,10 @@ void EQ::Net::DaybreakConnection::OutOfOrderAck(int stream, uint16_t seq) m_stats.last_ping = round_time; m_rolling_ping = (m_rolling_ping * 2 + round_time) / 3; - s->outstanding_bytes -= iter->second.packet.Length(); - s->outstanding_packets.erase(iter); - ProcessOutboundQueue(); + s->sent_packets.erase(iter); } } -void EQ::Net::DaybreakConnection::BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent) -{ - auto s = &m_streams[stream]; - //If we can send the packet then send it - //else buffer it to be sent when we can send it - if (s->outstanding_bytes + sent.packet.Length() >= m_owner->m_options.max_outstanding_bytes || s->outstanding_packets.size() + 1 >= m_owner->m_options.max_outstanding_packets) { - //Would go over one of the limits, buffer this packet. - DaybreakBufferedPacket bp; - bp.sent = std::move(sent); - bp.seq = seq; - s->buffered_packets.push_back(bp); - return; - } - - s->outstanding_bytes += sent.packet.Length(); - s->outstanding_packets.insert(std::make_pair(seq, sent)); - InternalBufferedSend(sent.packet); -} - void EQ::Net::DaybreakConnection::SendAck(int stream_id, uint16_t seq) { DaybreakReliableHeader ack; @@ -1187,10 +1139,6 @@ void EQ::Net::DaybreakConnection::InternalBufferedSend(Packet &p) FlushBuffer(); } - if (m_buffered_packets.size() == 0) { - m_hold_time = Clock::now(); - } - DynamicPacket copy; copy.PutPacket(0, p); m_buffered_packets.push_back(copy); @@ -1253,13 +1201,13 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) for (int i = 0; i < 2; ++i) { switch (m_encode_passes[i]) { case EncodeCompression: - Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); - break; + Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + break; case EncodeXOR: - Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); - break; + Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + break; default: - break; + break; } } @@ -1345,9 +1293,11 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - BufferPacket(stream_id, stream->sequence_out, sent); + stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); stream->sequence_out++; + InternalBufferedSend(first_packet); + while (used < length) { auto left = length - used; DynamicPacket packet; @@ -1371,8 +1321,10 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - BufferPacket(stream_id, stream->sequence_out, sent); + stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); stream->sequence_out++; + + InternalBufferedSend(packet); } } else { @@ -1389,8 +1341,10 @@ void EQ::Net::DaybreakConnection::InternalQueuePacket(Packet &p, int stream_id, sent.last_sent = Clock::now(); sent.first_sent = Clock::now(); sent.times_resent = 0; - BufferPacket(stream_id, stream->sequence_out, sent); + stream->sent_packets.insert(std::make_pair(stream->sequence_out, sent)); stream->sequence_out++; + + InternalBufferedSend(packet); } } diff --git a/common/net/daybreak_connection.h b/common/net/daybreak_connection.h index bbd0c7d93..016ef3258 100644 --- a/common/net/daybreak_connection.h +++ b/common/net/daybreak_connection.h @@ -8,8 +8,7 @@ #include #include #include -#include -#include +#include #include namespace EQ @@ -145,12 +144,6 @@ namespace EQ size_t times_resent; }; - struct DaybreakBufferedPacket - { - uint16_t seq; - DaybreakSentPacket sent; - }; - struct DaybreakStream { DaybreakStream() { @@ -158,20 +151,17 @@ namespace EQ sequence_out = 0; fragment_current_bytes = 0; fragment_total_bytes = 0; - outstanding_bytes = 0; } uint16_t sequence_in; uint16_t sequence_out; - std::unordered_map packet_queue; - std::deque buffered_packets; + std::map packet_queue; DynamicPacket fragment_packet; uint32_t fragment_current_bytes; uint32_t fragment_total_bytes; - std::unordered_map outstanding_packets; - size_t outstanding_bytes; + std::map sent_packets; }; DaybreakStream m_streams[4]; @@ -179,8 +169,7 @@ namespace EQ void Process(); void ProcessPacket(Packet &p); - void ProcessInboundQueue(); - void ProcessOutboundQueue(); + void ProcessQueue(); void RemoveFromQueue(int stream, uint16_t seq); void AddToQueue(int stream, uint16_t seq, const Packet &p); void ProcessDecodedPacket(const Packet &p); @@ -196,7 +185,6 @@ namespace EQ void ProcessResend(int stream); void Ack(int stream, uint16_t seq); void OutOfOrderAck(int stream, uint16_t seq); - void BufferPacket(int stream, uint16_t seq, DaybreakSentPacket &sent); void SendConnect(); void SendKeepAlive(); @@ -219,8 +207,8 @@ namespace EQ keepalive_delay_ms = 9000; resend_delay_ms = 150; resend_delay_factor = 1.5; - resend_delay_min = 300; - resend_delay_max = 3000; + resend_delay_min = 150; + resend_delay_max = 1000; connect_delay_ms = 500; stale_connection_ms = 90000; connect_stale_ms = 5000; @@ -236,8 +224,6 @@ namespace EQ tic_rate_hertz = 60.0; resend_timeout = 90000; connection_close_time = 2000; - max_outstanding_packets = 400; - max_outstanding_bytes = 400 * 512; } size_t max_packet_size; @@ -260,8 +246,6 @@ namespace EQ size_t connection_close_time; DaybreakEncodeType encode_passes[2]; int port; - size_t max_outstanding_packets; - size_t max_outstanding_bytes; }; class DaybreakConnectionManager From c8b20ecb1a21986d2ebd452d127d3d666f76294e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 12 Jul 2017 22:01:59 -0500 Subject: [PATCH 143/218] Adjust switch case formatting in daybreak_connection.cpp --- common/net/daybreak_connection.cpp | 596 ++++++++++++++--------------- 1 file changed, 298 insertions(+), 298 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 1213b65eb..283f8f93d 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -135,26 +135,26 @@ void EQ::Net::DaybreakConnectionManager::Process() switch (status) { - case StatusConnecting: { - auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); - if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) { - connection->SendConnect(); - } - } - break; - case StatusConnected: { - if (m_options.keepalive_delay_ms != 0) { + case StatusConnecting: { auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); - if ((size_t)time_since_last_send.count() > m_options.keepalive_delay_ms) { - connection->SendKeepAlive(); + if ((size_t)time_since_last_send.count() > m_options.connect_delay_ms) { + connection->SendConnect(); + } + break; + } + case StatusConnected: { + if (m_options.keepalive_delay_ms != 0) { + auto time_since_last_send = std::chrono::duration_cast(now - connection->m_last_send); + if ((size_t)time_since_last_send.count() > m_options.keepalive_delay_ms) { + connection->SendKeepAlive(); + } } } - } - case StatusDisconnecting: - connection->Process(); - break; - default: - break; + case StatusDisconnecting: + connection->Process(); + break; + default: + break; } iter++; @@ -170,12 +170,12 @@ void EQ::Net::DaybreakConnectionManager::ProcessResend() switch (status) { - case StatusConnected: - case StatusDisconnecting: - connection->ProcessResend(); - break; - default: - break; + case StatusConnected: + case StatusDisconnecting: + connection->ProcessResend(); + break; + default: + break; } iter++; @@ -406,14 +406,14 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { - case EncodeCompression: - Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; - case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; - default: - break; + case EncodeCompression: + Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; + case EncodeXOR: + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; + default: + break; } } @@ -424,11 +424,11 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { - case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); - break; - default: - break; + case EncodeXOR: + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + break; + default: + break; } } @@ -490,274 +490,274 @@ void EQ::Net::DaybreakConnection::ProcessDecodedPacket(const Packet &p) } switch (p.GetInt8(1)) { - case OP_Combined: { - if (m_status == StatusDisconnecting) { - SendDisconnect(); - return; - } - - char *current = (char*)p.Data() + 2; - char *end = (char*)p.Data() + p.Length(); - while (current < end) { - uint8_t subpacket_length = *(uint8_t*)current; - current += 1; - - if (end < current + subpacket_length) { + case OP_Combined: { + if (m_status == StatusDisconnecting) { + SendDisconnect(); return; } - ProcessDecodedPacket(StaticPacket(current, subpacket_length)); - current += subpacket_length; - } - break; - } + char *current = (char*)p.Data() + 2; + char *end = (char*)p.Data() + p.Length(); + while (current < end) { + uint8_t subpacket_length = *(uint8_t*)current; + current += 1; - case OP_AppCombined: - { - if (m_status == StatusDisconnecting) { - SendDisconnect(); - return; - } - - uint8_t *current = (uint8_t*)p.Data() + 2; - uint8_t *end = (uint8_t*)p.Data() + p.Length(); - - while (current < end) { - uint32_t subpacket_length = 0; - if (*current == 0xFF) - { - if (end < current + 3) { - throw std::out_of_range("Error in OP_AppCombined, end < current + 3"); + if (end < current + subpacket_length) { + return; } - if (*(current + 1) == 0xFF && *(current + 2) == 0xFF) { - if (end < current + 7) { - throw std::out_of_range("Error in OP_AppCombined, end < current + 7"); + ProcessDecodedPacket(StaticPacket(current, subpacket_length)); + current += subpacket_length; + } + break; + } + + case OP_AppCombined: + { + if (m_status == StatusDisconnecting) { + SendDisconnect(); + return; + } + + uint8_t *current = (uint8_t*)p.Data() + 2; + uint8_t *end = (uint8_t*)p.Data() + p.Length(); + + while (current < end) { + uint32_t subpacket_length = 0; + if (*current == 0xFF) + { + if (end < current + 3) { + throw std::out_of_range("Error in OP_AppCombined, end < current + 3"); } - subpacket_length = (uint32_t)( - (*(current + 3) << 24) | - (*(current + 4) << 16) | - (*(current + 5) << 8) | - (*(current + 6)) - ); - current += 7; + if (*(current + 1) == 0xFF && *(current + 2) == 0xFF) { + if (end < current + 7) { + throw std::out_of_range("Error in OP_AppCombined, end < current + 7"); + } + + subpacket_length = (uint32_t)( + (*(current + 3) << 24) | + (*(current + 4) << 16) | + (*(current + 5) << 8) | + (*(current + 6)) + ); + current += 7; + } + else { + subpacket_length = (uint32_t)( + (*(current + 1) << 8) | + (*(current + 2)) + ); + current += 3; + } } else { - subpacket_length = (uint32_t)( - (*(current + 1) << 8) | - (*(current + 2)) - ); - current += 3; + subpacket_length = (uint32_t)((*(current + 0))); + current += 1; + } + + ProcessDecodedPacket(StaticPacket(current, subpacket_length)); + current += subpacket_length; + } + } + + case OP_SessionRequest: + { + if (m_status == StatusConnected) { + auto request = p.GetSerialize(0); + + if (NetworkToHost(request.connect_code) != m_connect_code) { + return; + } + + DaybreakConnectReply reply; + reply.zero = 0; + reply.opcode = OP_SessionResponse; + reply.connect_code = HostToNetwork(m_connect_code); + reply.encode_key = HostToNetwork(m_encode_key); + reply.crc_bytes = m_crc_bytes; + reply.max_packet_size = HostToNetwork(m_max_packet_size); + reply.encode_pass1 = m_encode_passes[0]; + reply.encode_pass2 = m_encode_passes[1]; + DynamicPacket p; + p.PutSerialize(0, reply); + InternalSend(p); + } + + break; + } + + case OP_SessionResponse: + { + if (m_status == StatusConnecting) { + auto reply = p.GetSerialize(0); + + if (m_connect_code == reply.connect_code) { + m_encode_key = reply.encode_key; + m_crc_bytes = reply.crc_bytes; + m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1; + m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; + m_max_packet_size = reply.max_packet_size; + ChangeStatus(StatusConnected); } } - else { - subpacket_length = (uint32_t)((*(current + 0))); - current += 1; - } - - ProcessDecodedPacket(StaticPacket(current, subpacket_length)); - current += subpacket_length; + break; } - } - case OP_SessionRequest: - { - if (m_status == StatusConnected) { - auto request = p.GetSerialize(0); - - if (NetworkToHost(request.connect_code) != m_connect_code) { + case OP_Packet: + case OP_Packet2: + case OP_Packet3: + case OP_Packet4: + { + if (m_status == StatusDisconnecting) { + SendDisconnect(); return; } - DaybreakConnectReply reply; - reply.zero = 0; - reply.opcode = OP_SessionResponse; - reply.connect_code = HostToNetwork(m_connect_code); - reply.encode_key = HostToNetwork(m_encode_key); - reply.crc_bytes = m_crc_bytes; - reply.max_packet_size = HostToNetwork(m_max_packet_size); - reply.encode_pass1 = m_encode_passes[0]; - reply.encode_pass2 = m_encode_passes[1]; - DynamicPacket p; - p.PutSerialize(0, reply); - InternalSend(p); - } + auto header = p.GetSerialize(0); + auto sequence = NetworkToHost(header.sequence); + auto stream_id = header.opcode - OP_Packet; + auto stream = &m_streams[stream_id]; - break; - } - - case OP_SessionResponse: - { - if (m_status == StatusConnecting) { - auto reply = p.GetSerialize(0); - - if (m_connect_code == reply.connect_code) { - m_encode_key = reply.encode_key; - m_crc_bytes = reply.crc_bytes; - m_encode_passes[0] = (DaybreakEncodeType)reply.encode_pass1; - m_encode_passes[1] = (DaybreakEncodeType)reply.encode_pass2; - m_max_packet_size = reply.max_packet_size; - ChangeStatus(StatusConnected); + auto order = CompareSequence(stream->sequence_in, sequence); + if (order == SequenceFuture) { + SendOutOfOrderAck(stream_id, sequence); + AddToQueue(stream_id, sequence, p); } - } - break; - } - - case OP_Packet: - case OP_Packet2: - case OP_Packet3: - case OP_Packet4: - { - if (m_status == StatusDisconnecting) { - SendDisconnect(); - return; - } - - auto header = p.GetSerialize(0); - auto sequence = NetworkToHost(header.sequence); - auto stream_id = header.opcode - OP_Packet; - auto stream = &m_streams[stream_id]; - - auto order = CompareSequence(stream->sequence_in, sequence); - if (order == SequenceFuture) { - SendOutOfOrderAck(stream_id, sequence); - AddToQueue(stream_id, sequence, p); - } - else if (order == SequencePast) { - SendAck(stream_id, stream->sequence_in - 1); - } - else { - RemoveFromQueue(stream_id, sequence); - SendAck(stream_id, stream->sequence_in); - stream->sequence_in++; - StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); - ProcessDecodedPacket(next); - } - - break; - } - - case OP_Fragment: - case OP_Fragment2: - case OP_Fragment3: - case OP_Fragment4: - { - auto header = p.GetSerialize(0); - auto sequence = NetworkToHost(header.sequence); - auto stream_id = header.opcode - OP_Fragment; - auto stream = &m_streams[stream_id]; - - auto order = CompareSequence(stream->sequence_in, sequence); - - if (order == SequenceFuture) { - SendOutOfOrderAck(stream_id, sequence); - AddToQueue(stream_id, sequence, p); - } - else if (order == SequencePast) { - SendAck(stream_id, stream->sequence_in - 1); - } - else { - RemoveFromQueue(stream_id, sequence); - SendAck(stream_id, stream->sequence_in); - stream->sequence_in++; - - if (stream->fragment_total_bytes == 0) { - auto fragheader = p.GetSerialize(0); - stream->fragment_total_bytes = NetworkToHost(fragheader.total_size); - stream->fragment_current_bytes = 0; - stream->fragment_packet.Reserve(stream->fragment_total_bytes); - stream->fragment_packet.PutData( - stream->fragment_current_bytes, - (char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size()); - - stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size()); + else if (order == SequencePast) { + SendAck(stream_id, stream->sequence_in - 1); } else { - stream->fragment_packet.PutData( - stream->fragment_current_bytes, - (char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); + RemoveFromQueue(stream_id, sequence); + SendAck(stream_id, stream->sequence_in); + stream->sequence_in++; + StaticPacket next((char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); + ProcessDecodedPacket(next); + } - stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size()); + break; + } - if (stream->fragment_current_bytes >= stream->fragment_total_bytes) { - ProcessDecodedPacket(stream->fragment_packet); - stream->fragment_packet.Clear(); - stream->fragment_total_bytes = 0; + case OP_Fragment: + case OP_Fragment2: + case OP_Fragment3: + case OP_Fragment4: + { + auto header = p.GetSerialize(0); + auto sequence = NetworkToHost(header.sequence); + auto stream_id = header.opcode - OP_Fragment; + auto stream = &m_streams[stream_id]; + + auto order = CompareSequence(stream->sequence_in, sequence); + + if (order == SequenceFuture) { + SendOutOfOrderAck(stream_id, sequence); + AddToQueue(stream_id, sequence, p); + } + else if (order == SequencePast) { + SendAck(stream_id, stream->sequence_in - 1); + } + else { + RemoveFromQueue(stream_id, sequence); + SendAck(stream_id, stream->sequence_in); + stream->sequence_in++; + + if (stream->fragment_total_bytes == 0) { + auto fragheader = p.GetSerialize(0); + stream->fragment_total_bytes = NetworkToHost(fragheader.total_size); stream->fragment_current_bytes = 0; + stream->fragment_packet.Reserve(stream->fragment_total_bytes); + stream->fragment_packet.PutData( + stream->fragment_current_bytes, + (char*)p.Data() + DaybreakReliableFragmentHeader::size(), p.Length() - DaybreakReliableFragmentHeader::size()); + + stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableFragmentHeader::size()); + } + else { + stream->fragment_packet.PutData( + stream->fragment_current_bytes, + (char*)p.Data() + DaybreakReliableHeader::size(), p.Length() - DaybreakReliableHeader::size()); + + stream->fragment_current_bytes += (uint32_t)(p.Length() - DaybreakReliableHeader::size()); + + if (stream->fragment_current_bytes >= stream->fragment_total_bytes) { + ProcessDecodedPacket(stream->fragment_packet); + stream->fragment_packet.Clear(); + stream->fragment_total_bytes = 0; + stream->fragment_current_bytes = 0; + } } } + + break; } - break; - } - - case OP_Ack: - case OP_Ack2: - case OP_Ack3: - case OP_Ack4: - { - auto header = p.GetSerialize(0); - auto sequence = NetworkToHost(header.sequence); - auto stream_id = header.opcode - OP_Ack; - Ack(stream_id, sequence); - break; - } - - case OP_OutOfOrderAck: - case OP_OutOfOrderAck2: - case OP_OutOfOrderAck3: - case OP_OutOfOrderAck4: - { - auto header = p.GetSerialize(0); - auto sequence = NetworkToHost(header.sequence); - auto stream_id = header.opcode - OP_OutOfOrderAck; - OutOfOrderAck(stream_id, sequence); - break; - } - - case OP_SessionDisconnect: - { - if (m_status == StatusConnected || m_status == StatusDisconnecting) { - FlushBuffer(); - SendDisconnect(); + case OP_Ack: + case OP_Ack2: + case OP_Ack3: + case OP_Ack4: + { + auto header = p.GetSerialize(0); + auto sequence = NetworkToHost(header.sequence); + auto stream_id = header.opcode - OP_Ack; + Ack(stream_id, sequence); + break; } - ChangeStatus(StatusDisconnecting); - break; - } - - case OP_Padding: - { - auto self = m_self.lock(); - if (m_owner->m_on_packet_recv && self) { - m_owner->m_on_packet_recv(self, StaticPacket((char*)p.Data() + 1, p.Length() - 1)); + case OP_OutOfOrderAck: + case OP_OutOfOrderAck2: + case OP_OutOfOrderAck3: + case OP_OutOfOrderAck4: + { + auto header = p.GetSerialize(0); + auto sequence = NetworkToHost(header.sequence); + auto stream_id = header.opcode - OP_OutOfOrderAck; + OutOfOrderAck(stream_id, sequence); + break; } - break; - } - case OP_SessionStatRequest: - { - auto request = p.GetSerialize(0); - DaybreakSessionStatResponse response; - response.zero = 0; - response.opcode = OP_SessionStatResponse; - response.timestamp = request.timestamp; - response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); - response.client_sent = request.packets_sent; - response.client_recv = request.packets_recv; - response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets); - response.server_recv = EQ::Net::HostToNetwork(m_stats.recv_packets); - DynamicPacket out; - out.PutSerialize(0, response); - InternalSend(out); - break; - } - case OP_SessionStatResponse: - break; - default: - LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1)); - break; + case OP_SessionDisconnect: + { + if (m_status == StatusConnected || m_status == StatusDisconnecting) { + FlushBuffer(); + SendDisconnect(); + } + + ChangeStatus(StatusDisconnecting); + break; + } + + case OP_Padding: + { + auto self = m_self.lock(); + if (m_owner->m_on_packet_recv && self) { + m_owner->m_on_packet_recv(self, StaticPacket((char*)p.Data() + 1, p.Length() - 1)); + } + break; + } + case OP_SessionStatRequest: + { + auto request = p.GetSerialize(0); + + DaybreakSessionStatResponse response; + response.zero = 0; + response.opcode = OP_SessionStatResponse; + response.timestamp = request.timestamp; + response.our_timestamp = EQ::Net::HostToNetwork(std::chrono::duration_cast(std::chrono::high_resolution_clock::now().time_since_epoch()).count()); + response.client_sent = request.packets_sent; + response.client_recv = request.packets_recv; + response.server_sent = EQ::Net::HostToNetwork(m_stats.sent_packets); + response.server_recv = EQ::Net::HostToNetwork(m_stats.recv_packets); + DynamicPacket out; + out.PutSerialize(0, response); + InternalSend(out); + break; + } + case OP_SessionStatResponse: + break; + default: + LogF(Logs::Detail, Logs::Netcode, "Unhandled opcode {0:#x}", p.GetInt8(1)); + break; } } else { @@ -782,16 +782,16 @@ bool EQ::Net::DaybreakConnection::ValidateCRC(Packet &p) int calculated = 0; int actual = 0; switch (m_crc_bytes) { - case 2: - actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff; - calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff; - break; - case 4: - actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]); - calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key); - break; - default: - return false; + case 2: + actual = NetworkToHost(*(int16_t*)&data[p.Length() - (size_t)m_crc_bytes]) & 0xffff; + calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key) & 0xffff; + break; + case 4: + actual = NetworkToHost(*(int32_t*)&data[p.Length() - (size_t)m_crc_bytes]); + calculated = Crc32(data, (int)(p.Length() - (size_t)m_crc_bytes), m_encode_key); + break; + default: + return false; } if (actual == calculated) { @@ -809,14 +809,14 @@ void EQ::Net::DaybreakConnection::AppendCRC(Packet &p) int calculated = 0; switch (m_crc_bytes) { - case 2: - calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff; - p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated)); - break; - case 4: - calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key); - p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated)); - break; + case 2: + calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key) & 0xffff; + p.PutInt16(p.Length(), EQ::Net::HostToNetwork((int16_t)calculated)); + break; + case 4: + calculated = Crc32(p.Data(), (int)p.Length(), m_encode_key); + p.PutInt32(p.Length(), EQ::Net::HostToNetwork(calculated)); + break; } } @@ -1200,14 +1200,14 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) for (int i = 0; i < 2; ++i) { switch (m_encode_passes[i]) { - case EncodeCompression: - Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); - break; - case EncodeXOR: - Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); - break; - default: - break; + case EncodeCompression: + Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + break; + case EncodeXOR: + Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + break; + default: + break; } } From be0374d1975c92841f8d2c1847a24cdef36bb8f9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Thu, 13 Jul 2017 00:52:42 -0500 Subject: [PATCH 144/218] Performance adjustment to SendPosition update logic --- zone/mob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index eebb9798f..68f55626b 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1445,7 +1445,7 @@ void Mob::SendPosition() MakeSpawnUpdateNoDelta(spu); /* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ - if (DistanceNoZ(last_major_update_position, m_Position) > 100) { + if (DistanceSquared(last_major_update_position, m_Position) > (100 * 100)) { entity_list.QueueClients(this, app, true, true); last_major_update_position = m_Position; } From 94038ebb7521a7c178a67ae4c6ab3d22d9e2b8e2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 02:05:35 -0400 Subject: [PATCH 145/218] WIP on auras Lots to do still Normal buffing auras currently work for the most part --- common/emu_oplist.h | 2 + common/eq_packet_structs.h | 18 + common/shareddb.cpp | 1 + common/spdat.h | 8 +- utils/patches/patch_RoF2.conf | 4 + utils/sql/git/required/2017_07_xx_aura.sql | 13 + zone/CMakeLists.txt | 2 + zone/aura.cpp | 435 +++++++++++++++++++++ zone/aura.h | 76 ++++ zone/bonuses.cpp | 18 + zone/client_packet.cpp | 24 ++ zone/client_packet.h | 1 + zone/common.h | 4 + zone/entity.h | 1 + zone/mob.h | 34 ++ zone/npc.h | 2 + zone/raids.cpp | 8 + zone/raids.h | 1 + zone/spell_effects.cpp | 4 + zone/spells.cpp | 25 ++ zone/string_ids.h | 2 + zone/zonedb.h | 13 + 22 files changed, 692 insertions(+), 4 deletions(-) create mode 100644 utils/sql/git/required/2017_07_xx_aura.sql create mode 100644 zone/aura.cpp create mode 100644 zone/aura.h diff --git a/common/emu_oplist.h b/common/emu_oplist.h index e695c94a9..29a20cb14 100644 --- a/common/emu_oplist.h +++ b/common/emu_oplist.h @@ -408,6 +408,7 @@ N(OP_ReloadUI), N(OP_RemoveAllDoors), N(OP_RemoveBlockedBuffs), N(OP_RemoveNimbusEffect), +N(OP_RemoveTrap), N(OP_Report), N(OP_ReqClientSpawn), N(OP_ReqNewZone), @@ -523,6 +524,7 @@ N(OP_TributeToggle), N(OP_TributeUpdate), N(OP_Untargetable), N(OP_UpdateAA), +N(OP_UpdateAura), N(OP_UpdateLeadershipAA), N(OP_VetClaimReply), N(OP_VetClaimRequest), diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c234e303a..021b18557 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -5332,6 +5332,24 @@ struct fling_struct { /* 28 */ }; +// used when action == 0 +struct AuraCreate_Struct { +/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset +/* 04 */ uint32 type; // unsure -- normal auras show 1 clicky (ex. Circle of Power) show 0 +/* 08 */ char aura_name[64]; +/* 72 */ uint32 entity_id; +/* 76 */ uint32 icon; +/* 80 */ +}; + +// used when action == 1 +struct AuraDestory_Struct { +/* 00 */ uint32 action; // 0 = add, 1 = delete, 2 = reset +/* 04 */ uint32 entity_id; +/* 08 */ +}; +// I think we can assume it's just action for 2, client doesn't seem to do anything with the rest of the data in that case + // Restore structure packing to default #pragma pack() diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 2efb06913..331826ef2 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1674,6 +1674,7 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) { for (y = 0; y < 16; y++) sp[tempid].deities[y]=atoi(row[126+y]); + sp[tempid].new_icon=atoi(row[144]); sp[tempid].uninterruptable=atoi(row[146]) != 0; sp[tempid].ResistDiff=atoi(row[147]); sp[tempid].dot_stacking_exempt = atoi(row[148]) != 0; diff --git a/common/spdat.h b/common/spdat.h index bd1dacdf8..605e9a6cf 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -562,9 +562,9 @@ typedef enum { #define SE_LimitManaMin 348 // implemented #define SE_ShieldEquipDmgMod 349 // implemented[AA] Increase melee base damage (indirectly increasing hate) when wearing a shield. #define SE_ManaBurn 350 // implemented - Drains mana for damage/heal at a defined ratio up to a defined maximum amount of mana. -//#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this -//#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755) -//#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect +#define SE_PersistentEffect 351 // *not implemented. creates a trap/totem that casts a spell (spell id + base1?) when anything comes near it. can probably make a beacon for this +#define SE_IncreaseTrapCount 352 // *not implemented - looks to be some type of invulnerability? Test ITC (8755) +#define SE_AdditionalAura 353 // *not implemented - allows use of more than 1 aura, aa effect //#define SE_DeactivateAllTraps 354 // *not implemented - looks to be some type of invulnerability? Test DAT (8757) //#define SE_LearnTrap 355 // *not implemented - looks to be some type of invulnerability? Test LT (8758) //#define SE_ChangeTriggerType 356 // not used @@ -757,7 +757,7 @@ struct SPDat_Spell_Struct // -- DIETY_BERTOXXULOUS ... DIETY_VEESHAN /* 142 */ //int8 npc_no_cast; // 142: between 0 & 100 -- NPC_NO_CAST /* 143 */ //int ai_pt_bonus; // 143: always set to 0, client doesn't save this -- AI_PT_BONUS -/* 144 */ //int16 new_icon // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON +/* 144 */ int16 new_icon; // Spell icon used by the client in uifiles/default/spells??.tga, both for spell gems & buff window. Looks to depreciate icon & memicon -- NEW_ICON /* 145 */ //int16 spellanim; // Doesn't look like it's the same as #doanim, so not sure what this is, particles I think -- SPELL_EFFECT_INDEX /* 146 */ bool uninterruptable; // Looks like anything != 0 is uninterruptable. Values are mostly -1, 0, & 1 (Fetid Breath = 90?) -- NO_INTERRUPT /* 147 */ int16 ResistDiff; // -- RESIST_MOD diff --git a/utils/patches/patch_RoF2.conf b/utils/patches/patch_RoF2.conf index ee9b0e646..e63e5e9e9 100644 --- a/utils/patches/patch_RoF2.conf +++ b/utils/patches/patch_RoF2.conf @@ -675,3 +675,7 @@ OP_RAWOutOfSession=0x0000 # we need to document the differences between these packets to make identifying them easier OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs OP_InitialHPUpdate=0x0000 + +#aura related +OP_UpdateAura=0x1456 +OP_RemoveTrap=0x71da diff --git a/utils/sql/git/required/2017_07_xx_aura.sql b/utils/sql/git/required/2017_07_xx_aura.sql new file mode 100644 index 000000000..ed777d2e5 --- /dev/null +++ b/utils/sql/git/required/2017_07_xx_aura.sql @@ -0,0 +1,13 @@ +CREATE TABLE `auras` ( + `type` INT(10) NOT NULL, + `npc_type` INT(10) NOT NULL, + `name` VARCHAR(64) NOT NULL, + `spell_id` INT(10) NOT NULL, + `distance` INT(10) NOT NULL DEFAULT 60, + `aura_type` INT(10) NOT NULL DEFAULT 1, + `spawn_type` INT(10) NOT NULL DEFAULT 0, + `movement` INT(10) NOT NULL DEFAULT 0, + `duration` INT(10) NOT NULL DEFAULT 5400, + `icon` INT(10) NOT NULL DEFAULT -1, + PRIMARY KEY(`type`) +) diff --git a/zone/CMakeLists.txt b/zone/CMakeLists.txt index 0c2c9bd63..0171c8eb9 100644 --- a/zone/CMakeLists.txt +++ b/zone/CMakeLists.txt @@ -5,6 +5,7 @@ SET(zone_sources aa_ability.cpp aggro.cpp aggromanager.cpp + aura.cpp attack.cpp beacon.cpp bonuses.cpp @@ -136,6 +137,7 @@ SET(zone_headers aa.h aa_ability.h aggromanager.h + aura.h basic_functions.h beacon.h bot.h diff --git a/zone/aura.cpp b/zone/aura.cpp new file mode 100644 index 000000000..6b4e06323 --- /dev/null +++ b/zone/aura.cpp @@ -0,0 +1,435 @@ +#include "../common/string_util.h" + +#include "aura.h" +#include "client.h" +#include "string_ids.h" +#include "raids.h" + +Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) + : NPC(type_data, 0, owner->GetPosition(), FlyMode3), spell_id(record.spell_id), distance(record.distance), + remove_timer(record.duration), movement_timer(100), process_timer(100) +{ + GiveNPCTypeData(type_data); // we will delete this later on + m_owner = owner->GetID(); + + if (record.aura_type < static_cast(AuraType::Max)) + type = static_cast(record.aura_type); + else + type = AuraType::OnAllGroupMembers; + + if (record.spawn_type < static_cast(AuraSpawns::Max)) + spawn_type = static_cast(record.spawn_type); + else + spawn_type = AuraSpawns::GroupMembers; + + if (record.movement < static_cast(AuraMovement::Max)) + movement_type = static_cast(record.movement); + else + movement_type = AuraMovement::Follow; + + switch (type) { + case AuraType::OnAllFriendlies: + process_func = &Aura::ProcessOnAllFriendlies; + break; + case AuraType::OnAllGroupMembers: + process_func = &Aura::ProcessOnAllGroupMembers; + break; + case AuraType::OnGroupMembersPets: + process_func = &Aura::ProcessOnGroupMembersPets; + break; + case AuraType::Totem: + process_func = &Aura::ProcessTotem; + break; + case AuraType::EnterTrap: + process_func = &Aura::ProcessEnterTrap; + break; + case AuraType::ExitTrap: + process_func = &Aura::ProcessExitTrap; + break; + default: + process_func = nullptr; + } +} + +void Aura::ProcessOnAllFriendlies(Mob *owner) +{ + Shout("Stub 1"); +} + +void Aura::ProcessOnAllGroupMembers(Mob *owner) +{ + if (!process_timer.Check()) + return; + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + std::set delayed_remove; + if (owner->IsRaidGrouped() && owner->IsClient()) { // currently raids are just client, but safety check + auto raid = owner->GetRaid(); + if (raid == nullptr) { // well shit + Depop(); + return; + } + auto group_id = raid->GetGroup(owner->CastToClient()); + + // some lambdas so the for loop is less horrible ... + auto verify_raid_client = [&raid, &group_id, this](Client *c) { + auto idx = raid->GetPlayerIndex(c); + if (c->GetID() == m_owner) { + return DistanceSquared(GetPosition(), c->GetPosition()) <= distance; + } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { + return false; + } else if (DistanceSquared(GetPosition(), c->GetPosition()) > distance) { + return false; + } + return true; + }; + + auto verify_raid_client_pet = [&raid, &group_id, this](Mob *m) { + auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient()); + if (m->GetOwner()->GetID() == m_owner) { + return DistanceSquared(GetPosition(), m->GetPosition()) <= distance; + } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { + return false; + } else if (DistanceSquared(GetPosition(), m->GetPosition()) > distance) { + return false; + } + return true; + }; + + auto verify_raid_client_swarm = [&raid, &group_id, this](NPC *n) { + auto owner = entity_list.GetMob(n->GetSwarmOwner()); + if (owner == nullptr) + return false; + auto idx = raid->GetPlayerIndex(owner->CastToClient()); + if (owner->GetID() == m_owner) { + return DistanceSquared(GetPosition(), n->GetPosition()) <= distance; + } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { + return false; + } else if (DistanceSquared(GetPosition(), n->GetPosition()) > distance) { + return false; + } + return true; + }; + + for (auto &e : mob_list) { + auto mob = e.second; + // step 1: check if we're already managing this NPC's buff + auto it = casted_on.find(mob->GetID()); + if (it != casted_on.end()) { + // verify still good! + if (mob->IsClient()) { + if (!verify_raid_client(mob->CastToClient())) + delayed_remove.insert(mob->GetID()); + } else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner()) { + if (!verify_raid_client_pet(mob)) + delayed_remove.insert(mob->GetID()); + } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { + auto npc = mob->CastToNPC(); + if (!verify_raid_client_swarm(npc)) + delayed_remove.insert(mob->GetID()); + } + } else { // we're not on it! + if (mob->IsClient() && verify_raid_client(mob->CastToClient())) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { + auto npc = mob->CastToNPC(); + if (verify_raid_client_swarm(npc)) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } + } + } + } + } else if (owner->IsGrouped()) { + auto group = owner->GetGroup(); + if (group == nullptr) { // uh oh + Depop(); + return; + } + + // lambdas to make for loop less ugly + auto verify_group_pet = [&group, this](Mob *m) { + auto owner = m->GetOwner(); + if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), m->GetPosition()) <= distance) + return true; + return false; + }; + + auto verify_group_swarm = [&group, this](NPC *n) { + auto owner = entity_list.GetMob(n->GetSwarmOwner()); + if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), n->GetPosition()) <= distance) + return true; + return false; + }; + + for (auto &e : mob_list) { + auto mob = e.second; + auto it = casted_on.find(mob->GetID()); + + if (it != casted_on.end()) { // make sure we're still valid + if (mob->IsPet()) { + if (!verify_group_pet(mob)) + delayed_remove.insert(mob->GetID()); + } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo()) { + if (!verify_group_swarm(mob->CastToNPC())) + delayed_remove.insert(mob->GetID()); + } else if (!group->IsGroupMember(mob) || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) { + delayed_remove.insert(mob->GetID()); + } + } else { // not on, check if we should be! + if (mob->IsPet() && verify_group_pet(mob)) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } else if (group->IsGroupMember(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } + } + } + } else { + auto verify_solo = [&owner, this](Mob *m) { + if (m->IsPet() && m->GetOwnerID() == owner->GetID()) + return true; + else if (m->IsNPC() && m->CastToNPC()->GetSwarmOwner() == owner->GetID()) + return true; + else if (m->GetID() == owner->GetID()) + return true; + else + return false; + }; + for (auto &e : mob_list) { + auto mob = e.second; + auto it = casted_on.find(mob->GetID()); + bool good = verify_solo(mob); + + if (it != casted_on.end()) { // make sure still valid + if (!good || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) { + delayed_remove.insert(mob->GetID()); + } + } else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } + } + } + + bool is_buff = IsBuffSpell(spell_id); + + for (auto &e : delayed_remove) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove + mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); + casted_on.erase(e); + } + + if (cast_timer.Enabled() || !cast_timer.Check()) + return; + + // TODO: some auras have to recast (DRU for example, non-buff too) + /* for (auto &e : casted_on) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr && (!is_buff || !mob->IsAffectedByBuff(spell_id))) + + }*/ +} + +void Aura::ProcessOnGroupMembersPets(Mob *owner) +{ + Shout("Stub 3"); +} + +void Aura::ProcessTotem(Mob *owner) +{ + Shout("Stub 4"); +} + +void Aura::ProcessEnterTrap(Mob *owner) +{ + Shout("Stub 5"); +} + +void Aura::ProcessExitTrap(Mob *owner) +{ + Shout("Stub 6"); +} + +bool Aura::Process() +{ + // Aura::Depop clears buffs + if (p_depop) + return false; + + auto owner = entity_list.GetMob(m_owner); + if (owner == nullptr) { + Depop(); + return true; + } + + if (movement_type == AuraMovement::Follow && GetPosition() != owner->GetPosition() && movement_timer.Check()) { + m_Position = owner->GetPosition(); + SendPosUpdate(); + } + // TODO: waypoints? + + if (process_func) + process_func(*this, owner); + + // TODO: quest calls + return true; +} + +void Aura::Depop(bool unused) +{ + // TODO: clean up buffs + p_depop = true; +} + +void Mob::MakeAura(uint16 spell_id) +{ + // TODO: verify room in AuraMgr + if (!IsValidSpell(spell_id)) + return; + + AuraRecord record; + if (!database.GetAuraEntry(spell_id, record)) { + Message(13, "Unable to find data for aura %s", spells[spell_id].name); + Log(Logs::General, Logs::Error, "Unable to find data for aura %d, check auras table.", spell_id); + return; + } + + if (!IsValidSpell(record.spell_id)) { + Message(13, "Casted spell (%d) is not valid for aura %s", record.spell_id, spells[spell_id].name); + Log(Logs::General, Logs::Error, "Casted spell (%d) is not valid for aura %d, check auras table.", + record.spell_id, spell_id); + return; + } + + if (record.aura_type > static_cast(AuraType::Max)) { + return; // TODO: log + } + + bool trap = false; + + switch (static_cast(record.aura_type)) { + case AuraType::ExitTrap: + case AuraType::EnterTrap: + case AuraType::Totem: + trap = true; + break; + default: + trap = false; + break; + } + + if (!CanSpawnAura(trap)) + return; + + const auto base = database.LoadNPCTypesData(record.npc_type); + if (base == nullptr) { + Message(13, "Unable to load NPC data for aura %s", spells[spell_id].teleport_zone); + Log(Logs::General, Logs::Error, + "Unable to load NPC data for aura %s (NPC ID %d), check auras and npc_types tables.", + spells[spell_id].teleport_zone, record.npc_type); + return; + } + + auto npc_type = new NPCType; + memcpy(npc_type, base, sizeof(NPCType)); + + strn0cpy(npc_type->name, record.name, 64); + + auto npc = new Aura(npc_type, this, record); + entity_list.AddNPC(npc, true, true); + + if (trap) + AddTrap(npc, record); + else + AddAura(npc, record); +} + +bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record) +{ + auto query = StringFormat("SELECT npc_type, name, spell_id, distance, aura_type, spawn_type, movement, " + "duration, icon FROM auras WHERE type='%d'", + spell_id); + + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + if (results.RowCount() != 1) + return false; + + auto row = results.begin(); + + record.npc_type = atoi(row[0]); + strn0cpy(record.name, row[1], 64); + record.spell_id = atoi(row[2]); + record.distance = atoi(row[3]); + record.distance *= record.distance; // so we can avoid sqrt + record.aura_type = atoi(row[4]); + record.spawn_type = atoi(row[5]); + record.movement = atoi(row[6]); + record.duration = atoi(row[7]) * 1000; // DB is in seconds + record.icon = atoi(row[8]); + + return true; +} + +void Mob::AddAura(Aura *aura, AuraRecord &record) +{ + // this is called only when it's safe + assert(aura != nullptr); + strn0cpy(aura_mgr.auras[aura_mgr.count].name, aura->GetCleanName(), 64); + aura_mgr.auras[aura_mgr.count].spawn_id = aura->GetID(); + if (record.icon == -1) + aura_mgr.auras[aura_mgr.count].icon = spells[record.spell_id].new_icon; + else + aura_mgr.auras[aura_mgr.count].icon = record.icon; + if (IsClient()) { + auto outapp = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraCreate_Struct)); + auto aura_create = (AuraCreate_Struct *)outapp->pBuffer; + aura_create->action = 0; + aura_create->type = 1; // this can be 0 sometimes too + strn0cpy(aura_create->aura_name, aura_mgr.auras[aura_mgr.count].name, 64); + aura_create->entity_id = aura_mgr.auras[aura_mgr.count].spawn_id; + aura_create->icon = aura_mgr.auras[aura_mgr.count].icon; + CastToClient()->FastQueuePacket(&outapp); + } + // we can increment this now + aura_mgr.count++; +} + +void Mob::AddTrap(Aura *aura, AuraRecord &record) +{ + // this is called only when it's safe + assert(aura != nullptr); + strn0cpy(trap_mgr.auras[trap_mgr.count].name, aura->GetCleanName(), 64); + trap_mgr.auras[trap_mgr.count].spawn_id = aura->GetID(); + if (record.icon == -1) + trap_mgr.auras[trap_mgr.count].icon = spells[record.spell_id].new_icon; + else + trap_mgr.auras[trap_mgr.count].icon = record.icon; + // doesn't send to client + trap_mgr.count++; +} + +bool Mob::CanSpawnAura(bool trap) +{ + if (trap && !HasFreeTrapSlots()) { + Message_StringID(MT_SpellFailure, NO_MORE_TRAPS); + return false; + } else if (!trap && !HasFreeAuraSlots()) { + Message_StringID(MT_SpellFailure, NO_MORE_AURAS); + return false; + } + + return true; +} + diff --git a/zone/aura.h b/zone/aura.h new file mode 100644 index 000000000..cdc01be55 --- /dev/null +++ b/zone/aura.h @@ -0,0 +1,76 @@ +#ifndef AURA_H +#define AURA_H + +#include +#include + +#include "mob.h" +#include "npc.h" +#include "../common/types.h" +#include "../common/timer.h" + +class Group; +class Raid; +class Mob; +struct NPCType; + +enum class AuraType { + OnAllFriendlies, // AE PC/Pet basically (ex. Circle of Power) + OnAllGroupMembers, // Normal buffing aura (ex. Champion's Aura) + OnGroupMembersPets, // Hits just pets (ex. Rathe's Strength) + Totem, // Starts pulsing on a timer when an enemy enters (ex. Idol of Malos) + EnterTrap, // Casts once when an enemy enters (ex. Fire Rune) + ExitTrap, // Casts when they start to flee (ex. Poison Spikes Trap) + FullyScripted, // We just call script function not a predefined + Max +}; + +enum class AuraSpawns { + GroupMembers, // most auras use this + Everyone, // this is like traps and clickies who cast on everyone + Noone, // custom! + Max +}; + +enum class AuraMovement { + Follow, // follows caster + Stationary, + Pathing, // some sorted pathing TODO: implement + Max +}; + +class Aura : public NPC +{ +public: + Aura(NPCType *type_data, Mob *owner, AuraRecord &record); + ~Aura() { }; + + bool IsAura() const { return true; } + bool Process(); + void Depop(bool unused = false); + + void ProcessOnAllFriendlies(Mob *owner); + void ProcessOnAllGroupMembers(Mob *owner); + void ProcessOnGroupMembersPets(Mob *owner); + void ProcessTotem(Mob *owner); + void ProcessEnterTrap(Mob *owner); + void ProcessExitTrap(Mob *owner); + +private: + int m_owner; + int spell_id; // spell we cast + int distance; // distance we remove + Timer remove_timer; // when we depop + Timer process_timer; // rate limit process calls + Timer cast_timer; // some auras pulse + Timer movement_timer; // rate limit movement updates + AuraType type; + AuraSpawns spawn_type; + AuraMovement movement_type; + + std::function process_func; + std::set casted_on; // we keep track of the other entities we've casted on +}; + +#endif /* !AURA_H */ + diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 22a323a81..4406508fe 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1460,6 +1460,14 @@ void Mob::ApplyAABonuses(const AA::Rank &rank, StatBonuses *newbon) newbon->FeignedMinionChance = base1; break; + case SE_AdditionalAura: + newbon->aura_slots += base1; + break; + + case SE_IncreaseTrapCount: + newbon->trap_slots += base1; + break; + // to do case SE_PetDiscipline: break; @@ -3201,6 +3209,16 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses *ne if (new_bonus->FeignedCastOnChance < effect_value) new_bonus->FeignedCastOnChance = effect_value; break; + + case SE_AdditionalAura: + if (new_bonus->aura_slots < effect_value) + new_bonus->aura_slots = effect_value; + break; + + case SE_IncreaseTrapCount: + if (new_bonus->trap_slots < effect_value) + new_bonus->trap_slots = effect_value; + break; //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5e1bcc8ca..eb17f4db8 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -383,6 +383,7 @@ void MapOpcodes() ConnectedOpcodes[OP_TributeUpdate] = &Client::Handle_OP_TributeUpdate; ConnectedOpcodes[OP_VetClaimRequest] = &Client::Handle_OP_VetClaimRequest; ConnectedOpcodes[OP_VoiceMacroIn] = &Client::Handle_OP_VoiceMacroIn; + ConnectedOpcodes[OP_UpdateAura] = &Client::Handle_OP_UpdateAura;; ConnectedOpcodes[OP_WearChange] = &Client::Handle_OP_WearChange; ConnectedOpcodes[OP_WhoAllRequest] = &Client::Handle_OP_WhoAllRequest; ConnectedOpcodes[OP_WorldUnknown001] = &Client::Handle_OP_Ignore; @@ -14360,6 +14361,29 @@ void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app) } +void Client::Handle_OP_UpdateAura(const EQApplicationPacket *app) +{ + if (app->size < 4) { + Log(Logs::General, Logs::None, "Size mismatch in OP_UpdateAura"); + return; + } + auto action = *(uint32_t *)app->pBuffer; // action tells us the size + switch (action) { + case 2: + RemoveAllAuras(); + break; + case 1: { + auto ads = (AuraDestory_Struct *)app->pBuffer; + RemoveAura(ads->entity_id); + break; + } + case 0: // client doesn't send this + break; + } + + return; +} + void Client::Handle_OP_WearChange(const EQApplicationPacket *app) { if (app->size != sizeof(WearChange_Struct)) { diff --git a/zone/client_packet.h b/zone/client_packet.h index 76a26e04e..e84f89aaa 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -288,6 +288,7 @@ void Handle_OP_TributeNPC(const EQApplicationPacket *app); void Handle_OP_TributeToggle(const EQApplicationPacket *app); void Handle_OP_TributeUpdate(const EQApplicationPacket *app); + void Handle_OP_UpdateAura(const EQApplicationPacket *app); void Handle_OP_VetClaimRequest(const EQApplicationPacket *app); void Handle_OP_VoiceMacroIn(const EQApplicationPacket *app); void Handle_OP_WearChange(const EQApplicationPacket *app); diff --git a/zone/common.h b/zone/common.h index 7294c87dc..246600c8f 100644 --- a/zone/common.h +++ b/zone/common.h @@ -105,6 +105,8 @@ #define PET_BUTTON_FOCUS 8 #define PET_BUTTON_SPELLHOLD 9 +#define AURA_HARDCAP 2 + typedef enum { //focus types focusSpellHaste = 1, focusSpellDuration, @@ -536,6 +538,8 @@ struct StatBonuses { int16 FeignedCastOnChance; // Percent Value bool PetCommands[PET_MAXCOMMANDS]; // SPA 267 int FeignedMinionChance; // SPA 281 base1 = chance, just like normal FD + int aura_slots; + int trap_slots; }; typedef struct diff --git a/zone/entity.h b/zone/entity.h index 036e0c419..29075d9fe 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -80,6 +80,7 @@ public: virtual bool IsBeacon() const { return false; } virtual bool IsEncounter() const { return false; } virtual bool IsBot() const { return false; } + virtual bool IsAura() const { return false; } virtual bool Process() { return false; } virtual bool Save() { return true; } diff --git a/zone/mob.h b/zone/mob.h index 5292aff00..f95322d36 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -45,6 +45,8 @@ class EQApplicationPacket; class Group; class NPC; class Raid; +class Aura; +struct AuraRecord; struct NewSpawn_Struct; struct PlayerPositionUpdateServer_Struct; @@ -85,6 +87,22 @@ public: int params[MAX_SPECIAL_ATTACK_PARAMS]; }; + struct AuraInfo { + char name[64]; + int spawn_id; + int icon; + AuraInfo() : spawn_id(0), icon(0) + { + memset(name, 0, 64); + } + }; + + struct AuraMgr { + int count; // active auras + AuraInfo auras[AURA_HARDCAP]; + AuraMgr() : count(0) { } + }; + Mob(const char* in_name, const char* in_lastname, int32 in_cur_hp, @@ -308,6 +326,7 @@ public: void BuffProcess(); virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); void BuffFadeBySpellID(uint16 spell_id); + void BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id); void BuffFadeByEffect(int effectid, int skipslot = -1); void BuffFadeAll(); void BuffFadeNonPersistDeath(); @@ -315,6 +334,7 @@ public: void BuffFadeBySlot(int slot, bool iRecalcBonuses = true); void BuffFadeDetrimentalByCaster(Mob *caster); void BuffFadeBySitModifier(); + bool IsAffectedByBuff(uint16 spell_id); void BuffModifyDurationBySpellID(uint16 spell_id, int32 newDuration); int AddBuff(Mob *caster, const uint16 spell_id, int duration = 0, int32 level_override = -1); int CanBuffStack(uint16 spellid, uint8 caster_level, bool iFailIfOverwrite = false); @@ -604,6 +624,17 @@ public: bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc = true); + void MakeAura(uint16 spell_id); + inline int GetAuraSlots() { return 1 + aabonuses.aura_slots + itembonuses.aura_slots + spellbonuses.aura_slots; } + inline int GetTrapSlots() { return 1 + aabonuses.trap_slots + itembonuses.trap_slots + spellbonuses.trap_slots; } + inline bool HasFreeAuraSlots() { return aura_mgr.count < GetAuraSlots(); } + inline bool HasFreeTrapSlots() { return trap_mgr.count < GetTrapSlots(); } + void AddAura(Aura *aura, AuraRecord &record); + void AddTrap(Aura *aura, AuraRecord &record); + bool CanSpawnAura(bool trap); + void RemoveAura(int spawn_id) {} + void RemoveAllAuras() {} + //Procs void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary, bool FromSkillProc = false, int damage = 0); bool AddRangedProc(uint16 spell_id, uint16 iChance = 3, uint16 base_spell_id = SPELL_UNKNOWN); @@ -1465,6 +1496,9 @@ protected: bool IsHorse; + AuraMgr aura_mgr; + AuraMgr trap_mgr; + private: void _StopSong(); //this is not what you think it is Mob* target; diff --git a/zone/npc.h b/zone/npc.h index 30e54da55..c973eb79d 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -90,6 +90,7 @@ class Client; class Group; class Raid; class Spawn2; +class Aura; namespace EQEmu { @@ -425,6 +426,7 @@ protected: NPCType* NPCTypedata_ours; //special case for npcs with uniquely created data. friend class EntityList; + friend class Aura; std::list faction_list; uint32 copper; uint32 silver; diff --git a/zone/raids.cpp b/zone/raids.cpp index baf2d71b0..26845910c 100644 --- a/zone/raids.cpp +++ b/zone/raids.cpp @@ -491,6 +491,14 @@ uint32 Raid::GetPlayerIndex(const char *name){ return 0; //should never get to here if we do everything else right, set it to 0 so we never crash things that rely on it. } +uint32 Raid::GetPlayerIndex(Client *c) +{ + for (int i = 0; i < MAX_RAID_MEMBERS; ++i) + if (c == members[i].member) + return i; + return 0xFFFFFFFF; // return sentinel value, make sure you check it unlike the above function +} + Client *Raid::GetClientByIndex(uint16 index) { if(index > MAX_RAID_MEMBERS) diff --git a/zone/raids.h b/zone/raids.h index 232a0057f..df43d7755 100644 --- a/zone/raids.h +++ b/zone/raids.h @@ -142,6 +142,7 @@ public: //keeps me from having to keep iterating through the list //when I want lots of data from the same entry uint32 GetPlayerIndex(const char *name); + uint32 GetPlayerIndex(Client *c); //for perl interface Client *GetClientByIndex(uint16 index); const char *GetClientNameByIndex(uint8 index); diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7cddf0057..4d3f1ee1d 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2791,6 +2791,10 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove break; } + case SE_PersistentEffect: + MakeAura(spell_id); + break; + // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: diff --git a/zone/spells.cpp b/zone/spells.cpp index 58121a760..d95d328fe 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4189,6 +4189,21 @@ void Mob::BuffFadeBySpellID(uint16 spell_id) CalcBonuses(); } +void Mob::BuffFadeBySpellIDAndCaster(uint16 spell_id, uint16 caster_id) +{ + bool recalc_bonus = false; + auto buff_count = GetMaxTotalSlots(); + for (int i = 0; i < buff_count; ++i) { + if (buffs[i].spellid == spell_id && buffs[i].casterid == caster_id) { + BuffFadeBySlot(i, false); + recalc_bonus = true; + } + } + + if (recalc_bonus) + CalcBonuses(); +} + // removes buffs containing effectid, skipping skipslot void Mob::BuffFadeByEffect(int effectid, int skipslot) { @@ -4207,6 +4222,16 @@ void Mob::BuffFadeByEffect(int effectid, int skipslot) CalcBonuses(); } +bool Mob::IsAffectedByBuff(uint16 spell_id) +{ + int buff_count = GetMaxTotalSlots(); + for (int i = 0; i < buff_count; ++i) + if (buffs[i].spellid == spell_id) + return true; + + return false; +} + // checks if 'this' can be affected by spell_id from caster // returns true if the spell should fail, false otherwise bool Mob::IsImmuneToSpell(uint16 spell_id, Mob *caster) diff --git a/zone/string_ids.h b/zone/string_ids.h index 65810d576..663d2067a 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -361,6 +361,7 @@ #define GAIN_GROUP_LEADERSHIP_EXP 8788 // #define GAIN_RAID_LEADERSHIP_EXP 8789 // #define BUFF_MINUTES_REMAINING 8799 //%1 (%2 minutes remaining) +#define NO_MORE_TRAPS 9002 //You have already placed your maximum number of traps. #define FEAR_TOO_HIGH 9035 //Your target is too high of a level for your fear spell. #define SLOW_MOSTLY_SUCCESSFUL 9029 //Your spell was mostly successful. #define SLOW_PARTIALLY_SUCCESSFUL 9030 // Your spell was partially successful. @@ -375,6 +376,7 @@ #define SHAKE_OFF_STUN 9077 //You shake off the stun effect! #define STRIKETHROUGH_STRING 9078 //You strike through your opponent's defenses! #define SPELL_REFLECT 9082 //%1's spell has been reflected by %2. +#define NO_MORE_AURAS 9160 //You do not have sufficient focus to maintain that ability. #define NEW_SPELLS_AVAIL 9149 //You have new spells available to you. Check the merchants near your guild master. #define FD_CAST_ON_NO_BREAK 9174 //The strength of your will allows you to resume feigning death. #define SNEAK_RESTRICT 9240 //You can not use this ability because you have not been hidden for long enough. diff --git a/zone/zonedb.h b/zone/zonedb.h index b592be480..50c924b02 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -123,6 +123,18 @@ struct PetRecord { uint32 equipmentset; // default equipment for the pet }; +struct AuraRecord { + uint32 npc_type; + char name[64]; // name shown in UI if shown and spawn name + int spell_id; + int distance; + int aura_type; + int spawn_type; + int movement; + int duration; // seconds some live for 90 mins (normal) others for 2 mins (traps) + int icon; // -1 will use the buffs NEW_ICON +}; + // Actual pet info for a client. struct PetInfo { uint16 SpellID; @@ -404,6 +416,7 @@ public: void AddLootDropToNPC(NPC* npc, uint32 lootdrop_id, ItemList* itemlist, uint8 droplimit, uint8 mindrop); uint32 GetMaxNPCSpellsID(); uint32 GetMaxNPCSpellsEffectsID(); + bool GetAuraEntry(uint16 spell_id, AuraRecord &record); DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID); DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID); From ee618f70ab29df3953dc95f8fe80cd1c3819ebe2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 13:49:32 -0400 Subject: [PATCH 146/218] Add support for setting cast_time of aura --- utils/sql/git/required/2017_07_xx_aura.sql | 1 + zone/aura.cpp | 29 +++++++++++++++------- zone/zonedb.h | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/utils/sql/git/required/2017_07_xx_aura.sql b/utils/sql/git/required/2017_07_xx_aura.sql index ed777d2e5..9437d1c7c 100644 --- a/utils/sql/git/required/2017_07_xx_aura.sql +++ b/utils/sql/git/required/2017_07_xx_aura.sql @@ -9,5 +9,6 @@ CREATE TABLE `auras` ( `movement` INT(10) NOT NULL DEFAULT 0, `duration` INT(10) NOT NULL DEFAULT 5400, `icon` INT(10) NOT NULL DEFAULT -1, + `cast_time` INT(10) NOT NULL DEFAULT 0, PRIMARY KEY(`type`) ) diff --git a/zone/aura.cpp b/zone/aura.cpp index 6b4e06323..7f9368008 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -12,6 +12,11 @@ Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) GiveNPCTypeData(type_data); // we will delete this later on m_owner = owner->GetID(); + if (record.cast_time) { + cast_timer.SetTimer(record.cast_time); + cast_timer.Disable(); // we don't want to be enabled yet + } + if (record.aura_type < static_cast(AuraType::Max)) type = static_cast(record.aura_type); else @@ -58,8 +63,6 @@ void Aura::ProcessOnAllFriendlies(Mob *owner) void Aura::ProcessOnAllGroupMembers(Mob *owner) { - if (!process_timer.Check()) - return; auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline std::set delayed_remove; if (owner->IsRaidGrouped() && owner->IsClient()) { // currently raids are just client, but safety check @@ -228,15 +231,19 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) casted_on.erase(e); } - if (cast_timer.Enabled() || !cast_timer.Check()) + // so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it + if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty()) + cast_timer.Start(); + + if (!cast_timer.Enabled() || !cast_timer.Check()) return; - // TODO: some auras have to recast (DRU for example, non-buff too) - /* for (auto &e : casted_on) { + // some auras have to recast (DRU for example, non-buff too) + for (auto &e : casted_on) { auto mob = entity_list.GetMob(e); - if (mob != nullptr && (!is_buff || !mob->IsAffectedByBuff(spell_id))) - - }*/ + if (mob != nullptr) + SpellFinished(spell_id, mob); + } } void Aura::ProcessOnGroupMembersPets(Mob *owner) @@ -277,6 +284,9 @@ bool Aura::Process() } // TODO: waypoints? + if (!process_timer.Check()) + return true; + if (process_func) process_func(*this, owner); @@ -356,7 +366,7 @@ void Mob::MakeAura(uint16 spell_id) bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record) { auto query = StringFormat("SELECT npc_type, name, spell_id, distance, aura_type, spawn_type, movement, " - "duration, icon FROM auras WHERE type='%d'", + "duration, icon, cast_time FROM auras WHERE type='%d'", spell_id); auto results = QueryDatabase(query); @@ -378,6 +388,7 @@ bool ZoneDatabase::GetAuraEntry(uint16 spell_id, AuraRecord &record) record.movement = atoi(row[6]); record.duration = atoi(row[7]) * 1000; // DB is in seconds record.icon = atoi(row[8]); + record.cast_time = atoi(row[9]) * 1000; // DB is in seconds return true; } diff --git a/zone/zonedb.h b/zone/zonedb.h index 50c924b02..b91ea3cdd 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -133,6 +133,7 @@ struct AuraRecord { int movement; int duration; // seconds some live for 90 mins (normal) others for 2 mins (traps) int icon; // -1 will use the buffs NEW_ICON + int cast_time; // seconds some auras recast on a timer, most seem to be every 12 seconds }; // Actual pet info for a client. From 5c75a68715edc6e242b2b5dc02f8c4c49e1cdd0b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 14 Jul 2017 14:23:35 -0500 Subject: [PATCH 147/218] HP Update tuning - HP Updates are now forced when a client is targeted --- zone/client.cpp | 4 ++-- zone/client.h | 4 ++-- zone/mob.cpp | 62 ++++++++++++++++++++++++++++--------------------- zone/mob.h | 2 +- 4 files changed, 40 insertions(+), 32 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 0bcbb4ec2..bc784d415 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -119,7 +119,6 @@ Client::Client(EQStreamInterface* ieqs) 0, 0 ), - //these must be listed in the order they appear in client.h position_timer(250), hpupdate_timer(2000), camp_timer(29000), @@ -159,7 +158,8 @@ Client::Client(EQStreamInterface* ieqs) last_region_type(RegionTypeUnsupported), m_dirtyautohaters(false), npc_close_scan_timer(6000), - hp_self_update_throttle_timer(500) + hp_self_update_throttle_timer(300), + hp_other_update_throttle_timer(500) { for(int cf=0; cf < _FilterCount; cf++) diff --git a/zone/client.h b/zone/client.h index ff617f009..d88769ee1 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1485,8 +1485,8 @@ private: Timer helm_toggle_timer; Timer aggro_meter_timer; Timer npc_close_scan_timer; - Timer hp_self_update_throttle_timer; - + Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */ + Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */ glm::vec3 m_Proximity; void BulkSendInventoryItems(); diff --git a/zone/mob.cpp b/zone/mob.cpp index 68f55626b..0a4a84746 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1302,49 +1302,50 @@ void Mob::CreateHPPacket(EQApplicationPacket* app) } // sends hp update of this mob to people who might care -void Mob::SendHPUpdate(bool skip_self) +void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= false*/) { /* If our HP is different from last HP update call - let's update ourself */ - if (IsClient() && cur_hp != last_hp) { - /* This is to prevent excessive packet sending under trains/fast combat */ - if (this->CastToClient()->hp_self_update_throttle_timer.Check()) { - Log(Logs::General, Logs::HP_Update, - "Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s", - this->GetCleanName(), - cur_hp, - last_hp, - (skip_self ? "true" : "false") - ); + if (IsClient()) { + if (cur_hp != last_hp || force_update_all) { + /* This is to prevent excessive packet sending under trains/fast combat */ + if (this->CastToClient()->hp_self_update_throttle_timer.Check() || force_update_all) { + Log(Logs::General, Logs::HP_Update, + "Mob::SendHPUpdate :: Update HP of self (%s) HP: %i last: %i skip_self: %s", + this->GetCleanName(), + cur_hp, + last_hp, + (skip_self ? "true" : "false") + ); - if (!skip_self || this->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::UF) { - auto client_packet = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct)); - SpawnHPUpdate_Struct* hp_packet_client = (SpawnHPUpdate_Struct*)client_packet->pBuffer; + if (!skip_self || this->CastToClient()->ClientVersion() >= EQEmu::versions::ClientVersion::SoD) { + auto client_packet = new EQApplicationPacket(OP_HPUpdate, sizeof(SpawnHPUpdate_Struct)); + SpawnHPUpdate_Struct* hp_packet_client = (SpawnHPUpdate_Struct*)client_packet->pBuffer; - hp_packet_client->cur_hp = CastToClient()->GetHP() - itembonuses.HP; - hp_packet_client->spawn_id = GetID(); - hp_packet_client->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; + hp_packet_client->cur_hp = CastToClient()->GetHP() - itembonuses.HP; + hp_packet_client->spawn_id = GetID(); + hp_packet_client->max_hp = CastToClient()->GetMaxHP() - itembonuses.HP; - CastToClient()->QueuePacket(client_packet); + CastToClient()->QueuePacket(client_packet); - safe_delete(client_packet); + safe_delete(client_packet); - ResetHPUpdateTimer(); + ResetHPUpdateTimer(); + } + + /* Used to check if HP has changed to update self next round */ + last_hp = cur_hp; } } } - /* Used to check if HP has changed to update self next round */ - last_hp = cur_hp; - int8 current_hp_percent = (max_hp == 0 ? 0 : static_cast(cur_hp * 100 / max_hp)); Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: SendHPUpdate %s HP is %i last %i", this->GetCleanName(), current_hp_percent, last_hp_percent); - if (current_hp_percent == last_hp_percent) { + if (current_hp_percent == last_hp_percent && !force_update_all) { Log(Logs::General, Logs::HP_Update, "Mob::SendHPUpdate :: Same HP - skipping update"); ResetHPUpdateTimer(); - return; } else { @@ -1362,7 +1363,7 @@ void Mob::SendHPUpdate(bool skip_self) CreateHPPacket(&hp_packet); - /* Update those who have use targeted */ + /* Update those who have us targeted */ entity_list.QueueClientsByTarget(this, &hp_packet, false, 0, false, true, EQEmu::versions::bit_AllClients); /* Update those who have us on x-target */ @@ -3407,9 +3408,13 @@ int Mob::GetHaste() } void Mob::SetTarget(Mob* mob) { - if (target == mob) return; + + if (target == mob) + return; + target = mob; entity_list.UpdateHoTT(this); + if(IsNPC()) parse->EventNPC(EVENT_TARGET_CHANGE, CastToNPC(), mob, "", 0); else if (IsClient()) @@ -3417,6 +3422,9 @@ void Mob::SetTarget(Mob* mob) { if(IsPet() && GetOwner() && GetOwner()->IsClient()) GetOwner()->CastToClient()->UpdateXTargetType(MyPetTarget, mob); + + if (this->IsClient() && this->GetTarget() && this->CastToClient()->hp_other_update_throttle_timer.Check()) + this->GetTarget()->SendHPUpdate(false, true); } float Mob::FindGroundZ(float new_x, float new_y, float z_offset) diff --git a/zone/mob.h b/zone/mob.h index 5292aff00..319a28649 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -583,7 +583,7 @@ public: static void CreateSpawnPacket(EQApplicationPacket* app, NewSpawn_Struct* ns); virtual void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); void CreateHPPacket(EQApplicationPacket* app); - void SendHPUpdate(bool skip_self = false); + void SendHPUpdate(bool skip_self = false, bool force_update_all = false); virtual void ResetHPUpdateTimer() {}; // does nothing //Util From 574a5e303c095eb65de89e968140cd612c1785c7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 15:50:57 -0400 Subject: [PATCH 148/218] Aura "OnAllGroupMembers" won't cast instant spells on entering area Ex. The bard regen auras just cast on a timer --- zone/aura.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 7f9368008..add3e25d9 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -65,6 +65,8 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) { auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline std::set delayed_remove; + bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter + if (owner->IsRaidGrouped() && owner->IsClient()) { // currently raids are just client, but safety check auto raid = owner->GetRaid(); if (raid == nullptr) { // well shit @@ -133,15 +135,18 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) } else { // we're not on it! if (mob->IsClient() && verify_raid_client(mob->CastToClient())) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { auto npc = mob->CastToNPC(); if (verify_raid_client_swarm(npc)) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } } } @@ -185,13 +190,16 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) } else { // not on, check if we should be! if (mob->IsPet() && verify_group_pet(mob)) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } else if (group->IsGroupMember(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } } } @@ -217,13 +225,12 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) } } else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { casted_on.insert(mob->GetID()); - SpellFinished(spell_id, mob); + if (is_buff) + SpellFinished(spell_id, mob); } } } - bool is_buff = IsBuffSpell(spell_id); - for (auto &e : delayed_remove) { auto mob = entity_list.GetMob(e); if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove From 2a7a88ff4756e13b790cf4af63f0e00a5b01f226 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 18:27:57 -0400 Subject: [PATCH 149/218] Implement some trap functions --- zone/aura.cpp | 69 ++++++++++++++++++++++++++++++++++++++++++++++++--- zone/aura.h | 1 + 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index add3e25d9..326ff8974 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -61,6 +61,11 @@ void Aura::ProcessOnAllFriendlies(Mob *owner) Shout("Stub 1"); } +Mob *Aura::GetOwner() +{ + return entity_list.GetMob(m_owner); +} + void Aura::ProcessOnAllGroupMembers(Mob *owner) { auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline @@ -260,12 +265,63 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) void Aura::ProcessTotem(Mob *owner) { - Shout("Stub 4"); + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + std::set delayed_remove; + bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter + + for (auto &e : mob_list) { + auto mob = e.second; + if (mob == this) + continue; + if (owner->IsAttackAllowed(mob)) { // might need more checks ... + bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance; + auto it = casted_on.find(mob->GetID()); + if (it != casted_on.end()) { + if (!in_range) + delayed_remove.insert(mob->GetID()); + } else if (in_range) { + casted_on.insert(mob->GetID()); + SpellFinished(spell_id, mob); + } + } + } + + for (auto &e : delayed_remove) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove + mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); + casted_on.erase(e); + } + + // so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it + if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty()) + cast_timer.Start(); + + if (!cast_timer.Enabled() || !cast_timer.Check()) + return; + + for (auto &e : casted_on) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr) + SpellFinished(spell_id, mob); + } } void Aura::ProcessEnterTrap(Mob *owner) { - Shout("Stub 5"); + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + + for (auto &e : mob_list) { + auto mob = e.second; + if (mob == this) + continue; + // might need more checks ... + if (owner->IsAttackAllowed(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + SpellFinished(spell_id, mob); + Depop(); // if we're a buff (ex. NEC) we don't want to strip :P + break; + } + } } void Aura::ProcessExitTrap(Mob *owner) @@ -303,7 +359,14 @@ bool Aura::Process() void Aura::Depop(bool unused) { - // TODO: clean up buffs + if (IsBuffSpell(spell_id)) { + for (auto &e : casted_on) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr) + mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); + } + } + casted_on.clear(); p_depop = true; } diff --git a/zone/aura.h b/zone/aura.h index cdc01be55..8d467d945 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -48,6 +48,7 @@ public: bool IsAura() const { return true; } bool Process(); void Depop(bool unused = false); + Mob *GetOwner(); void ProcessOnAllFriendlies(Mob *owner); void ProcessOnAllGroupMembers(Mob *owner); From 43204e52f8a0c17ece27ca3d404f2946662bdb2f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 14 Jul 2017 20:49:57 -0500 Subject: [PATCH 150/218] Client position updates should be smoother (granted the client has a good connection) Clients should also no longer randomly disappear --- changelog.txt | 6 + common/ruletypes.h | 1 + zone/attack.cpp | 2 +- zone/bot.cpp | 6 +- zone/client.cpp | 19 ++-- zone/client.h | 9 +- zone/client_packet.cpp | 237 +++++++++++++++------------------------- zone/client_process.cpp | 61 ++++------- zone/merc.cpp | 4 +- zone/mob.cpp | 32 +++--- zone/mob.h | 2 +- zone/perl_mob.cpp | 2 +- zone/questmgr.cpp | 6 +- zone/spell_effects.cpp | 2 +- zone/waypoints.cpp | 6 +- 15 files changed, 165 insertions(+), 230 deletions(-) diff --git a/changelog.txt b/changelog.txt index 51011d64b..9568f8392 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- + +== 7/14/2017 == +Akkadius: HP Update tuning - HP Updates are now forced when a client is targeted +Akkadius: Client position updates should be smoother (granted the client has a good connection) + - Clients should also no longer randomly disappear + == 7/11/2017 == Akkadius: Raid/Group/XTarget HP/Mana/Endurance updates now only send when percentage changes Akkadius: Raid/Group Mana/Endurance updates should now update real-time once again diff --git a/common/ruletypes.h b/common/ruletypes.h index 397f1a832..fe385b18f 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -150,6 +150,7 @@ RULE_BOOL(Character, AllowMQTarget, false) // Disables putting players in the 'h RULE_BOOL(Character, UseOldBindWound, false) // Uses the original bind wound behavior RULE_BOOL(Character, GrantHoTTOnCreate, false) // Grant Health of Target's Target leadership AA on character creation RULE_BOOL(Character, UseOldConSystem, false) // Grant Health of Target's Target leadership AA on character creation +RULE_BOOL(Character, OPClientUpdateVisualDebug, false) // Shows a pulse and forward directional particle each time the client sends its position to server RULE_CATEGORY_END() RULE_CATEGORY(Mercs) diff --git a/zone/attack.cpp b/zone/attack.cpp index ee1384b44..4b480f580 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -3551,7 +3551,7 @@ void Mob::CommonDamage(Mob* attacker, int &damage, const uint16 spell_id, const Teleport(new_pos); if (position_update_melee_push_timer.Check()) { - SendPosUpdate(); + SendPositionUpdate(); } } } diff --git a/zone/bot.cpp b/zone/bot.cpp index 129cdb9b3..f5a9285a3 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2172,7 +2172,7 @@ void Bot::AI_Process() { } if(IsMoving()) - SendPosUpdate(); + SendPositionUpdate(); else SendPosition(); } @@ -2383,7 +2383,7 @@ void Bot::AI_Process() { // TODO: Test RuleB(Bots, UpdatePositionWithTimer) if(IsMoving()) - SendPosUpdate(); + SendPositionUpdate(); else SendPosition(); } @@ -2505,7 +2505,7 @@ void Bot::AI_Process() { } if(IsMoving()) - SendPosUpdate(); + SendPositionUpdate(); else SendPosition(); } diff --git a/zone/client.cpp b/zone/client.cpp index bc784d415..08eb7e60a 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -159,11 +159,12 @@ Client::Client(EQStreamInterface* ieqs) m_dirtyautohaters(false), npc_close_scan_timer(6000), hp_self_update_throttle_timer(300), - hp_other_update_throttle_timer(500) + hp_other_update_throttle_timer(500), + position_update_timer(0) { - for(int cf=0; cf < _FilterCount; cf++) - ClientFilters[cf] = FilterShow; + for (int client_filter = 0; client_filter < _FilterCount; client_filter++) + ClientFilters[client_filter] = FilterShow; character_id = 0; conn_state = NoPacketsReceived; @@ -196,7 +197,7 @@ Client::Client(EQStreamInterface* ieqs) last_reported_endurance = 0; last_reported_endurance_percent = 0; last_reported_mana_percent = 0; - gmhideme = false; + gm_hide_me = false; AFK = false; LFG = false; LFGFromLevel = 0; @@ -260,7 +261,7 @@ Client::Client(EQStreamInterface* ieqs) memset(&m_epp, 0, sizeof(m_epp)); PendingTranslocate = false; PendingSacrifice = false; - BoatID = 0; + controlling_boat_id = 0; KarmaUpdateTimer = new Timer(RuleI(Chat, KarmaUpdateIntervalMS)); GlobalChatLimiterTimer = new Timer(RuleI(Chat, IntervalDurationMS)); @@ -1971,7 +1972,7 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) } bool Client::GMHideMe(Client* client) { - if (gmhideme) { + if (gm_hide_me) { if (client == 0) return true; else if (admin > client->Admin()) @@ -3240,9 +3241,9 @@ void Client::SetHideMe(bool flag) { EQApplicationPacket app; - gmhideme = flag; + gm_hide_me = flag; - if(gmhideme) + if(gm_hide_me) { database.SetHideMe(AccountID(),true); CreateDespawnPacket(&app, false); @@ -6373,7 +6374,7 @@ void Client::LocateCorpse() SetHeading(CalculateHeadingToTarget(ClosestCorpse->GetX(), ClosestCorpse->GetY())); SetTarget(ClosestCorpse); SendTargetCommand(ClosestCorpse->GetID()); - SendPosUpdate(2); + SendPositionUpdate(2); } else if(!GetTarget()) Message_StringID(clientMessageError, SENSE_CORPSE_NONE); diff --git a/zone/client.h b/zone/client.h index d88769ee1..640d9dc98 100644 --- a/zone/client.h +++ b/zone/client.h @@ -320,7 +320,7 @@ public: bool GetRevoked() const { return revoked; } void SetRevoked(bool rev) { revoked = rev; } inline uint32 GetIP() const { return ip; } - inline bool GetHideMe() const { return gmhideme; } + inline bool GetHideMe() const { return gm_hide_me; } void SetHideMe(bool hm); inline uint16 GetPort() const { return port; } bool IsDead() const { return(dead); } @@ -1072,7 +1072,7 @@ public: void Signal(uint32 data); Mob *GetBindSightTarget() { return bind_sight_target; } void SetBindSightTarget(Mob *n) { bind_sight_target = n; } - const uint16 GetBoatID() const { return BoatID; } + const uint16 GetBoatID() const { return controlling_boat_id; } void SendRewards(); bool TryReward(uint32 claim_id); QGlobalCache *GetQGlobals() { return qGlobals; } @@ -1376,7 +1376,7 @@ private: bool duelaccepted; std::list keyring; bool tellsoff; // GM /toggle - bool gmhideme; + bool gm_hide_me; bool LFG; bool LFP; uint8 LFGFromLevel; @@ -1396,7 +1396,7 @@ private: uint32 weight; bool berserk; bool dead; - uint16 BoatID; + uint16 controlling_boat_id; uint16 TrackingID; uint16 CustomerID; uint16 TraderID; @@ -1487,6 +1487,7 @@ private: Timer npc_close_scan_timer; Timer hp_self_update_throttle_timer; /* This is to prevent excessive packet sending under trains/fast combat */ Timer hp_other_update_throttle_timer; /* This is to keep clients from DOSing the server with macros that change client targets constantly */ + Timer position_update_timer; /* Timer used when client hasn't updated within a 10 second window */ glm::vec3 m_Proximity; void BulkSendInventoryItems(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 5e1bcc8ca..f71aaf518 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1287,7 +1287,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) lsaccountid = atoi(row[2]); gmspeed = atoi(row[3]); revoked = atoi(row[4]); - gmhideme = atoi(row[5]); + gm_hide_me = atoi(row[5]); account_creation = atoul(row[6]); } @@ -1355,7 +1355,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (level) { level = m_pp.level; } /* If GM, not trackable */ - if (gmhideme) { trackable = false; } + if (gm_hide_me) { trackable = false; } /* Set Con State for Reporting */ conn_state = PlayerProfileLoaded; @@ -3881,7 +3881,7 @@ void Client::Handle_OP_BoardBoat(const EQApplicationPacket *app) Mob* boat = entity_list.GetMob(boatname); if (!boat || (boat->GetRace() != CONTROLLED_BOAT && boat->GetRace() != 502)) return; - BoatID = boat->GetID(); // set the client's BoatID to show that it's on this boat + controlling_boat_id = boat->GetID(); // set the client's BoatID to show that it's on this boat return; } @@ -4372,7 +4372,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) if (dead) return; - //currently accepting two sizes, one has an extra byte on the end + /* Invalid size check */ if (app->size != sizeof(PlayerPositionUpdateClient_Struct) && app->size != (sizeof(PlayerPositionUpdateClient_Struct) + 1) ) { @@ -4381,30 +4381,30 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) } PlayerPositionUpdateClient_Struct* ppu = (PlayerPositionUpdateClient_Struct*)app->pBuffer; + /* Boat handling */ if (ppu->spawn_id != GetID()) { - // check if the id is for a boat the player is controlling - if (ppu->spawn_id == BoatID) { - Mob* boat = entity_list.GetMob(BoatID); - if (boat == 0) { // if the boat ID is invalid, reset the id and abort - BoatID = 0; + /* If player is controlling boat */ + if (ppu->spawn_id == controlling_boat_id) { + Mob* boat = entity_list.GetMob(controlling_boat_id); + if (boat == 0) { + controlling_boat_id = 0; return; } - // set the boat's position deltas - auto boatDelta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading); - boat->SetDelta(boatDelta); - // send an update to everyone nearby except the client controlling the boat - auto outapp = - new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading); + boat->SetDelta(boat_delta); + + auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* ppus = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; boat->MakeSpawnUpdate(ppus); entity_list.QueueCloseClients(boat, outapp, true, 300, this, false); safe_delete(outapp); - // update the boat's position on the server, without sending an update + + /* Update the boat's position on the server, without sending an update */ boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ19toFloat(ppu->heading), false); return; } - else return; // if not a boat, do nothing + else return; } float dist = 0; @@ -4415,51 +4415,34 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) dist += tmp*tmp; dist = sqrt(dist); - //the purpose of this first block may not be readily apparent - //basically it's so people don't do a moderate warp every 2.5 seconds - //letting it even out and basically getting the job done without triggering - if (dist == 0) - { - if (m_DistanceSinceLastPositionCheck > 0.0) - { + /* Hack checks */ + if (dist == 0) { + if (m_DistanceSinceLastPositionCheck > 0.0) { uint32 cur_time = Timer::GetCurrentTime(); - if ((cur_time - m_TimeSinceLastPositionCheck) > 0) - { + if ((cur_time - m_TimeSinceLastPositionCheck) > 0) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); int runs = GetRunspeed(); - if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) - { - if (IsShadowStepExempted()) - { - if (m_DistanceSinceLastPositionCheck > 800) - { + if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { + if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) { + if (IsShadowStepExempted()) { + if (m_DistanceSinceLastPositionCheck > 800) { CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos); } } - else if (IsKnockBackExempted()) - { - //still potential to trigger this if you're knocked back off a - //HUGE fall that takes > 2.5 seconds - if (speed > 30.0f) - { + else if (IsKnockBackExempted()) { + if (speed > 30.0f) { CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos); } } - else if (!IsPortExempted()) - { - if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) - { - if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { + else if (!IsPortExempted()) { + if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) { + if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) { m_TimeSinceLastPositionCheck = cur_time; m_DistanceSinceLastPositionCheck = 0.0f; CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos); //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); } - else - { + else { CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos); } } @@ -4474,64 +4457,42 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) m_CheatDetectMoved = false; } } - else - { + else { m_TimeSinceLastPositionCheck = Timer::GetCurrentTime(); m_CheatDetectMoved = false; } } - else - { + else { m_DistanceSinceLastPositionCheck += dist; m_CheatDetectMoved = true; - if (m_TimeSinceLastPositionCheck == 0) - { + if (m_TimeSinceLastPositionCheck == 0) { m_TimeSinceLastPositionCheck = Timer::GetCurrentTime(); } - else - { + else { uint32 cur_time = Timer::GetCurrentTime(); - if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) - { + if ((cur_time - m_TimeSinceLastPositionCheck) > 2500) { float speed = (m_DistanceSinceLastPositionCheck * 100) / (float)(cur_time - m_TimeSinceLastPositionCheck); int runs = GetRunspeed(); - if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { - if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) - { - if (IsShadowStepExempted()) - { - if (m_DistanceSinceLastPositionCheck > 800) - { - //if(!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) - //{ + if (speed > (runs * RuleR(Zone, MQWarpDetectionDistanceFactor))) { + if (!GetGMSpeed() && (runs >= GetBaseRunspeed() || (speed > (GetBaseRunspeed() * RuleR(Zone, MQWarpDetectionDistanceFactor))))) { + if (IsShadowStepExempted()) { + if (m_DistanceSinceLastPositionCheck > 800) { CheatDetected(MQWarpShadowStep, ppu->x_pos, ppu->y_pos, ppu->z_pos); - //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); - //} } } - else if (IsKnockBackExempted()) - { - //still potential to trigger this if you're knocked back off a - //HUGE fall that takes > 2.5 seconds - if (speed > 30.0f) - { + else if (IsKnockBackExempted()) { + if (speed > 30.0f) { CheatDetected(MQWarpKnockBack, ppu->x_pos, ppu->y_pos, ppu->z_pos); } } - else if (!IsPortExempted()) - { - if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) - { - if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) - { + else if (!IsPortExempted()) { + if (!IsMQExemptedArea(zone->GetZoneID(), ppu->x_pos, ppu->y_pos, ppu->z_pos)) { + if (speed > (runs * 2 * RuleR(Zone, MQWarpDetectionDistanceFactor))) { m_TimeSinceLastPositionCheck = cur_time; m_DistanceSinceLastPositionCheck = 0.0f; CheatDetected(MQWarp, ppu->x_pos, ppu->y_pos, ppu->z_pos); - //Death(this, 10000000, SPELL_UNKNOWN, _1H_BLUNT); } - else - { + else { CheatDetected(MQWarpLight, ppu->x_pos, ppu->y_pos, ppu->z_pos); } } @@ -4550,7 +4511,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) DragCorpses(); } - //Check to see if PPU should trigger an update to the rewind position. + /* Check to see if PPU should trigger an update to the rewind position. */ float rewind_x_diff = 0; float rewind_y_diff = 0; @@ -4559,14 +4520,19 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) rewind_y_diff = ppu->y_pos - m_RewindLocation.y; rewind_y_diff *= rewind_y_diff; - //We only need to store updated values if the player has moved. - //If the player has moved more than units for x or y, then we'll store - //his pre-PPU x and y for /rewind, in case he gets stuck. + /* + We only need to store updated values if the player has moved. + If the player has moved more than units for x or y, then we'll store + his pre-PPU x and y for /rewind, in case he gets stuck. + */ + if ((rewind_x_diff > 750) || (rewind_y_diff > 750)) m_RewindLocation = glm::vec3(m_Position); - //If the PPU was a large jump, such as a cross zone gate or Call of Hero, - //just update rewind coords to the new ppu coords. This will prevent exploitation. + /* + If the PPU was a large jump, such as a cross zone gate or Call of Hero, + just update rewind coordinates to the new ppu coordinates. This will prevent exploitation. + */ if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000)) m_RewindLocation = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos); @@ -4579,7 +4545,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) m_Proximity = glm::vec3(ppu->x_pos, ppu->y_pos, ppu->z_pos); } - // Update internal state + /* Update internal state */ m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, ppu->delta_heading); if (IsTracking() && ((m_Position.x != ppu->x_pos) || (m_Position.y != ppu->y_pos))) { @@ -4587,7 +4553,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20); } - // Break Hide if moving without sneaking and set rewind timer if moved + /* Break Hide if moving without sneaking and set rewind timer if moved */ if (ppu->y_pos != m_Position.y || ppu->x_pos != m_Position.x) { if ((hidden || improved_hidden) && !sneaking) { hidden = false; @@ -4632,39 +4598,39 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) client_scan_npc_aggro_timer.Start(3000); } } + + /* Update internal server position from what the client has sent */ + m_Position.x = ppu->x_pos; + m_Position.y = ppu->y_pos; + m_Position.z = ppu->z_pos; + m_Position.w = EQ19toFloat(ppu->heading); + + animation = ppu->animation; - // Outgoing client packet - float tmpheading = EQ19toFloat(ppu->heading); - /* The clients send an update at best every 1.3 seconds - * We want to avoid reflecting these updates to other clients as much as possible - * The client also sends an update every 280 ms while turning, if we prevent - * sending these by checking if the location is the same too aggressively, clients end up spinning - * so keep a count of how many packets are the same within a tolerance and stop when we get there */ - - bool pos_same = FCMP(ppu->y_pos, m_Position.y) && FCMP(ppu->x_pos, m_Position.x) && FCMP(tmpheading, m_Position.w) && ppu->animation == animation; - if (!pos_same || (pos_same && position_update_same_count < 6)) - { - if (pos_same) - position_update_same_count++; - else - position_update_same_count = 0; - - m_Position.x = ppu->x_pos; - m_Position.y = ppu->y_pos; - m_Position.z = ppu->z_pos; - m_Position.w = tmpheading; - animation = ppu->animation; - - auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* ppu = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; - MakeSpawnUpdate(ppu); - if (gmhideme) - entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); - else - entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, false); - safe_delete(outapp); + /* Visual Debugging */ + if (RuleB(Character, OPClientUpdateVisualDebug)) { + Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos, ppu->heading); + this->SendAppearanceEffect(78, 0, 0, 0, 0); + this->SendAppearanceEffect(41, 0, 0, 0, 0); } + /* Broadcast update to other clients */ + auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* position_update = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; + + MakeSpawnUpdate(position_update); + + position_update_timer.Start(10000, true); + + if (gm_hide_me) { + entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); + } + else { + entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, true); + } + + safe_delete(outapp); + if (zone->watermap) { if (zone->watermap->InLiquid(glm::vec3(m_Position))) CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17); @@ -4674,27 +4640,6 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) return; } -/* -void Client::Handle_OP_CloseContainer(const EQApplicationPacket *app) -{ -if (app->size != sizeof(CloseContainer_Struct)) { -LogFile->write(EQEMuLog::Error, "Invalid size on CloseContainer_Struct: Expected %i, Got %i", -sizeof(CloseContainer_Struct), app->size); -return; -} - -SetTradeskillObject(nullptr); - -ClickObjectAck_Struct* oos = (ClickObjectAck_Struct*)app->pBuffer; -Entity* entity = entity_list.GetEntityObject(oos->drop_id); -if (entity && entity->IsObject()) { -Object* object = entity->CastToObject(); -object->Close(); -} -return; -} -*/ - void Client::Handle_OP_CombatAbility(const EQApplicationPacket *app) { if (app->size != sizeof(CombatAbility_Struct)) { @@ -8945,12 +8890,12 @@ void Client::Handle_OP_LeaveAdventure(const EQApplicationPacket *app) void Client::Handle_OP_LeaveBoat(const EQApplicationPacket *app) { - Mob* boat = entity_list.GetMob(this->BoatID); // find the mob corresponding to the boat id + Mob* boat = entity_list.GetMob(this->controlling_boat_id); // find the mob corresponding to the boat id if (boat) { if ((boat->GetTarget() == this) && boat->GetHateAmount(this) == 0) // if the client somehow left while still controlling the boat (and the boat isn't attacking them) boat->SetTarget(0); // fix it to stop later problems } - this->BoatID = 0; + this->controlling_boat_id = 0; return; } diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 2bf1d5818..11954798d 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -63,64 +63,49 @@ extern EntityList entity_list; bool Client::Process() { bool ret = true; - if (Connected() || IsLD()) - { + if (Connected() || IsLD()) { // try to send all packets that weren't sent before - if (!IsLD() && zoneinpacket_timer.Check()) - { + if (!IsLD() && zoneinpacket_timer.Check()) { SendAllPackets(); } - if (adventure_request_timer) - { - if (adventure_request_timer->Check()) - { + if (adventure_request_timer) { + if (adventure_request_timer->Check()) { safe_delete(adventure_request_timer); } } - if (adventure_create_timer) - { - if (adventure_create_timer->Check()) - { + if (adventure_create_timer) { + if (adventure_create_timer->Check()) { safe_delete(adventure_create_timer); } } - if (adventure_leave_timer) - { - if (adventure_leave_timer->Check()) - { + if (adventure_leave_timer) { + if (adventure_leave_timer->Check()) { safe_delete(adventure_leave_timer); } } - if (adventure_door_timer) - { - if (adventure_door_timer->Check()) - { + if (adventure_door_timer) { + if (adventure_door_timer->Check()) { safe_delete(adventure_door_timer); } } - if (adventure_stats_timer) - { - if (adventure_stats_timer->Check()) - { + if (adventure_stats_timer) { + if (adventure_stats_timer->Check()) { safe_delete(adventure_stats_timer); } } - if (adventure_leaderboard_timer) - { - if (adventure_leaderboard_timer->Check()) - { + if (adventure_leaderboard_timer) { + if (adventure_leaderboard_timer->Check()) { safe_delete(adventure_leaderboard_timer); } } - if (dead) - { + if (dead) { SetHP(-100); if (RespawnFromHoverTimer.Check()) HandleRespawnFromHover(0); @@ -134,6 +119,11 @@ bool Client::Process() { if (hpupdate_timer.Check(false)) SendHPUpdate(); + /* I haven't naturally updated my position in 10 seconds, updating manually */ + if (position_update_timer.Check()) { + SendPositionUpdate(); + } + if (mana_timer.Check()) CheckManaEndUpdate(); @@ -271,15 +261,6 @@ bool Client::Process() { close_mobs.insert(std::pair(mob, distance)); } } - - /* Clients need to be kept up to date for position updates more often otherwise they disappear */ - if (mob->IsClient() && this != mob && !mob->IsMoving() && distance <= client_update_range) { - auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* spawn_update = (PlayerPositionUpdateServer_Struct*)app->pBuffer; - mob->MakeSpawnUpdate(spawn_update); - this->FastQueuePacket(&app, false); - safe_delete(app); - } } } @@ -460,7 +441,7 @@ bool Client::Process() { { animation = 0; m_Delta = glm::vec4(0.0f, 0.0f, 0.0f, m_Delta.w); - SendPosUpdate(2); + SendPositionUpdate(2); } } diff --git a/zone/merc.cpp b/zone/merc.cpp index 2b1ef7098..80565c6b4 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1589,7 +1589,7 @@ void Merc::AI_Process() { } if(IsMoving()) - SendPosUpdate(); + SendPositionUpdate(); else SendPosition(); } @@ -1714,7 +1714,7 @@ void Merc::AI_Process() { } if(IsMoving()) - SendPosUpdate(); + SendPositionUpdate(); else SendPosition(); } diff --git a/zone/mob.cpp b/zone/mob.cpp index 0a4a84746..02cd1a5dc 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1458,7 +1458,7 @@ void Mob::SendPosition() } // this one is for mobs on the move, with deltas - this makes them walk -void Mob::SendPosUpdate(uint8 iSendToSelf) { +void Mob::SendPositionUpdate(uint8 iSendToSelf) { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdate(spu); @@ -1496,27 +1496,27 @@ void Mob::MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct *spu) { // this is for SendPosUpdate() void Mob::MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu) { - spu->spawn_id = GetID(); - spu->x_pos = FloatToEQ19(m_Position.x); - spu->y_pos = FloatToEQ19(m_Position.y); - spu->z_pos = FloatToEQ19(m_Position.z); - spu->delta_x = NewFloatToEQ13(m_Delta.x); - spu->delta_y = NewFloatToEQ13(m_Delta.y); - spu->delta_z = NewFloatToEQ13(m_Delta.z); - spu->heading = FloatToEQ19(m_Position.w); - spu->padding0002 =0; - spu->padding0006 =7; - spu->padding0014 =0x7f; - spu->padding0018 =0x5df27; + spu->spawn_id = GetID(); + spu->x_pos = FloatToEQ19(m_Position.x); + spu->y_pos = FloatToEQ19(m_Position.y); + spu->z_pos = FloatToEQ19(m_Position.z); + spu->delta_x = NewFloatToEQ13(m_Delta.x); + spu->delta_y = NewFloatToEQ13(m_Delta.y); + spu->delta_z = NewFloatToEQ13(m_Delta.z); + spu->heading = FloatToEQ19(m_Position.w); + spu->padding0002 = 0; + spu->padding0006 = 7; + spu->padding0014 = 0x7f; + spu->padding0018 = 0x5df27; #ifdef BOTS if (this->IsClient() || this->IsBot()) #else - if(this->IsClient()) + if (this->IsClient()) #endif spu->animation = animation; else spu->animation = pRunAnimSpeed;//animation; - + spu->delta_heading = NewFloatToEQ13(m_Delta.w); } @@ -2745,7 +2745,7 @@ void Mob::FaceTarget(Mob* MobToFace) { if(oldheading != newheading) { SetHeading(newheading); if(moving) - SendPosUpdate(); + SendPositionUpdate(); else { SendPosition(); diff --git a/zone/mob.h b/zone/mob.h index 319a28649..56004157d 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -522,7 +522,7 @@ public: virtual void GMMove(float x, float y, float z, float heading = 0.01, bool SendUpdate = true); void SetDelta(const glm::vec4& delta); void SetTargetDestSteps(uint8 target_steps) { tar_ndx = target_steps; } - void SendPosUpdate(uint8 iSendToSelf = 0); + void SendPositionUpdate(uint8 iSendToSelf = 0); void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); void SendPosition(); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index 9af0fa43f..f95deb3de 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1268,7 +1268,7 @@ XS(XS_Mob_SendPosUpdate) iSendToSelf = (uint8)SvUV(ST(1)); } - THIS->SendPosUpdate(iSendToSelf); + THIS->SendPositionUpdate(iSendToSelf); } XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 757098c57..c77e96979 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -215,7 +215,7 @@ Mob* QuestManager::spawn2(int npc_type, int grid, int unused, const glm::vec4& p { npc->AssignWaypoints(grid); } - npc->SendPosUpdate(); + npc->SendPositionUpdate(); return npc; } return nullptr; @@ -237,7 +237,7 @@ Mob* QuestManager::unique_spawn(int npc_type, int grid, int unused, const glm::v { npc->AssignWaypoints(grid); } - npc->SendPosUpdate(); + npc->SendPositionUpdate(); return npc; } return nullptr; @@ -1660,7 +1660,7 @@ void QuestManager::respawn(int npcTypeID, int grid) { if(grid > 0) owner->CastToNPC()->AssignWaypoints(grid); - owner->SendPosUpdate(); + owner->SendPositionUpdate(); } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 7cddf0057..42b50edf3 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -847,7 +847,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove SetHeading(CalculateHeadingToTarget(ClosestMob->GetX(), ClosestMob->GetY())); SetTarget(ClosestMob); CastToClient()->SendTargetCommand(ClosestMob->GetID()); - SendPosUpdate(2); + SendPositionUpdate(2); } else Message_StringID(clientMessageError, SENSE_NOTHING); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index fbbce67b9..61fc7983f 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -614,12 +614,12 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo if (IsClient()) { - SendPosUpdate(1); + SendPositionUpdate(1); CastToClient()->ResetPositionTimer(); } else { - SendPosUpdate(); + SendPositionUpdate(); SetAppearance(eaStanding, false); } @@ -702,7 +702,7 @@ bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ this->SetMoving(true); moved = true; m_Delta = glm::vec4(m_Position.x - nx, m_Position.y - ny, m_Position.z - nz, 0.0f); - SendPosUpdate(); + SendPositionUpdate(); } tar_ndx++; From 6c1efd74cb8e8afdc25b6a7bcb27a774f2ae5893 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 14 Jul 2017 21:45:38 -0500 Subject: [PATCH 151/218] Resolve an issue with NPC's not returning back to guard point when once engaged and dropped aggro --- zone/mob.cpp | 4 ++-- zone/mob_ai.cpp | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 02cd1a5dc..fc7772b8d 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1437,7 +1437,7 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal } } -// this one just warps the mob to the current location +/* Used for NPCs mainly */ void Mob::SendPosition() { @@ -1446,7 +1446,7 @@ void Mob::SendPosition() MakeSpawnUpdateNoDelta(spu); /* When an NPC has made a large distance change - we should update all clients to prevent "ghosts" */ - if (DistanceSquared(last_major_update_position, m_Position) > (100 * 100)) { + if (DistanceSquared(last_major_update_position, m_Position) >= (100 * 100)) { entity_list.QueueClients(this, app, true, true); last_major_update_position = m_Position; } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 633dde297..a016b98e6 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1006,7 +1006,12 @@ void Mob::AI_Process() { } else if (!this->CheckLosFN(this->GetTarget())) { Mob* target = this->GetTarget(); - this->GMMove(target->GetX(), target->GetY(), target->GetZ(), target->GetHeading()); + + m_Position.x = target->GetX(); + m_Position.y = target->GetY(); + m_Position.z = target->GetZ(); + m_Position.w = target->GetHeading(); + SendPosition(); } } } From c7e33eb6b919f3492e30281d029835bf804b262c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 23:13:33 -0400 Subject: [PATCH 152/218] Fix totems issue and add despawn Despawn should tell client ... still TODO --- zone/aura.cpp | 7 +++++++ zone/spells.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 326ff8974..9ad2ec468 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -273,6 +273,8 @@ void Aura::ProcessTotem(Mob *owner) auto mob = e.second; if (mob == this) continue; + if (mob == owner) + continue; if (owner->IsAttackAllowed(mob)) { // might need more checks ... bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance; auto it = casted_on.find(mob->GetID()); @@ -341,6 +343,11 @@ bool Aura::Process() return true; } + if (remove_timer.Check()) { + Depop(); + return true; + } + if (movement_type == AuraMovement::Follow && GetPosition() != owner->GetPosition() && movement_timer.Check()) { m_Position = owner->GetPosition(); SendPosUpdate(); diff --git a/zone/spells.cpp b/zone/spells.cpp index d95d328fe..8e7d6721a 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -3447,7 +3447,7 @@ bool Mob::SpellOnTarget(uint16 spell_id, Mob *spelltar, bool reflect, bool use_r if(spelltar->IsClient() && spelltar->CastToClient()->IsHoveringForRespawn()) return false; - if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar) && !IsResurrectionEffects(spell_id)) { + if(IsDetrimentalSpell(spell_id) && !IsAttackAllowed(spelltar, true) && !IsResurrectionEffects(spell_id)) { if(!IsClient() || !CastToClient()->GetGM()) { Message_StringID(MT_SpellFailure, SPELL_NO_HOLD); return false; From 2342caff323fb22826815a1e2cd0983e5a19b8c7 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 14 Jul 2017 23:15:37 -0400 Subject: [PATCH 153/218] Update for changes on master --- zone/aura.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 9ad2ec468..038abc35d 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -350,7 +350,7 @@ bool Aura::Process() if (movement_type == AuraMovement::Follow && GetPosition() != owner->GetPosition() && movement_timer.Check()) { m_Position = owner->GetPosition(); - SendPosUpdate(); + SendPositionUpdate(); } // TODO: waypoints? From b0710ff8d135d3eeee8dec6489e6a2e2ebb6aef0 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 02:19:29 -0400 Subject: [PATCH 154/218] Add SQL to add all but rogue auras --- utils/sql/git/optional/auras.sql | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 utils/sql/git/optional/auras.sql diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql new file mode 100644 index 000000000..016aee45c --- /dev/null +++ b/utils/sql/git/optional/auras.sql @@ -0,0 +1,120 @@ +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8926, @suggestedid, "Aura_of_Insight", 8939, 60, 1, 0, 0, 5400, 99, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8488, @suggestedid, "Aura_of_the_Muse", 8489, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8921, @suggestedid, "Myrmidon's_Aura", 8935, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8468, @suggestedid, "Champion's_Aura", 8469, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8925, @suggestedid, "Holy_Aura", 8938, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8481, @suggestedid, "Blessed_Aura", 8482, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8923, @suggestedid, "Disciples_Aura", 8937, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8474, @suggestedid, "Master's_Aura", 8475, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8933, @suggestedid, "Earthen_Strength", 8948, 60, 2, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8518, @suggestedid, "Rathe's_Strength", 8519, 60, 2, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8931, @suggestedid, "Beguiler's_Aura", 8946, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8509, @suggestedid, "Illusionist's_Aura", 8510, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8929, @suggestedid, "Aura_of_the_Grove", 8943, 60, 1, 0, 0, 5400, 1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8499, @suggestedid, "Aura_of_Life", 8500, 60, 1, 0, 0, 5400, 1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8928, @suggestedid, "Aura_of_the_Zealot", 8940, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8495, @suggestedid, "Aura_of_the_Pious", 8496, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8924, @suggestedid, "Aura_of_Rage", 8959, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8477, @suggestedid, "Bloodlust_Aura", 8478, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8930, @suggestedid, "Soul_Idol", 8945, 60, 3, 1, 1, 120, -1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8504, @suggestedid, "Spirit_Idol", 8505, 60, 3, 1, 1, 12, -1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8934, @suggestedid, "a_dark_rune", 8949, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8523, @suggestedid, "a_death_rune", 8524, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8932, @suggestedid, "a_fiery_rune", 8947, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8513, @suggestedid, "a_fire_rune", 8514, 25, 4, 1, 1, 120, -1, -1); + From 19bee763bdb1957dbca046433919b572622cfae1 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Jul 2017 09:36:43 -0400 Subject: [PATCH 155/218] Make world messages about logging in and logging out more detailed. Previously logging in (from desktop) and out (from game) both of which land you at char select both said Logging (In). Now it tells you which is occuring. There really is no Logging Out Compleetely message - not sure where that could or should be added. --- world/client.cpp | 29 ++++++++++++++++++++++++----- world/cliententry.h | 1 + 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index 19c7747b5..31ec305ba 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -449,17 +449,33 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { return false; } - cle->SetOnline(); - if(minilogin){ + cle->SetOnline(); WorldConfig::DisableStats(); Log(Logs::General, Logs::World_Server, "MiniLogin Account #%d",cle->AccountID()); } else { - if (!is_player_zoning) { - Log(Logs::General, Logs::World_Server, - "Account (%s) Logging in :: LSID: %d ", cle->AccountName(), cle->LSID()); + // Track who is in and who is out of the game + char *inout= (char *) ""; + + if (cle->GetOnline() < CLE_Status_Online){ + // Desktop -> Char Select + inout = (char *) "In"; } + else { + // Game -> Char Select + inout=(char *) "Out"; + } + + // Always at Char select at this point. + // Either from a fresh client launch or coming back from the game. + // Exiting the game entirely does not come through here. + // Could use a Logging Out Completely message somewhere. + cle->SetOnline(CLE_Status_CharSelect); + + Log(Logs::General, Logs::World_Server, + "Account (%s) Logging(%s) to character select :: LSID: %d ", + cle->AccountName(), inout, cle->LSID()); } const WorldConfig *Config=WorldConfig::get(); @@ -1021,6 +1037,9 @@ bool Client::HandlePacket(const EQApplicationPacket *app) { } case OP_WorldLogout: { + //Log(Logs::General, Logs::World_Server, + //"Account (%s) Logging Off :: LSID: %d ", cle->AccountName(), cle->LSID()); + //online.erase(cle->LSID()); eqs->Close(); cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction. return false; diff --git a/world/cliententry.h b/world/cliententry.h index cb096950c..24a837ae9 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -50,6 +50,7 @@ public: inline const char* LSName() const { return plsname; } inline int16 WorldAdmin() const { return pworldadmin; } inline const char* GetLSKey() const { return plskey; } + inline const int8 GetOnline() const { return pOnline; } // Account stuff inline uint32 AccountID() const { return paccountid; } From 06b91a6e01a25cea7e904d1177ec6169facefaf9 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Jul 2017 09:54:04 -0400 Subject: [PATCH 156/218] Removed some instrumentation. Added a comment/observation. --- world/client.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/world/client.cpp b/world/client.cpp index 31ec305ba..60221f25b 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1037,9 +1037,7 @@ bool Client::HandlePacket(const EQApplicationPacket *app) { } case OP_WorldLogout: { - //Log(Logs::General, Logs::World_Server, - //"Account (%s) Logging Off :: LSID: %d ", cle->AccountName(), cle->LSID()); - //online.erase(cle->LSID()); + // I don't see this getting executed on logout eqs->Close(); cle->SetOnline(CLE_Status_Offline); //allows this player to log in again without an ip restriction. return false; From 89a5a45d7e0e84e142a3ea2a95cbe44bb5274544 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Jul 2017 10:27:51 -0400 Subject: [PATCH 157/218] Fix logging in compare. --- world/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/client.cpp b/world/client.cpp index 60221f25b..b31f77c02 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -458,7 +458,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { // Track who is in and who is out of the game char *inout= (char *) ""; - if (cle->GetOnline() < CLE_Status_Online){ + if (cle->GetOnline() == CLE_Status_Never){ // Desktop -> Char Select inout = (char *) "In"; } From 91589eae34986bab5ccb8eff86879cc8765f66af Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Jul 2017 11:14:28 -0400 Subject: [PATCH 158/218] Added back if_player_logging check. --- world/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/world/client.cpp b/world/client.cpp index b31f77c02..94aa906e9 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -454,7 +454,7 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { WorldConfig::DisableStats(); Log(Logs::General, Logs::World_Server, "MiniLogin Account #%d",cle->AccountID()); } - else { + else if (!is_player_zoning) { // Track who is in and who is out of the game char *inout= (char *) ""; From 0b647c7ae58a5171ca4941145f8b92b3b142dbbd Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 15 Jul 2017 12:09:47 -0400 Subject: [PATCH 159/218] Added back SetOnline for logging clients. Not sure it's needed honestly, but I left it as I found it + the better messages. --- world/client.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/world/client.cpp b/world/client.cpp index 94aa906e9..4fd157088 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -477,6 +477,9 @@ bool Client::HandleSendLoginInfoPacket(const EQApplicationPacket *app) { "Account (%s) Logging(%s) to character select :: LSID: %d ", cle->AccountName(), inout, cle->LSID()); } + else { + cle->SetOnline(); + } const WorldConfig *Config=WorldConfig::get(); From 56c570fd199301ffb6b15678884ec7cdcca7f940 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 14:52:57 -0400 Subject: [PATCH 160/218] Fix SQL --- utils/sql/git/optional/auras.sql | 119 +++++++++++++------------------ 1 file changed, 48 insertions(+), 71 deletions(-) diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql index 016aee45c..afccaf760 100644 --- a/utils/sql/git/optional/auras.sql +++ b/utils/sql/git/optional/auras.sql @@ -1,120 +1,97 @@ -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8926, @suggestedid, "Aura_of_Insight", 8939, 60, 1, 0, 0, 5400, 99, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8926, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89260, cast_time=89261; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8488, @suggestedid, "Aura_of_the_Muse", 8489, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8488, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84880, cast_time=84881; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8921, @suggestedid, "Myrmidon's_Aura", 8935, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8921, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89210, cast_time=89211; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8468, @suggestedid, "Champion's_Aura", 8469, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8468, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84680, cast_time=84681; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8925, @suggestedid, "Holy_Aura", 8938, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8925, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89250, cast_time=89251; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8481, @suggestedid, "Blessed_Aura", 8482, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8481, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84810, cast_time=84811; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8923, @suggestedid, "Disciples_Aura", 8937, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8923, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89230, cast_time=89231; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8474, @suggestedid, "Master's_Aura", 8475, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8474, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84740, cast_time=84741; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8933, @suggestedid, "Earthen_Strength", 8948, 60, 2, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8933, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=89330, cast_time=89331; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8518, @suggestedid, "Rathe's_Strength", 8519, 60, 2, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8518, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=85180, cast_time=85181; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8931, @suggestedid, "Beguiler's_Aura", 8946, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8931, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89310, cast_time=89311; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8509, @suggestedid, "Illusionist's_Aura", 8510, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8509, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=85090, cast_time=85091; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8929, @suggestedid, "Aura_of_the_Grove", 8943, 60, 1, 0, 0, 5400, 1, 12); +INSERT INTO auras SET npc_type=@suggestedid, type=8929, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89290, cast_time=89291; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8499, @suggestedid, "Aura_of_Life", 8500, 60, 1, 0, 0, 5400, 1, 12); +INSERT INTO auras SET npc_type=@suggestedid, type=8499, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84990, cast_time=84991; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8928, @suggestedid, "Aura_of_the_Zealot", 8940, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8928, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89280, cast_time=89281; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8495, @suggestedid, "Aura_of_the_Pious", 8496, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8495, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84950, cast_time=84951; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8924, @suggestedid, "Aura_of_Rage", 8959, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8924, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89240, cast_time=89241; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8477, @suggestedid, "Bloodlust_Aura", 8478, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8477, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84770, cast_time=84771; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8930, @suggestedid, "Soul_Idol", 8945, 60, 3, 1, 1, 120, -1, 12); +INSERT INTO auras SET npc_type=@suggestedid, type=8930, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=89300, cast_time=89301; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8504, @suggestedid, "Spirit_Idol", 8505, 60, 3, 1, 1, 12, -1, 12); +INSERT INTO auras SET npc_type=@suggestedid, type=8504, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=12, icon=85040, cast_time=85041; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8934, @suggestedid, "a_dark_rune", 8949, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8934, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=89340, cast_time=89341; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8523, @suggestedid, "a_death_rune", 8524, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8523, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=85230, cast_time=85231; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8932, @suggestedid, "a_fiery_rune", 8947, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET npc_type=@suggestedid, type=8932, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=89320, cast_time=89321; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO auras SET npc_type=@suggestedid, type=8513, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=85130, cast_time=85131; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8513, @suggestedid, "a_fire_rune", 8514, 25, 4, 1, 1, 120, -1, -1); From f9480f251801042bc9069fab876de9500906bf2e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 15 Jul 2017 17:05:28 -0500 Subject: [PATCH 161/218] Taper down on non-moving client update spam --- zone/client.cpp | 2 +- zone/client_packet.cpp | 26 ++++++++++++++------------ zone/client_process.cpp | 2 +- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/zone/client.cpp b/zone/client.cpp index 08eb7e60a..12988450b 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -160,7 +160,7 @@ Client::Client(EQStreamInterface* ieqs) npc_close_scan_timer(6000), hp_self_update_throttle_timer(300), hp_other_update_throttle_timer(500), - position_update_timer(0) + position_update_timer(10000) { for (int client_filter = 0; client_filter < _FilterCount; client_filter++) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f71aaf518..f2906e093 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4614,22 +4614,24 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) this->SendAppearanceEffect(41, 0, 0, 0, 0); } - /* Broadcast update to other clients */ - auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); - PlayerPositionUpdateServer_Struct* position_update = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; + /* Only feed real time updates when client is moving */ + if (is_client_moving) { - MakeSpawnUpdate(position_update); + /* Broadcast update to other clients */ + auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + PlayerPositionUpdateServer_Struct* position_update = (PlayerPositionUpdateServer_Struct*)outapp->pBuffer; - position_update_timer.Start(10000, true); + MakeSpawnUpdate(position_update); - if (gm_hide_me) { - entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); + if (gm_hide_me) { + entity_list.QueueClientsStatus(this, outapp, true, Admin(), 250); + } + else { + entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, true); + } + + safe_delete(outapp); } - else { - entity_list.QueueCloseClients(this, outapp, true, 300, nullptr, true); - } - - safe_delete(outapp); if (zone->watermap) { if (zone->watermap->InLiquid(glm::vec3(m_Position))) diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 11954798d..672848acc 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -120,7 +120,7 @@ bool Client::Process() { SendHPUpdate(); /* I haven't naturally updated my position in 10 seconds, updating manually */ - if (position_update_timer.Check()) { + if (!is_client_moving && position_update_timer.Check()) { SendPositionUpdate(); } From 92031bbd708bb5edd9d45ab7f33b0d6567dc031d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 23:10:25 -0400 Subject: [PATCH 162/218] Add remove aura functions --- zone/aura.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ zone/mob.h | 4 ++-- 2 files changed, 66 insertions(+), 2 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 038abc35d..2b0bd9c1a 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -521,3 +521,67 @@ bool Mob::CanSpawnAura(bool trap) return true; } +void Mob::RemoveAllAuras() +{ + // this is sent on camp/zone, so it just despawns? + if (aura_mgr.count) { + for (auto &e : aura_mgr.auras) { + auto mob = entity_list.GetMob(e.spawn_id); + if (mob) + mob->Depop(); + } + } + + if (trap_mgr.count) { + for (auto &e : trap_mgr.auras) { + auto mob = entity_list.GetMob(e.spawn_id); + if (mob) + mob->Depop(); + } + } + return; +} + +void Mob::RemoveAura(int spawn_id, bool expired) +{ + for (int i = 0; i < aura_mgr.count; ++i) { + auto &aura = aura_mgr.auras[i]; + if (aura.spawn_id == spawn_id) { + auto mob = entity_list.GetMob(aura.spawn_id); + if (mob) + mob->Depop(); + if (expired && IsClient()) + CastToClient()->SendColoredText( + CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color + while (aura_mgr.count - 1 > i) { + i++; + aura.spawn_id = aura_mgr.auras[i].spawn_id; + aura.icon = aura_mgr.auras[i].icon; + strn0cpy(aura.name, aura_mgr.auras[i].name, 64); + } + aura_mgr.count--; + return; + } + } + + for (int i = 0; i < trap_mgr.count; ++i) { + auto &aura = trap_mgr.auras[i]; + auto mob = entity_list.GetMob(aura.spawn_id); + if (mob) + mob->Depop(); + if (expired && IsClient()) + CastToClient()->SendColoredText( + CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color + while (trap_mgr.count - 1 > i) { + i++; + aura.spawn_id = trap_mgr.auras[i].spawn_id; + aura.icon = trap_mgr.auras[i].icon; + strn0cpy(aura.name, trap_mgr.auras[i].name, 64); + } + trap_mgr.count--; + return; + } + + return; +} + diff --git a/zone/mob.h b/zone/mob.h index a91975d85..b6a56acdf 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -632,8 +632,8 @@ public: void AddAura(Aura *aura, AuraRecord &record); void AddTrap(Aura *aura, AuraRecord &record); bool CanSpawnAura(bool trap); - void RemoveAura(int spawn_id) {} - void RemoveAllAuras() {} + void RemoveAura(int spawn_id, bool expired = false); + void RemoveAllAuras(); //Procs void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary, bool FromSkillProc = false, int damage = 0); From ff005a22a35065b239bd28c56e493eef85ad2fb9 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 23:24:11 -0400 Subject: [PATCH 163/218] Revert "Fix SQL" This reverts commit 56c570fd199301ffb6b15678884ec7cdcca7f940. --- utils/sql/git/optional/auras.sql | 211 +++++++++++++++++-------------- 1 file changed, 117 insertions(+), 94 deletions(-) diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql index afccaf760..016aee45c 100644 --- a/utils/sql/git/optional/auras.sql +++ b/utils/sql/git/optional/auras.sql @@ -1,97 +1,120 @@ -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8926, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89260, cast_time=89261; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8488, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84880, cast_time=84881; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8921, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89210, cast_time=89211; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8468, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84680, cast_time=84681; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8925, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89250, cast_time=89251; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8481, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84810, cast_time=84811; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8923, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89230, cast_time=89231; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8474, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84740, cast_time=84741; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8933, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=89330, cast_time=89331; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8518, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=85180, cast_time=85181; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8931, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89310, cast_time=89311; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8509, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=85090, cast_time=85091; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8929, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89290, cast_time=89291; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8499, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84990, cast_time=84991; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8928, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89280, cast_time=89281; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8495, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84950, cast_time=84951; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8924, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=89240, cast_time=89241; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8477, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=84770, cast_time=84771; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8930, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=89300, cast_time=89301; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8504, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=12, icon=85040, cast_time=85041; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8934, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=89340, cast_time=89341; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8523, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=85230, cast_time=85231; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8932, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=89320, cast_time=89321; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET npc_type=@suggestedid, type=8513, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=85130, cast_time=85131; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8926, @suggestedid, "Aura_of_Insight", 8939, 60, 1, 0, 0, 5400, 99, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8488, @suggestedid, "Aura_of_the_Muse", 8489, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8921, @suggestedid, "Myrmidon's_Aura", 8935, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8468, @suggestedid, "Champion's_Aura", 8469, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8925, @suggestedid, "Holy_Aura", 8938, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8481, @suggestedid, "Blessed_Aura", 8482, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8923, @suggestedid, "Disciples_Aura", 8937, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8474, @suggestedid, "Master's_Aura", 8475, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8933, @suggestedid, "Earthen_Strength", 8948, 60, 2, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8518, @suggestedid, "Rathe's_Strength", 8519, 60, 2, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8931, @suggestedid, "Beguiler's_Aura", 8946, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8509, @suggestedid, "Illusionist's_Aura", 8510, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8929, @suggestedid, "Aura_of_the_Grove", 8943, 60, 1, 0, 0, 5400, 1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8499, @suggestedid, "Aura_of_Life", 8500, 60, 1, 0, 0, 5400, 1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8928, @suggestedid, "Aura_of_the_Zealot", 8940, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8495, @suggestedid, "Aura_of_the_Pious", 8496, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8924, @suggestedid, "Aura_of_Rage", 8959, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8477, @suggestedid, "Bloodlust_Aura", 8478, 60, 1, 0, 0, 5400, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8930, @suggestedid, "Soul_Idol", 8945, 60, 3, 1, 1, 120, -1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8504, @suggestedid, "Spirit_Idol", 8505, 60, 3, 1, 1, 12, -1, 12); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8934, @suggestedid, "a_dark_rune", 8949, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8523, @suggestedid, "a_death_rune", 8524, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8932, @suggestedid, "a_fiery_rune", 8947, 25, 4, 1, 1, 120, -1, -1); + +SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) +INSERT INTO auras VALUES(8513, @suggestedid, "a_fire_rune", 8514, 25, 4, 1, 1, 120, -1, -1); From 58970282da6de6e0f6cc9c13be4f2a494f739bc1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 23:37:54 -0400 Subject: [PATCH 164/218] Fix SQL for real --- utils/sql/git/optional/auras.sql | 71 +++++++++++--------------------- 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql index 016aee45c..c1a9bed4d 100644 --- a/utils/sql/git/optional/auras.sql +++ b/utils/sql/git/optional/auras.sql @@ -1,120 +1,97 @@ SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8926, @suggestedid, "Aura_of_Insight", 8939, 60, 1, 0, 0, 5400, 99, -1); +INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8488, @suggestedid, "Aura_of_the_Muse", 8489, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8921, @suggestedid, "Myrmidon's_Aura", 8935, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8468, @suggestedid, "Champion's_Aura", 8469, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8925, @suggestedid, "Holy_Aura", 8938, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8481, @suggestedid, "Blessed_Aura", 8482, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8923, @suggestedid, "Disciples_Aura", 8937, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8474, @suggestedid, "Master's_Aura", 8475, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8933, @suggestedid, "Earthen_Strength", 8948, 60, 2, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8518, @suggestedid, "Rathe's_Strength", 8519, 60, 2, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8931, @suggestedid, "Beguiler's_Aura", 8946, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8509, @suggestedid, "Illusionist's_Aura", 8510, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8929, @suggestedid, "Aura_of_the_Grove", 8943, 60, 1, 0, 0, 5400, 1, 12); +INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8499, @suggestedid, "Aura_of_Life", 8500, 60, 1, 0, 0, 5400, 1, 12); +INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8928, @suggestedid, "Aura_of_the_Zealot", 8940, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8495, @suggestedid, "Aura_of_the_Pious", 8496, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8924, @suggestedid, "Aura_of_Rage", 8959, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8477, @suggestedid, "Bloodlust_Aura", 8478, 60, 1, 0, 0, 5400, -1, -1); +INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8930, @suggestedid, "Soul_Idol", 8945, 60, 3, 1, 1, 120, -1, 12); +INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8504, @suggestedid, "Spirit_Idol", 8505, 60, 3, 1, 1, 12, -1, 12); +INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8934, @suggestedid, "a_dark_rune", 8949, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8523, @suggestedid, "a_death_rune", 8524, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8932, @suggestedid, "a_fiery_rune", 8947, 25, 4, 1, 1, 120, -1, -1); +INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) -INSERT INTO auras VALUES(8513, @suggestedid, "a_fire_rune", 8514, 25, 4, 1, 1, 120, -1, -1); From 10325fed8b985d2d4443972e398016701a2114e6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 15 Jul 2017 23:44:18 -0400 Subject: [PATCH 165/218] Forgot to restore this part --- utils/sql/git/optional/auras.sql | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql index c1a9bed4d..7ca6ecc97 100644 --- a/utils/sql/git/optional/auras.sql +++ b/utils/sql/git/optional/auras.sql @@ -1,96 +1,96 @@ -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; -SELECT MAX(id) + 1 INTO @suggestedid FROM npc_types where id LIKE '2000___'; +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) From 55c557f22741c12d72da6b5570512c0ef2470eaa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 16 Jul 2017 00:26:18 -0400 Subject: [PATCH 166/218] Add ProcessOnAllFriendlies --- zone/aura.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 2b0bd9c1a..a37bef2d8 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -56,16 +56,57 @@ Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) } } -void Aura::ProcessOnAllFriendlies(Mob *owner) -{ - Shout("Stub 1"); -} - Mob *Aura::GetOwner() { return entity_list.GetMob(m_owner); } +// not 100% sure how this one should work and PVP affects ... +void Aura::ProcessOnAllFriendlies(Mob *owner) +{ + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + std::set delayed_remove; + bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter + + for (auto &e : mob_list) { + auto mob = e.second; + if (mob->IsClient() || mob->IsPetOwnerClient() || mob->IsMerc()) { + auto it = casted_on.find(mob->GetID()); + + if (it != casted_on.end()) { // we are already on the list, let's check for removal + if (DistanceSquared(GetPosition(), mob->GetPosition()) > distance) + delayed_remove.insert(mob->GetID()); + } else { // not on list, lets check if we're in range + if (DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } + } + } + } + + for (auto &e : delayed_remove) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove + mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); + casted_on.erase(e); + } + + // so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it + if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty()) + cast_timer.Start(); + + if (!cast_timer.Enabled() || !cast_timer.Check()) + return; + + for (auto &e : casted_on) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr) + SpellFinished(spell_id, mob); + } +} + void Aura::ProcessOnAllGroupMembers(Mob *owner) { auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline From 70a74d661540b6012fc64cb04085fa7469109a19 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sat, 15 Jul 2017 23:57:08 -0500 Subject: [PATCH 167/218] Fix for mobs who are hailed while moving - this allows them to properly stop, and return on their grid after pause time --- zone/mob.cpp | 30 ++++++++++++++---------------- zone/mob.h | 2 +- zone/waypoints.cpp | 10 ++++------ 3 files changed, 19 insertions(+), 23 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index fc7772b8d..33863081a 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1437,10 +1437,8 @@ void Mob::SendHPUpdate(bool skip_self /*= false*/, bool force_update_all /*= fal } } -/* Used for NPCs mainly */ -void Mob::SendPosition() -{ - +/* Used for mobs standing still - this does not send a delta */ +void Mob::SendPosition() { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; MakeSpawnUpdateNoDelta(spu); @@ -1457,7 +1455,7 @@ void Mob::SendPosition() safe_delete(app); } -// this one is for mobs on the move, with deltas - this makes them walk +/* Position updates for mobs on the move */ void Mob::SendPositionUpdate(uint8 iSendToSelf) { auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); PlayerPositionUpdateServer_Struct* spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; @@ -2729,25 +2727,25 @@ bool Mob::HateSummon() { return false; } -void Mob::FaceTarget(Mob* MobToFace) { - Mob* facemob = MobToFace; - if(!facemob) { +void Mob::FaceTarget(Mob* mob_to_face /*= 0*/) { + Mob* faced_mob = mob_to_face; + if(!faced_mob) { if(!GetTarget()) { return; } else { - facemob = GetTarget(); + faced_mob = GetTarget(); } } - float oldheading = GetHeading(); - float newheading = CalculateHeadingToTarget(facemob->GetX(), facemob->GetY()); - if(oldheading != newheading) { - SetHeading(newheading); - if(moving) + float current_heading = GetHeading(); + float new_heading = CalculateHeadingToTarget(faced_mob->GetX(), faced_mob->GetY()); + if(current_heading != new_heading) { + SetHeading(new_heading); + if (moving) { SendPositionUpdate(); - else - { + } + else { SendPosition(); } } diff --git a/zone/mob.h b/zone/mob.h index 56004157d..8286bf647 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -556,7 +556,7 @@ public: void SetPrimaryAggro(bool value) { PrimaryAggro = value; if (value) AssistAggro = false; } void SetAssistAggro(bool value) { AssistAggro = value; if (PrimaryAggro) AssistAggro = false; } bool HateSummon(); - void FaceTarget(Mob* MobToFace = 0); + void FaceTarget(Mob* mob_to_face = 0); void SetHeading(float iHeading) { if(m_Position.w != iHeading) { pLastChange = Timer::GetCurrentTime(); m_Position.w = iHeading; } } void WipeHateList(); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 61fc7983f..d1581a21c 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -134,17 +134,15 @@ void NPC::PauseWandering(int pausetime) { // causes wandering to stop but is resumable // 0 pausetime means pause until resumed // otherwise automatically resume when time is up - if (GetGrid() != 0) - { + if (GetGrid() != 0) { + moving = false; DistractedFromGrid = true; Log(Logs::Detail, Logs::Pathing, "Paused Wandering requested. Grid %d. Resuming in %d ms (0=not until told)", GetGrid(), pausetime); SendPosition(); - if (pausetime<1) - { // negative grid number stops him dead in his tracks until ResumeWandering() + if (pausetime < 1) { // negative grid number stops him dead in his tracks until ResumeWandering() SetGrid(0 - GetGrid()); } - else - { // specified waiting time, he'll resume after that + else { // specified waiting time, he'll resume after that AI_walking_timer->Start(pausetime * 1000); // set the timer } } From f7cc23d41553c6a3c02610871abd477baae57ef4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 03:21:13 -0500 Subject: [PATCH 168/218] Cracked the code on FixZ offsets --- zone/waypoints.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index d1581a21c..15ab630ca 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -849,6 +849,7 @@ void Mob::FixZ() { { /* Any more than 5 in the offset makes NPC's hop/snap to ceiling in small corridors */ float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 5); + new_z += (this->GetSize() / 1.55); auto duration = timer.elapsed(); @@ -864,7 +865,7 @@ void Mob::FixZ() { duration ); - if ((new_z > -2000) && std::abs(m_Position.z - new_z) < 35) { + if ((new_z > -2000) && new_z != -999999) { if (RuleB(Map, MobZVisualDebug)) this->SendAppearanceEffect(78, 0, 0, 0, 0); From b2b447516de781e330099437c04ffc4f88145296 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 03:31:26 -0500 Subject: [PATCH 169/218] Make a FixZ call at waypoint arrive so bad grids don't make NPC's hop --- zone/mob_ai.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index a016b98e6..56ebb6fc2 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1573,6 +1573,8 @@ void NPC::AI_DoMovement() { SetHeading(m_CurrentWayPoint.w); } + this->FixZ(); + SendPosition(); //kick off event_waypoint arrive From 0b489bc507ddbff193e616d2d958eef7d095eb9e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 04:36:36 -0500 Subject: [PATCH 170/218] LoS Drop when close adjustment --- zone/mob_ai.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 56ebb6fc2..e1e4682b0 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1001,7 +1001,7 @@ void Mob::AI_Process() { if (this->GetTarget()) { /* If we are engaged, moving and following client, let's look for best Z more often */ float target_distance = DistanceNoZ(this->GetPosition(), this->GetTarget()->GetPosition()); - if (target_distance >= 50) { + if (target_distance >= 25) { this->FixZ(); } else if (!this->CheckLosFN(this->GetTarget())) { From 6f2de7d31ba80cdb4e54b3b88ed8429250051a66 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 16 Jul 2017 13:33:17 -0400 Subject: [PATCH 171/218] Add function for group pet type auras --- zone/aura.cpp | 168 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index a37bef2d8..deef3abd2 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -301,7 +301,173 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) void Aura::ProcessOnGroupMembersPets(Mob *owner) { - Shout("Stub 3"); + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + std::set delayed_remove; + bool is_buff = IsBuffSpell(spell_id); // non-buff spells don't cast on enter + // This type can either live on the pet (level 55/70 MAG aura) or on the pet owner (level 85 MAG aura) + auto group_member = owner->GetOwnerOrSelf(); + + if (group_member->IsRaidGrouped() && group_member->IsClient()) { // currently raids are just client, but safety check + auto raid = group_member->GetRaid(); + if (raid == nullptr) { // well shit + Depop(); + return; + } + auto group_id = raid->GetGroup(group_member->CastToClient()); + + // some lambdas so the for loop is less horrible ... + auto verify_raid_client_pet = [&raid, &group_id, this](Mob *m) { + auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient()); + if (m->GetOwner()->GetID() == m_owner) { + return DistanceSquared(GetPosition(), m->GetPosition()) <= distance; + } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { + return false; + } else if (DistanceSquared(GetPosition(), m->GetPosition()) > distance) { + return false; + } + return true; + }; + + auto verify_raid_client_swarm = [&raid, &group_id, this](NPC *n) { + auto owner = entity_list.GetMob(n->GetSwarmOwner()); + if (owner == nullptr) + return false; + auto idx = raid->GetPlayerIndex(owner->CastToClient()); + if (owner->GetID() == m_owner) { + return DistanceSquared(GetPosition(), n->GetPosition()) <= distance; + } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { + return false; + } else if (DistanceSquared(GetPosition(), n->GetPosition()) > distance) { + return false; + } + return true; + }; + + for (auto &e : mob_list) { + auto mob = e.second; + // step 1: check if we're already managing this NPC's buff + auto it = casted_on.find(mob->GetID()); + if (it != casted_on.end()) { + // verify still good! + if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner()) { + if (!verify_raid_client_pet(mob)) + delayed_remove.insert(mob->GetID()); + } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { + auto npc = mob->CastToNPC(); + if (!verify_raid_client_swarm(npc)) + delayed_remove.insert(mob->GetID()); + } + } else { // we're not on it! + if (mob->IsClient()) { + continue; // never hit client + } else if (mob->IsPet() && mob->IsPetOwnerClient() && mob->GetOwner() && verify_raid_client_pet(mob)) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } else if (mob->IsNPC() && mob->IsPetOwnerClient()) { + auto npc = mob->CastToNPC(); + if (verify_raid_client_swarm(npc)) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } + } + } + } + } else if (group_member->IsGrouped()) { + auto group = group_member->GetGroup(); + if (group == nullptr) { // uh oh + Depop(); + return; + } + + // lambdas to make for loop less ugly + auto verify_group_pet = [&group, this](Mob *m) { + auto owner = m->GetOwner(); + if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), m->GetPosition()) <= distance) + return true; + return false; + }; + + auto verify_group_swarm = [&group, this](NPC *n) { + auto owner = entity_list.GetMob(n->GetSwarmOwner()); + if (owner != nullptr && group->IsGroupMember(owner) && DistanceSquared(GetPosition(), n->GetPosition()) <= distance) + return true; + return false; + }; + + for (auto &e : mob_list) { + auto mob = e.second; + auto it = casted_on.find(mob->GetID()); + + if (it != casted_on.end()) { // make sure we're still valid + if (mob->IsPet()) { + if (!verify_group_pet(mob)) + delayed_remove.insert(mob->GetID()); + } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo()) { + if (!verify_group_swarm(mob->CastToNPC())) + delayed_remove.insert(mob->GetID()); + } + } else { // not on, check if we should be! + if (mob->IsClient()) { + continue; + } else if (mob->IsPet() && verify_group_pet(mob)) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } else if (mob->IsNPC() && mob->CastToNPC()->GetSwarmInfo() && verify_group_swarm(mob->CastToNPC())) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } + } + } + } else { + auto verify_solo = [&group_member, this](Mob *m) { + if (m->IsPet() && m->GetOwnerID() == group_member->GetID()) + return true; + else if (m->IsNPC() && m->CastToNPC()->GetSwarmOwner() == group_member->GetID()) + return true; + else + return false; + }; + for (auto &e : mob_list) { + auto mob = e.second; + auto it = casted_on.find(mob->GetID()); + bool good = verify_solo(mob); + + if (it != casted_on.end()) { // make sure still valid + if (!good || DistanceSquared(GetPosition(), mob->GetPosition()) > distance) { + delayed_remove.insert(mob->GetID()); + } + } else if (good && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { + casted_on.insert(mob->GetID()); + if (is_buff) + SpellFinished(spell_id, mob); + } + } + } + + for (auto &e : delayed_remove) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr && is_buff) // some auras cast instant spells so no need to remove + mob->BuffFadeBySpellIDAndCaster(spell_id, GetID()); + casted_on.erase(e); + } + + // so if we have a cast timer and our set isn't empty and timer is disabled we need to enable it + if (cast_timer.GetDuration() > 0 && !cast_timer.Enabled() && !casted_on.empty()) + cast_timer.Start(); + + if (!cast_timer.Enabled() || !cast_timer.Check()) + return; + + // some auras have to recast (DRU for example, non-buff too) + for (auto &e : casted_on) { + auto mob = entity_list.GetMob(e); + if (mob != nullptr) + SpellFinished(spell_id, mob); + } } void Aura::ProcessTotem(Mob *owner) From 8b5389e719bf85f698395b655f062f6397b51dcc Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 16 Jul 2017 15:19:10 -0400 Subject: [PATCH 172/218] Fix pet aura --- zone/aura.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index deef3abd2..ec007c614 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -316,9 +316,9 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) auto group_id = raid->GetGroup(group_member->CastToClient()); // some lambdas so the for loop is less horrible ... - auto verify_raid_client_pet = [&raid, &group_id, this](Mob *m) { + auto verify_raid_client_pet = [&raid, &group_id, &group_member, this](Mob *m) { auto idx = raid->GetPlayerIndex(m->GetOwner()->CastToClient()); - if (m->GetOwner()->GetID() == m_owner) { + if (m->GetOwner()->GetID() == group_member->GetID()) { return DistanceSquared(GetPosition(), m->GetPosition()) <= distance; } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { return false; From 3312d8c05bf29a457646a2a5ce7e2ece6a49c957 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sun, 16 Jul 2017 15:20:57 -0400 Subject: [PATCH 173/218] Fix swarm pets too --- zone/aura.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index ec007c614..70dad8cbe 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -328,12 +328,12 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) return true; }; - auto verify_raid_client_swarm = [&raid, &group_id, this](NPC *n) { + auto verify_raid_client_swarm = [&raid, &group_id, &group_member, this](NPC *n) { auto owner = entity_list.GetMob(n->GetSwarmOwner()); if (owner == nullptr) return false; auto idx = raid->GetPlayerIndex(owner->CastToClient()); - if (owner->GetID() == m_owner) { + if (owner->GetID() == group_member->GetID()) { return DistanceSquared(GetPosition(), n->GetPosition()) <= distance; } else if (idx == 0xFFFFFFFF || raid->members[idx].GroupNumber != group_id || raid->members[idx].GroupNumber == 0xFFFFFFFF) { return false; From e265f7713c36f8f249396e5bc8d06bc6153daa93 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 21:35:50 -0500 Subject: [PATCH 174/218] Fix eqemu_server.pl installer to use PEQ quests repo and fix new_server file count check --- utils/scripts/eqemu_server.pl | 52 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index c67170785..ef7e56a35 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -201,7 +201,7 @@ sub new_server { } closedir(DIR); - if($file_count > 1 && (!-e "install_variables.txt" && !-e "../install_variables.txt")){ + if($file_count > 4 && (!-e "install_variables.txt" && !-e "../install_variables.txt")){ print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; <>; exit; @@ -281,6 +281,8 @@ sub new_server { show_install_summary_info(); + rmtree('updates_staged'); + return; } else { @@ -1505,12 +1507,12 @@ sub map_files_fetch{ } sub quest_files_fetch{ - if (!-e "updates_staged/Quests-Plugins-master/quests/") { + if (!-e "updates_staged/projecteqquests-master/") { print "[Update] Fetching Latest Quests --- \n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); print "[Install] Fetched latest quests...\n"; mkdir('updates_staged'); - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); } $fc = 0; @@ -1518,7 +1520,7 @@ sub quest_files_fetch{ use File::Compare; my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/quests/"; + my $start_dir = "updates_staged/projecteqquests-master/"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir @@ -1527,7 +1529,7 @@ sub quest_files_fetch{ if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file =~s/updates_staged\/projecteqquests-master\//quests\//g; if (!-e $destination_file) { copy_file($staged_file, $destination_file); @@ -1557,27 +1559,28 @@ sub quest_files_fetch{ } } - rmtree('updates_staged'); - if($fc == 0){ print "[Update] No Quest Updates found... \n\n"; } } sub lua_modules_fetch { - if (!-e "updates_staged/Quests-Plugins-master/quests/lua_modules/") { - print "[Update] Fetching Latest LUA Modules --- \n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest LUA Modules...\n"; - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + if (!-e "updates_staged/projecteqquests-master/") { + print "[Update] Fetching Latest lua modules --- \n"; + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); + print "[Install] Fetched latest lua modules...\n"; + mkdir('updates_staged'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); } $fc = 0; use File::Find; use File::Compare; + mkdir('lua_modules'); + my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/quests/lua_modules/"; + my $start_dir = "updates_staged/projecteqquests-master/lua_modules/"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir @@ -1586,7 +1589,7 @@ sub lua_modules_fetch { if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\/quests\///g; + $destination_file =~s/updates_staged\/projecteqquests-master\/lua_modules\//lua_modules\//g; if (!-e $destination_file) { copy_file($staged_file, $destination_file); @@ -1621,19 +1624,22 @@ sub lua_modules_fetch { } sub plugins_fetch{ - if (!-e "updates_staged/Quests-Plugins-master/plugins/") { - print "[Update] Fetching Latest Plugins\n"; - get_remote_file("https://github.com/EQEmu/Quests-Plugins/archive/master.zip", "updates_staged/Quests-Plugins-master.zip", 1); - print "[Update] Fetched latest plugins\n"; - unzip('updates_staged/Quests-Plugins-master.zip', 'updates_staged/'); + if (!-e "updates_staged/projecteqquests-master/") { + print "[Update] Fetching Latest plugins --- \n"; + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); + print "[Install] Fetched latest plugins...\n"; + mkdir('updates_staged'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); } $fc = 0; use File::Find; use File::Compare; + mkdir('plugins'); + my @files; - my $start_dir = "updates_staged/Quests-Plugins-master/plugins/"; + my $start_dir = "updates_staged/projecteqquests-master/plugins/"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir @@ -1642,7 +1648,7 @@ sub plugins_fetch{ if($file=~/\.pl|\.lua|\.ext/i){ $staged_file = $file; $destination_file = $file; - $destination_file =~s/updates_staged\/Quests-Plugins-master\///g; + $destination_file =~s/updates_staged\/projecteqquests-master\///g; if (!-e $destination_file) { copy_file($staged_file, $destination_file); @@ -2173,4 +2179,4 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} +} \ No newline at end of file From 7881d6609a538451eabb99811660b7005d1a3910 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 22:34:22 -0500 Subject: [PATCH 175/218] Make sure we send client updates for heading or animation changes while still --- zone/client_packet.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index f2906e093..e8ae68e69 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -4599,14 +4599,14 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) } } + float new_heading = EQ19toFloat(ppu->heading); + int32 new_animation = ppu->animation; + /* Update internal server position from what the client has sent */ m_Position.x = ppu->x_pos; m_Position.y = ppu->y_pos; m_Position.z = ppu->z_pos; - m_Position.w = EQ19toFloat(ppu->heading); - animation = ppu->animation; - /* Visual Debugging */ if (RuleB(Character, OPClientUpdateVisualDebug)) { Log(Logs::General, Logs::Debug, "ClientUpdate: ppu x: %f y: %f z: %f h: %u", ppu->x_pos, ppu->y_pos, ppu->z_pos, ppu->heading); @@ -4615,7 +4615,10 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) } /* Only feed real time updates when client is moving */ - if (is_client_moving) { + if (is_client_moving || new_heading != m_Position.w || new_animation != animation) { + + animation = ppu->animation; + m_Position.w = EQ19toFloat(ppu->heading); /* Broadcast update to other clients */ auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); From 78d95cab89d971343c22c29256dd4b2120eec5c9 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 16 Jul 2017 23:55:15 -0500 Subject: [PATCH 176/218] Fix logic loop issue with NPC pathing in zones with .path files, this creates a new rule in place of the old and a new one will be automatically created in the database --- common/ruletypes.h | 2 +- zone/pathing.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/ruletypes.h b/common/ruletypes.h index fe385b18f..a51a224b0 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -290,7 +290,7 @@ RULE_BOOL(Pathing, AggroReturnToGrid, true) // Enable pathing for aggroed roamin RULE_BOOL(Pathing, Guard, true) // Enable pathing for mobs moving to their guard point. RULE_BOOL(Pathing, Find, true) // Enable pathing for FindPerson requests from the client. RULE_BOOL(Pathing, Fear, true) // Enable pathing for fear -RULE_REAL(Pathing, ZDiffThreshold, 10) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. +RULE_REAL(Pathing, ZDiffThresholdNew, 80) // If a mob las LOS to it's target, it will run to it if the Z difference is < this. RULE_INT(Pathing, LOSCheckFrequency, 1000) // A mob will check for LOS to it's target this often (milliseconds). RULE_INT(Pathing, RouteUpdateFrequencyShort, 1000) // How often a new route will be calculated if the target has moved. RULE_INT(Pathing, RouteUpdateFrequencyLong, 5000) // How often a new route will be calculated if the target has moved. diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 25d996eac..009c1a152 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -759,7 +759,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && - (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) { + (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) PathingLOSState = HaveLOS; else @@ -851,7 +851,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && - (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) { + (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) PathingLOSState = HaveLOS; else @@ -888,7 +888,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa float Distance = VectorDistanceNoRoot(From, To); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && - (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) { + (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { Log(Logs::Detail, Logs::None, " Checking for short LOS at distance %8.3f.", Distance); if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) PathingLOSState = HaveLOS; @@ -1039,7 +1039,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa float Distance = VectorDistanceNoRoot(From, To); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckLong)) && - (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThreshold))) { + (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { Log(Logs::Detail, Logs::None, " Checking for long LOS at distance %8.3f.", Distance); if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) @@ -1143,7 +1143,7 @@ bool PathManager::NoHazards(glm::vec3 From, glm::vec3 To) float NewZ = zone->zonemap->FindBestZ(MidPoint, nullptr); - if (std::abs(NewZ - From.z) > RuleR(Pathing, ZDiffThreshold)) { + if (std::abs(NewZ - From.z) > RuleR(Pathing, ZDiffThresholdNew)) { Log(Logs::Detail, Logs::None, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f", From.x, From.y, From.z, MidPoint.x, MidPoint.y, MidPoint.z, NewZ - From.z); @@ -1215,7 +1215,7 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To) } else { - if (std::abs(NewZ - best_z2) > RuleR(Pathing, ZDiffThreshold)) { + if (std::abs(NewZ - best_z2) > RuleR(Pathing, ZDiffThresholdNew)) { Log(Logs::Detail, Logs::None, " HAZARD DETECTED, water is fairly deep at %8.3f units deep", std::abs(NewZ - best_z2)); From f917a38e1a913142da2ec2a470d8acd9de898097 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 17 Jul 2017 19:35:00 -0400 Subject: [PATCH 177/218] Fix a few things with auras --- zone/aura.cpp | 48 ++++++++++++++++++++++++++---------------------- zone/mob.h | 3 ++- 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 70dad8cbe..47f486bdd 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -683,6 +683,7 @@ void Mob::AddAura(Aura *aura, AuraRecord &record) assert(aura != nullptr); strn0cpy(aura_mgr.auras[aura_mgr.count].name, aura->GetCleanName(), 64); aura_mgr.auras[aura_mgr.count].spawn_id = aura->GetID(); + aura_mgr.auras[aura_mgr.count].aura = aura; if (record.icon == -1) aura_mgr.auras[aura_mgr.count].icon = spells[record.spell_id].new_icon; else @@ -707,6 +708,7 @@ void Mob::AddTrap(Aura *aura, AuraRecord &record) assert(aura != nullptr); strn0cpy(trap_mgr.auras[trap_mgr.count].name, aura->GetCleanName(), 64); trap_mgr.auras[trap_mgr.count].spawn_id = aura->GetID(); + trap_mgr.auras[trap_mgr.count].aura = aura; if (record.icon == -1) trap_mgr.auras[trap_mgr.count].icon = spells[record.spell_id].new_icon; else @@ -733,17 +735,15 @@ void Mob::RemoveAllAuras() // this is sent on camp/zone, so it just despawns? if (aura_mgr.count) { for (auto &e : aura_mgr.auras) { - auto mob = entity_list.GetMob(e.spawn_id); - if (mob) - mob->Depop(); + if (e.aura) + e.aura->Depop(); } } if (trap_mgr.count) { for (auto &e : trap_mgr.auras) { - auto mob = entity_list.GetMob(e.spawn_id); - if (mob) - mob->Depop(); + if (e.aura) + e.aura->Depop(); } } return; @@ -754,9 +754,8 @@ void Mob::RemoveAura(int spawn_id, bool expired) for (int i = 0; i < aura_mgr.count; ++i) { auto &aura = aura_mgr.auras[i]; if (aura.spawn_id == spawn_id) { - auto mob = entity_list.GetMob(aura.spawn_id); - if (mob) - mob->Depop(); + if (aura.aura) + aura.aura->Depop(); if (expired && IsClient()) CastToClient()->SendColoredText( CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color @@ -764,6 +763,8 @@ void Mob::RemoveAura(int spawn_id, bool expired) i++; aura.spawn_id = aura_mgr.auras[i].spawn_id; aura.icon = aura_mgr.auras[i].icon; + aura.aura = aura_mgr.auras[i].aura; + aura_mgr.auras[i].aura = nullptr; strn0cpy(aura.name, aura_mgr.auras[i].name, 64); } aura_mgr.count--; @@ -773,20 +774,23 @@ void Mob::RemoveAura(int spawn_id, bool expired) for (int i = 0; i < trap_mgr.count; ++i) { auto &aura = trap_mgr.auras[i]; - auto mob = entity_list.GetMob(aura.spawn_id); - if (mob) - mob->Depop(); - if (expired && IsClient()) - CastToClient()->SendColoredText( - CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color - while (trap_mgr.count - 1 > i) { - i++; - aura.spawn_id = trap_mgr.auras[i].spawn_id; - aura.icon = trap_mgr.auras[i].icon; - strn0cpy(aura.name, trap_mgr.auras[i].name, 64); + if (aura.spawn_id == spawn_id) { + if (aura.aura) + aura.aura->Depop(); + if (expired && IsClient()) + CastToClient()->SendColoredText( + CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color + while (trap_mgr.count - 1 > i) { + i++; + aura.spawn_id = trap_mgr.auras[i].spawn_id; + aura.icon = trap_mgr.auras[i].icon; + aura.aura = trap_mgr.auras[i].aura; + trap_mgr.auras[i].aura = nullptr; + strn0cpy(aura.name, trap_mgr.auras[i].name, 64); + } + trap_mgr.count--; + return; } - trap_mgr.count--; - return; } return; diff --git a/zone/mob.h b/zone/mob.h index 5aceda8f0..8e980519a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -91,7 +91,8 @@ public: char name[64]; int spawn_id; int icon; - AuraInfo() : spawn_id(0), icon(0) + Aura *aura; + AuraInfo() : spawn_id(0), icon(0), aura(nullptr) { memset(name, 0, 64); } From a83edb83bad31ffa681a62ebac623879391f56c7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Jul 2017 15:26:20 -0500 Subject: [PATCH 178/218] Change eqemu_server.pl to use new map download methodology --- utils/scripts/eqemu_server.pl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index ef7e56a35..42d956edd 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1454,7 +1454,7 @@ sub map_files_fetch_bulk{ get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); unzip('maps/maps.zip', 'maps/'); my @files; - my $start_dir = "maps/EQEmuMaps-master/maps"; + my $start_dir = "maps/EQEmuMaps-master/"; find( sub { push @files, $File::Find::name unless -d; }, $start_dir @@ -2179,4 +2179,5 @@ sub generate_random_password { map $alphanumeric[rand @alphanumeric], 0..$passwordsize; return $randpassword; -} \ No newline at end of file +} + From fe8c55ac631c6d346d1c8ea42c369511007ca693 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 18 Jul 2017 17:52:39 -0400 Subject: [PATCH 179/218] Auras now zone --- utils/sql/git/required/2017_07_xx_aura.sql | 8 ++++++ zone/aura.cpp | 16 ++++++++++- zone/aura.h | 6 ++++ zone/client_packet.cpp | 2 ++ zone/client_process.cpp | 2 ++ zone/mob.h | 2 ++ zone/zonedb.cpp | 32 ++++++++++++++++++++++ zone/zonedb.h | 2 ++ 8 files changed, 69 insertions(+), 1 deletion(-) diff --git a/utils/sql/git/required/2017_07_xx_aura.sql b/utils/sql/git/required/2017_07_xx_aura.sql index 9437d1c7c..96ea45185 100644 --- a/utils/sql/git/required/2017_07_xx_aura.sql +++ b/utils/sql/git/required/2017_07_xx_aura.sql @@ -12,3 +12,11 @@ CREATE TABLE `auras` ( `cast_time` INT(10) NOT NULL DEFAULT 0, PRIMARY KEY(`type`) ) + +CREATE TABLE `character_auras` ( + `id` INT(10) NOT NULL, + `slot` TINYINT(10) NOT NULL, + `spell_id` INT(10) NOT NULL, + PRIMARY KEY (`id`, `slot`) +); + diff --git a/zone/aura.cpp b/zone/aura.cpp index 47f486bdd..0bbe86b8d 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -7,7 +7,7 @@ Aura::Aura(NPCType *type_data, Mob *owner, AuraRecord &record) : NPC(type_data, 0, owner->GetPosition(), FlyMode3), spell_id(record.spell_id), distance(record.distance), - remove_timer(record.duration), movement_timer(100), process_timer(100) + remove_timer(record.duration), movement_timer(100), process_timer(100), aura_id(-1) { GiveNPCTypeData(type_data); // we will delete this later on m_owner = owner->GetID(); @@ -584,6 +584,7 @@ void Aura::Depop(bool unused) p_depop = true; } +// This creates an aura from a casted spell void Mob::MakeAura(uint16 spell_id) { // TODO: verify room in AuraMgr @@ -639,6 +640,7 @@ void Mob::MakeAura(uint16 spell_id) strn0cpy(npc_type->name, record.name, 64); auto npc = new Aura(npc_type, this, record); + npc->SetAuraID(spell_id); entity_list.AddNPC(npc, true, true); if (trap) @@ -732,6 +734,13 @@ bool Mob::CanSpawnAura(bool trap) void Mob::RemoveAllAuras() { + if (IsClient()) { + database.SaveAuras(CastToClient()); + EQApplicationPacket outapp(OP_UpdateAura, 4); + outapp.WriteUInt32(2); + CastToClient()->QueuePacket(&outapp); + } + // this is sent on camp/zone, so it just despawns? if (aura_mgr.count) { for (auto &e : aura_mgr.auras) { @@ -740,12 +749,17 @@ void Mob::RemoveAllAuras() } } + aura_mgr.count = 0; + if (trap_mgr.count) { for (auto &e : trap_mgr.auras) { if (e.aura) e.aura->Depop(); } } + + trap_mgr.count = 0; + return; } diff --git a/zone/aura.h b/zone/aura.h index 8d467d945..7980f0b0a 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -57,8 +57,14 @@ public: void ProcessEnterTrap(Mob *owner); void ProcessExitTrap(Mob *owner); + // we only save auras that follow you, and player casted + inline bool AuraZones() { return movement_type == AuraMovement::Follow && aura_id > -1; } + inline int GetSpellID() { return spell_id; } + inline int GetAuraID() { return aura_id; } + inline void SetAuraID(int in) { aura_id = in; } private: int m_owner; + int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell int spell_id; // spell we cast int distance; // distance we remove Timer remove_timer; // when we depop diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 752d43eee..3a52fc19e 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -883,6 +883,8 @@ void Client::CompleteConnect() SetPetCommandState(PET_BUTTON_SPELLHOLD, 0); } + database.LoadAuras(this); // this ends up spawning them so probably safer to load this later (here) + entity_list.RefreshClientXTargets(this); worldserver.RequestTellQueue(GetName()); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 672848acc..3e08c1fba 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -723,6 +723,8 @@ void Client::OnDisconnect(bool hard_disconnect) { } } + RemoveAllAuras(); + Mob *Other = trade->With(); if(Other) { diff --git a/zone/mob.h b/zone/mob.h index 8e980519a..4fcc81b5a 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -625,6 +625,7 @@ public: bool PlotPositionAroundTarget(Mob* target, float &x_dest, float &y_dest, float &z_dest, bool lookForAftArc = true); + // aura functions void MakeAura(uint16 spell_id); inline int GetAuraSlots() { return 1 + aabonuses.aura_slots + itembonuses.aura_slots + spellbonuses.aura_slots; } inline int GetTrapSlots() { return 1 + aabonuses.trap_slots + itembonuses.trap_slots + spellbonuses.trap_slots; } @@ -635,6 +636,7 @@ public: bool CanSpawnAura(bool trap); void RemoveAura(int spawn_id, bool expired = false); void RemoveAllAuras(); + inline AuraMgr &GetAuraMgr() { return aura_mgr; } // mainly used for zone db loading/saving //Procs void TriggerDefensiveProcs(Mob *on, uint16 hand = EQEmu::inventory::slotPrimary, bool FromSkillProc = false, int damage = 0); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d647dcbf7..e48990c6a 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -11,6 +11,7 @@ #include "merc.h" #include "zone.h" #include "zonedb.h" +#include "aura.h" #include #include @@ -3148,6 +3149,37 @@ void ZoneDatabase::LoadBuffs(Client *client) } } +void ZoneDatabase::SaveAuras(Client *c) +{ + auto query = StringFormat("DELETE FROM `character_auras` WHERE `id` = %u", c->CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + const auto &auras = c->GetAuraMgr(); + for (int i = 0; i < auras.count; ++i) { + auto aura = auras.auras[i].aura; + if (aura && aura->AuraZones()) { + query = StringFormat("INSERT INTO `character_auras` (id, slot, spell_id) VALUES(%u, %d, %d)", + c->CharacterID(), i, aura->GetAuraID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + } + } +} + +void ZoneDatabase::LoadAuras(Client *c) +{ + auto query = StringFormat("SELECT `spell_id` FROM `character_auras` WHERE `id` = %u ORDER BY `slot`", c->CharacterID()); + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + for (auto row = results.begin(); row != results.end(); ++row) + c->MakeAura(atoi(row[0])); +} + void ZoneDatabase::SavePetInfo(Client *client) { PetInfo *petinfo = nullptr; diff --git a/zone/zonedb.h b/zone/zonedb.h index b91ea3cdd..a8ab3659f 100644 --- a/zone/zonedb.h +++ b/zone/zonedb.h @@ -273,6 +273,8 @@ public: void SaveBuffs(Client *c); void LoadBuffs(Client *c); + void SaveAuras(Client *c); + void LoadAuras(Client *c); void LoadPetInfo(Client *c); void SavePetInfo(Client *c); void RemoveTempFactions(Client *c); From 7cda4aaa2c0fb6cd7c4a7674c22a93dd42456ac6 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Jul 2017 19:09:28 -0500 Subject: [PATCH 180/218] Fix some pathing logic that is using Z to match a node reach when it is error prone in certain scenarios Fixed a decent amount of path logging --- common/eqemu_logsys.h | 4 +- zone/pathing.cpp | 134 +++++++++++++++++++++--------------------- zone/waypoints.cpp | 4 +- 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/common/eqemu_logsys.h b/common/eqemu_logsys.h index 7ae5a0296..56542c07d 100644 --- a/common/eqemu_logsys.h +++ b/common/eqemu_logsys.h @@ -87,6 +87,7 @@ enum LogCategory { Client_Login, Headless_Client, HP_Update, + FixZ, MaxCategoryID /* Don't Remove this*/ }; @@ -138,7 +139,8 @@ static const char* LogCategoryName[LogCategory::MaxCategoryID] = { "Login Server", "Client Login", "Headless Client", - "HP Update" + "HP Update", + "FixZ" }; } diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 009c1a152..5fe4a7e57 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -206,7 +206,7 @@ glm::vec3 PathManager::GetPathNodeCoordinates(int NodeNumber, bool BestZ) std::deque PathManager::FindRoute(int startID, int endID) { - Log(Logs::Detail, Logs::None, "FindRoute from node %i to %i", startID, endID); + Log(Logs::Detail, Logs::Pathing, "FindRoute from node %i to %i", startID, endID); memset(ClosedListFlag, 0, sizeof(int) * Head.PathNodeCount); @@ -329,7 +329,7 @@ std::deque PathManager::FindRoute(int startID, int endID) } } - Log(Logs::Detail, Logs::None, "Unable to find a route."); + Log(Logs::Detail, Logs::Pathing, "Unable to find a route."); return Route; } @@ -351,7 +351,7 @@ auto path_compare = [](const PathNodeSortStruct& a, const PathNodeSortStruct& b) std::deque PathManager::FindRoute(glm::vec3 Start, glm::vec3 End) { - Log(Logs::Detail, Logs::None, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z); + Log(Logs::Detail, Logs::Pathing, "FindRoute(%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f)", Start.x, Start.y, Start.z, End.x, End.y, End.z); std::deque noderoute; @@ -384,7 +384,7 @@ std::deque PathManager::FindRoute(glm::vec3 Start, glm::vec3 End) for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { - Log(Logs::Detail, Logs::None, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id); + Log(Logs::Detail, Logs::Pathing, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id); if(!zone->zonemap->LineIntersectsZone(Start, PathNodes[(*Iterator).id].v, 1.0f, nullptr)) { @@ -394,11 +394,11 @@ std::deque PathManager::FindRoute(glm::vec3 Start, glm::vec3 End) } if(ClosestPathNodeToStart <0 ) { - Log(Logs::Detail, Logs::None, "No LOS to any starting Path Node within range."); + Log(Logs::Detail, Logs::Pathing, "No LOS to any starting Path Node within range."); return noderoute; } - Log(Logs::Detail, Logs::None, "Closest Path Node To Start: %2d", ClosestPathNodeToStart); + Log(Logs::Detail, Logs::Pathing, "Closest Path Node To Start: %2d", ClosestPathNodeToStart); // Find the nearest PathNode the end point has LOS to @@ -421,8 +421,8 @@ std::deque PathManager::FindRoute(glm::vec3 Start, glm::vec3 End) for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { - Log(Logs::Detail, Logs::None, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id); - Log(Logs::Detail, Logs::None, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)", + Log(Logs::Detail, Logs::Pathing, "Checking Reachability of Node %i from End Position.", PathNodes[(*Iterator).id].id); + Log(Logs::Detail, Logs::Pathing, " (%8.3f, %8.3f, %8.3f) to (%8.3f, %8.3f, %8.3f)", End.x, End.y, End.z, PathNodes[(*Iterator).id].v.x, PathNodes[(*Iterator).id].v.y, PathNodes[(*Iterator).id].v.z); @@ -434,11 +434,11 @@ std::deque PathManager::FindRoute(glm::vec3 Start, glm::vec3 End) } if(ClosestPathNodeToEnd < 0) { - Log(Logs::Detail, Logs::None, "No LOS to any end Path Node within range."); + Log(Logs::Detail, Logs::Pathing, "No LOS to any end Path Node within range."); return noderoute; } - Log(Logs::Detail, Logs::None, "Closest Path Node To End: %2d", ClosestPathNodeToEnd); + Log(Logs::Detail, Logs::Pathing, "Closest Path Node To End: %2d", ClosestPathNodeToEnd); if(ClosestPathNodeToStart == ClosestPathNodeToEnd) { @@ -673,7 +673,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if(To == From) return To; - Log(Logs::Detail, Logs::None, "UpdatePath. From(%8.3f, %8.3f, %8.3f) To(%8.3f, %8.3f, %8.3f)", From.x, From.y, From.z, To.x, To.y, To.z); + Log(Logs::Detail, Logs::Pathing, "UpdatePath. From(%8.3f, %8.3f, %8.3f) To(%8.3f, %8.3f, %8.3f)", From.x, From.y, From.z, To.x, To.y, To.z); if(From == PathingLastPosition) { @@ -681,7 +681,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if((PathingLoopCount > 5) && !IsRooted()) { - Log(Logs::Detail, Logs::None, "appears to be stuck. Teleporting them to next position.", GetName()); + Log(Logs::Detail, Logs::Pathing, "appears to be stuck. Teleporting them to next position.", GetName()); if(Route.empty()) { @@ -721,7 +721,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // If we are already pathing, and the destination is the same as before ... if(SameDestination) { - Log(Logs::Detail, Logs::None, " Still pathing to the same destination."); + Log(Logs::Detail, Logs::Pathing, " Still pathing to the same destination."); // Get the coordinates of the first path node we are going to. NextNode = Route.front(); @@ -730,9 +730,9 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // May need to refine this as rounding errors may mean we never have equality // We have reached the path node. - if(NodeLoc == From) + if(NodeLoc.x == From.x && NodeLoc.y == From.y) { - Log(Logs::Detail, Logs::None, " Arrived at node %i", NextNode); + Log(Logs::Detail, Logs::Pathing, " Arrived at node %i", NextNode); NodeReached = true; @@ -746,17 +746,17 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // target, and we may run past the target if we don't check LOS at this point. int RouteSize = Route.size(); - Log(Logs::Detail, Logs::None, "Route size is %i", RouteSize); + Log(Logs::Detail, Logs::Pathing, "Route size is %i", RouteSize); if((RouteSize == 2) || ((PathingTraversedNodes >= RuleI(Pathing, MinNodesTraversedForLOSCheck)) && (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck)) && PathingLOSCheckTimer->Check())) { - Log(Logs::Detail, Logs::None, " Checking distance to target."); + Log(Logs::Detail, Logs::Pathing, " Checking distance to target."); float Distance = VectorDistanceNoRoot(From, To); - Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance); + Log(Logs::Detail, Logs::Pathing, " Distance between From and To (NoRoot) is %8.3f", Distance); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { @@ -764,18 +764,18 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa PathingLOSState = HaveLOS; else PathingLOSState = NoLOS; - Log(Logs::Detail, Logs::None, "NoLOS"); + Log(Logs::Detail, Logs::Pathing, "NoLOS"); if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To)) { - Log(Logs::Detail, Logs::None, " No hazards. Running directly to target."); + Log(Logs::Detail, Logs::Pathing, " No hazards. Running directly to target."); Route.clear(); return To; } else { - Log(Logs::Detail, Logs::None, " Continuing on node path."); + Log(Logs::Detail, Logs::Pathing, " Continuing on node path."); } } else @@ -801,7 +801,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if(Route.empty()) { - Log(Logs::Detail, Logs::None, "Missing node after teleport."); + Log(Logs::Detail, Logs::Pathing, "Missing node after teleport."); return To; } @@ -811,7 +811,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Teleport(NodeLoc); - Log(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z); + Log(Logs::Detail, Logs::Pathing, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z); Route.pop_front(); @@ -822,7 +822,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa } zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this); - Log(Logs::Detail, Logs::None, " Now moving to node %i", NextNode); + Log(Logs::Detail, Logs::Pathing, " Now moving to node %i", NextNode); return zone->pathing->GetPathNodeCoordinates(NextNode); } @@ -830,7 +830,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa { // we have run all the nodes, all that is left is the direct path from the last node // to the destination - Log(Logs::Detail, Logs::None, " Reached end of node path, running direct to target."); + Log(Logs::Detail, Logs::Pathing, " Reached end of node path, running direct to target."); return To; } @@ -844,11 +844,11 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa && (RouteSize <= RuleI(Pathing, MinNodesLeftForLOSCheck)) && PathingLOSCheckTimer->Check()) { - Log(Logs::Detail, Logs::None, " Checking distance to target."); + Log(Logs::Detail, Logs::Pathing, " Checking distance to target."); float Distance = VectorDistanceNoRoot(From, To); - Log(Logs::Detail, Logs::None, " Distance between From and To (NoRoot) is %8.3f", Distance); + Log(Logs::Detail, Logs::Pathing, " Distance between From and To (NoRoot) is %8.3f", Distance); if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { @@ -856,18 +856,18 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa PathingLOSState = HaveLOS; else PathingLOSState = NoLOS; - Log(Logs::Detail, Logs::None, "NoLOS"); + Log(Logs::Detail, Logs::Pathing, "NoLOS"); if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To)) { - Log(Logs::Detail, Logs::None, " No hazards. Running directly to target."); + Log(Logs::Detail, Logs::Pathing, " No hazards. Running directly to target."); Route.clear(); return To; } else { - Log(Logs::Detail, Logs::None, " Continuing on node path."); + Log(Logs::Detail, Logs::Pathing, " Continuing on node path."); } } else @@ -879,7 +879,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa { // We get here if we were already pathing, but our destination has now changed. // - Log(Logs::Detail, Logs::None, " Target has changed position."); + Log(Logs::Detail, Logs::Pathing, " Target has changed position."); // Update our record of where we are going to. PathingDestination = To; // Check if we now have LOS etc to the new destination. @@ -889,23 +889,23 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckShort)) && (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { - Log(Logs::Detail, Logs::None, " Checking for short LOS at distance %8.3f.", Distance); + Log(Logs::Detail, Logs::Pathing, " Checking for short LOS at distance %8.3f.", Distance); if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) PathingLOSState = HaveLOS; else PathingLOSState = NoLOS; - Log(Logs::Detail, Logs::None, "NoLOS"); + Log(Logs::Detail, Logs::Pathing, "NoLOS"); if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To)) { - Log(Logs::Detail, Logs::None, " No hazards. Running directly to target."); + Log(Logs::Detail, Logs::Pathing, " No hazards. Running directly to target."); Route.clear(); return To; } else { - Log(Logs::Detail, Logs::None, " Continuing on node path."); + Log(Logs::Detail, Logs::Pathing, " Continuing on node path."); } } } @@ -916,19 +916,19 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa { if(!PathingRouteUpdateTimerShort->Check()) { - Log(Logs::Detail, Logs::None, "Short route update timer not yet expired."); + Log(Logs::Detail, Logs::Pathing, "Short route update timer not yet expired."); return zone->pathing->GetPathNodeCoordinates(Route.front()); } - Log(Logs::Detail, Logs::None, "Short route update timer expired."); + Log(Logs::Detail, Logs::Pathing, "Short route update timer expired."); } else { if(!PathingRouteUpdateTimerLong->Check()) { - Log(Logs::Detail, Logs::None, "Long route update timer not yet expired."); + Log(Logs::Detail, Logs::Pathing, "Long route update timer not yet expired."); return zone->pathing->GetPathNodeCoordinates(Route.front()); } - Log(Logs::Detail, Logs::None, "Long route update timer expired."); + Log(Logs::Detail, Logs::Pathing, "Long route update timer expired."); } // We are already pathing, destination changed, no LOS. Find the nearest node to our destination. @@ -937,7 +937,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // Destination unreachable via pathing, return direct route. if(DestinationPathNode == -1) { - Log(Logs::Detail, Logs::None, " Unable to find path node for new destination. Running straight to target."); + Log(Logs::Detail, Logs::Pathing, " Unable to find path node for new destination. Running straight to target."); Route.clear(); return To; } @@ -945,7 +945,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // one, we will carry on on our path. if(DestinationPathNode == Route.back()) { - Log(Logs::Detail, Logs::None, " Same destination Node (%i). Continue with current path.", DestinationPathNode); + Log(Logs::Detail, Logs::Pathing, " Same destination Node (%i). Continue with current path.", DestinationPathNode); NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front()); @@ -953,7 +953,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // Check if we have reached a path node. if(NodeLoc == From) { - Log(Logs::Detail, Logs::None, " Arrived at node %i, moving to next one.\n", Route.front()); + Log(Logs::Detail, Logs::Pathing, " Arrived at node %i, moving to next one.\n", Route.front()); NodeReached = true; @@ -976,7 +976,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if(Route.empty()) { - Log(Logs::Detail, Logs::None, "Missing node after teleport."); + Log(Logs::Detail, Logs::Pathing, "Missing node after teleport."); return To; } @@ -986,7 +986,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa Teleport(NodeLoc); - Log(Logs::Detail, Logs::None, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z); + Log(Logs::Detail, Logs::Pathing, " TELEPORTED to %8.3f, %8.3f, %8.3f\n", NodeLoc.x, NodeLoc.y, NodeLoc.z); Route.pop_front(); @@ -996,7 +996,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa NextNode = Route.front(); } // Return the coords of our next path node on the route. - Log(Logs::Detail, Logs::None, " Now moving to node %i", NextNode); + Log(Logs::Detail, Logs::Pathing, " Now moving to node %i", NextNode); zone->pathing->OpenDoors(PathingLastNodeVisited, NextNode, this); @@ -1004,7 +1004,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa } else { - Log(Logs::Detail, Logs::None, " Reached end of path grid. Running direct to target."); + Log(Logs::Detail, Logs::Pathing, " Reached end of path grid. Running direct to target."); return To; } } @@ -1012,7 +1012,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa } else { - Log(Logs::Detail, Logs::None, " Target moved. End node is different. Clearing route."); + Log(Logs::Detail, Logs::Pathing, " Target moved. End node is different. Clearing route."); Route.clear(); // We will now fall through to get a new route. @@ -1022,11 +1022,11 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa } - Log(Logs::Detail, Logs::None, " Our route list is empty."); + Log(Logs::Detail, Logs::Pathing, " Our route list is empty."); if((SameDestination) && !PathingLOSCheckTimer->Check()) { - Log(Logs::Detail, Logs::None, " Destination same as before, LOS check timer not reached. Returning To."); + Log(Logs::Detail, Logs::Pathing, " Destination same as before, LOS check timer not reached. Returning To."); return To; } @@ -1040,22 +1040,22 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if ((Distance <= RuleR(Pathing, MinDistanceForLOSCheckLong)) && (std::abs(From.z - To.z) <= RuleR(Pathing, ZDiffThresholdNew))) { - Log(Logs::Detail, Logs::None, " Checking for long LOS at distance %8.3f.", Distance); + Log(Logs::Detail, Logs::Pathing, " Checking for long LOS at distance %8.3f.", Distance); if(!zone->zonemap->LineIntersectsZone(HeadPosition, To, 1.0f, nullptr)) PathingLOSState = HaveLOS; else PathingLOSState = NoLOS; - Log(Logs::Detail, Logs::None, "NoLOS"); + Log(Logs::Detail, Logs::Pathing, "NoLOS"); if((PathingLOSState == HaveLOS) && zone->pathing->NoHazards(From, To)) { - Log(Logs::Detail, Logs::None, "Target is reachable. Running directly there."); + Log(Logs::Detail, Logs::Pathing, "Target is reachable. Running directly there."); return To; } } - Log(Logs::Detail, Logs::None, " Calculating new route to target."); + Log(Logs::Detail, Logs::Pathing, " Calculating new route to target."); Route = zone->pathing->FindRoute(From, To); @@ -1063,14 +1063,14 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa if(Route.empty()) { - Log(Logs::Detail, Logs::None, " No route available, running direct."); + Log(Logs::Detail, Logs::Pathing, " No route available, running direct."); return To; } if(SameDestination && (Route.front() == PathingLastNodeVisited)) { - Log(Logs::Detail, Logs::None, " Probable loop detected. Same destination and Route.front() == PathingLastNodeVisited."); + Log(Logs::Detail, Logs::Pathing, " Probable loop detected. Same destination and Route.front() == PathingLastNodeVisited."); Route.clear(); @@ -1078,7 +1078,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa } NodeLoc = zone->pathing->GetPathNodeCoordinates(Route.front()); - Log(Logs::Detail, Logs::None, " New route determined, heading for node %i", Route.front()); + Log(Logs::Detail, Logs::Pathing, " New route determined, heading for node %i", Route.front()); PathingLoopCount = 0; @@ -1119,7 +1119,7 @@ int PathManager::FindNearestPathNode(glm::vec3 Position) for(auto Iterator = SortedByDistance.begin(); Iterator != SortedByDistance.end(); ++Iterator) { - Log(Logs::Detail, Logs::None, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id); + Log(Logs::Detail, Logs::Pathing, "Checking Reachability of Node %i from Start Position.", PathNodes[(*Iterator).id].id); if(!zone->zonemap->LineIntersectsZone(Position, PathNodes[(*Iterator).id].v, 1.0f, nullptr)) { @@ -1129,7 +1129,7 @@ int PathManager::FindNearestPathNode(glm::vec3 Position) } if(ClosestPathNodeToStart <0 ) { - Log(Logs::Detail, Logs::None, "No LOS to any starting Path Node within range."); + Log(Logs::Detail, Logs::Pathing, "No LOS to any starting Path Node within range."); return -1; } return ClosestPathNodeToStart; @@ -1144,14 +1144,14 @@ bool PathManager::NoHazards(glm::vec3 From, glm::vec3 To) float NewZ = zone->zonemap->FindBestZ(MidPoint, nullptr); if (std::abs(NewZ - From.z) > RuleR(Pathing, ZDiffThresholdNew)) { - Log(Logs::Detail, Logs::None, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f", + Log(Logs::Detail, Logs::Pathing, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f", From.x, From.y, From.z, MidPoint.x, MidPoint.y, MidPoint.z, NewZ - From.z); return false; } else { - Log(Logs::Detail, Logs::None, "No HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f", + Log(Logs::Detail, Logs::Pathing, "No HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Z Change is %8.3f", From.x, From.y, From.z, MidPoint.x, MidPoint.y, MidPoint.z, NewZ - From.z); } @@ -1182,7 +1182,7 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To) glm::vec3 TestPoint(curx, cury, curz); float NewZ = zone->zonemap->FindBestZ(TestPoint, nullptr); if (std::abs(NewZ - last_z) > 5.0f) { - Log(Logs::Detail, Logs::None, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Best Z %8.3f, Z Change is %8.3f", + Log(Logs::Detail, Logs::Pathing, " HAZARD DETECTED moving from %8.3f, %8.3f, %8.3f to %8.3f, %8.3f, %8.3f. Best Z %8.3f, Z Change is %8.3f", From.x, From.y, From.z, TestPoint.x, TestPoint.y, TestPoint.z, NewZ, NewZ - From.z); return false; } @@ -1210,20 +1210,20 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To) } if (best_z2 == -999990) { - Log(Logs::Detail, Logs::None, " HAZARD DETECTED, really deep water/lava!"); + Log(Logs::Detail, Logs::Pathing, " HAZARD DETECTED, really deep water/lava!"); return false; } else { if (std::abs(NewZ - best_z2) > RuleR(Pathing, ZDiffThresholdNew)) { - Log(Logs::Detail, Logs::None, + Log(Logs::Detail, Logs::Pathing, " HAZARD DETECTED, water is fairly deep at %8.3f units deep", std::abs(NewZ - best_z2)); return false; } else { - Log(Logs::Detail, Logs::None, + Log(Logs::Detail, Logs::Pathing, " HAZARD NOT DETECTED, water is shallow at %8.3f units deep", std::abs(NewZ - best_z2)); } @@ -1231,12 +1231,12 @@ bool PathManager::NoHazardsAccurate(glm::vec3 From, glm::vec3 To) } else { - Log(Logs::Detail, Logs::None, "Hazard point not in water or lava!"); + Log(Logs::Detail, Logs::Pathing, "Hazard point not in water or lava!"); } } else { - Log(Logs::Detail, Logs::None, "No water map loaded for hazards!"); + Log(Logs::Detail, Logs::Pathing, "No water map loaded for hazards!"); } curx += stepx; @@ -1291,7 +1291,7 @@ void PathManager::OpenDoors(int Node1, int Node2, Mob *ForWho) if(d && !d->IsDoorOpen() ) { - Log(Logs::Detail, Logs::None, "Opening door %i for %s", PathNodes[Node1].Neighbours[i].DoorID, ForWho->GetName()); + Log(Logs::Detail, Logs::Pathing, "Opening door %i for %s", PathNodes[Node1].Neighbours[i].DoorID, ForWho->GetName()); d->ForceOpen(ForWho); } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 15ab630ca..c56f0daaf 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -855,7 +855,7 @@ void Mob::FixZ() { Log( Logs::Moderate, - Logs::Pathing, + Logs::FixZ, "Mob::FixZ() (%s) returned %4.3f at %4.3f, %4.3f, %4.3f - Took %lf", this->GetCleanName(), new_z, @@ -875,7 +875,7 @@ void Mob::FixZ() { if (RuleB(Map, MobZVisualDebug)) this->SendAppearanceEffect(103, 0, 0, 0, 0); - Log(Logs::General, Logs::Debug, "%s is failing to find Z %f", this->GetCleanName(), std::abs(m_Position.z - new_z)); + Log(Logs::General, Logs::FixZ, "%s is failing to find Z %f", this->GetCleanName(), std::abs(m_Position.z - new_z)); } last_z = m_Position.z; From 20b6c2f556b4ff9c8c3b311f921ca7e989d1c6cd Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 18 Jul 2017 19:16:41 -0500 Subject: [PATCH 181/218] One more NodeLoc compare adjustment --- zone/pathing.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/pathing.cpp b/zone/pathing.cpp index 5fe4a7e57..0bc054d58 100644 --- a/zone/pathing.cpp +++ b/zone/pathing.cpp @@ -951,7 +951,7 @@ glm::vec3 Mob::UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &Wa // May need to refine this as rounding errors may mean we never have equality // Check if we have reached a path node. - if(NodeLoc == From) + if(NodeLoc.x == From.x && NodeLoc.y == From.y) { Log(Logs::Detail, Logs::Pathing, " Arrived at node %i, moving to next one.\n", Route.front()); From ec77e3a6fd2e2529a7e8e2b329a0c5d08faec9bf Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 19 Jul 2017 02:17:08 -0400 Subject: [PATCH 182/218] Add show_name and untargetable to npc_types fixes #637 Note the bodytype hack is still there since I was having issues with some npcs still showing names --- common/eq_packet_structs.h | 1 + common/patches/rof.cpp | 2 +- common/patches/rof2.cpp | 2 +- common/patches/sod.cpp | 2 +- common/patches/sof.cpp | 10 +++++----- common/patches/uf.cpp | 2 +- utils/sql/git/required/2017_07_19_show_name.sql | 3 +++ zone/client.cpp | 1 + zone/entity.cpp | 4 ++++ zone/npc.cpp | 2 ++ zone/zonedb.cpp | 6 +++++- zone/zonedump.h | 2 ++ 12 files changed, 27 insertions(+), 10 deletions(-) create mode 100644 utils/sql/git/required/2017_07_19_show_name.sql diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index c234e303a..6e853b4bd 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -305,6 +305,7 @@ union uint8 DestructibleUnk8; uint32 DestructibleUnk9; bool targetable_with_hotkey; + bool show_name; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 23e521a57..7ce6f900f 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3930,7 +3930,7 @@ namespace RoF if (strlen(emu->suffix)) PacketSize += strlen(emu->suffix) + 1; - bool ShowName = 1; + bool ShowName = emu->show_name; if (emu->bodytype >= 66) { emu->race = 127; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 5befaf08c..30efa95b9 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4086,7 +4086,7 @@ namespace RoF2 PacketSize += strlen(emu->DestructibleString) + 1; } - bool ShowName = 1; + bool ShowName = emu->show_name; if (emu->bodytype >= 66) { emu->race = 127; diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index f6d85f2bb..276f939e5 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2560,7 +2560,7 @@ namespace SoD PacketSize += strlen(emu->DestructibleString) + 1; } - bool ShowName = 1; + bool ShowName = emu->show_name; if (emu->bodytype >= 66) { emu->race = 127; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 44f093044..77d65ce16 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -2097,7 +2097,7 @@ namespace SoF int k; for (r = 0; r < entrycount; r++, eq++, emu++) { - eq->showname = 1; //New Field - Toggles Name Display on or off - 0 = off, 1 = on + eq->showname = emu->show_name ? 1 : 0; //New Field - Toggles Name Display on or off - 0 = off, 1 = on eq->linkdead = 0; //New Field - Toggles LD on or off after name - 0 = off, 1 = on eq->statue = 0; //New Field - 1 freezes animation eq->showhelm = emu->showhelm; @@ -2136,10 +2136,10 @@ namespace SoF eq->findable = emu->findable; if (emu->bodytype >= 66) { - eq->bodytype = 11; //non-targetable - eq->showname = 0; //no visible name - eq->race = 127; //invisible man - eq->gender = 0; //invisible men are gender 0 + eq->bodytype = 11; //non-targetable + eq->showname = 0; //no visible name + eq->race = 127; //invisible man + eq->gender = 0; //invisible men are gender 0 } else { diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index b6d251953..8b0c86cc5 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2844,7 +2844,7 @@ namespace UF PacketSize += strlen(emu->DestructibleString) + 1; } - bool ShowName = 1; + bool ShowName = emu->show_name; if (emu->bodytype >= 66) { emu->race = 127; diff --git a/utils/sql/git/required/2017_07_19_show_name.sql b/utils/sql/git/required/2017_07_19_show_name.sql new file mode 100644 index 000000000..e5bda11cf --- /dev/null +++ b/utils/sql/git/required/2017_07_19_show_name.sql @@ -0,0 +1,3 @@ +ALTER TABLE `npc_types` ADD COLUMN `show_name` TINYINT(2) NOT NULL DEFAULT 1; +ALTER TABLE `npc_types` ADD COLUMN `untargetable` TINYINT(2) NOT NULL DEFAULT 0; +UPDATE `npc_types` SET `show_name` = 0, `untargetable` = 1 WHERE `bodytype` >= 66; diff --git a/zone/client.cpp b/zone/client.cpp index 12988450b..4866013a3 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1944,6 +1944,7 @@ void Client::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.guildID = GuildID(); // ns->spawn.linkdead = IsLD() ? 1 : 0; // ns->spawn.pvp = GetPVP() ? 1 : 0; + ns->spawn.show_name = true; strcpy(ns->spawn.title, m_pp.title); diff --git a/zone/entity.cpp b/zone/entity.cpp index 52eb41165..e9d8139a7 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -659,6 +659,8 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) QueueClients(npc, app); npc->SendArmorAppearance(); npc->SetAppearance(npc->GetGuardPointAnim(),false); + if (!npc->IsTargetable()) + npc->SendTargetable(false); safe_delete(app); } else { auto ns = new NewSpawn_Struct; @@ -799,6 +801,8 @@ void EntityList::CheckSpawnQueue() NPC *pnpc = it->second; pnpc->SendArmorAppearance(); pnpc->SetAppearance(pnpc->GetGuardPointAnim(), false); + if (!pnpc->IsTargetable()) + pnpc->SendTargetable(false); } safe_delete(outapp); iterator.RemoveCurrent(); diff --git a/zone/npc.cpp b/zone/npc.cpp index 8ddd9b2e3..a4e6c4214 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -375,6 +375,7 @@ NPC::NPC(const NPCType* d, Spawn2* in_respawn, const glm::vec4& position, int if CalcBonuses(); raid_target = d->raid_target; ignore_despawn = d->ignore_despawn; + m_targetable = !d->untargetable; } NPC::~NPC() @@ -1906,6 +1907,7 @@ void NPC::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) ns->spawn.is_npc = 1; UpdateActiveLight(); ns->spawn.light = GetActiveLightType(); + ns->spawn.show_name = NPCTypedata->show_name; } void NPC::PetOnSpawn(NewSpawn_Struct* ns) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index d647dcbf7..c90b30ce7 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1967,7 +1967,9 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load "npc_types.handtexture, " "npc_types.legtexture, " "npc_types.feettexture, " - "npc_types.ignore_despawn " + "npc_types.ignore_despawn, " + "npc_types.show_name, " + "npc_types.untargetable " "FROM npc_types %s", where_condition.c_str() ); @@ -2143,6 +2145,8 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->legtexture = atoi(row[95]); temp_npctype_data->feettexture = atoi(row[96]); temp_npctype_data->ignore_despawn = atoi(row[97]) == 1 ? true : false; + temp_npctype_data->show_name = atoi(row[98]) != 0 ? true : false; + temp_npctype_data->untargetable = atoi(row[99]) != 0 ? true : false; // If NPC with duplicate NPC id already in table, // free item we attempted to add. diff --git a/zone/zonedump.h b/zone/zonedump.h index 713bfca7e..2bd78c2d8 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -133,6 +133,8 @@ struct NPCType uint8 legtexture; uint8 feettexture; bool ignore_despawn; + bool show_name; // should default on + bool untargetable; }; namespace player_lootitem { From 12bed1462ff403e019b6564532a3d5eb02f25ad2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 19 Jul 2017 12:59:02 -0400 Subject: [PATCH 183/218] Forgot to update manifest last night --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/common/version.h b/common/version.h index 2391862a1..a1cfbce16 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9112 +#define CURRENT_BINARY_DATABASE_VERSION 9113 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 5586b9848..8070c328e 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -366,6 +366,7 @@ 9110|2017_04_10_graveyard.sql|show index from graveyard WHERE key_name = 'zone_id_nonunique'|empty| 9111|2017_06_24_saylink_index.sql|SHOW INDEX FROM `saylink` WHERE `key_name` = 'phrase_index'|empty| 9112|2017_06_24_rule_values_expand.sql|SHOW COLUMNS FROM rule_values WHERE Field = 'rule_value' and Type = 'varchar(30)'|empty| +9113|2017_07_19_show_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'show_name'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From f97693f8e1b817fcf700b442103d5a8a6f22cfd6 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 19 Jul 2017 14:52:04 -0400 Subject: [PATCH 184/218] Work on spawn filtering --- zone/client.h | 1 + zone/entity.cpp | 18 +++++++----------- zone/mob.h | 1 + 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/zone/client.h b/zone/client.h index 640d9dc98..952c98333 100644 --- a/zone/client.h +++ b/zone/client.h @@ -299,6 +299,7 @@ public: const char* GetBuyerWelcomeMessage() { return BuyerWelcomeMessage.c_str(); } void FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho); + bool ShouldISpawnFor(Client *c) { return !GMHideMe(c) && !IsHoveringForRespawn(); } virtual bool Process(); void LogMerchant(Client* player, Mob* merchant, uint32 quantity, uint32 price, const EQEmu::ItemData* item, bool buying); void SendPacketQueue(bool Block = true); diff --git a/zone/entity.cpp b/zone/entity.cpp index e9d8139a7..344e79a04 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -1246,12 +1246,9 @@ void EntityList::SendZoneSpawns(Client *client) auto it = mob_list.begin(); while (it != mob_list.end()) { Mob *ent = it->second; - if (!(ent->InZone()) || (ent->IsClient())) { - if (ent->CastToClient()->GMHideMe(client) || - ent->CastToClient()->IsHoveringForRespawn()) { - ++it; - continue; - } + if (!ent->InZone() || !ent->ShouldISpawnFor(client)) { + ++it; + continue; } app = new EQApplicationPacket; @@ -1279,17 +1276,16 @@ void EntityList::SendZoneSpawnsBulk(Client *client) for (auto it = mob_list.begin(); it != mob_list.end(); ++it) { spawn = it->second; if (spawn && spawn->GetID() > 0 && spawn->Spawned()) { - if (spawn->IsClient() && (spawn->CastToClient()->GMHideMe(client) || - spawn->CastToClient()->IsHoveringForRespawn())) + if (!spawn->ShouldISpawnFor(client)) continue; #if 1 const glm::vec4& spos = spawn->GetPosition(); - + delaypkt = false; if (DistanceSquared(cpos, spos) > dmax || (spawn->IsClient() && (spawn->GetRace() == MINOR_ILL_OBJ || spawn->GetRace() == TREE))) delaypkt = true; - + if (delaypkt) { app = new EQApplicationPacket; spawn->CreateSpawnPacket(app); @@ -2659,7 +2655,7 @@ void EntityList::SendPositionUpdates(Client *client, uint32 cLastUpdate, float u mob && !mob->IsCorpse() && (it->second != client) && (mob->IsClient() || iSendEvenIfNotChanged || (mob->LastChange() >= cLastUpdate)) - && (!it->second->IsClient() || !it->second->CastToClient()->GMHideMe(client)) + && (it->second->ShouldISpawnFor(client)) ) { if ( update_range == 0 diff --git a/zone/mob.h b/zone/mob.h index 4fcc81b5a..0b683ede0 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -549,6 +549,7 @@ public: void SendPosition(); void SetSpawned() { spawned = true; }; bool Spawned() { return spawned; }; + virtual bool ShouldISpawnFor(Client *c) { return true; } void SetFlyMode(uint8 flymode); inline void Teleport(glm::vec3 NewPosition) { m_Position.x = NewPosition.x; m_Position.y = NewPosition.y; m_Position.z = NewPosition.z; }; From 7d5089f5e8257bab31d51f5b1738689e538452df Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 20 Jul 2017 13:24:55 -0400 Subject: [PATCH 185/218] Call RemoveAura now instead of Depop when we need to --- zone/aura.cpp | 23 ++++++++++++----------- zone/aura.h | 2 +- zone/mob.h | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 0bbe86b8d..62441415e 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -116,7 +116,7 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) if (owner->IsRaidGrouped() && owner->IsClient()) { // currently raids are just client, but safety check auto raid = owner->GetRaid(); if (raid == nullptr) { // well shit - Depop(); + owner->RemoveAura(GetID(), false, true); return; } auto group_id = raid->GetGroup(owner->CastToClient()); @@ -200,7 +200,7 @@ void Aura::ProcessOnAllGroupMembers(Mob *owner) } else if (owner->IsGrouped()) { auto group = owner->GetGroup(); if (group == nullptr) { // uh oh - Depop(); + owner->RemoveAura(GetID(), false, true); return; } @@ -310,7 +310,7 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) if (group_member->IsRaidGrouped() && group_member->IsClient()) { // currently raids are just client, but safety check auto raid = group_member->GetRaid(); if (raid == nullptr) { // well shit - Depop(); + owner->RemoveAura(GetID(), false, true); return; } auto group_id = raid->GetGroup(group_member->CastToClient()); @@ -377,7 +377,7 @@ void Aura::ProcessOnGroupMembersPets(Mob *owner) } else if (group_member->IsGrouped()) { auto group = group_member->GetGroup(); if (group == nullptr) { // uh oh - Depop(); + owner->RemoveAura(GetID(), false, true); return; } @@ -527,7 +527,7 @@ void Aura::ProcessEnterTrap(Mob *owner) // might need more checks ... if (owner->IsAttackAllowed(mob) && DistanceSquared(GetPosition(), mob->GetPosition()) <= distance) { SpellFinished(spell_id, mob); - Depop(); // if we're a buff (ex. NEC) we don't want to strip :P + owner->RemoveAura(GetID(), false); // if we're a buff (ex. NEC) we don't want to strip :P break; } } @@ -551,7 +551,7 @@ bool Aura::Process() } if (remove_timer.Check()) { - Depop(); + owner->RemoveAura(GetID(), false, true); return true; } @@ -571,9 +571,10 @@ bool Aura::Process() return true; } -void Aura::Depop(bool unused) +void Aura::Depop(bool skip_strip) { - if (IsBuffSpell(spell_id)) { + // NEC trap casts a dot, so we need some way to not strip :P + if (!skip_strip && IsBuffSpell(spell_id)) { for (auto &e : casted_on) { auto mob = entity_list.GetMob(e); if (mob != nullptr) @@ -763,13 +764,13 @@ void Mob::RemoveAllAuras() return; } -void Mob::RemoveAura(int spawn_id, bool expired) +void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired) { for (int i = 0; i < aura_mgr.count; ++i) { auto &aura = aura_mgr.auras[i]; if (aura.spawn_id == spawn_id) { if (aura.aura) - aura.aura->Depop(); + aura.aura->Depop(skip_strip); if (expired && IsClient()) CastToClient()->SendColoredText( CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color @@ -790,7 +791,7 @@ void Mob::RemoveAura(int spawn_id, bool expired) auto &aura = trap_mgr.auras[i]; if (aura.spawn_id == spawn_id) { if (aura.aura) - aura.aura->Depop(); + aura.aura->Depop(skip_strip); if (expired && IsClient()) CastToClient()->SendColoredText( CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color diff --git a/zone/aura.h b/zone/aura.h index 7980f0b0a..da5f610c9 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -47,7 +47,7 @@ public: bool IsAura() const { return true; } bool Process(); - void Depop(bool unused = false); + void Depop(bool skip_strip = false); Mob *GetOwner(); void ProcessOnAllFriendlies(Mob *owner); diff --git a/zone/mob.h b/zone/mob.h index 0b683ede0..c32887ff5 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -635,7 +635,7 @@ public: void AddAura(Aura *aura, AuraRecord &record); void AddTrap(Aura *aura, AuraRecord &record); bool CanSpawnAura(bool trap); - void RemoveAura(int spawn_id, bool expired = false); + void RemoveAura(int spawn_id, bool skip_strip = false, bool expired = false); void RemoveAllAuras(); inline AuraMgr &GetAuraMgr() { return aura_mgr; } // mainly used for zone db loading/saving From 89bbf05b63db232c61e99ff849356f2004a770a8 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 20 Jul 2017 14:24:35 -0400 Subject: [PATCH 186/218] Add OP_RemoveTrap support --- zone/client_packet.cpp | 19 ++++++++++++++++--- zone/client_packet.h | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 3a52fc19e..af6ac0649 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -323,6 +323,7 @@ void MapOpcodes() ConnectedOpcodes[OP_RecipesSearch] = &Client::Handle_OP_RecipesSearch; ConnectedOpcodes[OP_ReloadUI] = &Client::Handle_OP_ReloadUI; ConnectedOpcodes[OP_RemoveBlockedBuffs] = &Client::Handle_OP_RemoveBlockedBuffs; + ConnectedOpcodes[OP_RemoveTrap] = &Client::Handle_OP_RemoveTrap; ConnectedOpcodes[OP_Report] = &Client::Handle_OP_Report; ConnectedOpcodes[OP_RequestDuel] = &Client::Handle_OP_RequestDuel; ConnectedOpcodes[OP_RequestTitles] = &Client::Handle_OP_RequestTitles; @@ -11795,6 +11796,18 @@ void Client::Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app) } } +void Client::Handle_OP_RemoveTrap(const EQApplicationPacket *app) +{ + if (app->size != 4) {// just an int + Log(Logs::General, Logs::None, "Size mismatch in OP_RemoveTrap expected 4 got %i", app->size); + DumpPacket(app); + return; + } + + auto id = app->ReadUInt32(0); + RemoveAura(id); +} + void Client::Handle_OP_Report(const EQApplicationPacket *app) { if (!CanUseReport) @@ -14315,13 +14328,13 @@ void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app) void Client::Handle_OP_UpdateAura(const EQApplicationPacket *app) { - if (app->size < 4) { + if (app->size != 4) { Log(Logs::General, Logs::None, "Size mismatch in OP_UpdateAura"); return; } - auto action = *(uint32_t *)app->pBuffer; // action tells us the size + auto action = app->ReadUInt32(0); // action tells us the size switch (action) { - case 2: + case 2: // client doesn't send this, but this is what it does RemoveAllAuras(); break; case 1: { diff --git a/zone/client_packet.h b/zone/client_packet.h index e84f89aaa..c63a57825 100644 --- a/zone/client_packet.h +++ b/zone/client_packet.h @@ -236,6 +236,7 @@ void Handle_OP_RecipesSearch(const EQApplicationPacket *app); void Handle_OP_ReloadUI(const EQApplicationPacket *app); void Handle_OP_RemoveBlockedBuffs(const EQApplicationPacket *app); + void Handle_OP_RemoveTrap(const EQApplicationPacket *app); void Handle_OP_Report(const EQApplicationPacket *app); void Handle_OP_RequestDuel(const EQApplicationPacket *app); void Handle_OP_RequestTitles(const EQApplicationPacket *app); From ef742055033a1942724733559a36886c243a2c3e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 20 Jul 2017 14:38:56 -0400 Subject: [PATCH 187/218] Add OPs for the rest of the clients with support --- utils/patches/patch_RoF.conf | 4 ++++ utils/patches/patch_SoD.conf | 4 ++++ utils/patches/patch_SoF.conf | 4 ++++ utils/patches/patch_UF.conf | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/utils/patches/patch_RoF.conf b/utils/patches/patch_RoF.conf index a746804d9..339bfd800 100644 --- a/utils/patches/patch_RoF.conf +++ b/utils/patches/patch_RoF.conf @@ -672,3 +672,7 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs OP_InitialHPUpdate=0x0000 OP_ItemRecastDelay=0x57ed + +#aura related +OP_UpdateAura=0x1fa9 +OP_RemoveTrap=0x6a4d diff --git a/utils/patches/patch_SoD.conf b/utils/patches/patch_SoD.conf index 08e072d33..ed7a19715 100644 --- a/utils/patches/patch_SoD.conf +++ b/utils/patches/patch_SoD.conf @@ -669,3 +669,7 @@ OP_Some3ByteHPUpdate=0x0000 # initial HP update for mobs OP_InitialHPUpdate=0x0000 # OP_ItemRecastDelay=0x15c4 + +#aura related +OP_UpdateAura=0x169a +OP_RemoveTrap=0x4bb6 diff --git a/utils/patches/patch_SoF.conf b/utils/patches/patch_SoF.conf index d758daea9..7ed41ff4a 100644 --- a/utils/patches/patch_SoF.conf +++ b/utils/patches/patch_SoF.conf @@ -658,3 +658,7 @@ OP_ItemRecastDelay=0x0ada #OP_NpcMoveUpdate=0x0d11 #SEQ 10/07/08 --NEW FROM SEQ #OP_Zone_MissingName01=0x0000 # #new titles avaliable: # + +#aura related +OP_UpdateAura=0x62a9 +OP_RemoveTrap=0x7bd9 diff --git a/utils/patches/patch_UF.conf b/utils/patches/patch_UF.conf index 2002a85f9..af698d52a 100644 --- a/utils/patches/patch_UF.conf +++ b/utils/patches/patch_UF.conf @@ -685,3 +685,7 @@ OP_ItemRecastDelay=0x82d7 # unhandled OP_ShieldGroup=0x23a1 + +#aura related +OP_UpdateAura=0x2480 +OP_RemoveTrap=0x0115 From 57d260f30ad8f8f294f669fce192e67e43d5b093 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Thu, 20 Jul 2017 15:18:27 -0400 Subject: [PATCH 188/218] Add show_name to auras SQL --- utils/sql/git/optional/auras.sql | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql index 7ca6ecc97..dc83ff93b 100644 --- a/utils/sql/git/optional/auras.sql +++ b/utils/sql/git/optional/auras.sql @@ -1,97 +1,97 @@ SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0"; -- admin (15-Jul-17 1:42:03) +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) From d8bbd85abb2f976adc8f9eaa5809a33e0883bfe1 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 21 Jul 2017 00:46:12 -0500 Subject: [PATCH 189/218] Fix issue with clients logging in locally on the same subnet --- world/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/world/client.cpp b/world/client.cpp index 4fd157088..aaf7d4c9c 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1281,6 +1281,10 @@ void Client::Clearance(int8 response) } else { zs_addr = zs->GetIP().c_str(); + if (!zs_addr[0]) { + zs_addr = WorldConfig::get()->LocalAddress.c_str(); + } + if(strcmp(zs_addr, "127.0.0.1") == 0) { Log(Logs::Detail, Logs::World_Server, "Local zone address was %s, setting local address to: %s", zs_addr, WorldConfig::get()->LocalAddress.c_str()); From aa8a2ea41bde4d49d483efbf16b2ba33eefee878 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Fri, 21 Jul 2017 14:56:51 -0400 Subject: [PATCH 190/218] Repair fear pathing to ignore Z aspects and allow FixZ and pathing to handle it. Added the true flag for ResistCheck.Charisma so the proper Charisma bonuses are applied. --- zone/fearpath.cpp | 30 +++++++----------------------- zone/spell_effects.cpp | 2 +- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index ea5bb16d9..e0217bd5e 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -152,28 +152,12 @@ void Mob::CalculateNewFearpoint() Log(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection."); } - int loop = 0; - float ranx, rany, ranz; - currently_fleeing = false; - while (loop < 100) //Max 100 tries - { - int ran = 250 - (loop*2); - loop++; - ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - ranz = FindGroundZ(ranx,rany); - if (ranz == -999999) - continue; - float fdist = ranz - GetZ(); - if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz)) - { - currently_fleeing = true; - break; - } - } - if (currently_fleeing) - m_FearWalkTarget = glm::vec3(ranx, rany, ranz); - else //Break fear - BuffFadeByEffect(SE_Fear); + int ran = 250; + float ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); + float rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); + + m_FearWalkTarget = glm::vec3(ranx, rany, GetZ()); + + currently_fleeing = true; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 42b50edf3..2f0d65907 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -3640,7 +3640,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_Fear: { if (zone->random.Roll(RuleI(Spells, FearBreakCheckChance))) { - float resist_check = ResistSpell(spells[buff.spellid].resisttype, buff.spellid, caster); + float resist_check = ResistSpell(spells[buff.spellid].resisttype, buff.spellid, caster,0,0,true); if (resist_check == 100) break; From ceb0fe22f1f9528f3b42bd01bb60a112b836af59 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Fri, 21 Jul 2017 16:25:13 -0400 Subject: [PATCH 191/218] Fix OP_UpdateAura handling --- zone/client_packet.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index af6ac0649..8a2c266f1 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -14328,24 +14328,18 @@ void Client::Handle_OP_VoiceMacroIn(const EQApplicationPacket *app) void Client::Handle_OP_UpdateAura(const EQApplicationPacket *app) { - if (app->size != 4) { - Log(Logs::General, Logs::None, "Size mismatch in OP_UpdateAura"); + if (app->size != sizeof(AuraDestory_Struct)) { + Log(Logs::General, Logs::None, "Size mismatch in OP_UpdateAura expected %i got %i", + sizeof(AuraDestory_Struct), app->size); return; } - auto action = app->ReadUInt32(0); // action tells us the size - switch (action) { - case 2: // client doesn't send this, but this is what it does - RemoveAllAuras(); - break; - case 1: { - auto ads = (AuraDestory_Struct *)app->pBuffer; - RemoveAura(ads->entity_id); - break; - } - case 0: // client doesn't send this - break; - } + // client only sends this for removing + auto aura = (AuraDestory_Struct *)app->pBuffer; + if (aura->action != 1) + return; // could log I guess, but should only ever get this action + + RemoveAura(aura->entity_id); return; } From a36b37b1ea1724d43aa777e8f13e6cca9d353c5c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Fri, 21 Jul 2017 16:53:27 -0500 Subject: [PATCH 192/218] Adjust syntax --- zone/fearpath.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index e0217bd5e..6632cc6fa 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -153,11 +153,11 @@ void Mob::CalculateNewFearpoint() } int ran = 250; - float ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - float rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - - m_FearWalkTarget = glm::vec3(ranx, rany, GetZ()); - - currently_fleeing = true; + float ranx = GetX() + zone->random.Int(0, ran - 1) - zone->random.Int(0, ran - 1); + float rany = GetY() + zone->random.Int(0, ran - 1)-zone->random.Int(0, ran - 1); + + m_FearWalkTarget = glm::vec3(ranx, rany, GetZ()); + + currently_fleeing = true; } From e84799e15b9948873ffcab26f335ed9c353e8187 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 22 Jul 2017 12:45:21 -0400 Subject: [PATCH 193/218] Went back to older fearpath, only kept change where pathing issues can't cause the fear spell to be dropped. --- zone/fearpath.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index e0217bd5e..4d39717b5 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -152,12 +152,26 @@ void Mob::CalculateNewFearpoint() Log(Logs::Detail, Logs::None, "No path found to selected node. Falling through to old fear point selection."); } - int ran = 250; - float ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - float rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); - - m_FearWalkTarget = glm::vec3(ranx, rany, GetZ()); - - currently_fleeing = true; + int loop = 0; + float ranx, rany, ranz; + currently_fleeing = false; + while (loop < 100) //Max 100 tries + { + int ran = 250 - (loop*2); + loop++; + ranx = GetX()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); + rany = GetY()+zone->random.Int(0, ran-1)-zone->random.Int(0, ran-1); + ranz = FindGroundZ(ranx,rany); + if (ranz == -999999) + continue; + float fdist = ranz - GetZ(); + if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz)) + { + currently_fleeing = true; + break; + } + } + if (currently_fleeing) + m_FearWalkTarget = glm::vec3(ranx, rany, ranz); } From 49d0c308e88db272fc31ca9e80ce420c5378faf5 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 15:46:16 -0400 Subject: [PATCH 194/218] Limit aura spawns This is probably not the best performance, but it's the only solution that is easy to implement. --- zone/aura.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- zone/aura.h | 7 +++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 62441415e..0812a8109 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -538,6 +538,32 @@ void Aura::ProcessExitTrap(Mob *owner) Shout("Stub 6"); } +// this is less than ideal, but other solutions are a bit all over the place +// and hard to reason about +void Aura::ProcessSpawns() +{ + const auto &clients = entity_list.GetClientList(); + for (auto &e : clients) { + auto c = e.second; + bool spawned = spawned_for.find(c->GetID()) != spawned_for.end(); + if (ShouldISpawnFor(c)) { + if (!spawned) { + EQApplicationPacket app; + CreateSpawnPacket(&app, this); + c->QueuePacket(&app); + SendArmorAppearance(c); + spawned_for.insert(c->GetID()); + } + } else if (spawned) { + EQApplicationPacket app; + CreateDespawnPacket(&app, false); + c->QueuePacket(&app); + spawned_for.erase(c->GetID()); + } + } + return; +} + bool Aura::Process() { // Aura::Depop clears buffs @@ -564,6 +590,8 @@ bool Aura::Process() if (!process_timer.Check()) return true; + ProcessSpawns(); // bit of a hack + if (process_func) process_func(*this, owner); @@ -571,6 +599,60 @@ bool Aura::Process() return true; } +bool Aura::ShouldISpawnFor(Client *c) +{ + if (spawn_type == AuraSpawns::Noone) + return false; + + if (spawn_type == AuraSpawns::Everyone) + return true; + + // hey, it's our owner! + if (c->GetID() == m_owner) + return true; + + // so this one is a bit trickier + auto owner = GetOwner(); + if (owner == nullptr) + return false; // hmm + + owner = owner->GetOwnerOrSelf(); // pet auras we need the pet's owner + if (owner == nullptr) // shouldn't really be needed + return false; + + // gotta check again for pet aura case -.- + if (owner == c) + return true; + + if (owner->IsRaidGrouped() && owner->IsClient()) { + auto raid = owner->GetRaid(); + if (raid == nullptr) + return false; // hmm + auto group_id = raid->GetGroup(owner->CastToClient()); + if (group_id == 0xFFFFFFFF) // owner handled above, and they're in a raid and groupless + return false; + + auto idx = raid->GetPlayerIndex(c); + if (idx == 0xFFFFFFFF) // they're not in our raid! + return false; + + if (raid->members[idx].GroupNumber != group_id) // in our raid, but not our group + return false; + + return true; // we got here so we know that 1 they're in our raid and 2 they're in our group! + } else if (owner->IsGrouped()) { + auto group = owner->GetGroup(); + if (group == nullptr) + return false; // hmm + + // easy, in our group + return group->IsGroupMember(c); + } + + // our owner is not raided or grouped, and they're handled above so we don't spawn! + return false; +} + void Aura::Depop(bool skip_strip) { // NEC trap casts a dot, so we need some way to not strip :P @@ -642,7 +724,7 @@ void Mob::MakeAura(uint16 spell_id) auto npc = new Aura(npc_type, this, record); npc->SetAuraID(spell_id); - entity_list.AddNPC(npc, true, true); + entity_list.AddNPC(npc, false); if (trap) AddTrap(npc, record); diff --git a/zone/aura.h b/zone/aura.h index da5f610c9..7156f7531 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -56,12 +56,18 @@ public: void ProcessTotem(Mob *owner); void ProcessEnterTrap(Mob *owner); void ProcessExitTrap(Mob *owner); + void ProcessSpawns(); // we only save auras that follow you, and player casted inline bool AuraZones() { return movement_type == AuraMovement::Follow && aura_id > -1; } inline int GetSpellID() { return spell_id; } inline int GetAuraID() { return aura_id; } inline void SetAuraID(int in) { aura_id = in; } + + bool ShouldISpawnFor(Client *c); + // so when we join a group, we need to spawn not already spawned auras + // This is only possible when spawn type is GroupMembers + inline bool JoinGroupSpawnCheck() { return spawn_type == AuraSpawns::GroupMembers; } private: int m_owner; int aura_id; // spell ID of the aura spell -1 if aura isn't from a casted spell @@ -77,6 +83,7 @@ private: std::function process_func; std::set casted_on; // we keep track of the other entities we've casted on + std::set spawned_for; }; #endif /* !AURA_H */ From a1ff12d9abdc6f358c4d35122d1680968c82b5f8 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 22 Jul 2017 14:18:30 -0700 Subject: [PATCH 195/218] Fix for unreliable packets not being processed or sent correctly --- common/net/daybreak_connection.cpp | 43 +++++++++++++++--------------- common/net/eqstream.cpp | 7 ++++- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/common/net/daybreak_connection.cpp b/common/net/daybreak_connection.cpp index 283f8f93d..095fab525 100644 --- a/common/net/daybreak_connection.cpp +++ b/common/net/daybreak_connection.cpp @@ -382,13 +382,8 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) return; } - if (p.GetInt8(0) != 0) { - LogF(Logs::Detail, Logs::Netcode, "Error parsing packet, did not start with a 0 frame, not a valid protocol packet."); - return; - } - auto opcode = p.GetInt8(1); - if (opcode == OP_KeepAlive || opcode == OP_OutboundPing) { + if (p.GetInt8(0) == 0 && (opcode == OP_KeepAlive || opcode == OP_OutboundPing)) { return; } @@ -407,10 +402,16 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { case EncodeCompression: - Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + if(temp.GetInt8(0) == 0) + Decompress(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + else + Decompress(temp, 1, temp.Length() - 1); break; case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + if (temp.GetInt8(0) == 0) + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + else + Decode(temp, 1, temp.Length() - 1); break; default: break; @@ -425,7 +426,10 @@ void EQ::Net::DaybreakConnection::ProcessPacket(Packet &p) for (int i = 1; i >= 0; --i) { switch (m_encode_passes[i]) { case EncodeXOR: - Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + if (temp.GetInt8(0) == 0) + Decode(temp, DaybreakHeader::size(), temp.Length() - DaybreakHeader::size()); + else + Decode(temp, 1, temp.Length() - 1); break; default: break; @@ -1187,24 +1191,21 @@ void EQ::Net::DaybreakConnection::InternalSend(Packet &p) if (PacketCanBeEncoded(p)) { DynamicPacket out; - - if (p.GetUInt8(0) != 0) { - out.PutUInt8(0, 0); - out.PutUInt8(1, OP_Combined); - out.PutUInt8(2, p.Length()); - out.PutPacket(3, p); - } - else { - out.PutPacket(0, p); - } + out.PutPacket(0, p); for (int i = 0; i < 2; ++i) { switch (m_encode_passes[i]) { case EncodeCompression: - Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + if(out.GetInt8(0) == 0) + Compress(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + else + Compress(out, 1, out.Length() - 1); break; case EncodeXOR: - Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + if (out.GetInt8(0) == 0) + Encode(out, DaybreakHeader::size(), out.Length() - DaybreakHeader::size()); + else + Encode(out, 1, out.Length() - 1); break; default: break; diff --git a/common/net/eqstream.cpp b/common/net/eqstream.cpp index 26fdf1d8e..ffa441939 100644 --- a/common/net/eqstream.cpp +++ b/common/net/eqstream.cpp @@ -81,7 +81,12 @@ void EQ::Net::EQStream::QueuePacket(const EQApplicationPacket *p, bool ack_req) break; } - m_connection->QueuePacket(out); + if (ack_req) { + m_connection->QueuePacket(out); + } + else { + m_connection->QueuePacket(out, 0, false); + } } } From 51c9cec35a07815c889085bbb1659322e55d60e1 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 17:35:42 -0400 Subject: [PATCH 196/218] Limit position updates to those that care --- zone/aura.cpp | 17 +++++++++++++++-- zone/aura.h | 1 + 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 0812a8109..4df64b154 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -583,14 +583,27 @@ bool Aura::Process() if (movement_type == AuraMovement::Follow && GetPosition() != owner->GetPosition() && movement_timer.Check()) { m_Position = owner->GetPosition(); - SendPositionUpdate(); + auto app = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct)); + auto spu = (PlayerPositionUpdateServer_Struct*)app->pBuffer; + MakeSpawnUpdate(spu); + auto it = spawned_for.begin(); + while (it != spawned_for.end()) { + auto client = entity_list.GetClientByID(*it); + if (client) { + client->QueuePacket(app); + ++it; + } else { + it = spawned_for.erase(it); + } + } } // TODO: waypoints? if (!process_timer.Check()) return true; - ProcessSpawns(); // bit of a hack + if (spawn_type != AuraSpawns::Noone) + ProcessSpawns(); // bit of a hack if (process_func) process_func(*this, owner); diff --git a/zone/aura.h b/zone/aura.h index 7156f7531..ff4f2d51c 100644 --- a/zone/aura.h +++ b/zone/aura.h @@ -41,6 +41,7 @@ enum class AuraMovement { class Aura : public NPC { + // NOTE: We may have to override more virtual functions if they're causing issues public: Aura(NPCType *type_data, Mob *owner, AuraRecord &record); ~Aura() { }; From 03399fe3fdff629502a7f45c0df031dd6aea4f7e Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Sat, 22 Jul 2017 17:57:23 -0400 Subject: [PATCH 197/218] Repair so that mobs that are fleeing or feared use FixZ. --- zone/fearpath.cpp | 11 +++++++---- zone/waypoints.cpp | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/zone/fearpath.cpp b/zone/fearpath.cpp index 4d39717b5..c2ce95fbe 100644 --- a/zone/fearpath.cpp +++ b/zone/fearpath.cpp @@ -154,7 +154,8 @@ void Mob::CalculateNewFearpoint() int loop = 0; float ranx, rany, ranz; - currently_fleeing = false; + + currently_fleeing = true; while (loop < 100) //Max 100 tries { int ran = 250 - (loop*2); @@ -167,11 +168,13 @@ void Mob::CalculateNewFearpoint() float fdist = ranz - GetZ(); if (fdist >= -12 && fdist <= 12 && CheckCoordLosNoZLeaps(GetX(),GetY(),GetZ(),ranx,rany,ranz)) { - currently_fleeing = true; break; } } - if (currently_fleeing) - m_FearWalkTarget = glm::vec3(ranx, rany, ranz); + + if (loop <= 100) + { + m_FearWalkTarget = glm::vec3(ranx, rany, ranz); + } } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index c56f0daaf..8eb838a72 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -495,7 +495,8 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo m_Position.y = new_y; m_Position.z = new_z; - if(fix_z_timer.Check() && !this->IsEngaged()) + if(fix_z_timer.Check() && + (!this->IsEngaged() || flee_mode || currently_fleeing)) this->FixZ(); tar_ndx++; @@ -1129,4 +1130,4 @@ void NPC::SaveGuardSpotCharm() void NPC::RestoreGuardSpotCharm() { m_GuardPoint = m_GuardPointSaved; -} \ No newline at end of file +} From f534e69a90234a7668678a31c427a9ecef312603 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 19:17:05 -0400 Subject: [PATCH 198/218] Update SQL --- utils/sql/git/optional/auras.sql | 97 ------------------- utils/sql/git/required/2017_07_xx_aura.sql | 105 +++++++++++++++++++++ 2 files changed, 105 insertions(+), 97 deletions(-) delete mode 100644 utils/sql/git/optional/auras.sql diff --git a/utils/sql/git/optional/auras.sql b/utils/sql/git/optional/auras.sql deleted file mode 100644 index dc83ff93b..000000000 --- a/utils/sql/git/optional/auras.sql +++ /dev/null @@ -1,97 +0,0 @@ -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; - -SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -- admin (15-Jul-17 1:42:03) -INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; -UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); -- admin (15-Jul-17 1:42:03) - diff --git a/utils/sql/git/required/2017_07_xx_aura.sql b/utils/sql/git/required/2017_07_xx_aura.sql index 96ea45185..075522779 100644 --- a/utils/sql/git/required/2017_07_xx_aura.sql +++ b/utils/sql/git/required/2017_07_xx_aura.sql @@ -20,3 +20,108 @@ CREATE TABLE `character_auras` ( PRIMARY KEY (`id`, `slot`) ); +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap55", lastname="", level="55", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="poison_spurs", spell_id=8936, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; + +SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; +INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap", lastname="", level="70", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="Poison Spikes", spell_id=8472, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; +UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); + From 44eef6482c725f57f86a69eb351c90086dd0125b Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 19:38:49 -0400 Subject: [PATCH 199/218] Implement custom aura exit trap type I thought this type existed on live, but I guess it doesn't --- zone/aura.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 4df64b154..52b8a32d8 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -535,7 +535,27 @@ void Aura::ProcessEnterTrap(Mob *owner) void Aura::ProcessExitTrap(Mob *owner) { - Shout("Stub 6"); + auto &mob_list = entity_list.GetMobList(); // read only reference so we can do it all inline + + for (auto &e : mob_list) { + auto mob = e.second; + if (mob == this) + continue; + // might need more checks ... + if (owner->IsAttackAllowed(mob)) { + bool in_range = DistanceSquared(GetPosition(), mob->GetPosition()) <= distance; + auto it = casted_on.find(mob->GetID()); + if (it != casted_on.end()) { + if (!in_range) { + SpellFinished(spell_id, mob); + owner->RemoveAura(GetID(), false); // if we're a buff we don't want to strip :P + break; + } + } else if (in_range) { + casted_on.insert(mob->GetID()); + } + } + } } // this is less than ideal, but other solutions are a bit all over the place From 947341a5eecd3ff3decf23bbe1d4670ef1bc2933 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 21:21:15 -0400 Subject: [PATCH 200/218] Rename SQL and add manifest --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + .../git/required/{2017_07_xx_aura.sql => 2017_07_22_aura.sql} | 0 3 files changed, 2 insertions(+), 1 deletion(-) rename utils/sql/git/required/{2017_07_xx_aura.sql => 2017_07_22_aura.sql} (100%) diff --git a/common/version.h b/common/version.h index a1cfbce16..52af87872 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9113 +#define CURRENT_BINARY_DATABASE_VERSION 9114 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9017 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 8070c328e..faccf9e48 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -367,6 +367,7 @@ 9111|2017_06_24_saylink_index.sql|SHOW INDEX FROM `saylink` WHERE `key_name` = 'phrase_index'|empty| 9112|2017_06_24_rule_values_expand.sql|SHOW COLUMNS FROM rule_values WHERE Field = 'rule_value' and Type = 'varchar(30)'|empty| 9113|2017_07_19_show_name.sql|SHOW COLUMNS FROM `npc_types` LIKE 'show_name'|empty| +9114|2017_07_22_aura.sql|SHOW TABLES LIKE 'auras'|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2017_07_xx_aura.sql b/utils/sql/git/required/2017_07_22_aura.sql similarity index 100% rename from utils/sql/git/required/2017_07_xx_aura.sql rename to utils/sql/git/required/2017_07_22_aura.sql From 07c80f9560b95915d7eb4937f8415f634f5d9e1a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 21:52:51 -0400 Subject: [PATCH 201/218] Fix SQL --- utils/sql/git/required/2017_07_22_aura.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/git/required/2017_07_22_aura.sql b/utils/sql/git/required/2017_07_22_aura.sql index 075522779..f48a44500 100644 --- a/utils/sql/git/required/2017_07_22_aura.sql +++ b/utils/sql/git/required/2017_07_22_aura.sql @@ -11,7 +11,7 @@ CREATE TABLE `auras` ( `icon` INT(10) NOT NULL DEFAULT -1, `cast_time` INT(10) NOT NULL DEFAULT 0, PRIMARY KEY(`type`) -) +); CREATE TABLE `character_auras` ( `id` INT(10) NOT NULL, From 06246675725e8eb8062acb8f1bea0d2f2a428dee Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 22 Jul 2017 21:54:40 -0400 Subject: [PATCH 202/218] Fix SQL --- utils/sql/git/required/2017_07_22_aura.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/utils/sql/git/required/2017_07_22_aura.sql b/utils/sql/git/required/2017_07_22_aura.sql index f48a44500..409df9c72 100644 --- a/utils/sql/git/required/2017_07_22_aura.sql +++ b/utils/sql/git/required/2017_07_22_aura.sql @@ -118,10 +118,10 @@ INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spel SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap55", lastname="", level="55", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="poison_spurs", spell_id=8936, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; +INSERT INTO auras SET type=8922, npc_type=@suggestedid, name="poison_spurs", spell_id=8936, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap", lastname="", level="70", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; -INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="Poison Spikes", spell_id=8472, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; +INSERT INTO auras SET type=8471, npc_type=@suggestedid, name="Poison Spikes", spell_id=8472, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); From a0cfba5b3eef866b826d66bb752e55a3bd8147da Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Jul 2017 12:32:58 -0400 Subject: [PATCH 203/218] Fix show_name for bots --- zone/bot.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index f5a9285a3..c78c41d62 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -2929,6 +2929,7 @@ void Bot::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; ns->spawn.helm = helmtexture; //(GetShowHelm() ? helmtexture : 0); //0xFF; ns->spawn.equip_chest2 = texture; //0xFF; + ns->spawn.show_name = true; const EQEmu::ItemData* item = nullptr; const EQEmu::ItemInstance* inst = nullptr; uint32 spawnedbotid = 0; From df1e486df642e3e21a6aba2d9d4b3b683f2b909e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Jul 2017 14:35:22 -0400 Subject: [PATCH 204/218] Fix isquest issue with SQL --- utils/sql/git/required/2017_07_22_aura.sql | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/utils/sql/git/required/2017_07_22_aura.sql b/utils/sql/git/required/2017_07_22_aura.sql index 409df9c72..5ab461eaa 100644 --- a/utils/sql/git/required/2017_07_22_aura.sql +++ b/utils/sql/git/required/2017_07_22_aura.sql @@ -21,107 +21,107 @@ CREATE TABLE `character_auras` ( ); SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8926, npc_type=@suggestedid, name="Aura_of_Insight", spell_id=8939, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=99, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfTheMuse", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8488, npc_type=@suggestedid, name="Aura_of_the_Muse", spell_id=8489, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8921, npc_type=@suggestedid, name="Myrmidon's_Aura", spell_id=8935, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOChampionsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8468, npc_type=@suggestedid, name="Champion's_Aura", spell_id=8469, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8925, npc_type=@suggestedid, name="Holy_Aura", spell_id=8938, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOBlessedAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8481, npc_type=@suggestedid, name="Blessed_Aura", spell_id=8482, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8923, npc_type=@suggestedid, name="Disciples_Aura", spell_id=8937, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOMastersAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8474, npc_type=@suggestedid, name="Master's_Aura", spell_id=8475, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8933, npc_type=@suggestedid, name="Earthen_Strength", spell_id=8948, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOQuicksandTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8518, npc_type=@suggestedid, name="Rathe's_Strength", spell_id=8519, distance=60, aura_type=2, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8931, npc_type=@suggestedid, name="Beguiler's_Aura", spell_id=8946, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOIllusionistsAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8509, npc_type=@suggestedid, name="Illusionist's_Aura", spell_id=8510, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8929, npc_type=@suggestedid, name="Aura_of_the_Grove", spell_id=8943, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOLivingVineTrap", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8499, npc_type=@suggestedid, name="Aura_of_Life", spell_id=8500, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8928, npc_type=@suggestedid, name="Aura_of_the_Zealot", spell_id=8940, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOAuraOfThePious", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8495, npc_type=@suggestedid, name="Aura_of_the_Pious", spell_id=8496, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura55", lastname="", level="55", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8924, npc_type=@suggestedid, name="Aura_of_Rage", spell_id=8959, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOBloodlustAura", lastname="", level="70", race="127", class="62", bodytype="11", hp="4027.6216", mana="0.0000", gender="0", texture="0", helmtexture="0", herosforgemodel="0", size="2", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8477, npc_type=@suggestedid, name="Bloodlust_Aura", spell_id=8478, distance=60, aura_type=1, spawn_type=0, movement=0, duration=5400, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap55", lastname="", level="55", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8930, npc_type=@suggestedid, name="Soul_Idol", spell_id=8945, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOIdolOfMalaTrap", lastname="", level="70", race="514", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="2.5", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8504, npc_type=@suggestedid, name="Spirit_Idol", spell_id=8505, distance=60, aura_type=3, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=12; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8934, npc_type=@suggestedid, name="a_dark_rune", spell_id=8949, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IODeathRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8523, npc_type=@suggestedid, name="a_death_rune", spell_id=8524, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap55", lastname="", level="55", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8932, npc_type=@suggestedid, name="a_fiery_rune", spell_id=8947, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOFireRuneTrap", lastname="", level="70", race="510", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8513, npc_type=@suggestedid, name="a_fire_rune", spell_id=8514, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap55", lastname="", level="55", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap55", lastname="", level="55", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8922, npc_type=@suggestedid, name="poison_spurs", spell_id=8936, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; SELECT IFNULL((MAX(id) + 1), 2000000) INTO @suggestedid FROM npc_types where id LIKE '2000___'; -INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap", lastname="", level="70", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", isquest="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; +INSERT INTO npc_types SET id=@suggestedid, name="IOPoisonSpikesTrap", lastname="", level="70", race="513", class="62", bodytype="5", hp="4027.6216", mana="0.0000", gender="2", texture="0", helmtexture="0", herosforgemodel="0", size="3", hp_regen_rate="0", mana_regen_rate="0", loottable_id="0", npc_spells_id="0", mindmg="52.7514", maxdmg="166.8270", attack_count="-1", special_abilities="12,1^13,1^14,1^15,1^16,1^17,1^18,1^19,1^20,1^21,1^22,1^23,1^24,1^25,1^28,1^31,1^35,1^", aggroradius="70", assistradius="0", face="0", luclin_hairstyle="0", luclin_haircolor="0", luclin_eyecolor="0", luclin_eyecolor2="0", luclin_beardcolor="0", luclin_beard="0", drakkin_heritage="0", drakkin_tattoo="0", drakkin_details="0", armortint_red="0", armortint_green="0", armortint_blue="0", d_melee_texture1="0", d_melee_texture2="0", prim_melee_type="28", sec_melee_type="28", runspeed="1.25", MR="21.1027", CR="21.1027", DR="21.1027", FR="21.1027", PR="21.1027", Corrup="21.1027", PhR="48.3333", see_invis="0", see_invis_undead="0", qglobal="0", AC="257.3784", npc_aggro="0", spawn_limit="0", attack_delay="29.4486", findable="0", STR="205.0000", STA="205.0000", DEX="205.0000", AGI="205.0000", _INT="205.0000", WIS="205.0000", CHA="205.0000", see_hide="0", see_improved_hide="0", trackable="0", ATK="0", Accuracy="0", Avoidance="0", slow_mitigation="0", version="0", maxlevel="0", scalerate="100", private_corpse="0", unique_spawn_by_name="0", underwater="0", emoteid="0", spellscale="100", healscale="100", no_target_hotkey="0", raid_target="0", light="0", ignore_despawn="0", show_name="0"; INSERT INTO auras SET type=8471, npc_type=@suggestedid, name="Poison Spikes", spell_id=8472, distance=25, aura_type=4, spawn_type=1, movement=1, duration=120, icon=-1, cast_time=-1; UPDATE npc_types SET special_abilities = TRIM(TRAILING '^' FROM special_abilities); From a0140ff943c85471ab0127d6a6cd4fdb4dfaef1c Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Jul 2017 15:27:33 -0400 Subject: [PATCH 205/218] Fix client UI when auras expire --- zone/aura.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/zone/aura.cpp b/zone/aura.cpp index 52b8a32d8..8c54b75ee 100644 --- a/zone/aura.cpp +++ b/zone/aura.cpp @@ -886,9 +886,17 @@ void Mob::RemoveAura(int spawn_id, bool skip_strip, bool expired) if (aura.spawn_id == spawn_id) { if (aura.aura) aura.aura->Depop(skip_strip); - if (expired && IsClient()) + if (expired && IsClient()) { CastToClient()->SendColoredText( CC_Yellow, StringFormat("%s has expired.", aura.name)); // TODO: verify color + // need to update client UI too + auto app = new EQApplicationPacket(OP_UpdateAura, sizeof(AuraDestory_Struct)); + auto ads = (AuraDestory_Struct *)app->pBuffer; + ads->action = 1; // delete + ads->entity_id = spawn_id; + CastToClient()->QueuePacket(app); + safe_delete(app); + } while (aura_mgr.count - 1 > i) { i++; aura.spawn_id = aura_mgr.auras[i].spawn_id; From 6bf2cf8cb8e48a0135d0a4daf563d7f93603ad60 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Jul 2017 22:51:00 -0400 Subject: [PATCH 206/218] Fix aura removal --- zone/client_packet.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 8a2c266f1..777bcdeb9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -14340,6 +14340,7 @@ void Client::Handle_OP_UpdateAura(const EQApplicationPacket *app) return; // could log I guess, but should only ever get this action RemoveAura(aura->entity_id); + QueuePacket(app); // if we don't resend this, the client gets confused return; } From f6f3060c9da5a278e5d62b16d5efafc0da70ee16 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 24 Jul 2017 22:58:58 -0400 Subject: [PATCH 207/218] Fix trap removal --- zone/client_packet.cpp | 12 +++++++++++- zone/string_ids.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 777bcdeb9..95c9013b2 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -11805,7 +11805,17 @@ void Client::Handle_OP_RemoveTrap(const EQApplicationPacket *app) } auto id = app->ReadUInt32(0); - RemoveAura(id); + bool good = false; + for (int i = 0; i < trap_mgr.count; ++i) { + if (trap_mgr.auras[i].spawn_id == id) { + good = true; + break; + } + } + if (good) + RemoveAura(id); + else + Message_StringID(MT_SpellFailure, NOT_YOUR_TRAP); // pretty sure this was red } void Client::Handle_OP_Report(const EQApplicationPacket *app) diff --git a/zone/string_ids.h b/zone/string_ids.h index 663d2067a..c8175c8b6 100644 --- a/zone/string_ids.h +++ b/zone/string_ids.h @@ -286,6 +286,7 @@ #define TRADESKILL_LEARN_RECIPE 3457 //You have learned the recipe %1! #define EXPEDITION_MIN_REMAIN 3551 //You only have %1 minutes remaining before this expedition comes to an end. #define LOOT_NOT_ALLOWED 3562 //You are not allowed to loot the item: %1. +#define NOT_YOUR_TRAP 3671 //You cannot remove this, you are only allowed to remove traps you have set. #define NO_CAST_ON_PET 4045 //You cannot cast this spell on your pet. #define REWIND_WAIT 4059 //You must wait a bit longer before using the rewind command again. #define CORPSEDRAG_LIMIT 4061 //You are already dragging as much as you can! From 0b11340c4ec951b4458db3c60e3a161862531e0e Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 26 Jul 2017 00:58:46 -0400 Subject: [PATCH 208/218] Forgot show_name for mercs too --- zone/merc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/merc.cpp b/zone/merc.cpp index 80565c6b4..a3ff051f2 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1211,6 +1211,7 @@ void Merc::FillSpawnStruct(NewSpawn_Struct* ns, Mob* ForWho) { ns->spawn.flymode = 0; ns->spawn.NPC = 1; // 0=player,1=npc,2=pc corpse,3=npc corpse ns->spawn.IsMercenary = 1; + ns->spawn.show_name = true; UpdateActiveLight(); ns->spawn.light = m_Light.Type[EQEmu::lightsource::LightActive]; From 02b7e3fafb69450aba9d4b7501ec68664ac14665 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 15:37:35 -0400 Subject: [PATCH 209/218] Comment spawn struct for RoF2 These should change anything, just useful comments for clean up --- common/patches/rof2.cpp | 23 ++++++++++++----------- common/patches/rof2_structs.h | 21 +++++++++++++++++---- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 30efa95b9..460e1eb6e 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4276,19 +4276,19 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->lastName); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle ?? + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // aatitle VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC ? 0 : 1); // unknown - Must be 1 for guild name to be shown abover players head. - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // TempPet VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->petOwnerId); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown13 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // FindBits MQ2 name VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->PlayerState); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown15 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown16 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // unknown17 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown18 - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // unknown19 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // NpcTintIndex + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // PrimaryTintIndex + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0); // SecondaryTintIndex + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // These do something with OP_WeaponEquip1 + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // ^ if ((emu->NPC == 0) || (emu->race <= 12) || (emu->race == 128) || (emu->race == 130) || (emu->race == 330) || (emu->race == 522)) { @@ -4358,10 +4358,11 @@ namespace RoF2 Buffer += 8; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary); - VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); + VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); // RealEstateItemGuid + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateID + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, 0xffffffff); // RealEstateItemID // 29 zero bytes follow + // PhysicsEffects follow here ... unsure what they are but it's a count followed by a struct like {spellid, casterid, effectid, baseeffect} Buffer += 29; if (Buffer != (BufferStart + PacketSize)) { diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 379941d51..15af6cca4 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -328,6 +328,7 @@ showeq -> eqemu sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g' */ +// I think this is actually 5 bytes struct Spawn_Struct_Bitfields { /*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster) @@ -337,7 +338,7 @@ struct Spawn_Struct_Bitfields /*06*/ unsigned gm:1; /*06*/ unsigned sneak:1; /*08*/ unsigned lfg:1; -/*09*/ unsigned unknown09:1; +/*09*/ unsigned betabuffed:1; /*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which /*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below /*12*/ unsigned invis2:1; // This one also make the NPC/PC invis @@ -354,12 +355,24 @@ struct Spawn_Struct_Bitfields /*23*/ unsigned showhelm:1; /*24*/ unsigned unknown24:1; // Prefixes name with ! /*25*/ unsigned trader:1; -/*26*/ unsigned unknown26:1; +/*26*/ unsigned animationonpop:1; /*27*/ unsigned targetable:1; /*28*/ unsigned targetable_with_hotkey:1; /*29*/ unsigned showname:1; -/*30*/ unsigned unknown30:1; +/*30*/ unsigned idleanimationsoff:1; /*30*/ unsigned untargetable:1; // Untargetable with mouse +/* do these later +31 unsigned bclickthrough:1; +32 unsigned unknown32:1; +33 unsigned buyer:1; +34 unsigned offline:1; +35 unsigned interactiveobject:1; +36 unsigned flung:1; // hmm this vfunc appears to do stuff with lev and flung variables +37 unsigned title:1; +38 unsigned suffix:1; +39 padding +40 padding +*/ /* // Unknown in RoF2 unsigned betabuffed:1; @@ -498,7 +511,7 @@ struct Spawn_Struct /*0000*/ //char title[0]; // only read if(hasTitleOrSuffix & 4) /*0000*/ //char suffix[0]; // only read if(hasTitleOrSuffix & 8) - char unknown20[8]; + char unknown20[8]; // 2 ints, first unknown, 2nd SplineID uint8 IsMercenary; // If NPC == 1 and this == 1, then the NPC name is Orange. /*0000*/ char unknown21[55]; }; From 4f016de277037d403122dbdf4c545767aff723f2 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 18:15:56 -0400 Subject: [PATCH 210/218] More comments to RoF2 Spawn Struct --- common/patches/rof2.cpp | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 460e1eb6e..2e8d8458b 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -4120,6 +4120,7 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->name); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->spawnId); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->level); + // actually melee range variable, this probably screws the shit out of melee ranges :D if (emu->DestructibleObject) { VARSTRUCT_ENCODE_TYPE(float, Buffer, 10); // was int and 0x41200000 @@ -4128,7 +4129,7 @@ namespace RoF2 { VARSTRUCT_ENCODE_TYPE(float, Buffer, SpawnSize - 0.7); // Eye Height? } - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->NPC); // 0 PC, 1 NPC etc structs::Spawn_Struct_Bitfields *Bitfields = (structs::Spawn_Struct_Bitfields*)Buffer; @@ -4159,6 +4160,7 @@ namespace RoF2 Buffer += sizeof(structs::Spawn_Struct_Bitfields); + // actually part of bitfields uint8 OtherData = 0; if (emu->class_ == 62) //LDoN Chest @@ -4174,6 +4176,7 @@ namespace RoF2 OtherData = OtherData | 0xe1; // Live has 0xe1 for OtherData VARSTRUCT_ENCODE_TYPE(uint8, Buffer, OtherData); + // float EmitterScalingRadius if (emu->DestructibleObject) { @@ -4183,6 +4186,7 @@ namespace RoF2 { VARSTRUCT_ENCODE_TYPE(float, Buffer, -1); // unknown3 } + // int DefaultEmitterID VARSTRUCT_ENCODE_TYPE(float, Buffer, 0); // unknown4 if (emu->DestructibleObject || emu->class_ == 62) @@ -4192,8 +4196,9 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->DestructibleString); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleAppearance); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk1); // ObjectAnimationID + // these 10 are SoundIDs VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID1); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID2); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleID3); @@ -4205,8 +4210,8 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk5); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk6); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk7); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); - VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->DestructibleUnk8); // bInteractiveObjectCollidable + VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->DestructibleUnk9); // IteractiveObjectType } @@ -4214,6 +4219,7 @@ namespace RoF2 { // Setting this next field to zero will cause a crash. Looking at ShowEQ, if it is zero, the bodytype field is not // present. Will sort that out later. + // This is the CharacterPropertyHash, it can have multiple fields VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 1); // This is a properties count field VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->bodytype); } @@ -4233,10 +4239,10 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_tattoo); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->drakkin_details); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown9 - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // unknown10 - VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // unknown11 + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->equip_chest2); // InNonPCRaceIllusion + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // material + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // variation + VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->helm); // headtype VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->size); VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->face); @@ -4244,6 +4250,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(float, Buffer, emu->runspeed); VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->race); + // From MQ2: todo: create enum for this byte. Holding: Nothing=0 A RightHand Weapon=1 A Shield=2 Dual Wielding Two Weapons=3 A Spear=4 A LeftHand Weapon=5 A Two Handed Weapon=6 A bow=7 VARSTRUCT_ENCODE_TYPE(uint8, Buffer, 0); // ShowEQ calls this 'Holding' VARSTRUCT_ENCODE_TYPE(uint32, Buffer, emu->deity); if (emu->NPC) @@ -4356,6 +4363,9 @@ namespace RoF2 VARSTRUCT_ENCODE_STRING(Buffer, emu->suffix); } + // skipping two ints + // unknown, maybe some sort of spawn ID + // SplineID -- no idea Buffer += 8; VARSTRUCT_ENCODE_TYPE(uint8, Buffer, emu->IsMercenary); VARSTRUCT_ENCODE_STRING(Buffer, "0000000000000000"); // RealEstateItemGuid From e32b6c55e4f0b6d41efc3cd7ea4240d4c76695b4 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 18:23:42 -0400 Subject: [PATCH 211/218] Add enum GravityBehavior (FlyMode) from MQ2 --- zone/common.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/zone/common.h b/zone/common.h index 246600c8f..7b6382a20 100644 --- a/zone/common.h +++ b/zone/common.h @@ -207,6 +207,16 @@ typedef enum { //fear states enum { FlyMode0 = 0, FlyMode1 = 1, Flymode2 = 2, FlyMode3 = 3 }; +// This is actually FlyMode, from MQ2 +enum GravityBehavior { + Ground, + Flying, + Levitating, + Water, + Floating, // boat + LevitateWhileRunning +}; + struct TradeEntity; class Trade; enum TradeState { From 034ebab0643d12accba01b7d2d1d7852f6efc02a Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 18:47:35 -0400 Subject: [PATCH 212/218] Fix some comments --- common/patches/rof2_structs.h | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 15af6cca4..9fac34e28 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -329,14 +329,17 @@ sed -e 's/_t//g' -e 's/seto_0xFF/set_to_0xFF/g' */ // I think this is actually 5 bytes +// IDA's pseudocode reads this as 5 bytes pulled into 2 DWORDs struct Spawn_Struct_Bitfields { + // byte 1 /*00*/ unsigned gender:2; // Gender (0=male, 1=female, 2=monster) /*02*/ unsigned ispet:1; // Guessed based on observing live spawns /*03*/ unsigned afk:1; // 0=no, 1=afk /*04*/ unsigned anon:2; // 0=normal, 1=anon, 2=roleplay /*06*/ unsigned gm:1; -/*06*/ unsigned sneak:1; +/*07*/ unsigned sneak:1; + // byte 2 /*08*/ unsigned lfg:1; /*09*/ unsigned betabuffed:1; /*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which @@ -345,6 +348,7 @@ struct Spawn_Struct_Bitfields /*13*/ unsigned invis3:1; // This one also make the NPC/PC invis /*14*/ unsigned invis4:1; // This one also make the NPC/PC invis /*15*/ unsigned invis6:1; // This one also make the NPC/PC invis + // byte 3 /*16*/ unsigned invis7:1; // This one also make the NPC/PC invis /*17*/ unsigned invis8:1; // This one also make the NPC/PC invis /*18*/ unsigned invis9:1; // This one also make the NPC/PC invis @@ -353,6 +357,7 @@ struct Spawn_Struct_Bitfields /*21*/ unsigned invis12:1; // This one also make the NPC/PC invis /*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2 /*23*/ unsigned showhelm:1; + // byte 4 /*24*/ unsigned unknown24:1; // Prefixes name with ! /*25*/ unsigned trader:1; /*26*/ unsigned animationonpop:1; @@ -360,18 +365,17 @@ struct Spawn_Struct_Bitfields /*28*/ unsigned targetable_with_hotkey:1; /*29*/ unsigned showname:1; /*30*/ unsigned idleanimationsoff:1; -/*30*/ unsigned untargetable:1; // Untargetable with mouse +/*31*/ unsigned untargetable:1; // bClickThrough /* do these later -31 unsigned bclickthrough:1; -32 unsigned unknown32:1; -33 unsigned buyer:1; -34 unsigned offline:1; -35 unsigned interactiveobject:1; -36 unsigned flung:1; // hmm this vfunc appears to do stuff with lev and flung variables -37 unsigned title:1; -38 unsigned suffix:1; -39 padding -40 padding +32 unsigned buyer:1; +33 unsigned offline:1; +34 unsigned interactiveobject:1; +35 unsigned flung:1; // hmm this vfunc appears to do stuff with leve and flung variables +36 unsigned title:1; +37 unsigned suffix:1; +38 unsigned padding1:1; +39 unsigned padding2:1; +40 unsinged padding3:1; */ /* // Unknown in RoF2 From 210655ddc708d96576b24cb1470ec42f2d6f80fa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 19:15:27 -0400 Subject: [PATCH 213/218] More SpawnStruct comments --- common/patches/rof2_structs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index 9fac34e28..fa2db6416 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -342,6 +342,7 @@ struct Spawn_Struct_Bitfields // byte 2 /*08*/ unsigned lfg:1; /*09*/ unsigned betabuffed:1; +// really just invis:12 -- max invis (and see invis) is 3000 (GMs can get 3001) need 12 bits to store that /*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which /*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below /*12*/ unsigned invis2:1; // This one also make the NPC/PC invis From 2286203123a32cd6408763904a8d689dde49dbec Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Sat, 29 Jul 2017 23:31:47 -0400 Subject: [PATCH 214/218] Fix invis in spawn structs --- common/patches/rof2_structs.h | 17 ++--------------- common/patches/rof_structs.h | 13 +------------ common/patches/sod_structs.h | 3 +-- common/patches/uf_structs.h | 3 +-- 4 files changed, 5 insertions(+), 31 deletions(-) diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index fa2db6416..1b3c41794 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -342,20 +342,7 @@ struct Spawn_Struct_Bitfields // byte 2 /*08*/ unsigned lfg:1; /*09*/ unsigned betabuffed:1; -// really just invis:12 -- max invis (and see invis) is 3000 (GMs can get 3001) need 12 bits to store that -/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which -/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below -/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis -/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis -/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis -/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis - // byte 3 -/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis -/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis -/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis -/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis -/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis -/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis +/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels /*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF2 /*23*/ unsigned showhelm:1; // byte 4 @@ -365,7 +352,7 @@ struct Spawn_Struct_Bitfields /*27*/ unsigned targetable:1; /*28*/ unsigned targetable_with_hotkey:1; /*29*/ unsigned showname:1; -/*30*/ unsigned idleanimationsoff:1; +/*30*/ unsigned idleanimationsoff:1; // what we called statue? /*31*/ unsigned untargetable:1; // bClickThrough /* do these later 32 unsigned buyer:1; diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 4c73c28d4..24439d7f0 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -339,18 +339,7 @@ struct Spawn_Struct_Bitfields /*06*/ unsigned sneak:1; /*08*/ unsigned lfg:1; /*09*/ unsigned unknown09:1; -/*10*/ unsigned invis:1; // May have invis & sneak the wrong way around ... not sure how to tell which is which -/*11*/ unsigned invis1:1; // GM Invis? Can only be seen with #gm on - same for the below -/*12*/ unsigned invis2:1; // This one also make the NPC/PC invis -/*13*/ unsigned invis3:1; // This one also make the NPC/PC invis -/*14*/ unsigned invis4:1; // This one also make the NPC/PC invis -/*15*/ unsigned invis6:1; // This one also make the NPC/PC invis -/*16*/ unsigned invis7:1; // This one also make the NPC/PC invis -/*17*/ unsigned invis8:1; // This one also make the NPC/PC invis -/*18*/ unsigned invis9:1; // This one also make the NPC/PC invis -/*19*/ unsigned invis10:1; // This one also make the NPC/PC invis -/*20*/ unsigned invis11:1; // This one also make the NPC/PC invis -/*21*/ unsigned invis12:1; // This one also make the NPC/PC invis +/*10*/ unsigned invis:12; // there are 3000 different (non-GM) invis levels /*22*/ unsigned linkdead:1; // 1 Toggles LD on or off after name. Correct for RoF /*23*/ unsigned showhelm:1; /*24*/ unsigned unknown24:1; // Prefixes name with ! diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index ed71d837b..af449f758 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields unsigned sneak:1; unsigned lfg:1; unsigned padding5:1; - unsigned invis:1; // 0 = visible, 1 = invis/sneaking - unsigned padding7:11; + unsigned invis:12; // there are 3000 different (non-GM) invis levels unsigned gm:1; unsigned anon:2; // 0=normal, 1=anon, 2=roleplay unsigned gender:2; // Gender (0=male, 1=female, 2=monster) diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index 5a9562117..b187f9f82 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -250,8 +250,7 @@ struct Spawn_Struct_Bitfields unsigned sneak:1; unsigned lfg:1; unsigned padding5:1; - unsigned invis:1; // 0 = visible, 1 = invis/sneaking - unsigned padding7:11; + unsigned invis:12; // there are 3000 different (non-GM) invis levels unsigned gm:1; unsigned anon:2; // 0=normal, 1=anon, 2=roleplay unsigned gender:2; // Gender (0=male, 1=female, 2=monster) From 0fc72875b2fb8f98f7fe170ed2a346bec76b5079 Mon Sep 17 00:00:00 2001 From: Paul Coene Date: Mon, 31 Jul 2017 09:21:49 -0400 Subject: [PATCH 215/218] Modify roam boxes to correctly modify and use destination Z --- zone/mob.h | 2 +- zone/mob_ai.cpp | 6 +++++- zone/waypoints.cpp | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/zone/mob.h b/zone/mob.h index 8286bf647..cd7ecf7a8 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1091,7 +1091,7 @@ protected: int _GetWalkSpeed() const; int _GetRunSpeed() const; int _GetFearSpeed() const; - virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ); + virtual bool MakeNewPositionAndSendUpdate(float x, float y, float z, int speed); virtual bool AI_EngagedCastCheck() { return(false); } virtual bool AI_PursueCastCheck() { return(false); } diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index e1e4682b0..14e9337ac 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -1536,7 +1536,11 @@ void NPC::AI_DoMovement() { Log(Logs::Detail, Logs::AI, "Roam Box: d=%.3f (%.3f->%.3f,%.3f->%.3f): Go To (%.3f,%.3f)", roambox_distance, roambox_min_x, roambox_max_x, roambox_min_y, roambox_max_y, roambox_movingto_x, roambox_movingto_y); - if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, GetZ(), walksp, true)) + + float new_z = this->FindGroundZ(m_Position.x, m_Position.y, 5); + new_z += (this->GetSize() / 1.55); + + if (!CalculateNewPosition2(roambox_movingto_x, roambox_movingto_y, new_z, walksp, true)) { roambox_movingto_x = roambox_max_x + 1; // force update pLastFightingDelayMoving = Timer::GetCurrentTime() + RandomTimer(roambox_min_delay, roambox_delay); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 8eb838a72..c1997af59 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -451,7 +451,7 @@ float Mob::CalculateHeadingToTarget(float in_x, float in_y) { return (256 * (360 - angle) / 360.0f); } -bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, bool checkZ) { +bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed) { if (GetID() == 0) return true; @@ -627,7 +627,7 @@ bool Mob::MakeNewPositionAndSendUpdate(float x, float y, float z, int speed, boo } bool Mob::CalculateNewPosition2(float x, float y, float z, int speed, bool checkZ, bool calcHeading) { - return MakeNewPositionAndSendUpdate(x, y, z, speed, checkZ); + return MakeNewPositionAndSendUpdate(x, y, z, speed); } bool Mob::CalculateNewPosition(float x, float y, float z, int speed, bool checkZ, bool calcHeading) { From 771c3b175ed28228cfd49648ab8a4e7ad818906d Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 1 Aug 2017 13:09:18 -0400 Subject: [PATCH 216/218] Fix AffectedBySpellExcludingSlot --- zone/spell_effects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index fc9cd51a3..6a50ab142 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -5963,7 +5963,8 @@ bool Mob::TryDeathSave() { bool Mob::AffectedBySpellExcludingSlot(int slot, int effect) { - for (int i = 0; i <= EFFECT_COUNT; i++) + int buff_count = GetMaxTotalSlots(); + for (int i = 0; i < buff_count; i++) { if (i == slot) continue; From 935dc7d8fbd89ebf8b90006301f58ed97b577c70 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 1 Aug 2017 19:57:30 -0400 Subject: [PATCH 217/218] Add more OP_SpawnAppearance types (RoF2 at least) --- common/eq_constants.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/common/eq_constants.h b/common/eq_constants.h index b4e887b0a..7a2917368 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -27,7 +27,7 @@ //SpawnAppearance types: (compared two clients for server-originating types: SoF & RoF2) #define AT_Die 0 // this causes the client to keel over and zone to bind point (default action) #define AT_WhoLevel 1 // the level that shows up on /who -//#define AT_2 2 // unknown +#define AT_HPMax 2 // idk #define AT_Invis 3 // 0 = visible, 1 = invisible #define AT_PVP 4 // 0 = blue, 1 = pvp (red) #define AT_Light 5 // light type emitted by player (lightstone, shiny shield) @@ -36,33 +36,33 @@ #define AT_SpawnID 16 // server to client, sets player spawn id #define AT_HP 17 // Client->Server, my HP has changed (like regen tic) #define AT_Linkdead 18 // 0 = normal, 1 = linkdead -#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate +#define AT_Levitate 19 // 0=off, 1=flymode, 2=levitate max 5, see GravityBehavior enum #define AT_GM 20 // 0 = normal, 1 = GM - all odd numbers seem to make it GM #define AT_Anon 21 // 0 = normal, 1 = anon, 2 = roleplay #define AT_GuildID 22 #define AT_GuildRank 23 // 0=member, 1=officer, 2=leader #define AT_AFK 24 // 0 = normal, 1 = afk #define AT_Pet 25 // Param is EntityID of owner, or 0 for when charm breaks -//#define AT_27 27 // unknown +#define AT_Summoned 27 // Unsure #define AT_Split 28 // 0 = normal, 1 = autosplit on (not showing in SoF+) (client-to-server only) #define AT_Size 29 // spawn's size (present: SoF, absent: RoF2) -//#define AT_30 30 // unknown -#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name -//#define AT_32 32 // unknown -//#define AT_33 33 // unknown +#define AT_SetType 30 // 0 = PC, 1 = NPC, 2 <= = corpse +#define AT_NPCName 31 // change PC's name's color to NPC color 0 = normal, 1 = npc name, Trader on RoF2? +#define AT_AARank 32 // AA Rank Title ID thingy, does is this the title in /who? +#define AT_CancelSneakHide 33 // Turns off Hide and Sneak //#define AT_34 34 // unknown (present: SoF, absent: RoF2) -//#define AT_35 35 // unknown -//#define AT_36 36 // unknown -//#define AT_37 37 // unknown -//#define AT_38 38 // unknown -//#define AT_39 39 // unknown +#define AT_AreaHPRegen 35 // guild hall regen pool sets to value * 0.001 +#define AT_AreaManaRegen 36 // guild hall regen pool sets to value * 0.001 +#define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001 +#define AT_FreezeBuffs 38 // Freezes beneficial buff timers +#define AT_NpcTintIndex 39 // not 100% sure #define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic -#define AT_DamageState 44 // The damage state of a destructible object (0 through 4) -//#define AT_46 46 // unknown -//#define AT_48 48 // unknown -//#define AT_49 49 // unknown -//#define AT_52 52 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34) -//#define AT_53 53 // (absent: SoF, present: RoF2) (not a replacement for RoF absent 29 or 34) +#define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though +#define AT_FindBits 46 // set FindBits, whatever those are! +#define AT_TextureType 48 // TextureType +#define AT_FacePick 49 // Turns off face pick window? maybe ... +#define AT_GuldShow 52 // this is what MQ2 call sit, not sure +#define AT_Offline 53 // Offline mode //#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2) From 28fca1f8dc8e4ddaa9c69d25133f6a718b4f4a12 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Tue, 1 Aug 2017 20:14:10 -0400 Subject: [PATCH 218/218] More OP_SpawnAppearance types --- common/eq_constants.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/common/eq_constants.h b/common/eq_constants.h index 7a2917368..d20bfdf4a 100644 --- a/common/eq_constants.h +++ b/common/eq_constants.h @@ -56,12 +56,16 @@ #define AT_AreaEndRegen 37 // guild hall regen pool sets to value * 0.001 #define AT_FreezeBuffs 38 // Freezes beneficial buff timers #define AT_NpcTintIndex 39 // not 100% sure +#define AT_GroupConsent 40 // auto consent group +#define AT_RaidConsent 41 // auto consent raid +#define AT_GuildConsent 42 // auto consent guild #define AT_ShowHelm 43 // 0 = hide graphic, 1 = show graphic #define AT_DamageState 44 // The damage state of a destructible object (0 through 10) plays soundids most only have 2 or 4 states though +#define AT_EQPlayers 45 // /eqplayersupdate #define AT_FindBits 46 // set FindBits, whatever those are! #define AT_TextureType 48 // TextureType #define AT_FacePick 49 // Turns off face pick window? maybe ... -#define AT_GuldShow 52 // this is what MQ2 call sit, not sure +#define AT_GuildShow 52 // this is what MQ2 call sit, not sure #define AT_Offline 53 // Offline mode //#define AT_Trader 300 // Bazaar Trader Mode (not present in SoF or RoF2)