From 4627bfe271e38b637fe165e4cb4e782814611716 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 10 Jun 2019 00:30:04 -0400 Subject: [PATCH 01/23] Mercs shouldn't do global loot (I think) --- zone/zonedb.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 093e1e30c..e3adc6d13 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2877,6 +2877,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->scalerate = atoi(row[43]); tmpNPCType->spellscale = atoi(row[44]); tmpNPCType->healscale = atoi(row[45]); + tmpNPCType->skip_global_loot = true; // If Merc with duplicate NPC id already in table, // free item we attempted to add. From 290133803ebffa1e701cba3d81bd0fce90d0b023 Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Mon, 10 Jun 2019 00:36:18 -0400 Subject: [PATCH 02/23] Add a hard off for NPC scaling for Merc/Bot They don't need it. We may want to add this to actually be in the DB for normal NPCs in the future. --- zone/bot.cpp | 1 + zone/npc.cpp | 1 + zone/npc.h | 2 ++ zone/npc_scale_manager.cpp | 5 ++++- zone/zonedb.cpp | 2 ++ zone/zonedump.h | 1 + 6 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index b221620e2..143520076 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -439,6 +439,7 @@ NPCType *Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::st bot_npc_type->skip_global_loot = true; //bot_npc_type->rare_spawn = false; bot_npc_type->stuck_behavior = Ground; + bot_npc_type->skip_auto_scale = true; return bot_npc_type; } diff --git a/zone/npc.cpp b/zone/npc.cpp index ac8825774..355196d2e 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -239,6 +239,7 @@ NPC::NPC(const NPCType *npc_type_data, Spawn2 *in_respawn, const glm::vec4 &posi p_depop = false; loottable_id = npc_type_data->loottable_id; skip_global_loot = npc_type_data->skip_global_loot; + skip_auto_scale = npc_type_data->skip_auto_scale; rare_spawn = npc_type_data->rare_spawn; no_target_hotkey = npc_type_data->no_target_hotkey; primary_faction = 0; diff --git a/zone/npc.h b/zone/npc.h index b9e0458e6..1957b8e63 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -468,6 +468,7 @@ public: virtual int GetStuckBehavior() const { return NPCTypedata_ours ? NPCTypedata_ours->stuck_behavior : NPCTypedata->stuck_behavior; } + inline bool IsSkipAutoScale() const { return skip_auto_scale; } protected: @@ -612,6 +613,7 @@ protected: private: uint32 loottable_id; bool skip_global_loot; + bool skip_auto_scale; bool p_depop; }; diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index dd1b9734d..c17619482 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -26,6 +26,9 @@ */ void NpcScaleManager::ScaleNPC(NPC * npc) { + if (npc->IsSkipAutoScale()) + return; + int8 npc_type = GetNPCScalingType(npc); int npc_level = npc->GetLevel(); bool is_auto_scaled = IsAutoScaled(npc); @@ -621,4 +624,4 @@ bool NpcScaleManager::ApplyGlobalBaseScalingToNPCDynamically(NPC *&npc) auto results = database.QueryDatabase(query); return results.Success(); -} \ No newline at end of file +} diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index e3adc6d13..76e3a4c5c 100755 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -2675,6 +2675,7 @@ const NPCType* ZoneDatabase::LoadNPCTypesData(uint32 npc_type_id, bool bulk_load temp_npctype_data->rare_spawn = atoi(row[108]) != 0; temp_npctype_data->stuck_behavior = atoi(row[109]); temp_npctype_data->use_model = atoi(row[110]); + temp_npctype_data->skip_auto_scale = false; // hardcoded here for now // If NPC with duplicate NPC id already in table, // free item we attempted to add. @@ -2878,6 +2879,7 @@ const NPCType* ZoneDatabase::GetMercType(uint32 id, uint16 raceid, uint32 client tmpNPCType->spellscale = atoi(row[44]); tmpNPCType->healscale = atoi(row[45]); tmpNPCType->skip_global_loot = true; + tmpNPCType->skip_auto_scale = true; // If Merc with duplicate NPC id already in table, // free item we attempted to add. diff --git a/zone/zonedump.h b/zone/zonedump.h index be978a1be..71f530171 100644 --- a/zone/zonedump.h +++ b/zone/zonedump.h @@ -143,6 +143,7 @@ struct NPCType bool untargetable; bool skip_global_loot; bool rare_spawn; + bool skip_auto_scale; // just so it doesn't mess up bots or mercs, probably should add to DB too just in case int8 stuck_behavior; uint16 use_model; }; From c0e07cec015d9052d00a543cf481f4f2c90e7c3b Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jun 2019 00:01:18 -0500 Subject: [PATCH 03/23] Loader adjustments --- common/eqemu_config.cpp | 128 +++++++++++++++++++++++++--------------- common/eqemu_config.h | 1 + common/opcodemgr.cpp | 3 +- ucs/clientlist.cpp | 3 +- 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 3516f15d1..cae737e98 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -26,24 +26,26 @@ std::string EQEmuConfig::ConfigFile = "eqemu_config.json"; EQEmuConfig *EQEmuConfig::_config = nullptr; -void EQEmuConfig::parse_config() { - - ShortName = _root["server"]["world"].get("shortname", "").asString(); - LongName = _root["server"]["world"].get("longname", "").asString(); +void EQEmuConfig::parse_config() +{ + + ShortName = _root["server"]["world"].get("shortname", "").asString(); + LongName = _root["server"]["world"].get("longname", "").asString(); WorldAddress = _root["server"]["world"].get("address", "").asString(); LocalAddress = _root["server"]["world"].get("localaddress", "").asString(); - MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str()); - SharedKey = _root["server"]["world"].get("key", "").asString(); - LoginCount = 0; + MaxClients = atoi(_root["server"]["world"].get("maxclients", "-1").asString().c_str()); + SharedKey = _root["server"]["world"].get("key", "").asString(); + LoginCount = 0; if (_root["server"]["world"]["loginserver"].isObject()) { - LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString(); - LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); + LoginHost = _root["server"]["world"]["loginserver"].get("host", "login.eqemulator.net").asString(); + LoginPort = atoi(_root["server"]["world"]["loginserver"].get("port", "5998").asString().c_str()); LoginLegacy = false; - if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") LoginLegacy = true; - LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString(); + if (_root["server"]["world"]["loginserver"].get("legacy", "0").asString() == "1") { LoginLegacy = true; } + LoginAccount = _root["server"]["world"]["loginserver"].get("account", "").asString(); LoginPassword = _root["server"]["world"]["loginserver"].get("password", "").asString(); - } else { + } + else { char str[32]; loginlist.Clear(); do { @@ -53,74 +55,102 @@ void EQEmuConfig::parse_config() { } auto loginconfig = new LoginConfig; - loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString(); - loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str()); - loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString(); + loginconfig->LoginHost = _root["server"]["world"][str].get("host", "login.eqemulator.net").asString(); + loginconfig->LoginPort = atoi(_root["server"]["world"][str].get("port", "5998").asString().c_str()); + loginconfig->LoginAccount = _root["server"]["world"][str].get("account", "").asString(); loginconfig->LoginPassword = _root["server"]["world"][str].get("password", "").asString(); loginconfig->LoginLegacy = false; - if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") loginconfig->LoginLegacy = true; + if (_root["server"]["world"][str].get("legacy", "0").asString() == "1") { loginconfig->LoginLegacy = true; } loginlist.Insert(loginconfig); } while (LoginCount < 100); } - - + + // from xml converts to json as locked: "", so i default to "false". //The only way to enable locked is by switching to true, meaning this value is always false until manually set true Locked = false; - if (_root["server"]["world"].get("locked", "false").asString() == "true") Locked = true; - WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString(); + if (_root["server"]["world"].get("locked", "false").asString() == "true") { Locked = true; } + WorldIP = _root["server"]["world"]["tcp"].get("host", "127.0.0.1").asString(); WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); - - TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString(); + + TelnetIP = _root["server"]["world"]["telnet"].get("ip", "127.0.0.1").asString(); TelnetTCPPort = atoi(_root["server"]["world"]["telnet"].get("port", "9001").asString().c_str()); TelnetEnabled = false; - if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") TelnetEnabled = true; + if (_root["server"]["world"]["telnet"].get("enabled", "false").asString() == "true") { TelnetEnabled = true; } WorldHTTPMimeFile = _root["server"]["world"]["http"].get("mimefile", "mime.types").asString(); - WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); - WorldHTTPEnabled = false; - if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") WorldHTTPEnabled = true; + WorldHTTPPort = atoi(_root["server"]["world"]["http"].get("port", "9080").asString().c_str()); + WorldHTTPEnabled = false; + if (_root["server"]["world"]["http"].get("enabled", "false").asString() == "true") { + WorldHTTPEnabled = true; + } + + /** + * UCS + */ ChatHost = _root["server"]["chatserver"].get("host", "eqchat.eqemulator.net").asString(); ChatPort = atoi(_root["server"]["chatserver"].get("port", "7778").asString().c_str()); - MailHost = _root["server"]["mailserver"].get("host", "eqmail.eqemulator.net").asString(); MailPort = atoi(_root["server"]["mailserver"].get("port", "7778").asString().c_str()); + /** + * Database + */ DatabaseUsername = _root["server"]["database"].get("username", "eq").asString(); DatabasePassword = _root["server"]["database"].get("password", "eq").asString(); - DatabaseHost = _root["server"]["database"].get("host", "localhost").asString(); - DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str()); - DatabaseDB = _root["server"]["database"].get("db", "eq").asString(); + DatabaseHost = _root["server"]["database"].get("host", "localhost").asString(); + DatabasePort = atoi(_root["server"]["database"].get("port", "3306").asString().c_str()); + DatabaseDB = _root["server"]["database"].get("db", "eq").asString(); - QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString(); - QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); + /** + * QS + */ + QSDatabaseHost = _root["server"]["qsdatabase"].get("host", "localhost").asString(); + QSDatabasePort = atoi(_root["server"]["qsdatabase"].get("port", "3306").asString().c_str()); QSDatabaseUsername = _root["server"]["qsdatabase"].get("username", "eq").asString(); QSDatabasePassword = _root["server"]["qsdatabase"].get("password", "eq").asString(); - QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); + QSDatabaseDB = _root["server"]["qsdatabase"].get("db", "eq").asString(); + /** + * Zones + */ DefaultStatus = atoi(_root["server"]["zones"].get("defaultstatus", 0).asString().c_str()); - ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); - ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); + ZonePortLow = atoi(_root["server"]["zones"]["ports"].get("low", "7000").asString().c_str()); + ZonePortHigh = atoi(_root["server"]["zones"]["ports"].get("high", "7999").asString().c_str()); - SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString(); - OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString(); - PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString(); + /** + * Files + */ + SpellsFile = _root["server"]["files"].get("spells", "spells_us.txt").asString(); + OpCodesFile = _root["server"]["files"].get("opcodes", "opcodes.conf").asString(); + MailOpCodesFile = _root["server"]["files"].get("mail_opcodes", "mail_opcodes.conf").asString(); + PluginPlFile = _root["server"]["files"].get("plugin.pl", "plugin.pl").asString(); - MapDir = _root["server"]["directories"].get("maps", "Maps/").asString(); - QuestDir = _root["server"]["directories"].get("quests", "quests/").asString(); - PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString(); + /** + * Directories + */ + MapDir = _root["server"]["directories"].get("maps", "Maps/").asString(); + QuestDir = _root["server"]["directories"].get("quests", "quests/").asString(); + PluginDir = _root["server"]["directories"].get("plugins", "plugins/").asString(); LuaModuleDir = _root["server"]["directories"].get("lua_modules", "lua_modules/").asString(); - PatchDir = _root["server"]["directories"].get("patches", "./").asString(); + PatchDir = _root["server"]["directories"].get("patches", "./").asString(); SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString(); - LogDir = _root["server"]["directories"].get("logs", "logs/").asString(); + LogDir = _root["server"]["directories"].get("logs", "logs/").asString(); + /** + * Logs + */ LogPrefix = _root["server"]["launcher"].get("logprefix", "logs/zone-").asString(); LogSuffix = _root["server"]["launcher"].get("logsuffix", ".log").asString(); - RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); - TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); - InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); + + /** + * Launcher + */ + RestartWait = atoi(_root["server"]["launcher"]["timers"].get("restart", "10000").asString().c_str()); + TerminateWait = atoi(_root["server"]["launcher"]["timers"].get("reterminate", "10000").asString().c_str()); + InitialBootWait = atoi(_root["server"]["launcher"]["timers"].get("initial", "20000").asString().c_str()); ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str()); #ifdef WIN32 ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString(); @@ -230,6 +260,9 @@ std::string EQEmuConfig::GetByName(const std::string &var_name) const if (var_name == "OpCodesFile") { return (OpCodesFile); } + if (var_name == "MailOpCodesFile") { + return (MailOpCodesFile); + } if (var_name == "PluginPlFile") { return (PluginPlFile); } @@ -312,6 +345,7 @@ void EQEmuConfig::Dump() const std::cout << "QSDatabasePort = " << QSDatabasePort << std::endl; std::cout << "SpellsFile = " << SpellsFile << std::endl; std::cout << "OpCodesFile = " << OpCodesFile << std::endl; + std::cout << "MailOpcodesFile = " << MailOpCodesFile << std::endl; std::cout << "PluginPlFile = " << PluginPlFile << std::endl; std::cout << "MapDir = " << MapDir << std::endl; std::cout << "QuestDir = " << QuestDir << std::endl; @@ -322,6 +356,6 @@ void EQEmuConfig::Dump() const std::cout << "LogDir = " << LogDir << std::endl; std::cout << "ZonePortLow = " << ZonePortLow << std::endl; std::cout << "ZonePortHigh = " << ZonePortHigh << std::endl; - std::cout << "DefaultStatus = " << (int)DefaultStatus << std::endl; + std::cout << "DefaultStatus = " << (int) DefaultStatus << std::endl; // std::cout << "DynamicCount = " << DynamicCount << std::endl; } diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 66cf962c6..e75737d76 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -84,6 +84,7 @@ class EQEmuConfig // From std::string SpellsFile; std::string OpCodesFile; + std::string MailOpCodesFile; std::string PluginPlFile; // From diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index f7a6ad3bf..2190db4a7 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -16,6 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "eqemu_logsys.h" #include "emu_opcodes.h" #include "opcodemgr.h" @@ -31,7 +32,7 @@ OpcodeManager::OpcodeManager() { bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors) { FILE *opf = fopen(filename, "r"); if(opf == nullptr) { - fprintf(stderr, "Unable to open opcodes file '%s'. Thats bad.\n", filename); + Log(Logs::General, Logs::Error, "Unable to open opcodes file '%s'", filename); return(false); } diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index a399485e4..ab058438c 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -465,6 +465,7 @@ static void ProcessCommandIgnore(Client *c, std::string Ignoree) { safe_delete(outapp); } + Clientlist::Clientlist(int ChatPort) { EQ::Net::EQStreamManagerOptions chat_opts(ChatPort, false, false); chat_opts.opcode_size = 1; @@ -478,7 +479,7 @@ Clientlist::Clientlist(int ChatPort) { ChatOpMgr = new RegularOpcodeManager; - if (!ChatOpMgr->LoadOpcodes("mail_opcodes.conf")) + if (!ChatOpMgr->LoadOpcodes(Config->MailOpCodesFile)) exit(1); chatsf->OnNewConnection([this](std::shared_ptr stream) { From ce41cf9cd5b7d9091b9aec243b96ff463f753160 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jun 2019 00:29:24 -0500 Subject: [PATCH 04/23] Load mail_opcodes.conf dynamically --- ucs/clientlist.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ucs/clientlist.cpp b/ucs/clientlist.cpp index ab058438c..e65638563 100644 --- a/ucs/clientlist.cpp +++ b/ucs/clientlist.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "../common/eqemu_logsys.h" #include "../common/misc_functions.h" +#include "ucsconfig.h" #include "clientlist.h" #include "database.h" #include "chatchannel.h" @@ -479,7 +480,10 @@ Clientlist::Clientlist(int ChatPort) { ChatOpMgr = new RegularOpcodeManager; - if (!ChatOpMgr->LoadOpcodes(Config->MailOpCodesFile)) + const ucsconfig *Config = ucsconfig::get(); + + Log(Logs::General, Logs::UCS_Server, "Loading '%s'", Config->MailOpCodesFile.c_str()); + if (!ChatOpMgr->LoadOpcodes(Config->MailOpCodesFile.c_str())) exit(1); chatsf->OnNewConnection([this](std::shared_ptr stream) { From a2dd1fc753cd4117780c92807e1d2fb69cea6061 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 10 Jun 2019 00:40:11 -0500 Subject: [PATCH 05/23] Update eqemu_server.pl --- utils/scripts/eqemu_server.pl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 0abafb7e5..bd17ad435 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -72,14 +72,6 @@ if (-e "eqemu_update.pl") { unlink("eqemu_update.pl"); } -if (-e "db_update") { - unlink("db_update"); -} - -if (-e "updates_staged") { - unlink("updates_staged"); -} - print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world"; check_db_version_table(); @@ -652,6 +644,14 @@ sub do_self_update_check_routine { } else { print "[Update] No script update necessary...\n"; + + if (-e "db_update") { + unlink("db_update"); + } + + if (-e "updates_staged") { + unlink("updates_staged"); + } } unlink("updates_staged/eqemu_server.pl"); From 660416065eefbfc24ac99230f758014164a0351c Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jun 2019 15:19:27 -0500 Subject: [PATCH 06/23] Fix scaling and display for cor / phr --- zone/mob_info.cpp | 4 ++-- zone/npc.cpp | 8 ++++++++ zone/npc_scale_manager.cpp | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index 1382e5c97..174a00330 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -189,11 +189,11 @@ inline std::string GetMobAttributeByString(Mob *mob, const std::string &attribut } if (attribute == "cor") { - return std::to_string(mob->GetCorrup()); + return commify(std::to_string(mob->GetCorrup())) + scaling_modified; } if (attribute == "phy") { - return std::to_string(mob->GetPhR()); + return commify(std::to_string(mob->GetPhR())) + scaling_modified; } if (attribute == "name") { diff --git a/zone/npc.cpp b/zone/npc.cpp index 355196d2e..b0367f469 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -2215,6 +2215,14 @@ void NPC::ModifyNPCStat(const char *identifier, const char *new_value) CR = atoi(val.c_str()); return; } + else if (id == "cor") { + Corrup = atoi(val.c_str()); + return; + } + else if (id == "phr") { + PhR = atoi(val.c_str()); + return; + } else if (id == "pr") { PR = atoi(val.c_str()); return; diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index c17619482..4047b0e6f 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -98,10 +98,10 @@ void NpcScaleManager::ScaleNPC(NPC * npc) npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str()); } if (npc->GetCorrup() == 0) { - npc->ModifyNPCStat("cr", std::to_string(scale_data.corruption_resist).c_str()); + npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist).c_str()); } if (npc->GetPhR() == 0) { - npc->ModifyNPCStat("pr", std::to_string(scale_data.physical_resist).c_str()); + npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist).c_str()); } if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) { int min_dmg = scale_data.min_dmg; From 882e3742d98ae5e366da80cef8cfcf5c8dcb5c54 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 11 Jun 2019 15:26:01 -0500 Subject: [PATCH 07/23] Make sure AC / Corrup and PhR do not auto scale unles auto scale criteria is met --- zone/npc_scale_manager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zone/npc_scale_manager.cpp b/zone/npc_scale_manager.cpp index 4047b0e6f..5daabcb16 100644 --- a/zone/npc_scale_manager.cpp +++ b/zone/npc_scale_manager.cpp @@ -45,7 +45,7 @@ void NpcScaleManager::ScaleNPC(NPC * npc) return; } - if (npc->GetAC() == 0) { + if (npc->GetAC() == 0 && is_auto_scaled) { npc->ModifyNPCStat("ac", std::to_string(scale_data.ac).c_str()); } if (npc->GetMaxHP() == 0) { @@ -97,10 +97,10 @@ void NpcScaleManager::ScaleNPC(NPC * npc) if (npc->GetDR() == 0) { npc->ModifyNPCStat("dr", std::to_string(scale_data.disease_resist).c_str()); } - if (npc->GetCorrup() == 0) { + if (npc->GetCorrup() == 0 && is_auto_scaled) { npc->ModifyNPCStat("cor", std::to_string(scale_data.corruption_resist).c_str()); } - if (npc->GetPhR() == 0) { + if (npc->GetPhR() == 0 && is_auto_scaled) { npc->ModifyNPCStat("phr", std::to_string(scale_data.physical_resist).c_str()); } if (npc->GetMinDMG() == 0 && npc->GetMaxDMG() == 0) { From d817f083733904e7a9071ed266c7da6baf4166ca Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 12 Jun 2019 01:27:55 -0500 Subject: [PATCH 08/23] Fix issue with pets causing players to be aggroed and ignoring distance checks --- zone/aggro.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index de83d12e8..934018b77 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -251,9 +251,10 @@ bool Mob::CheckWillAggro(Mob *mob) { return false; } - Mob *ownr = mob->GetOwner(); - if(ownr && ownr->IsClient() && !ownr->CastToClient()->ClientFinishedLoading()) + Mob *pet_owner = mob->GetOwner(); + if (pet_owner && pet_owner->IsClient()) { return false; + } float iAggroRange = GetAggroRange(); From 86ed2c1e76262390c808323f28cdcad943fad8e3 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Wed, 12 Jun 2019 01:50:01 -0500 Subject: [PATCH 09/23] Pets shouldn't be scanning for aggro --- zone/aggro.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 934018b77..4e3c33886 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -251,6 +251,13 @@ bool Mob::CheckWillAggro(Mob *mob) { return false; } + /** + * Pets shouldn't scan for aggro + */ + if (this->GetOwner()) { + return false; + } + Mob *pet_owner = mob->GetOwner(); if (pet_owner && pet_owner->IsClient()) { return false; From 7d1362732da83dfb7621023d777c312aa8f1efdf Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 13 Jun 2019 18:17:37 -0400 Subject: [PATCH 10/23] New Perl/Lua buff functionality. - Mob::FindBuffBySlot(slot) This allows you to find buffs by a specific slot. Example: https://i.imgur.com/VG68cxs.png Perl Example: https://pastebin.com/8HvMAC4h - Mob::BuffCount() This will find the active number of buffs an NPC/client has. Example: https://i.imgur.com/jrLRBwV.png Perl Example: https://pastebin.com/Wmg16wwp --- zone/lua_mob.cpp | 12 +++++++++++ zone/lua_mob.h | 2 ++ zone/mob.h | 2 ++ zone/perl_mob.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++ zone/spells.cpp | 17 +++++++++++++++ 5 files changed, 86 insertions(+) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 471ff6d00..59ff19d28 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -322,6 +322,16 @@ bool Lua_Mob::FindBuff(int spell_id) { return self->FindBuff(spell_id); } +uint16 Lua_Mob::FindBuffBySlot(int slot) { + Lua_Safe_Call_Int(); + return self->FindBuffBySlot(slot); +} + +uint32 Lua_Mob::BuffCount() { + Lua_Safe_Call_Int(); + return self->BuffCount(); +} + bool Lua_Mob::FindType(int type) { Lua_Safe_Call_Bool(); return self->FindType(type); @@ -2218,6 +2228,8 @@ luabind::scope lua_register_mob() { .def("IsInvisible", (bool(Lua_Mob::*)(Lua_Mob))&Lua_Mob::IsInvisible) .def("SetInvisible", &Lua_Mob::SetInvisible) .def("FindBuff", &Lua_Mob::FindBuff) + .def("FindBuffBySlot", (uint16(Lua_Mob::*)(int))&Lua_Mob::FindBuffBySlot) + .def("BuffCount", &Lua_Mob::BuffCount) .def("FindType", (bool(Lua_Mob::*)(int))&Lua_Mob::FindType) .def("FindType", (bool(Lua_Mob::*)(int,bool))&Lua_Mob::FindType) .def("FindType", (bool(Lua_Mob::*)(int,bool,int))&Lua_Mob::FindType) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index b132acbf6..509ef61d4 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -82,6 +82,8 @@ public: bool IsInvisible(Lua_Mob other); void SetInvisible(int state); bool FindBuff(int spell_id); + uint16 FindBuffBySlot(int slot); + uint32 BuffCount(); bool FindType(int type); bool FindType(int type, bool offensive); bool FindType(int type, bool offensive, int threshold); diff --git a/zone/mob.h b/zone/mob.h index a92f5cacb..ea71017c7 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -385,6 +385,8 @@ public: void DamageShield(Mob* other, bool spell_ds = false); int32 RuneAbsorb(int32 damage, uint16 type); bool FindBuff(uint16 spellid); + uint16 FindBuffBySlot(int slot); + uint32 BuffCount(); bool FindType(uint16 type, bool bOffensive = false, uint16 threshold = 100); int16 GetBuffSlotFromType(uint16 type); uint16 GetSpellIDFromSlot(uint8 slot); diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index f7cbfcfea..5dd4ce5be 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -1297,6 +1297,57 @@ XS(XS_Mob_FindBuff) { XSRETURN(1); } +XS(XS_Mob_FindBuffBySlot); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_FindBuffBySlot) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Mob::FindBuffBySlot(THIS, int slot)"); + { + Mob *THIS; + uint16 RETVAL; + dXSTARG; + int slot = SvIV(ST(1)); + + if (sv_derived_from(ST(0), "Mob")) { + IV tmp = SvIV((SV *) SvRV(ST(0))); + THIS = INT2PTR(Mob *, tmp); + } else + Perl_croak(aTHX_ "THIS is not of type Mob"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->FindBuffBySlot(slot); + XSprePUSH; + PUSHu((UV) RETVAL); + } + XSRETURN(1); +} + +XS(XS_Mob_BuffCount); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Mob_BuffCount) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Mob::BuffCount(THIS)"); + { + Mob *THIS; + uint32 RETVAL; + dXSTARG; + + if (sv_derived_from(ST(0), "Mob")) { + IV tmp = SvIV((SV *) SvRV(ST(0))); + THIS = INT2PTR(Mob *, tmp); + } else + Perl_croak(aTHX_ "THIS is not of type Mob"); + if (THIS == nullptr) + Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); + + RETVAL = THIS->BuffCount(); + XSprePUSH; + PUSHu((UV) RETVAL); + } + XSRETURN(1); +} + XS(XS_Mob_FindType); /* prototype to pass -Wmissing-prototypes */ XS(XS_Mob_FindType) { dXSARGS; @@ -8581,6 +8632,8 @@ XS(boot_Mob) { newXSproto(strcpy(buf, "IsInvisible"), XS_Mob_IsInvisible, file, "$;$"); newXSproto(strcpy(buf, "SetInvisible"), XS_Mob_SetInvisible, file, "$$"); newXSproto(strcpy(buf, "FindBuff"), XS_Mob_FindBuff, file, "$$"); + newXSproto(strcpy(buf, "FindBuffBySlot"), XS_Mob_FindBuffBySlot, file, "$$"); + newXSproto(strcpy(buf, "BuffCount"), XS_Mob_BuffCount, file, "$"); newXSproto(strcpy(buf, "FindType"), XS_Mob_FindType, file, "$$;$$"); newXSproto(strcpy(buf, "GetBuffSlotFromType"), XS_Mob_GetBuffSlotFromType, file, "$$"); newXSproto(strcpy(buf, "MakePet"), XS_Mob_MakePet, file, "$$$;$"); diff --git a/zone/spells.cpp b/zone/spells.cpp index 4bcb8b1c3..96818d8a3 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -4032,6 +4032,23 @@ bool Mob::FindBuff(uint16 spellid) return false; } +uint16 Mob::FindBuffBySlot(int slot) { + if (buffs[slot].spellid != SPELL_UNKNOWN) + return buffs[slot].spellid; + + return 0; +} + +uint32 Mob::BuffCount() { + uint32 active_buff_count = 0; + int buff_count = GetMaxTotalSlots(); + for (int i = 0; i < buff_count; i++) + if (buffs[i].spellid != SPELL_UNKNOWN) + active_buff_count++; + + return active_buff_count; +} + // removes all buffs void Mob::BuffFadeAll() { From 9356b5dc7f85415242a29da1b3019560d18da140 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sun, 16 Jun 2019 12:50:32 -0400 Subject: [PATCH 11/23] New Perl/Lua buff functionality. - Client::FindMemmedSpellBySlot(slot) This allows you to find memmed spells by a specific slot. Example: https://i.imgur.com/06OFT3c.png Perl Example: https://pastebin.com/BCr6KqSS - Client::MemmedCount() This will find the number of memmed spells the client has. Example: https://i.imgur.com/cY26DEl.png Perl Example: https://pastebin.com/T3ahSUgi --- zone/client.h | 2 ++ zone/lua_client.cpp | 12 ++++++++++ zone/lua_client.h | 2 ++ zone/perl_client.cpp | 53 ++++++++++++++++++++++++++++++++++++++++++++ zone/spells.cpp | 17 ++++++++++++++ 5 files changed, 86 insertions(+) diff --git a/zone/client.h b/zone/client.h index 94bc3f749..dfdfa8f8f 100644 --- a/zone/client.h +++ b/zone/client.h @@ -781,6 +781,8 @@ public: void UnmemSpell(int slot, bool update_client = true); void UnmemSpellBySpellID(int32 spell_id); void UnmemSpellAll(bool update_client = true); + uint16 FindMemmedSpellBySlot(int slot); + int MemmedCount(); void ScribeSpell(uint16 spell_id, int slot, bool update_client = true); void UnscribeSpell(int slot, bool update_client = true); void UnscribeSpellAll(bool update_client = true); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index fc89db7d9..9447c48af 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -550,6 +550,16 @@ void Lua_Client::UnmemSpellAll(bool update_client) { self->UnmemSpellAll(update_client); } +uint16 Lua_Client::FindMemmedSpellBySlot(int slot) { + Lua_Safe_Call_Int(); + return self->FindMemmedSpellBySlot(slot); +} + +int Lua_Client::MemmedCount() { + Lua_Safe_Call_Int(); + return self->MemmedCount(); +} + void Lua_Client::ScribeSpell(int spell_id, int slot) { Lua_Safe_Call_Void(); self->ScribeSpell(spell_id, slot); @@ -1618,6 +1628,8 @@ luabind::scope lua_register_client() { .def("UnmemSpellBySpellID", (void(Lua_Client::*)(int32))&Lua_Client::UnmemSpellBySpellID) .def("UnmemSpellAll", (void(Lua_Client::*)(void))&Lua_Client::UnmemSpellAll) .def("UnmemSpellAll", (void(Lua_Client::*)(bool))&Lua_Client::UnmemSpellAll) + .def("FindMemmedSpellBySlot", (uint16(Lua_Client::*)(int))&Lua_Client::FindMemmedSpellBySlot) + .def("MemmedCount", (int(Lua_Client::*)(void))&Lua_Client::MemmedCount) .def("ScribeSpell", (void(Lua_Client::*)(int,int))&Lua_Client::ScribeSpell) .def("ScribeSpell", (void(Lua_Client::*)(int,int,bool))&Lua_Client::ScribeSpell) .def("UnscribeSpell", (void(Lua_Client::*)(int))&Lua_Client::UnscribeSpell) diff --git a/zone/lua_client.h b/zone/lua_client.h index 95d6a0f55..fee4d31f0 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -135,6 +135,8 @@ public: void UnmemSpellBySpellID(int32 spell_id); void UnmemSpellAll(); void UnmemSpellAll(bool update_client); + uint16 FindMemmedSpellBySlot(int slot); + int MemmedCount(); void ScribeSpell(int spell_id, int slot); void ScribeSpell(int spell_id, int slot, bool update_client); void UnscribeSpell(int slot); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 9c0ae4200..148aa7731 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -2404,6 +2404,57 @@ XS(XS_Client_UnmemSpellAll) { XSRETURN_EMPTY; } +XS(XS_Client_FindMemmedSpellBySlot); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_FindMemmedSpellBySlot) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: Client::FindMemmedSpellBySlot(THIS, int slot)"); + { + Client *THIS; + uint16 RETVAL; + dXSTARG; + int slot = SvIV(ST(1)); + + 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."); + + RETVAL = THIS->FindMemmedSpellBySlot(slot); + XSprePUSH; + PUSHu((UV) RETVAL); + } + XSRETURN(1); +} + +XS(XS_Client_MemmedCount); /* prototype to pass -Wmissing-prototypes */ +XS(XS_Client_MemmedCount) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: Client::MemmedCount(THIS)"); + { + Client *THIS; + uint32 RETVAL; + dXSTARG; + + 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."); + + RETVAL = THIS->MemmedCount(); + XSprePUSH; + PUSHu((UV) RETVAL); + } + XSRETURN(1); +} + XS(XS_Client_ScribeSpell); /* prototype to pass -Wmissing-prototypes */ XS(XS_Client_ScribeSpell) { dXSARGS; @@ -6478,6 +6529,8 @@ XS(boot_Client) { newXSproto(strcpy(buf, "UnmemSpell"), XS_Client_UnmemSpell, file, "$$;$"); newXSproto(strcpy(buf, "UnmemSpellAll"), XS_Client_UnmemSpellAll, file, "$;$"); newXSproto(strcpy(buf, "UnmemSpellBySpellID"), XS_Client_UnmemSpellBySpellID, file, "$$"); + newXSproto(strcpy(buf, "FindMemmedSpellBySlot"), XS_Client_FindMemmedSpellBySlot, file, "$$"); + newXSproto(strcpy(buf, "MemmedCount"), XS_Client_MemmedCount, file, "$"); newXSproto(strcpy(buf, "UnscribeSpell"), XS_Client_UnscribeSpell, file, "$$;$"); newXSproto(strcpy(buf, "UnscribeSpellAll"), XS_Client_UnscribeSpellAll, file, "$;$"); newXSproto(strcpy(buf, "UntrainDisc"), XS_Client_UntrainDisc, file, "$$;$"); diff --git a/zone/spells.cpp b/zone/spells.cpp index 96818d8a3..45850fe07 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5056,6 +5056,23 @@ void Client::UnmemSpellAll(bool update_client) UnmemSpell(i, update_client); } +uint16 Client::FindMemmedSpellBySlot(int slot) { + if (m_pp.mem_spells[slot] != 0xFFFFFFFF) + return m_pp.mem_spells[slot]; + + return 0; +} + +int Client::MemmedCount() { + int memmed_count = 0; + for (int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) + if (m_pp.mem_spells[i] != 0xFFFFFFFF) + memmed_count++; + + return memmed_count; +} + + void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client) { if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0) From 51c51b0d7209c025b10eb288db5e2a8b67021065 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Sun, 16 Jun 2019 19:54:45 -0400 Subject: [PATCH 12/23] Export Mob::GetItemStat(item_id, identifier) to Lua. --- zone/lua_mob.cpp | 6 ++++++ zone/lua_mob.h | 1 + 2 files changed, 7 insertions(+) diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 59ff19d28..e801f07dc 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -2101,6 +2101,11 @@ int Lua_Mob::GetWeaponDamageBonus(Lua_Item weapon, bool offhand) { return self->GetWeaponDamageBonus(weapon, offhand); } +int Lua_Mob::GetItemStat(uint32 itemid, const char* identifier) { + Lua_Safe_Call_Int(); + return self->GetItemStat(itemid, identifier); +} + Lua_StatBonuses Lua_Mob::GetItemBonuses() { Lua_Safe_Call_Class(Lua_StatBonuses); @@ -2260,6 +2265,7 @@ luabind::scope lua_register_mob() { .def("IsWarriorClass", &Lua_Mob::IsWarriorClass) .def("GetHP", &Lua_Mob::GetHP) .def("GetMaxHP", &Lua_Mob::GetMaxHP) + .def("GetItemStat", (int(Lua_Mob::*)(uint32,const char*))&Lua_Mob::GetItemStat) .def("GetItemHPBonuses", &Lua_Mob::GetItemHPBonuses) .def("GetSpellHPBonuses", &Lua_Mob::GetSpellHPBonuses) .def("GetWalkspeed", &Lua_Mob::GetWalkspeed) diff --git a/zone/lua_mob.h b/zone/lua_mob.h index 509ef61d4..e7dcc1ee3 100644 --- a/zone/lua_mob.h +++ b/zone/lua_mob.h @@ -404,6 +404,7 @@ public: bool IsAmnesiad(); int32 GetMeleeMitigation(); int GetWeaponDamageBonus(Lua_Item weapon, bool offhand); + int GetItemStat(uint32 itemid, const char* identifier); Lua_StatBonuses GetItemBonuses(); Lua_StatBonuses GetSpellBonuses(); Lua_StatBonuses GetAABonuses(); From 0541eec8bff4453fac7c3c224abd426c6b0e073d Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 19 Jun 2019 17:47:24 -0400 Subject: [PATCH 13/23] Fix for thrown weapons hitting self --- zone/special_attacks.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index 1e38b481b..bcffa4077 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -1278,6 +1278,7 @@ void Client::ThrowingAttack(Mob* other, bool CanDoubleAttack) { //old was 51 } else if(dist < (RuleI(Combat, MinRangedAttackDist)*RuleI(Combat, MinRangedAttackDist))){ Message_StringID(15,RANGED_TOO_CLOSE);//Client enforces range and sends the message, this is a backup just incase. + return; } if(!IsAttackAllowed(other) || From 6256660972321914cdbabb0a1731528eb51e5616 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 19 Jun 2019 20:01:57 -0400 Subject: [PATCH 14/23] Fix for possible memory leak with mercenaries and bots --- zone/entity.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index ad8d1fb1b..1b636d329 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -509,16 +509,16 @@ void EntityList::MobProcess() } if(mob_dead) { - if(mob->IsNPC()) { - entity_list.RemoveNPC(id); - } - else if(mob->IsMerc()) { + if(mob->IsMerc()) { entity_list.RemoveMerc(id); -#ifdef BOTS } +#ifdef BOTS else if(mob->IsBot()) { entity_list.RemoveBot(id); + } #endif + else if(mob->IsNPC()) { + entity_list.RemoveNPC(id); } else { #ifdef _WINDOWS From 104edee427ca5c8a1b6b2ef42b0d119138c25050 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 19 Jun 2019 23:20:43 -0400 Subject: [PATCH 15/23] Fix for fishing not working correctly (thanks mackal!) --- zone/forage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/forage.cpp b/zone/forage.cpp index 77361ce33..3bdb87d7a 100644 --- a/zone/forage.cpp +++ b/zone/forage.cpp @@ -180,7 +180,7 @@ bool Client::CanFish() { const float LineLength = RuleR(Watermap, FishingLineLength); int HeadingDegrees; - HeadingDegrees = (int) ((GetHeading()*360)/256); + HeadingDegrees = (int) ((GetHeading()*360)/512); HeadingDegrees = HeadingDegrees % 360; rodPosition.x = m_Position.x + RodLength * sin(HeadingDegrees * M_PI/180.0f); From a2a13e97798e7d11dbfef28bcae6e0550642dfcf Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 20 Jun 2019 19:37:08 -0400 Subject: [PATCH 16/23] Revert "fixed opcode for deleteing a item out of a player's inventory slot" This reverts commit 65e429a59665b49cfcfb80b0d3e9a486080d906e. --- zone/inventory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index e86610697..9c802b5a3 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -972,8 +972,8 @@ void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_upd safe_delete(outapp); } else { - outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); - DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; + outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); + MoveItem_Struct* delitem = (MoveItem_Struct*)outapp->pBuffer; delitem->from_slot = slot_id; delitem->to_slot = 0xFFFFFFFF; delitem->number_in_stack = 0xFFFFFFFF; From ca874cb8612d9586616d17bf15d448b19dae8aaf Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 20 Jun 2019 22:09:49 -0400 Subject: [PATCH 17/23] Fix for NukeItem not taking items from general bags properly --- zone/inventory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 9c802b5a3..ec4f095b0 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -98,7 +98,7 @@ uint32 Client::NukeItem(uint32 itemnum, uint8 where_to_check) { x++; } - DeleteItemInInventory(i, 0, ((((uint64)1 << (EQEmu::invslot::GENERAL_BEGIN + ((i - EQEmu::invbag::GENERAL_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT))) & GetInv().GetLookup()->PossessionsBitmask) == 0)); + DeleteItemInInventory(i, 0, ((((uint64)1 << (EQEmu::invslot::GENERAL_BEGIN + ((i - EQEmu::invbag::GENERAL_BAGS_BEGIN) / EQEmu::invbag::SLOT_COUNT))) & GetInv().GetLookup()->PossessionsBitmask) != 0)); } } } From e903b06c224d3672da6fbc96ed6fbdaab70d67bb Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 21 Jun 2019 06:00:58 -0400 Subject: [PATCH 18/23] Added const cast Entity::CastToBot() --- zone/aggro.cpp | 1 + zone/entity.cpp | 11 +++++++++++ zone/entity.h | 1 + zone/perl_client.cpp | 28 ++++++++++++++++------------ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 4e3c33886..8a3da1092 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -735,6 +735,7 @@ type', in which case, the answer is yes. } #ifdef BOTS + // this is HIGHLY inefficient bool HasRuleDefined = false; bool IsBotAttackAllowed = false; IsBotAttackAllowed = Bot::IsBotAttackAllowed(mob1, mob2, HasRuleDefined); diff --git a/zone/entity.cpp b/zone/entity.cpp index 1b636d329..d1ecfc990 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -286,6 +286,17 @@ Bot *Entity::CastToBot() #endif return static_cast(this); } + +const Bot *Entity::CastToBot() const +{ +#ifdef _EQDEBUG + if (!IsBot()) { + std::cout << "CastToBot error" << std::endl; + return 0; + } +#endif + return static_cast(this); +} #endif EntityList::EntityList() diff --git a/zone/entity.h b/zone/entity.h index b815dc396..fb9b1f09b 100644 --- a/zone/entity.h +++ b/zone/entity.h @@ -116,6 +116,7 @@ public: #ifdef BOTS Bot* CastToBot(); + const Bot* CastToBot() const; #endif protected: diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 148aa7731..be1bf2a8e 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -1233,15 +1233,17 @@ XS(XS_Client_MovePC) { if (THIS->IsMerc()) { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Merc reference"); - } else if (THIS->IsNPC()) { + } +#ifdef BOTS + else if (THIS->IsBot()) { + Log(Logs::Detail, Logs::None, + "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Bot reference"); + } +#endif + else if (THIS->IsNPC()) { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type NPC reference"); } -#ifdef BOTS - else if (THIS->IsBot()) { - Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process a type Bot reference"); - } -#endif else { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePC) attempted to process an Unknown type reference"); @@ -1283,15 +1285,17 @@ XS(XS_Client_MovePCInstance) { if (THIS->IsMerc()) { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Merc reference"); - } else if (THIS->IsNPC()) { + } +#ifdef BOTS + else if (THIS->IsBot()) { + Log(Logs::Detail, Logs::None, + "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Bot reference"); + } +#endif + else if (THIS->IsNPC()) { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type NPC reference"); } -#ifdef BOTS - else if (THIS->IsBot()) { - Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process a type Bot reference"); - } -#endif else { Log(Logs::Detail, Logs::None, "[CLIENT] Perl(XS_Client_MovePCInstance) attempted to process an Unknown type reference"); From 2cd910ad864b9c40387bbaba9cb7bcfe1453f3d7 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 21 Jun 2019 07:58:47 -0400 Subject: [PATCH 19/23] Added ping() call to botdb --- zone/net.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zone/net.cpp b/zone/net.cpp index 6800e078d..9be5074f2 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -544,6 +544,7 @@ int main(int argc, char** argv) { if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); + botdb.ping(); entity_list.UpdateWho(); } }; From a8d3ba41a7c5e4749bb9b843ac0c7e7b581b5fd6 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 21 Jun 2019 18:36:33 -0400 Subject: [PATCH 20/23] Fix for non-BOTS compile failure --- zone/net.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zone/net.cpp b/zone/net.cpp index 9be5074f2..522512f51 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -544,7 +544,9 @@ int main(int argc, char** argv) { if (InterserverTimer.Check()) { InterserverTimer.Start(); database.ping(); +#ifdef BOTS botdb.ping(); +#endif entity_list.UpdateWho(); } }; From 5d138891d89833d7dae764b2ecc59755e7ab8655 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 22 Jun 2019 06:42:06 -0400 Subject: [PATCH 21/23] Fix for insufficient spell mana logging --- zone/spells.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/spells.cpp b/zone/spells.cpp index 45850fe07..8b1a08d19 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -455,7 +455,7 @@ bool Mob::DoCastSpell(uint16 spell_id, uint16 target_id, CastingSlot slot, { mana_cost = 0; } else { - Log(Logs::Detail, Logs::Spells, "Spell Error not enough mana spell=%d mymana=%d cost=%d\n", GetName(), spell_id, my_curmana, mana_cost); + Log(Logs::Detail, Logs::Spells, "Spell Error not enough mana spell=%d mymana=%d cost=%d\n", spell_id, my_curmana, mana_cost); if(IsClient()) { //clients produce messages... npcs should not for this case Message_StringID(13, INSUFFICIENT_MANA); From c9d4bb178fa7fad279ee2aa3d316b5ad3d9eab0e Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 22 Jun 2019 19:05:41 -0400 Subject: [PATCH 22/23] Added level to NPC spell list logging .. and some additional debug logging for same --- zone/mob_ai.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index 1f79fa5c1..0df05254e 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -2436,7 +2436,7 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { } DBnpcspells_Struct* parentlist = database.GetNPCSpells(spell_list->parent_list); #if MobAI_DEBUG_Spells >= 10 - std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u", this->GetName(), iDBSpellsID); + std::string debug_msg = StringFormat("Loading NPCSpells onto %s: dbspellsid=%u, level=%u", this->GetName(), iDBSpellsID, this->GetLevel()); if (spell_list) { debug_msg.append(StringFormat(" (found, %u), parentlist=%u", spell_list->entries.size(), spell_list->parent_list)); if (spell_list->parent_list) { @@ -2450,6 +2450,22 @@ bool NPC::AI_AddNPCSpells(uint32 iDBSpellsID) { debug_msg.append(" (not found)"); } Log(Logs::Detail, Logs::AI, "%s", debug_msg.c_str()); + +#ifdef MobAI_DEBUG_Spells >= 25 + if (parentlist) { + for (const auto &iter : parentlist->entries) { + Log(Logs::Detail, Logs::AI, "(%i) %s", iter.spellid, spells[iter.spellid].name); + } + } + Log(Logs::Detail, Logs::AI, "fin (parent list)"); + if (spell_list) { + for (const auto &iter : spell_list->entries) { + Log(Logs::Detail, Logs::AI, "(%i) %s", iter.spellid, spells[iter.spellid].name); + } + } + Log(Logs::Detail, Logs::AI, "fin (spell list)"); +#endif + #endif uint16 attack_proc_spell = -1; int8 proc_chance = 3; From 2e9cf7dbd7479f18a405adbc20f0cf3a53bdf934 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 22 Jun 2019 22:53:35 -0400 Subject: [PATCH 23/23] Added bot owner option 'stats update' --- common/version.h | 2 +- .../sql/git/bots/bots_db_update_manifest.txt | 1 + ...9_06_22_bots_owner_option_stats_update.sql | 1 + zone/bot.cpp | 5 +++- zone/bot_command.cpp | 28 +++++++++++++++---- zone/bot_database.cpp | 22 ++++++++++++++- zone/bot_database.h | 1 + zone/client.h | 6 +++- 8 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 utils/sql/git/bots/required/2019_06_22_bots_owner_option_stats_update.sql diff --git a/common/version.h b/common/version.h index 2d3df779d..1684fe0d2 100644 --- a/common/version.h +++ b/common/version.h @@ -34,7 +34,7 @@ #define CURRENT_BINARY_DATABASE_VERSION 9139 #ifdef BOTS - #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9022 + #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9023 #else #define CURRENT_BINARY_BOTS_DATABASE_VERSION 0 // must be 0 #endif diff --git a/utils/sql/git/bots/bots_db_update_manifest.txt b/utils/sql/git/bots/bots_db_update_manifest.txt index bb1cd70d9..21aa4161b 100644 --- a/utils/sql/git/bots/bots_db_update_manifest.txt +++ b/utils/sql/git/bots/bots_db_update_manifest.txt @@ -21,6 +21,7 @@ 9020|2018_08_13_bots_inventory_update.sql|SELECT * FROM `inventory_versions` WHERE `version` = 2 and `bot_step` = 0|not_empty| 9021|2018_10_09_bots_owner_options.sql|SHOW TABLES LIKE 'bot_owner_options'|empty| 9022|2019_02_07_bots_stance_type_update.sql|SELECT * FROM `bot_spell_casting_chances` WHERE `spell_type_index` = '255' AND `class_id` = '255' AND `stance_index` = '0'|not_empty| +9023|2019_06_22_bots_owner_option_stats_update.sql|SHOW COLUMNS FROM `bot_owner_options` LIKE 'stats_update'|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/bots/required/2019_06_22_bots_owner_option_stats_update.sql b/utils/sql/git/bots/required/2019_06_22_bots_owner_option_stats_update.sql new file mode 100644 index 000000000..15b09020f --- /dev/null +++ b/utils/sql/git/bots/required/2019_06_22_bots_owner_option_stats_update.sql @@ -0,0 +1 @@ +ALTER TABLE `bot_owner_options` ADD COLUMN `stats_update` SMALLINT(3) UNSIGNED NULL DEFAULT '0' AFTER `death_marquee`; diff --git a/zone/bot.cpp b/zone/bot.cpp index 143520076..04b4d49c9 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -3499,7 +3499,7 @@ void Bot::LevelBotWithClient(Client* client, uint8 level, bool sendlvlapp) { Bot* bot = *biter; if(bot && (bot->GetLevel() != client->GetLevel())) { bot->SetPetChooser(false); // not sure what this does, but was in bot 'update' code - bot->CalcBotStats(false); // TODO: look at this and see if 'true' should be passed... + bot->CalcBotStats(client->GetBotOptionStatsUpdate()); if(sendlvlapp) bot->SendLevelAppearance(); // modified from Client::SetLevel() @@ -4176,6 +4176,9 @@ void Bot::PerformTradeWithClient(int16 beginSlotID, int16 endSlotID, Client* cli size_t returned_count = client_return.size(); client->Message(CC_Lime, "Trade with '%s' resulted in %i accepted item%s, %i returned item%s.", GetCleanName(), accepted_count, ((accepted_count == 1) ? "" : "s"), returned_count, ((returned_count == 1) ? "" : "s")); + + if (accepted_count) + CalcBotStats(client->GetBotOptionStatsUpdate()); } bool Bot::Death(Mob *killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill) { diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index 085a730ea..0a32a1cb1 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -3441,16 +3441,34 @@ void bot_command_movement_speed(Client *c, const Seperator *sep) void bot_command_owner_option(Client *c, const Seperator *sep) { if (helper_is_help_or_usage(sep->arg[1])) { - c->Message(m_usage, "usage: %s [deathmarquee]", sep->arg[0]); + c->Message(m_usage, "usage: %s [deathmarquee | statsupdate] (argument: enable | disable | null (toggles))", sep->arg[0]); return; } std::string owner_option = sep->arg[1]; + std::string flag = sep->arg[2]; if (!owner_option.compare("deathmarquee")) { - c->SetBotOptionDeathMarquee(!c->GetBotOptionDeathMarquee()); - c->Message(m_action, "Bot death marquee is now %s.", (c->GetBotOptionDeathMarquee() == true ? "enabled" : "disabled")); + if (!flag.compare("enable")) + c->SetBotOptionDeathMarquee(true); + else if (!flag.compare("disable")) + c->SetBotOptionDeathMarquee(false); + else + c->SetBotOptionDeathMarquee(!c->GetBotOptionDeathMarquee()); + botdb.SaveOwnerOptionDeathMarquee(c->CharacterID(), c->GetBotOptionDeathMarquee()); + c->Message(m_action, "Bot 'death marquee' is now %s.", (c->GetBotOptionDeathMarquee() == true ? "enabled" : "disabled")); + } + else if (!owner_option.compare("statsupdate")) { + if (!flag.compare("enable")) + c->SetBotOptionStatsUpdate(true); + else if (!flag.compare("disable")) + c->SetBotOptionStatsUpdate(false); + else + c->SetBotOptionStatsUpdate(!c->GetBotOptionStatsUpdate()); + + botdb.SaveOwnerOptionStatsUpdate(c->CharacterID(), c->GetBotOptionStatsUpdate()); + c->Message(m_action, "Bot 'stats update' is now %s.", (c->GetBotOptionStatsUpdate() == true ? "enabled" : "disabled")); } else { c->Message(m_fail, "Owner option '%s' is not recognized.", owner_option.c_str()); @@ -5532,7 +5550,7 @@ void bot_subcommand_bot_update(Client *c, const Seperator *sep) continue; bot_iter->SetPetChooser(false); - bot_iter->CalcBotStats((sbl.size() == 1)); + bot_iter->CalcBotStats(c->GetBotOptionStatsUpdate()); bot_iter->SendAppearancePacket(AT_WhoLevel, bot_iter->GetLevel(), true, true); ++bot_count; } @@ -7321,7 +7339,7 @@ void bot_subcommand_inventory_remove(Client *c, const Seperator *sep) } my_bot->BotRemoveEquipItem(slotId); - my_bot->CalcBotStats(); + my_bot->CalcBotStats(c->GetBotOptionStatsUpdate()); } switch (slotId) { diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index ea5154598..90f184fa8 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -2188,7 +2188,7 @@ bool BotDatabase::LoadOwnerOptions(Client *owner) return false; query = StringFormat( - "SELECT `death_marquee` FROM `bot_owner_options`" + "SELECT `death_marquee`, `stats_update` FROM `bot_owner_options`" " WHERE `owner_id` = '%u'", owner->CharacterID() ); @@ -2204,6 +2204,7 @@ bool BotDatabase::LoadOwnerOptions(Client *owner) auto row = results.begin(); owner->SetBotOptionDeathMarquee((atoi(row[0]) != 0)); + owner->SetBotOptionStatsUpdate((atoi(row[1]) != 0)); return true; } @@ -2227,6 +2228,25 @@ bool BotDatabase::SaveOwnerOptionDeathMarquee(const uint32 owner_id, const bool return true; } +bool BotDatabase::SaveOwnerOptionStatsUpdate(const uint32 owner_id, const bool flag) +{ + if (!owner_id) + return false; + + query = StringFormat( + "UPDATE `bot_owner_options`" + " SET `stats_update` = '%u'" + " WHERE `owner_id` = '%u'", + (flag == true ? 1 : 0), + owner_id + ); + auto results = QueryDatabase(query); + if (!results.Success()) + return false; + + return true; +} + /* Bot bot-group functions */ bool BotDatabase::QueryBotGroupExistence(const std::string& group_name, bool& extant_flag) diff --git a/zone/bot_database.h b/zone/bot_database.h index 2840c415c..613c73967 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -148,6 +148,7 @@ public: bool LoadOwnerOptions(Client *owner); bool SaveOwnerOptionDeathMarquee(const uint32 owner_id, const bool flag); + bool SaveOwnerOptionStatsUpdate(const uint32 owner_id, const bool flag); /* Bot bot-group functions */ bool QueryBotGroupExistence(const std::string& botgroup_name, bool& extant_flag); diff --git a/zone/client.h b/zone/client.h index dfdfa8f8f..2adc2ea21 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1642,18 +1642,22 @@ private: #ifdef BOTS struct BotOwnerOptions { bool death_marquee; + bool stats_update; }; BotOwnerOptions bot_owner_options; const BotOwnerOptions DefaultBotOwnerOptions = { - false // death_marquee + false, // death_marquee + false // stats_update }; public: void SetBotOptionDeathMarquee(bool flag) { bot_owner_options.death_marquee = flag; } + void SetBotOptionStatsUpdate(bool flag) { bot_owner_options.stats_update = flag; } bool GetBotOptionDeathMarquee() const { return bot_owner_options.death_marquee; } + bool GetBotOptionStatsUpdate() const { return bot_owner_options.stats_update; } private: #endif