diff --git a/README.md b/README.md index baac6618e..47b835788 100644 --- a/README.md +++ b/README.md @@ -17,10 +17,7 @@ |:---:|:---:|:---:| |**Install Count**|![Windows Install Count](http://analytics.akkadius.com/?install_count&windows_count)|![Linux Install Count](http://analytics.akkadius.com/?install_count&linux_count)| ### > Windows -* [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) - - +* [Install](https://github.com/EQEmu/Server/wiki/Windows-Server) ### > Debian/Ubuntu/CentOS/Fedora * You can use curl or wget to kick off the installer (whichever your OS has) @@ -55,7 +52,7 @@ forum, although pull requests will be much quicker and easier on all parties. ## Resources - [EQEmulator Forums](http://www.eqemulator.org/forums) -- [EQEmulator Wiki](http://wiki.eqemulator.org/i?M=Wiki) +- [EQEmulator Wiki](https://github.com/EQEmu/Server/wiki) ## Related Repositories * [ProjectEQ Quests](https://github.com/ProjectEQ/projecteqquests) diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index d5cdbdb25..f04e9a93b 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -472,16 +472,6 @@ bool Database::CheckDatabaseConversions() { CheckDatabaseConvertPPDeblob(); CheckDatabaseConvertCorpseDeblob(); - /* Fetch EQEmu Server script */ - if (!std::ifstream("eqemu_server.pl")){ - std::cout << "Pulling down automatic database upgrade script..." << std::endl; -#ifdef _WIN32 - system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""); -#else - system("wget --no-check-certificate -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); -#endif - } - /* Run EQEmu Server script (Checks for database updates) */ system("perl eqemu_server.pl ran_from_world"); diff --git a/common/eqemu_config.cpp b/common/eqemu_config.cpp index 96980f834..3516f15d1 100644 --- a/common/eqemu_config.cpp +++ b/common/eqemu_config.cpp @@ -23,351 +23,112 @@ #include #include -std::string EQEmuConfig::ConfigFile = "eqemu_config.xml"; +std::string EQEmuConfig::ConfigFile = "eqemu_config.json"; EQEmuConfig *EQEmuConfig::_config = nullptr; -void EQEmuConfig::do_world(TiXmlElement *ele) -{ - const char *text; - TiXmlElement * sub_ele;; - text = ParseTextBlock(ele, "shortname"); - if (text) { - ShortName = text; - } - text = ParseTextBlock(ele, "longname"); - if (text) { - LongName = text; - } - text = ParseTextBlock(ele, "address", true); - if (text) { - WorldAddress = text; - } - text = ParseTextBlock(ele, "localaddress", true); - if (text) { - LocalAddress = text; - } - text = ParseTextBlock(ele, "maxclients", true); - if (text) { - MaxClients = atoi(text); - } - // Get the element - text = ParseTextBlock(ele, "key", true); - if (text) { - SharedKey = text; - } - // Get the element - sub_ele = ele->FirstChildElement("loginserver"); - if (sub_ele) { - text = ParseTextBlock(sub_ele, "host", true); - if (text) { - LoginHost = text; - } - text = ParseTextBlock(sub_ele, "port", true); - if (text) { - LoginPort = atoi(text); - } - text = ParseTextBlock(sub_ele, "legacy", true); - if (text) { - LoginLegacy = atoi(text) > 0 ? true : false; - } - text = ParseTextBlock(sub_ele, "account", true); - if (text) { - LoginAccount = text; - } - text = ParseTextBlock(sub_ele, "password", true); - if (text) { - LoginPassword = text; - } +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; + + 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()); + LoginLegacy = false; + 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 { - char str[32]; + char str[32]; + loginlist.Clear(); do { sprintf(str, "loginserver%i", ++LoginCount); - sub_ele = ele->FirstChildElement(str); - if (sub_ele) { - auto loginconfig = new LoginConfig; - text = ParseTextBlock(sub_ele, "host", true); - if (text) { - loginconfig->LoginHost = text; - } - text = ParseTextBlock(sub_ele, "port", true); - if (text) { - loginconfig->LoginPort = atoi(text); - } - text = ParseTextBlock(sub_ele, "legacy", true); - if (text) { - loginconfig->LoginLegacy = atoi(text) > 0 ? true : false; - } - text = ParseTextBlock(sub_ele, "account", true); - if (text) { - loginconfig->LoginAccount = text; - } - text = ParseTextBlock(sub_ele, "password", true); - if (text) { - loginconfig->LoginPassword = text; - } - loginlist.Insert(loginconfig); + if (!_root["server"]["world"][str].isObject()) { + break; } - } while (sub_ele); - } - // Check for locked - sub_ele = ele->FirstChildElement("locked"); - if (sub_ele != nullptr) { - Locked = true; - } - // Get the element - sub_ele = ele->FirstChildElement("tcp"); - if (sub_ele != nullptr) { - text = sub_ele->Attribute("ip"); - if (text) { - WorldIP = text; - } - text = sub_ele->Attribute("port"); - if (text) { - WorldTCPPort = atoi(text); - } - } - sub_ele = ele->FirstChildElement("telnet"); - if (sub_ele != nullptr) { - text = sub_ele->Attribute("ip"); - if (text) { - TelnetIP = text; - } - text = sub_ele->Attribute("port"); - if (text) { - TelnetTCPPort = atoi(text); - } - text = sub_ele->Attribute("enabled"); - if (text && !strcasecmp(text, "true")) { - TelnetEnabled = true; - } - } + 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->LoginPassword = _root["server"]["world"][str].get("password", "").asString(); - // Get the element - sub_ele = ele->FirstChildElement("http"); - if (sub_ele != nullptr) { -// text = sub_ele->Attribute("ip"); -// if (text) -// WorldIP=text; - text = sub_ele->Attribute("mimefile"); - if (text) { - WorldHTTPMimeFile = text; - } - text = sub_ele->Attribute("port"); - if (text) { - WorldHTTPPort = atoi(text); - } - text = sub_ele->Attribute("enabled"); - if (text && !strcasecmp(text, "true")) { - WorldHTTPEnabled = true; - } + loginconfig->LoginLegacy = false; + 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(); + WorldTCPPort = atoi(_root["server"]["world"]["tcp"].get("port", "9000").asString().c_str()); + + 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; + + 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; + + 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()); + + 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(); + + 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(); + + 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()); + + 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(); + + 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(); + SharedMemDir = _root["server"]["directories"].get("shared_memory", "shared/").asString(); + LogDir = _root["server"]["directories"].get("logs", "logs/").asString(); + + 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()); + ZoneBootInterval = atoi(_root["server"]["launcher"]["timers"].get("interval", "2000").asString().c_str()); +#ifdef WIN32 + ZoneExe = _root["server"]["launcher"].get("exe", "zone.exe").asString(); +#else + ZoneExe = _root["server"]["launcher"].get("exe", "./zone").asString(); +#endif + } - -void EQEmuConfig::do_chatserver(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "host", true); - if (text) { - ChatHost = text; - } - text = ParseTextBlock(ele, "port", true); - if (text) { - ChatPort = atoi(text); - } -} - -void EQEmuConfig::do_mailserver(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "host", true); - if (text) { - MailHost = text; - } - text = ParseTextBlock(ele, "port", true); - if (text) { - MailPort = atoi(text); - } -} - -void EQEmuConfig::do_database(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "host", true); - if (text) { - DatabaseHost = text; - } - text = ParseTextBlock(ele, "port", true); - if (text) { - DatabasePort = atoi(text); - } - text = ParseTextBlock(ele, "username", true); - if (text) { - DatabaseUsername = text; - } - text = ParseTextBlock(ele, "password", true); - if (text) { - DatabasePassword = text; - } - text = ParseTextBlock(ele, "db", true); - if (text) { - DatabaseDB = text; - } -} - - -void EQEmuConfig::do_qsdatabase(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "host", true); - if (text) { - QSDatabaseHost = text; - } - text = ParseTextBlock(ele, "port", true); - if (text) { - QSDatabasePort = atoi(text); - } - text = ParseTextBlock(ele, "username", true); - if (text) { - QSDatabaseUsername = text; - } - text = ParseTextBlock(ele, "password", true); - if (text) { - QSDatabasePassword = text; - } - text = ParseTextBlock(ele, "db", true); - if (text) { - QSDatabaseDB = text; - } -} - -void EQEmuConfig::do_zones(TiXmlElement *ele) -{ - const char *text; - TiXmlElement *sub_ele; -// TiXmlNode *node,*sub_node; - text = ParseTextBlock(ele, "defaultstatus", true); - if (text) { - DefaultStatus = atoi(text); - } - // Get the element - sub_ele = ele->FirstChildElement("ports"); - if (sub_ele != nullptr) { - text = sub_ele->Attribute("low"); - if (text) { - ZonePortLow = atoi(text); - }; - text = sub_ele->Attribute("high"); - if (text) { - ZonePortHigh = atoi(text); - } - } -} - -void EQEmuConfig::do_files(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "spells", true); - if (text) { - SpellsFile = text; - } - text = ParseTextBlock(ele, "opcodes", true); - if (text) { - OpCodesFile = text; - } - text = ParseTextBlock(ele, "plugin.pl", true); - if (text) { - PluginPlFile = text; - } -} - -void EQEmuConfig::do_directories(TiXmlElement *ele) -{ - const char *text; - text = ParseTextBlock(ele, "maps", true); - if (text) { - MapDir = text; - if ( MapDir.back() != '/' ) - MapDir += '/'; - } - text = ParseTextBlock(ele, "quests", true); - if (text) { - QuestDir = text; - if ( QuestDir.back() != '/' ) - QuestDir += '/'; - } - text = ParseTextBlock(ele, "plugins", true); - if (text) { - PluginDir = text; - if ( PluginDir.back() != '/' ) - PluginDir += '/'; - } - text = ParseTextBlock(ele, "lua_modules", true); - if (text) { - LuaModuleDir = text; - if ( LuaModuleDir.back() != '/' ) - LuaModuleDir += '/'; - } - text = ParseTextBlock(ele, "patches", true); - if (text) { - PatchDir = text; - if ( PatchDir.back() != '/' ) - PatchDir += '/'; - } - text = ParseTextBlock(ele, "shared_memory", true); - if (text) { - SharedMemDir = text; - if ( SharedMemDir.back() != '/' ) - SharedMemDir += '/'; - } - //Not Fully Implemented yet LogDir - text = ParseTextBlock(ele, "logs", true); - if (text) { - LogDir = text; - if ( LogDir.back() != '/' ) - LogDir += '/'; - } -} - -void EQEmuConfig::do_launcher(TiXmlElement *ele) -{ - const char *text; - TiXmlElement *sub_ele; - text = ParseTextBlock(ele, "logprefix", true); - if (text) { - LogPrefix = text; - } - text = ParseTextBlock(ele, "logsuffix", true); - if (text) { - LogSuffix = text; - } - // Get the element - text = ParseTextBlock(ele, "exe", true); - if (text) { - ZoneExe = text; - } - // Get the element - sub_ele = ele->FirstChildElement("timers"); - if (sub_ele != nullptr) { - text = sub_ele->Attribute("restart"); - if (text) { - RestartWait = atoi(text); - } - text = sub_ele->Attribute("reterminate"); - if (text) { - TerminateWait = atoi(text); - } - text = sub_ele->Attribute("initial"); - if (text) { - InitialBootWait = atoi(text); - } - text = sub_ele->Attribute("interval"); - if (text) { - ZoneBootInterval = atoi(text); - } - } -} - std::string EQEmuConfig::GetByName(const std::string &var_name) const { if (var_name == "ShortName") { @@ -564,4 +325,3 @@ void EQEmuConfig::Dump() const 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 0f51f550f..66cf962c6 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -18,8 +18,9 @@ #ifndef __EQEmuConfig_H #define __EQEmuConfig_H -#include "xml_parser.h" +#include "json/json.h" #include "linked_list.h" +#include struct LoginConfig { std::string LoginHost; @@ -29,7 +30,7 @@ struct LoginConfig { bool LoginLegacy; }; -class EQEmuConfig : public XMLParser +class EQEmuConfig { public: virtual std::string GetByName(const std::string &var_name) const; @@ -115,88 +116,14 @@ class EQEmuConfig : public XMLParser protected: static EQEmuConfig *_config; - + Json::Value _root; static std::string ConfigFile; -#define ELEMENT(name) \ - void do_##name(TiXmlElement *ele); -#include "eqemu_config_elements.h" - + void parse_config(); EQEmuConfig() - { - // import the needed handler prototypes -#define ELEMENT(name) \ - Handlers[#name]=(ElementHandler)&EQEmuConfig::do_##name; -#include "eqemu_config_elements.h" - // Set sane defaults - // Login server - LoginHost = "login.eqemulator.net"; - LoginPort = 5998; - LoginLegacy = false; - // World - Locked = false; - WorldTCPPort = 9000; - TelnetTCPPort = 9001; - TelnetEnabled = false; - WorldHTTPEnabled = false; - WorldHTTPPort = 9080; - WorldHTTPMimeFile = "mime.types"; - SharedKey = ""; //blank disables authentication - // Mail - ChatHost = "eqchat.eqemulator.net"; - ChatPort = 7778; - // Mail - MailHost = "eqmail.eqemulator.net"; - MailPort = 7779; - // Mysql - DatabaseHost = "localhost"; - DatabasePort = 3306; - DatabaseUsername = "eq"; - DatabasePassword = "eq"; - DatabaseDB = "eq"; - // QueryServ Database - QSDatabaseHost = "localhost"; - QSDatabasePort = 3306; - QSDatabaseUsername = "eq"; - QSDatabasePassword = "eq"; - QSDatabaseDB = "eq"; - // Files - SpellsFile = "spells_us.txt"; - OpCodesFile = "opcodes.conf"; - PluginPlFile = "plugin.pl"; - // Dirs - MapDir = "Maps/"; - QuestDir = "quests/"; - PluginDir = "plugins/"; - LuaModuleDir = "lua_modules/"; - PatchDir = "./"; - SharedMemDir = "shared/"; - LogDir = "logs/"; + { - // Launcher - LogPrefix = "logs/zone-"; - LogSuffix = ".log"; - RestartWait = 10000; //milliseconds - TerminateWait = 10000; //milliseconds - InitialBootWait = 20000; //milliseconds - ZoneBootInterval = 2000; //milliseconds - #ifdef WIN32 - ZoneExe = "zone.exe"; - #else - ZoneExe = "./zone"; - #endif - // Zones - ZonePortLow = 7000; - ZonePortHigh = 7999; - DefaultStatus = 0; - // For where zones need to connect to. - WorldIP = "127.0.0.1"; - TelnetIP = "127.0.0.1"; - // Dynamics to start - //DynamicCount=5; - MaxClients = -1; - LoginCount = 0; } virtual ~EQEmuConfig() {} @@ -205,9 +132,7 @@ class EQEmuConfig : public XMLParser // Produce a const singleton static const EQEmuConfig *get() { - if (_config == nullptr) { - LoadConfig(); - } + LoadConfig(); return (_config); } @@ -221,10 +146,28 @@ class EQEmuConfig : public XMLParser static bool LoadConfig() { if (_config != nullptr) { - delete _config; + return true; } _config = new EQEmuConfig; - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(), "server"); + + return parseFile(); + } + + // Load config file and parse data + static bool parseFile() { + if (_config == nullptr) { + return LoadConfig(); + } + + std::ifstream fconfig(EQEmuConfig::ConfigFile, std::ifstream::binary); + try { + fconfig >> _config->_root; + _config->parse_config(); + } + catch (std::exception) { + return false; + } + return true; } void Dump() const; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index b655cffb0..a57e798db 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3847,9 +3847,12 @@ namespace RoF OUT(y); OUT(x); OUT(z) - OUT(zone_reason); + OUT(zone_reason); OUT(success); + if (eq->success < 0) + eq->success -= 1; + FINISH_ENCODE(); } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index baf6d6b09..64b991ddc 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -3991,9 +3991,12 @@ namespace RoF2 OUT(y); OUT(x); OUT(z) - OUT(zone_reason); + OUT(zone_reason); OUT(success); + if (eq->success < 0) + eq->success -= 1; + FINISH_ENCODE(); } diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 6f4e649ff..0dd7067a9 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -164,7 +164,7 @@ namespace RoF2 ItemPacket11 = 111, ItemPacket12 = 112, ItemPacketRecovery = 113, - ItemPacket14 = 115 + ItemPacket14 = 115 // Parcel? adds to merchant window too }; } /*item*/ diff --git a/common/ruletypes.h b/common/ruletypes.h index ed5ae8e23..759934538 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -198,6 +198,7 @@ RULE_CATEGORY(Pets) RULE_REAL(Pets, AttackCommandRange, 150) RULE_BOOL(Pets, UnTargetableSwarmPet, false) RULE_REAL(Pets, PetPowerLevelCap, 10) // Max number of levels your pet can go up with pet power +RULE_BOOL(Pets, CanTakeNoDrop, false) // Can everyone trade nodrop gear to pets RULE_CATEGORY_END() RULE_CATEGORY(GM) @@ -508,6 +509,7 @@ RULE_INT(Combat, NPCAssistCapTimer, 6000) // Time in milliseconds a NPC will tak RULE_BOOL(Combat, UseRevampHandToHand, false) // use h2h revamped dmg/delays I believe this was implemented during SoF RULE_BOOL(Combat, ClassicMasterWu, false) // classic master wu uses a random special, modern doesn't RULE_INT(Combat, LevelToStopDamageCaps, 0) // 1 will effectively disable them, 20 should give basically same results as old incorrect system +RULE_BOOL(Combat, ClassicNPCBackstab, false) // true disables npc facestab - npcs get normal attack if not behind RULE_CATEGORY_END() RULE_CATEGORY(NPC) @@ -674,6 +676,12 @@ RULE_CATEGORY_END() RULE_CATEGORY(AA) RULE_INT(AA, ExpPerPoint, 23976503) //Amount of exp per AA. Is the same as the amount of exp to go from level 51 to level 52. RULE_BOOL(AA, Stacking, true) //Allow AA that belong to the same group to stack on SOF+ clients. +RULE_BOOL(AA, NormalizedAAEnabled, false) // TSS+ change to AA that normalizes AA XP to a fixed # of white con kills independent of level. +RULE_INT(AA, NormalizedAANumberOfWhiteConPerAA, 25) // The number of white con kills per AA point. +RULE_BOOL(AA, ModernAAScalingEnabled, false) // Are we linearly scaling AA XP based on total # of earned AA? +RULE_REAL(AA, ModernAAScalingStartPercent, 1000) // 1000% or 10x AA XP at the start of the scaling range +RULE_INT(AA, ModernAAScalingAAMinimum, 0) // The minimum number of earned AA before AA XP scaling begins. +RULE_INT(AA, ModernAAScalingAALimit, 4000) // The number of earned AA when AA XP scaling ends RULE_CATEGORY_END() RULE_CATEGORY(Console) diff --git a/libs/format/fmt/format.h b/libs/format/fmt/format.h index 47a8b74d8..9c2827d46 100644 --- a/libs/format/fmt/format.h +++ b/libs/format/fmt/format.h @@ -1719,6 +1719,8 @@ FMT_DEFINE_INT_FORMATTERS(unsigned long) FMT_DEFINE_INT_FORMATTERS(LongLong) FMT_DEFINE_INT_FORMATTERS(ULongLong) +#define CHAR_WIDTH 1 + /** \rst Returns a string formatter that pads the formatted argument with the fill @@ -1823,7 +1825,7 @@ class ArgFormatterBase : public ArgVisitor { typedef typename BasicWriter::CharPtr CharPtr; Char fill = internal::CharTraits::cast(spec_.fill()); CharPtr out = CharPtr(); - const unsigned CHAR_WIDTH = 1; + if (spec_.width_ > CHAR_WIDTH) { out = writer_.grow_buffer(spec_.width_); if (spec_.align_ == ALIGN_RIGHT) { diff --git a/queryserv/queryservconfig.h b/queryserv/queryservconfig.h index b48ecdecd..9878493f7 100644 --- a/queryserv/queryservconfig.h +++ b/queryserv/queryservconfig.h @@ -46,7 +46,7 @@ public: _chat_config=new queryservconfig; _config=_chat_config; - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + return _config->parseFile(); } }; diff --git a/ucs/ucsconfig.h b/ucs/ucsconfig.h index 23bc82a4f..5424dfeb5 100644 --- a/ucs/ucsconfig.h +++ b/ucs/ucsconfig.h @@ -46,7 +46,7 @@ public: _chat_config=new ucsconfig; _config=_chat_config; - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + return _config->parseFile(); } }; diff --git a/utils/defaults/eqemu_config.json b/utils/defaults/eqemu_config.json new file mode 100755 index 000000000..73930ab9f --- /dev/null +++ b/utils/defaults/eqemu_config.json @@ -0,0 +1,8 @@ +{ + "server": { + "world": { + "shortname": "setme", + "longname": "I Forgot To Edit My Config" + } + } +} diff --git a/utils/defaults/eqemu_config.json.full b/utils/defaults/eqemu_config.json.full new file mode 100755 index 000000000..49cb9a5c6 --- /dev/null +++ b/utils/defaults/eqemu_config.json.full @@ -0,0 +1,54 @@ +{ + "server": { + "zones": { + "defaultstatus": "20", + "ports": { + "low": "7000", + "high": "7100" + } + }, + "database": { + "password": "eq", + "db": "eq", + "host": "127.0.0.1", + "port": "3306", + "username": "eq" + }, + "world": { + "shortname": "setme", + "longname": "I Forgot To Edit My Config", + "loginserver": { + "password": "", + "host": "login.eqemulator.net", + "port": "5998", + "account": "" + }, + "tcp": { + "port": "9000", + "telnet": "disable", + "ip": "127.0.0.1" + }, + "key": "some long random string", + "http": { + "mimefile": "mime.types", + "port": "9080", + "enabled": "false" + } + }, + "mailserver": { + "host": "channels.eqemulator.net", + "port": "7778" + }, + "chatserver": { + "host": "channels.eqemulator.net", + "port": "7778" + }, + "qsdatabase": { + "host": "127.0.0.1", + "port": "3306", + "username": "eq", + "password": "eq", + "db": "eq" + } + } +} diff --git a/utils/doc_scripts/perlparse/main.go b/utils/doc_scripts/perlparse/main.go new file mode 100644 index 000000000..0178a4cf5 --- /dev/null +++ b/utils/doc_scripts/perlparse/main.go @@ -0,0 +1,355 @@ +//Parses perl scripts +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "regexp" + "strings" + + "github.com/pkg/errors" +) + +func main() { + path := "../../../zone/embparser_api.cpp" + err := readFile(path) + if err != nil { + log.Panicf("Failed to read file: %s", err.Error()) + } +} + +type API struct { + Function string + Arguments []*Argument +} + +type Argument struct { + Name string + Type string + API *API +} + +func readFile(path string) (err error) { + inFile, err := os.Open(path) + if err != nil { + err = errors.Wrap(err, "Failed to open file") + } + defer inFile.Close() + scanner := bufio.NewScanner(inFile) + scanner.Split(bufio.ScanLines) + + arguments := map[string][]*Argument{} + functions := []*API{} + reg, err := regexp.Compile(`\]+|\[+|\?+|[...]+`) + if err != nil { + err = errors.Wrap(err, "Failed to compile regex") + return + } + regType, err := regexp.Compile(`(unsigned long|long|int32|bool|uint[0-9]+|int|auto|float|unsigned int|char[ \*]).+([. a-zA-Z]+=)`) + if err != nil { + err = errors.Wrap(err, "Failed to compile type regex") + return + } + + lastArguments := []*Argument{} + lastAPI := &API{} + lineNum := 0 + for scanner.Scan() { + lineNum++ + key := "" + line := scanner.Text() + if len(line) < 1 { + continue + } + if len(lastArguments) > 0 { //existing args to parse + for i, argument := range lastArguments { + key = fmt.Sprintf("ST(%d)", i) + if strings.Contains(line, key) { + //We found a definition argument line + if argument.Type != "" { + continue + } + + match := regType.FindStringSubmatch(line) + if len(match) < 2 { + continue + } + + //key = `int` + //function = line[strings.Index(line, key)+len(key):] + newType := "" + + switch v := strings.TrimSpace(match[1]); v { + case "int": + newType = "int" + case "int32": + newType = "int" + case "float": + newType = "float" + case "unsigned int": + newType = "uint" + case "uint32": + newType = "uint" + case "uint8": + newType = "uint" + case "uint": + newType = "uint" + case "bool": + newType = "bool" + case "uint16": + newType = "uint" + case "long": + newType = "long" + case "unsigned long": + newType = "unsigned long" + case "char": + newType = "string" + case "auto": + //Auto is tricky + if strings.Contains(line, "glm::vec4") { + newType = "float" + } + + default: + log.Printf(`Unknown type: "%s" on line %d`, v, lineNum) + } + //log.Println("Found arg type", newType, "on index", i, argument.Name) + lastArguments[i].Type = newType + } + } + } + + function := "" + + argLine := "" + args := []string{} + //Find line + key = `Perl_croak(aTHX_ "Usage:` + if strings.Contains(line, key) { + function = line[strings.Index(line, key)+len(key):] + } + + for _, argument := range lastArguments { + arguments[argument.Name] = append(arguments[argument.Name], argument) + } + + lastArguments = []*Argument{} + + //Trim off the endings + key = `");` + if strings.Contains(function, key) { + function = function[0:strings.Index(function, key)] + } + //Strip out the arguments + key = `(` + if strings.Contains(function, key) { + argLine = function[strings.Index(function, key)+len(key):] + function = function[0:strings.Index(function, key)] + key = `)` + if strings.Contains(argLine, key) { + argLine = argLine[:strings.Index(argLine, key)] + } + key = `=` + if strings.Contains(argLine, key) { + argLine = argLine[:strings.Index(argLine, key)] + } + argLine = reg.ReplaceAllString(argLine, "") + } + key = `,` + argLine = strings.TrimSpace(argLine) + + if strings.Contains(argLine, key) { + args = strings.Split(argLine, key) + } + + if len(function) < 1 { + continue + } + + newArgs := []string{} + for j, _ := range args { + args[j] = strings.TrimSpace(args[j]) + if len(args[j]) == 0 { + continue + } + newArgs = append(newArgs, args[j]) + } + + lastAPI = &API{ + Function: function, + } + + for _, arg := range newArgs { + argType, _ := knownTypes[arg] + argument := &Argument{ + Name: arg, + Type: argType, + API: lastAPI, + } + lastArguments = append(lastArguments, argument) + } + lastAPI.Arguments = lastArguments + + functions = append(functions, lastAPI) + } + + foundCount := 0 + failCount := 0 + for key, val := range arguments { + isMissing := false + line := "" + line = fmt.Sprintf("%s used by %d functions:", key, len(val)) + for _, fnc := range val { + line += fmt.Sprintf("%s(%s %s), ", fnc.API.Function, fnc.Type, key) + if fnc.Type == "" { + isMissing = true + } + } + if isMissing { + fmt.Println(line) + failCount++ + } else { + foundCount++ + } + } + log.Println(foundCount, "functions properly identified,", failCount, "have errors") + + line := "" + for _, api := range functions { + line += fmt.Sprintf("void %s(", strings.TrimSpace(api.Function)) + for _, argument := range api.Arguments { + line += fmt.Sprintf("%s %s, ", argument.Type, argument.Name) + } + if len(api.Arguments) > 0 { + line = line[0 : len(line)-2] + } + line += ")\n" + } + fmt.Println(line) + return +} + +var knownTypes = map[string]string{ + "activity_id": "uint", + "alt_mode": "bool", + "anim_num": "int", + "best_z": "float", + "buttons": "int", + "channel_id": "int", + "char_id": "int", + "charges": "int", + "class_id": "int", + "client_name": "string", + "color": "int", + "color_id": "int", + "condition_id": "int", + "copper": "int", + "count": "int", + "debug_level": "int", + "decay_time": "int", + "dest_heading": "float", + "dest_x": "float", + "dest_y": "float", + "dest_z": "float", + "distance": "int", + "door_id": "int", + "doorid": "uint", + "duration": "int", + "effect_id": "int", + "elite_material_id": "int", + "enforce_level_requirement": "bool", + "explore_id": "uint", + "faction_value": "int", + "fade_in": "int", + "fade_out": "int", + "fadeout": "uint", + "firstname": "string", + "from": "string", + "gender_id": "int", + "gold": "int", + "grid_id": "int", + "guild_rank_id": "int", + "heading": "float", + "hero_forge_model_id": "int", + "ignore_quest_update": "bool", + "instance_id": "int", + "int_unused": "int", + "int_value": "int", + "is_enabled": "bool", + "is_strict": "bool", + "item_id": "int", + "key": "string", + "language_id": "int", + "lastname": "string", + "leader_name": "string", + "level": "int", + "link_name": "string", + "macro_id": "int", + "max_level": "int", + "max_x": "float", + "max_y": "float", + "max_z": "float", + "message": "string", + "milliseconds": "int", + "min_level": "int", + "min_x": "float", + "min_y": "float", + "min_z": "float", + "name": "string", + "new_hour": "int", + "new_min": "int", + "node1": "int", + "node2": "int", + "npc_id": "int", + "npc_type_id": "int", + "object_type": "int", + "options": "int", + "platinum": "int", + "popup_id": "int", + "priority": "int", + "quantity": "int", + "race_id": "int", + "remove_item": "bool", + "requested_id": "int", + "reset_base": "bool", + "saveguard": "bool", + "seconds": "int", + "send_to_world": "bool", + "signal_id": "int", + "silent": "bool", + "silver": "int", + "size": "int", + "stat_id": "int", + "str_value": "string", + "subject": "string", + "target_enum": "string", + "target_id": "int", + "task": "int", + "task_id": "uint", + "task_id1": "int", + "task_id10": "int", + "task_id2": "int", + "task_set": "int", + "taskid": "int", + "taskid1": "int", + "taskid2": "int", + "taskid3": "int", + "taskid4": "int", + "teleport": "int", + "temp": "int", + "texture_id": "int", + "theme_id": "int", + "update_world": "int", + "updated_time_till_repop": "uint", + "version": "int", + "wait_ms": "int", + "window_title": "string", + "x": "float", + "y": "float", + "z": "float", + "zone_id": "int", + "zone_short": "string", + `task_id%i`: "int", +} diff --git a/utils/scripts/database_dumper.pl b/utils/scripts/database_dumper.pl new file mode 100644 index 000000000..51b16eabc --- /dev/null +++ b/utils/scripts/database_dumper.pl @@ -0,0 +1,252 @@ +#!/usr/bin/perl + +############################################################ +#::: Script: db_dumper.pl +#::: Purpose: Utility to easily manage database backups and compress. +#::: Export Individual DB Tables... +#::: Export specific databases... +#::: Built for both Windows and Linux +#::: Windows uses WinRar or 7-Zip for compression +#::: Linux uses tar for compression +#::: Author: Akkadius +############################################################ + +$localdrive = "C:"; #::: Where Windows and all Install Programs are... +$linesep = "---------------------------------------"; + +use POSIX qw(strftime); +my $date = strftime "%m_%d_%Y", localtime; +print "\nTodays Date: " . $date . "\n"; + +use Config; +print "Operating System is: $Config{osname}\n"; +if($Config{osname}=~/linux/i){ $OS = "Linux"; } +if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } + +if(!$ARGV[0]){ + print "\nERROR! Need arguments\n"; + print "#::: Help :::#\n"; + print "######################################################\n"; + print "Arguments\n"; + print " loc=\"C:\\File Location\" - File path location to backup...\n"; + print " database=\"dbname\" - Manually specify databasename, default is database in eqemu_config.xml\n"; + print " tables=\"table1,table2,table3\" - Manually specify tables, default is to dump all tables from database\n"; + print " compress - Compress Database with 7-ZIP, will fallback to WinRAR depending on what is installed (Must be installed to default program dir)...\n"; + print " nolock - Does not lock tables, meant for backuping while the server is running..\n"; + print " backup_name=\"name\" - Sets database backup prefix name\n"; + print ' Example: perl DB_Dumper.pl Loc="E:\Backups"' . "\n"; + print "######################################################\n"; + exit; +} + +sub read_eqemu_config_json { + use JSON; + my $json = new JSON(); + + my $content; + open(my $fh, '<', "eqemu_config.json") or die "Unable to open config: eqemu_config.json - This must be in your EQEmu Server Folder\n"; { + local $/; + $content = <$fh>; + } + close($fh); + + $config = $json->decode($content); + + $db = $config->{"server"}{"database"}{"db"}; + $host = $config->{"server"}{"database"}{"host"}; + $user = $config->{"server"}{"database"}{"username"}; + $pass = $config->{"server"}{"database"}{"password"}; + $long_name = $config->{"server"}{"world"}{"longname"}; + +} + +read_eqemu_config_json(); + +$Debug = 0; +print "[db_dumper.pl] Arguments\n" if $Debug; +$n = 0; +while($ARGV[$n]){ + print $n . ': ' . $ARGV[$n] . "\n" if $Debug; + if($ARGV[$n]=~/nolock/i){ + $no_lock = 1; + } + if($ARGV[$n]=~/compress/i){ + print "[db_dumper.pl] Compression SET\n"; + $Compress = 1; + } + if($ARGV[$n]=~/database=/i){ + @DB_NAME = split('=', $ARGV[$n]); + print "[db_dumper.pl] Database is " . $DB_NAME[1] . "\n"; + $db = $DB_NAME[1]; + } + if($ARGV[$n]=~/backup_name=/i){ + @data = split('=', $ARGV[$n]); + print "[db_dumper.pl] Backup Name is " . $data[1] . "\n"; + $backup_name = $data[1]; + } + if($ARGV[$n]=~/loc=/i){ + @backup_location = split('=', $ARGV[$n]); + print "[db_dumper.pl] Backup Directory: " . $backup_location[1] . "\n"; + } + if($ARGV[$n]=~/tables=/i){ + @Tables = split('=', $ARGV[$n]); @TList = split(',', $Tables[1]); + foreach my $tables (@TList){ + $t_tables .= $tables . " "; + $t_tables_l .= $tables . "_"; + $t_tables_p .= $tables . "\n"; + } + print "[db_dumper.pl] Backing up tables: \n############################\n" . $t_tables_p . "############################\n"; + } + $n++; +} + +#::: Check for Backup Directory existence, if doesn't exist then create... +if (-d $backup_location[1]) { + print "[db_dumper.pl] Directory currently exists... Adding files to it...\n"; +} +elsif($backup_location[1] ne ""){ + print "[db_dumper.pl] Directory does NOT exist! Creating...\n"; + mkdir($backup_location[1]) or die 'Failed to create folder, maybe created the folder manually at "' . $backup_location[1]. '" ?'; +} +else{ + print "[db_dumper.pl] No save location specified... Saving to folder script is running in...\n"; +} +if($backup_location[1] ne ""){ + if($OS eq "Windows"){ $file_app = "\\"; } + if($OS eq "Linux"){ $file_app = "/"; } +} +else { + $file_app = ""; +} + +if($t_tables ne ""){ + $tables_f_l = substr($t_tables_l, 0, 20) . '-'; + if($backup_name){ + $target_file = $backup_name . '_' . $date . ''; + } + else { + $target_file = '' . $tables_f_l . '_' . $date . ''; + } + + print "[db_dumper.pl] Performing table based backup...\n"; + #::: Backup Database... + print "[db_dumper.pl] Backing up Database " . $db . "... \n"; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' ' . $t_tables . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; + printcmd($cmd); + system($cmd); +} +else{ #::: Entire DB Backup + + if($backup_name){ + $target_file = $backup_name . '_' . $db . '_' . $date . ''; + } + else { + $target_file = '' . $db . '_' . $date . ''; + } + + #::: Backup Database... + print "[db_dumper.pl] Backing up Database " . $db . "... \n"; + if($no_lock == 1){ + $added_parameters .= " --skip-lock-tables "; + } + $cmd = 'mysqldump -u' . $user . ' --host ' . $host . ' ' . $added_parameters . ' --max_allowed_packet=512M --password="' . $pass . '" ' . $db . ' > "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql"'; + printcmd($cmd); + system($cmd); +} + +#::: Get File Size +$fileloc = '' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql'; +$filesize = -s $fileloc; +if($filesize < 1000){ print "[db_dumper.pl] " . 'Error occurred... exiting...' . "\n"; exit; } +print "[db_dumper.pl] Backup DONE... DB Backup File Size '" . $filesize . "' (" . get_filesize_str($fileloc) . ")\n"; + +#::: WinRar Get, check compression flag +if($Compress == 1){ + if($OS eq "Windows"){ + if(-d $localdrive . "\\Program Files\\7-Zip"){ + print "[db_dumper.pl] ::: You have 7-Zip installed as 64 Bit...\n"; + $S_ZIP = $localdrive . "\\Program Files\\7-Zip"; + } + elsif(-d $localdrive . "\\Program Files (x86)\\7-Zip"){ + print "[db_dumper.pl] ::: You have 7-Zip installed as 32 Bit...\n"; + $S_ZIP = $localdrive . "\\Program Files (x86)\\7-Zip"; + } + elsif(-d $localdrive . "\\Program Files (x86)\\WinRAR"){ + print "[db_dumper.pl] ::: You have WinRAR installed as 32 Bit...\n"; + $WinRar = $localdrive . "\\Program Files (x86)\\WinRAR"; + } + elsif(-d $localdrive . "\\Program Files\\WinRAR"){ + print "[db_dumper.pl] ::: You have WinRAR installed as 64 Bit...\n"; + $WinRar = $localdrive . "\\Program Files\\WinRAR"; + } + else{ + print "[db_dumper.pl] No WinRAR installed... Will not compress...\n"; + } + if($S_ZIP ne ""){ + print "[db_dumper.pl] Compressing Database with 7-ZIP... \n"; + $cmd = '"' . $S_ZIP . '\\7z" a -t7z -m0=lzma -mx=9 "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.7z" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + $final_file = $target_file . ".7z"; + } + elsif($WinRar ne ""){ + print "[db_dumper.pl] Compressing Database with WinRAR... \n"; + $cmd = '"' . $WinRar . '\\rar" a "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.rar" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'del "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + $final_file = $target_file . ".rar"; + } + } + if($OS eq "Linux"){ + print "[db_dumper.pl] Compressing Database with Tarball... \n"; + $cmd = 'tar -zcvf "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.tar.gz" "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + print "[db_dumper.pl] \nDeleting RAW .sql Dump... \n"; + $cmd = 'rm "' . $backup_location[1] . '' . $file_app . '' . $target_file . '.sql" '; + printcmd($cmd); + system($cmd); + $final_file = $target_file . ".tar.gz"; + } +} +else { + $final_file = $target_file . ".sql"; +} + +#::: Get Final File Location for display +if($backup_location[1] ne ""){ $final_loc = $backup_location[1] . '' . $file_app . ""; } +else{ + if($OS eq "Windows"){ + $final_loc = `echo %cd%`; + } + elsif($OS eq "Linux"){ + $final_loc = `pwd`; + } +} + +print "[db_dumper.pl] Final file located: " . $final_loc . "" . $final_file . "\n"; + +sub printcmd{ + print "[db_dumper.pl] Command [" . $_[0] . "]\n"; +} + +sub get_filesize_str{ + my $file = shift(); + my $size = (stat($file))[7] || die "stat($file): $!\n"; + if ($size > 1099511627776) { return sprintf("%.2f TiB", $size / 1099511627776); } + elsif ($size > 1073741824) { return sprintf("%.2f GiB", $size / 1073741824); } + elsif ($size > 1048576) { return sprintf("%.2f MiB", $size / 1048576); } + elsif ($size > 1024) { return sprintf("%.2f KiB", $size / 1024); } + else { return "$size byte" . ($size == 1 ? "" : "s"); } +} diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 42d956edd..c70862aaa 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -48,10 +48,18 @@ if(-e "eqemu_server_skip_update.txt"){ } #::: Check for script self update +check_xml_to_json_conversion() if $ARGV[0] eq "convert_xml"; do_self_update_check_routine() if !$skip_self_update_check; get_windows_wget(); get_perl_version(); -read_eqemu_config_xml(); +if(-e "eqemu_config.json") { + read_eqemu_config_json(); +} +else { + #::: This will need to stay for servers who simply haven't updated yet + # This script can still update without the server bins being updated + read_eqemu_config_xml(); +} get_mysql_path(); #::: Remove old eqemu_update.pl @@ -265,7 +273,7 @@ sub new_server { analytics_insertion("new_server::install", $database_name); if($OS eq "Linux"){ - build_linux_source(); + build_linux_source("login"); } do_installer_routines(); @@ -281,6 +289,10 @@ sub new_server { show_install_summary_info(); + if($OS eq "Linux") { + unlink('/home/eqemu/install_variables.txt'); + } + rmtree('updates_staged'); return; @@ -291,6 +303,61 @@ sub new_server { } } +sub check_xml_to_json_conversion { + if(-e "eqemu_config.xml" && !-e "eqemu_config.json") { + + if($OS eq "Windows"){ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/xmltojson/xmltojson-windows-x86.exe", "xmltojson.exe"); + print "Converting eqemu_config.xml to eqemu_config.json\n"; + print `xmltojson eqemu_config.xml`; + } + if($OS eq "Linux"){ + get_remote_file("https://raw.githubusercontent.com/EQEmu/Server/master/utils/xmltojson/xmltojson-linux-x86", "xmltojson"); + print "Converting eqemu_config.xml to eqemu_config.json\n"; + print `chmod 755 xmltojson`; + print `./xmltojson eqemu_config.xml`; + } + + #::: Prettify and alpha order the config + use JSON; + my $json = new JSON(); + + my $content; + open(my $fh, '<', "eqemu_config.json") or die "cannot open file $filename"; { + local $/; + $content = <$fh>; + } + close($fh); + + $result = $json->decode($content); + $json->canonical(1); + + print $json->pretty->indent_length(5)->utf8->encode($result),"\n"; + + open(my $fh, '>', 'eqemu_config.json'); + print $fh $json->pretty->indent_length(5)->utf8->encode($result); + close $fh; + + mkdir('backups'); + copy_file("eqemu_config.xml", "backups/eqemu_config.xml"); + unlink('eqemu_config.xml'); + unlink('db_dumper.pl'); + + print "[Server Maintenance] eqemu_config.xml is now DEPRECATED \n"; + print "[Server Maintenance] eqemu_config.json is now the new Server config format \n"; + print " A backup of this old config is located in the backups folder of your server directory\n"; + print " --- \n"; + print " You may have some plugins and/or applications that still require reference of this config file\n"; + print " Please update these plugins/applications to use the new configuration format if needed\n"; + print " --- \n"; + print " Thanks for your understanding\n"; + print " The EQEmulator Team\n\n"; + + exit; + } + +} + sub build_linux_source { $build_options = $_[0]; @@ -330,10 +397,10 @@ sub build_linux_source { print "Generating CMake build files...\n"; if($os_flavor eq "fedora_core"){ - print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`; + print `cmake $cmake_options -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -DLUA_INCLUDE_DIR=/usr/include/lua-5.1/ -G "Unix Makefiles" ..`; } else { - print `cmake $cmake_options -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; + print `cmake $cmake_options -DEQEMU_BUILD_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; } print "Building EQEmu Server code. This will take a while."; @@ -352,6 +419,7 @@ sub build_linux_source { print `ln -s -f $source_dir/Server/build/bin/ucs .`; print `ln -s -f $source_dir/Server/build/bin/world .`; print `ln -s -f $source_dir/Server/build/bin/zone .`; + print `ln -s -f $source_dir/Server/build/bin/loginserver .`; } sub do_installer_routines { @@ -362,8 +430,8 @@ sub do_installer_routines { mkdir('updates_staged'); mkdir('shared'); - do_install_config_xml(); - read_eqemu_config_xml(); + do_install_config_json(); + read_eqemu_config_json(); get_installation_variables(); $db_name = "peq"; @@ -579,7 +647,12 @@ sub do_self_update_check_routine { sub get_installation_variables{ #::: Fetch installation variables before building the config if($OS eq "Linux"){ - open (INSTALL_VARS, "../install_variables.txt"); + if(-e "../install_variables.txt") { + open (INSTALL_VARS, "../install_variables.txt"); + } + elsif(-e "install_variables.txt") { + open (INSTALL_VARS, "./install_variables.txt"); + } } if($OS eq "Windows"){ open (INSTALL_VARS, "install_variables.txt"); @@ -593,73 +666,51 @@ sub get_installation_variables{ close (INSTALL_VARS); } -sub do_install_config_xml { +sub do_install_config_json { get_installation_variables(); - #::: Fetch XML template - get_remote_file($install_repository_request_url . "eqemu_config.xml", "eqemu_config_template.xml"); + #::: Fetch json template + get_remote_file($install_repository_request_url . "eqemu_config.json", "eqemu_config_template.json"); - #::: Open new config file - open (NEW_CONFIG, '>', 'eqemu_config.xml'); + use JSON; + my $json = new JSON(); + + my $content; + open(my $fh, '<', "eqemu_config_template.json") or die "cannot open file $filename"; { + local $/; + $content = <$fh>; + } + close($fh); + + $config = $json->decode($content); - $in_database_tag = 0; + $long_name = "Akkas " . $OS . " PEQ Installer (" . generate_random_password(5) . ')'; + $config->{"server"}{"world"}{"longname"} = $long_name; + $config->{"server"}{"world"}{"key"} = generate_random_password(30); - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "eqemu_config_template.xml"); - while (){ - chomp; - $o = $_; - - #::: Find replace variables - - if($o=~/\<\!--/i){ - next; - } - - if($o=~/database/i && $o=~/\<\//i){ - $in_database_tag = 0; - } - if($o=~/database/i){ - $in_database_tag = 1; - } - - if($o=~/key/i){ - my($replace_key) = $o =~ />(\w+)/i){ - my($replace_name) = $o =~ /(.*)<\/longname>/; - $append = '(' . generate_random_password(5) . ')'; - $o =~ s/$replace_name/Akkas $OS PEQ Installer $append/g; - } - if($o=~/\/i && $in_database_tag){ - my($replace_username) = $o =~ />(\w+)/i && $in_database_tag){ - my($replace_password) = $o =~ />(\w+)/i){ - my($replace_db_name) = $o =~ />(\w+){"server"}{"database"}{"username"} = $installation_variables{"mysql_eqemu_user"}; + $config->{"server"}{"database"}{"password"} = $installation_variables{"mysql_eqemu_password"}; + $config->{"server"}{"database"}{"db"} = $db_name; + + $config->{"server"}{"qsdatabase"}{"username"} = $installation_variables{"mysql_eqemu_user"}; + $config->{"server"}{"qsdatabase"}{"password"} = $installation_variables{"mysql_eqemu_password"}; + $config->{"server"}{"qsdatabase"}{"db"} = $db_name; + + $json->canonical(1); + $json->indent_length(5); + + open(my $fh, '>', 'eqemu_config.json'); + print $fh $json->pretty->indent_length(5)->utf8->encode($config); + close $fh; + + unlink("eqemu_config_template.json"); } sub fetch_utility_scripts { @@ -766,6 +817,7 @@ sub show_menu_prompt { elsif($input eq "setup_loginserver"){ do_windows_login_server_setup(); $dc = 1; } elsif($input eq "new_server"){ new_server(); $dc = 1; } elsif($input eq "setup_bots"){ setup_bots(); $dc = 1; } + elsif($input eq "linux_login_server_setup"){ do_linux_login_server_setup(); $dc = 1; } elsif($input eq "exit"){ exit; } @@ -858,13 +910,13 @@ sub check_for_database_dump_script{ return; } - #::: Check for script changes :: db_dumper.pl - get_remote_file($eqemu_repository_request_url . "utils/scripts/db_dumper.pl", "updates_staged/db_dumper.pl", 0, 1, 1); + #::: Check for script changes :: database_dumper.pl + get_remote_file($eqemu_repository_request_url . "utils/scripts/database_dumper.pl", "updates_staged/database_dumper.pl", 0, 1, 1); - if(-e "updates_staged/db_dumper.pl") { + if(-e "updates_staged/database_dumper.pl") { - my $remote_script_size = -s "updates_staged/db_dumper.pl"; - my $local_script_size = -s "db_dumper.pl"; + my $remote_script_size = -s "updates_staged/database_dumper.pl"; + my $local_script_size = -s "database_dumper.pl"; if($remote_script_size != $local_script_size){ print "[Update] Script has been updated, updating...\n"; @@ -876,14 +928,14 @@ sub check_for_database_dump_script{ $start_dir ); for my $file (@files) { - if($file=~/db_dumper/i){ + if($file=~/database_dumper/i){ $destination_file = $file; $destination_file =~s/updates_staged\///g; print "[Install] Installing :: " . $destination_file . "\n"; unlink($destination_file); copy_file($file, $destination_file); if($OS eq "Linux"){ - system("chmod 755 db_dumper.pl"); + system("chmod 755 database_dumper.pl"); } } } @@ -893,7 +945,7 @@ sub check_for_database_dump_script{ print "[Update] No script update necessary...\n"; } - unlink("updates_staged/db_dumper.pl"); + unlink("updates_staged/database_dumper.pl"); } return; @@ -903,7 +955,7 @@ sub check_for_database_dump_script{ sub database_dump { check_for_database_dump_script(); print "[Database] Performing database backup....\n"; - print `perl db_dumper.pl database="$db" loc="backups"`; + print `perl database_dumper.pl database="$db" loc="backups"`; } sub database_dump_player_tables { @@ -921,7 +973,7 @@ sub database_dump_player_tables { } $tables = substr($tables, 0, -1); - print `perl db_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; + print `perl database_dumper.pl database="$db" loc="backups" tables="$tables" backup_name="player_tables_export" nolock`; print "[Database] Press any key to continue...\n"; @@ -932,7 +984,7 @@ sub database_dump_player_tables { sub database_dump_compress { check_for_database_dump_script(); print "[Database] Performing database backup....\n"; - print `perl db_dumper.pl database="$db" loc="backups" compress`; + print `perl database_dumper.pl database="$db" loc="backups" compress`; } sub script_exit{ @@ -1008,7 +1060,7 @@ sub get_remote_file{ } #::: 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`; + $wget = `wget -N --cache=no --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"; @@ -1072,6 +1124,26 @@ sub read_eqemu_config_xml { close(CONFIG); } +sub read_eqemu_config_json { + use JSON; + my $json = new JSON(); + + my $content; + open(my $fh, '<', "eqemu_config.json") or die "cannot open file $filename"; { + local $/; + $content = <$fh>; + } + close($fh); + + $config = $json->decode($content); + + $db = $config->{"server"}{"database"}{"db"}; + $host = $config->{"server"}{"database"}{"host"}; + $user = $config->{"server"}{"database"}{"username"}; + $pass = $config->{"server"}{"database"}{"password"}; + +} + #::: Fetch Latest PEQ AA's sub aa_fetch{ if(!$db){ @@ -1277,6 +1349,8 @@ sub do_windows_login_server_setup { sub do_linux_login_server_setup { + build_linux_source(); + for my $file (@files) { $destination_file = $file; $destination_file =~s/updates_staged\/login_server\///g; @@ -1297,6 +1371,8 @@ sub do_linux_login_server_setup { get_remote_file($install_repository_request_url . "linux/login.ini", "login_template.ini"); get_remote_file($install_repository_request_url . "linux/login_opcodes.conf", "login_opcodes.conf"); get_remote_file($install_repository_request_url . "linux/login_opcodes_sod.conf", "login_opcodes_sod.conf"); + get_remote_file($install_repository_request_url . "linux/server_start_with_login.sh", "server_start_with_login.sh"); + system("chmod 755 *.sh"); get_installation_variables(); my $db_name = $installation_variables{"mysql_eqemu_db_name"}; diff --git a/utils/scripts/linux_installer/install.sh b/utils/scripts/linux_installer/install.sh index 55972e8c8..1a94320ae 100644 --- a/utils/scripts/linux_installer/install.sh +++ b/utils/scripts/linux_installer/install.sh @@ -119,6 +119,7 @@ if [[ "$OS" == "Debian" ]]; then apt-get $apt_options install zlibc apt-get $apt_options install libsodium-dev apt-get $apt_options install libsodium18 + apt-get $apt_options install libjson-perl # 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 @@ -159,7 +160,7 @@ EOF # Install prereqs yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm yum -y install deltarpm - yum -y install open-vm-tools vim cmake boost-* zlib-devel mariadb-server mariadb-client mariadb-devel mariadb-libs mariadb-compat perl-* lua* dos2unix php-mysql proftpd + yum -y install open-vm-tools vim cmake boost-* zlib-devel mariadb-server mariadb-client mariadb-devel mariadb-libs mariadb-compat perl-* lua* dos2unix php-mysql proftpd libuuid-devel yum -y groupinstall "Development Tools" "Basic Web Server" "Compatibility Libraries" elif [[ "$OS" == "fedora_core" ]]; then diff --git a/utils/sql/user_tables.txt b/utils/sql/user_tables.txt index 9e35ac5e2..a210aa381 100644 --- a/utils/sql/user_tables.txt +++ b/utils/sql/user_tables.txt @@ -17,7 +17,6 @@ character_bind character_corpses character_corpse_items character_languages -character_lookup character_skills character_spells character_memmed_spells @@ -89,4 +88,4 @@ spell_globals timers trader trader_audit -zone_flags \ No newline at end of file +zone_flags diff --git a/utils/xmltojson/.gitignore b/utils/xmltojson/.gitignore new file mode 100644 index 000000000..2f08e63ef --- /dev/null +++ b/utils/xmltojson/.gitignore @@ -0,0 +1,2 @@ +eqemu_config.xml +eqemu_config.json \ No newline at end of file diff --git a/utils/xmltojson/README.md b/utils/xmltojson/README.md new file mode 100644 index 000000000..a8fec4a3a --- /dev/null +++ b/utils/xmltojson/README.md @@ -0,0 +1 @@ +Converts the old eqemu_config.xml to eqemu_config.json diff --git a/utils/xmltojson/build.bat b/utils/xmltojson/build.bat new file mode 100644 index 000000000..be0e60488 --- /dev/null +++ b/utils/xmltojson/build.bat @@ -0,0 +1,21 @@ +@echo off +setlocal +set name="xmltojson" + +echo Building Linux +set GOOS=linux +set GOARCH=amd64 +go build -o %name%-linux-x64 main.go +set GOARCH=386 +go build -o %name%-linux-x86 main.go +echo Building Windows +set GOOS=windows +set GOARCH=amd64 +go build -o %name%-windows-x64.exe main.go +set GOARCH=386 +go build -o %name%-windows-x86.exe main.go +echo Building OSX +REM set GOOS=darwin +REM set GOARCH=amd64 +REM go build -o %name%-osx-x64 main.go +endlocal \ No newline at end of file diff --git a/utils/xmltojson/build.sh b/utils/xmltojson/build.sh new file mode 100644 index 000000000..079822f14 --- /dev/null +++ b/utils/xmltojson/build.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e +export NAME="xmltojson" +echo Building Linux +GOOS=linux GOARCH=amd64 go build -o $NAME-linux-x64 main.go +GOOS=linux GOARCH=386 go build -o $NAME-linux-x86 main.go +echo Building Windows +GOOS=windows GOARCH=amd64 go build -o $NAME-windows-x64.exe main.go +GOOS=windows GOARCH=386 go build -o $NAME-windows-x86.exe main.go +#echo Building OSX +#GOOS=darwin GOARCH=amd64 go build -o $NAME-osx-x64 main.go \ No newline at end of file diff --git a/utils/xmltojson/main.go b/utils/xmltojson/main.go new file mode 100644 index 000000000..867cb0c79 --- /dev/null +++ b/utils/xmltojson/main.go @@ -0,0 +1,85 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + "io/ioutil" + "os" + "strings" + + xj "github.com/basgys/goxml2json" +) + +func main() { + var err error + var data []byte + var sData string + buf := &bytes.Buffer{} + var buf2 bytes.Buffer + + if data, err = ioutil.ReadFile("eqemu_config.xml"); err != nil { + fmt.Println("Failed to open eqemu_config.xml:", err.Error()) + os.Exit(1) + } + + //detect malformed xml in eqemuconfig + sData = strings.Replace(string(data), "", "", 1) + r := strings.NewReader(sData) + dec := xj.NewDecoder(r) + root := &xj.Node{} + if err = dec.DecodeWithCustomPrefixes(root, "", ""); err != nil { + fmt.Println("Failed to decode eqemu_config.xml:", err.Error()) + os.Exit(1) + } + + if root.Children["server"] == nil || len(root.Children["server"]) < 1 { + fmt.Println("Server element not found") + os.Exit(1) + } + server := root.Children["server"][0] + + //locked: "true" is only way to trigger locked + if server.Children["world"] != nil && len(server.Children["world"]) > 0 { + world := server.Children["world"][0] + + if world.Children["locked"] != nil && len(world.Children["locked"]) > 0 { + fmt.Println("Locked!") + world.Children["locked"][0].Data = "true" + } + } + + elements := []string{ + "chatserver", + "directories", + "files", + "launcher", + "mailserver", + "webinterface", + "world", + "zones", + } + for _, ele := range elements { + if server.Children[ele] != nil && len(server.Children[ele]) > 0 && len(server.Children[ele][0].Children) == 0 { + delete(server.Children, ele) + } + } + + enc := xj.NewEncoder(buf) + err = enc.EncodeWithCustomPrefixes(root, "", "") + if err != nil { + fmt.Println("Failed to encode eqemu_config.xml:", err.Error()) + os.Exit(1) + } + + //prettyprint + if err = json.Indent(&buf2, buf.Bytes(), "", "\t"); err != nil { + fmt.Println("Failed to encode json:", err.Error()) + os.Exit(1) + } + + if err = ioutil.WriteFile("eqemu_config.json", buf2.Bytes(), 0744); err != nil { + fmt.Println("Failed to write eqemu_config.json:", err.Error()) + os.Exit(1) + } +} diff --git a/utils/xmltojson/xmltojson-linux-x64 b/utils/xmltojson/xmltojson-linux-x64 new file mode 100644 index 000000000..ea6e3dc25 Binary files /dev/null and b/utils/xmltojson/xmltojson-linux-x64 differ diff --git a/utils/xmltojson/xmltojson-linux-x86 b/utils/xmltojson/xmltojson-linux-x86 new file mode 100644 index 000000000..b94fcae51 Binary files /dev/null and b/utils/xmltojson/xmltojson-linux-x86 differ diff --git a/utils/xmltojson/xmltojson-windows-x64 b/utils/xmltojson/xmltojson-windows-x64 new file mode 100644 index 000000000..9c598dcff Binary files /dev/null and b/utils/xmltojson/xmltojson-windows-x64 differ diff --git a/utils/xmltojson/xmltojson-windows-x64.exe b/utils/xmltojson/xmltojson-windows-x64.exe new file mode 100644 index 000000000..520920988 Binary files /dev/null and b/utils/xmltojson/xmltojson-windows-x64.exe differ diff --git a/utils/xmltojson/xmltojson-windows-x86 b/utils/xmltojson/xmltojson-windows-x86 new file mode 100644 index 000000000..f25ae2a3c Binary files /dev/null and b/utils/xmltojson/xmltojson-windows-x86 differ diff --git a/utils/xmltojson/xmltojson-windows-x86.exe b/utils/xmltojson/xmltojson-windows-x86.exe new file mode 100644 index 000000000..53ff5f194 Binary files /dev/null and b/utils/xmltojson/xmltojson-windows-x86.exe differ diff --git a/world/net.cpp b/world/net.cpp index c0ab16ecc..458e56c63 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -104,6 +104,7 @@ EQEmuLogSys LogSys; WebInterfaceList web_interface; void CatchSignal(int sig_num); +void CheckForServerScript(bool force_download = false); inline void UpdateWindowTitle(std::string new_title) { #ifdef _WINDOWS @@ -116,6 +117,17 @@ int main(int argc, char** argv) { LogSys.LoadLogSettingsDefaults(); set_exception_handler(); + /* If eqemu_config.json does not exist - create it from conversion... */ + if (!std::ifstream("eqemu_config.json")) { + CheckForServerScript(true); + /* Run EQEmu Server script (Checks for database updates) */ + system("perl eqemu_server.pl convert_xml"); + } + else { + /* Download EQEmu Server Maintenance Script if doesn't exist */ + CheckForServerScript(); + } + /* Database Version Check */ uint32 Database_Version = CURRENT_BINARY_DATABASE_VERSION; uint32 Bots_Database_Version = CURRENT_BINARY_BOTS_DATABASE_VERSION; @@ -173,7 +185,7 @@ int main(int argc, char** argv) { } } - Log(Logs::General, Logs::World_Server, "Connecting to MySQL..."); + Log(Logs::General, Logs::World_Server, "Connecting to MySQL %s@%s:%i...", Config->DatabaseUsername.c_str(), Config->DatabaseHost.c_str(), Config->DatabasePort); if (!database.Connect( Config->DatabaseHost.c_str(), Config->DatabaseUsername.c_str(), @@ -577,4 +589,33 @@ int main(int argc, char** argv) { void CatchSignal(int sig_num) { Log(Logs::General, Logs::World_Server, "Caught signal %d", sig_num); RunLoops = false; +} + +void UpdateWindowTitle(char* iNewTitle) { +#ifdef _WINDOWS + char tmp[500]; + if (iNewTitle) { + snprintf(tmp, sizeof(tmp), "World: %s", iNewTitle); + } + else { + snprintf(tmp, sizeof(tmp), "World"); + } + SetConsoleTitle(tmp); +#endif +} + +void CheckForServerScript(bool force_download) { + /* Fetch EQEmu Server script */ + if (!std::ifstream("eqemu_server.pl") || force_download) { + + if(force_download) + std::remove("eqemu_server.pl"); /* Delete local before fetch */ + + std::cout << "Pulling down EQEmu Server Maintenance Script (eqemu_server.pl)..." << std::endl; +#ifdef _WIN32 + system("perl -MLWP::UserAgent -e \"require LWP::UserAgent; my $ua = LWP::UserAgent->new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get('https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl'); if ($response->is_success){ open(FILE, '> eqemu_server.pl'); print FILE $response->decoded_content; close(FILE); }\""); +#else + system("wget -N --no-check-certificate --quiet -O eqemu_server.pl https://raw.githubusercontent.com/EQEmu/Server/master/utils/scripts/eqemu_server.pl"); +#endif + } } \ No newline at end of file diff --git a/world/world_config.h b/world/world_config.h index 4689aa08f..2a274ed29 100644 --- a/world/world_config.h +++ b/world/world_config.h @@ -52,7 +52,7 @@ public: _world_config=new WorldConfig; _config=_world_config; - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + return _config->parseFile(); } // Accessors for the static private object diff --git a/zone/aggro.cpp b/zone/aggro.cpp index 340493578..cc70f1a4c 100644 --- a/zone/aggro.cpp +++ b/zone/aggro.cpp @@ -253,7 +253,7 @@ bool Mob::CheckWillAggro(Mob *mob) { //sometimes if a client has some lag while zoning into a dangerous place while either invis or a GM //they will aggro mobs even though it's supposed to be impossible, to lets make sure we've finished connecting if (mob->IsClient()) { - if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->zoning) + if (!mob->CastToClient()->ClientFinishedLoading() || mob->CastToClient()->IsHoveringForRespawn() || mob->CastToClient()->bZoning) return false; } diff --git a/zone/attack.cpp b/zone/attack.cpp index 88712a08b..f9edb46ac 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1728,6 +1728,15 @@ bool Client::Death(Mob* killerMob, int32 damage, uint16 spell, EQEmu::skills::Sk if (!RuleB(Character, UseDeathExpLossMult)) { exploss = (int)(GetLevel() * (GetLevel() / 18.0) * 12000); } + + if (RuleB(Zone, LevelBasedEXPMods)) { + // Death in levels with xp_mod (such as hell levels) was resulting + // in losing more that appropriate since the loss was the same but + // getting it back would take way longer. This makes the death the + // same amount of time to recover. Will also lose more if level is + // granting a bonus. + exploss *= zone->level_exp_mod[GetLevel()].ExpMod; + } if ((GetLevel() < RuleI(Character, DeathExpLossLevel)) || (GetLevel() > RuleI(Character, DeathExpLossMaxLevel)) || IsBecomeNPC()) { @@ -2675,7 +2684,7 @@ void Mob::AddToHateList(Mob* other, uint32 hate /*= 0*/, int32 damage /*= 0*/, b hate_list.AddEntToHateList(other, hate, damage, bFrenzy, !iBuffTic); - if (other->IsClient() && !on_hatelist) + if (other->IsClient() && !on_hatelist && !IsOnFeignMemory(other->CastToClient())) other->CastToClient()->AddAutoXTarget(this); #ifdef BOTS diff --git a/zone/client.cpp b/zone/client.cpp index 319752e36..844188edb 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -215,7 +215,7 @@ Client::Client(EQStreamInterface* ieqs) linkdead_timer.Disable(); zonesummon_id = 0; zonesummon_ignorerestrictions = 0; - zoning = false; + bZoning = false; zone_mode = ZoneUnsolicited; casting_spell_id = 0; npcflag = false; @@ -395,7 +395,7 @@ Client::~Client() { GetTarget()->IsTargeted(-1); //if we are in a group and we are not zoning, force leave the group - if(isgrouped && !zoning && is_zone_loaded) + if(isgrouped && !bZoning && is_zone_loaded) LeaveGroup(); UpdateWho(2); diff --git a/zone/client.h b/zone/client.h index 925f214b7..a22b1a186 100644 --- a/zone/client.h +++ b/zone/client.h @@ -606,6 +606,10 @@ public: uint32 GetExperienceForKill(Mob *against); void AddEXP(uint32 in_add_exp, uint8 conlevel = 0xFF, bool resexp = false); uint32 CalcEXP(uint8 conlevel = 0xFF); + void CalculateNormalizedAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp); + void CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp); + void CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel); + void CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, uint8 conlevel, bool resexp); void SetEXP(uint32 set_exp, uint32 set_aaxp, bool resexp=false); void AddLevelBasedExp(uint8 exp_percentage, uint8 max_level=0); void SetLeadershipEXP(uint32 group_exp, uint32 raid_exp); @@ -651,6 +655,7 @@ public: void Sacrifice(Client* caster); void GoToDeath(); inline const int32 GetInstanceID() const { return zone->GetInstanceID(); } + void SetZoning(bool in) { bZoning = in; } FACTION_VALUE GetReverseFactionCon(Mob* iOther); FACTION_VALUE GetFactionLevel(uint32 char_id, uint32 npc_id, uint32 p_race, uint32 p_class, uint32 p_deity, int32 pFaction, Mob* tnpc); @@ -1542,7 +1547,7 @@ private: bool npcflag; uint8 npclevel; bool feigned; - bool zoning; + bool bZoning; bool tgb; bool instalog; int32 last_reported_mana; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 57dc58195..ef7469aae 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -264,7 +264,7 @@ bool Client::Process() { if (distance <= scan_range) { close_mobs.insert(std::pair(mob, distance)); } - else if (mob->GetAggroRange() > scan_range) { + else if ((mob->GetAggroRange() * mob->GetAggroRange()) > scan_range) { close_mobs.insert(std::pair(mob, distance)); } } @@ -655,17 +655,17 @@ bool Client::Process() { { //client logged out or errored out //ResetTrade(); - if (client_state != CLIENT_KICKED && !zoning && !instalog) { + if (client_state != CLIENT_KICKED && !bZoning && !instalog) { Save(); } client_state = CLIENT_LINKDEAD; - if (zoning || instalog || GetGM()) + if (bZoning || instalog || GetGM()) { Group *mygroup = GetGroup(); if (mygroup) { - if (!zoning) + if (!bZoning) { entity_list.MessageGroup(this, true, 15, "%s logged out.", GetName()); LeaveGroup(); @@ -684,7 +684,7 @@ bool Client::Process() { Raid *myraid = entity_list.GetRaidByClient(this); if (myraid) { - if (!zoning) + if (!bZoning) { //entity_list.MessageGroup(this,true,15,"%s logged out.",GetName()); myraid->MemberZoned(this); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index b440fdd3b..0c8ef58b9 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -146,7 +146,7 @@ XS(XS__echo) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: echo(id#, str)"); + Perl_croak(aTHX_ "Usage: echo(color_id, message)"); quest_manager.echo(SvUV(ST(0)), SvPV_nolen(ST(1))); @@ -162,7 +162,7 @@ XS(XS__say) { else if (items == 2) quest_manager.say(SvPV_nolen(ST(0)), (int)SvIV(ST(1))); else - Perl_croak(aTHX_ "Usage: say(str [, language])"); + Perl_croak(aTHX_ "Usage: say(message [, language_id])"); XSRETURN_EMPTY; } @@ -172,7 +172,7 @@ XS(XS__me) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: %s(str)", "me"); + Perl_croak(aTHX_ "Usage: %s(message)", "me"); quest_manager.me(SvPV_nolen(ST(0))); @@ -188,7 +188,7 @@ XS(XS__summonitem) else if(items == 2) quest_manager.summonitem(SvUV(ST(0)), SvUV(ST(1))); else - Perl_croak(aTHX_ "Usage: summonitem(itemid, [charges])"); + Perl_croak(aTHX_ "Usage: summonitem(item_id, [charges])"); XSRETURN_EMPTY; } @@ -197,12 +197,12 @@ XS(XS__write) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: write(file, str)"); + Perl_croak(aTHX_ "Usage: write(file, message)"); char * file = (char *)SvPV_nolen(ST(0)); - char * str = (char *)SvPV_nolen(ST(1)); + char * message = (char *)SvPV_nolen(ST(1)); - quest_manager.write(file, str); + quest_manager.write(file, message); XSRETURN_EMPTY; } @@ -212,17 +212,17 @@ XS(XS__spawn) { dXSARGS; if (items != 6) - Perl_croak(aTHX_ "Usage: spawn(npc_type, grid, unused, x, y, z)"); + Perl_croak(aTHX_ "Usage: spawn(npc_type_id, grid_id, int_unused, x, y, z)"); uint16 RETVAL; dXSTARG; - int npc_type = (int)SvIV(ST(0)); - int grid = (int)SvIV(ST(1)); - int unused = (int)SvIV(ST(2)); + int npc_type_id = (int)SvIV(ST(0)); + int grid_id = (int)SvIV(ST(1)); + int int_unused = (int)SvIV(ST(2)); auto position = glm::vec4((float)SvNV(ST(3)), (float)SvNV(ST(4)), (float)SvNV(ST(5)), 0.0f); - Mob *r = quest_manager.spawn2(npc_type, grid, unused, position); + Mob *r = quest_manager.spawn2(npc_type_id, grid_id, int_unused, position); RETVAL = (r != nullptr) ? r->GetID() : 0; XSprePUSH; PUSHu((UV)RETVAL); @@ -234,17 +234,17 @@ XS(XS__spawn2) { dXSARGS; if (items != 7) - Perl_croak(aTHX_ "Usage: spawn2(npc_type, grid, unused, x, y, z, heading)"); + Perl_croak(aTHX_ "Usage: spawn2(npc_type_id, grid_id, int_unused, x, y, z, heading)"); uint16 RETVAL; dXSTARG; - int npc_type = (int)SvIV(ST(0)); - int grid = (int)SvIV(ST(1)); - int unused = (int)SvIV(ST(2)); + int npc_type_id = (int)SvIV(ST(0)); + int grid_id = (int)SvIV(ST(1)); + int int_unused = (int)SvIV(ST(2)); auto position = glm::vec4((float)SvNV(ST(3)), (float)SvNV(ST(4)), (float)SvNV(ST(5)), (float)SvNV(ST(6))); - Mob *r = quest_manager.spawn2(npc_type, grid, unused, position); + Mob *r = quest_manager.spawn2(npc_type_id, grid_id, int_unused, position); RETVAL = (r != nullptr) ? r->GetID() : 0; XSprePUSH; PUSHu((UV)RETVAL); @@ -256,14 +256,14 @@ XS(XS__unique_spawn) { dXSARGS; if (items != 6 && items != 7) - Perl_croak(aTHX_ "Usage: unique_spawn(npc_type, grid, unused, x, y, z, [heading])"); + Perl_croak(aTHX_ "Usage: unique_spawn(npc_type_id, grid_id, int_unused, x, y, z, [heading])"); uint16 RETVAL; dXSTARG; - int npc_type = (int)SvIV(ST(0)); - int grid = (int)SvIV(ST(1)); - int unused = (int)SvIV(ST(2)); + int npc_type_id = (int)SvIV(ST(0)); + int grid_id = (int)SvIV(ST(1)); + int int_unused = (int)SvIV(ST(2)); float x = (float)SvNV(ST(3)); float y = (float)SvNV(ST(4)); float z = (float)SvNV(ST(5)); @@ -271,7 +271,7 @@ XS(XS__unique_spawn) if(items == 7) heading = (float)SvNV(ST(6)); - Mob *r = quest_manager.unique_spawn(npc_type, grid, unused, glm::vec4(x, y, z, heading)); + Mob *r = quest_manager.unique_spawn(npc_type_id, grid_id, int_unused, glm::vec4(x, y, z, heading)); RETVAL = (r != nullptr) ? r->GetID() : 0; XSprePUSH; PUSHu((UV)RETVAL); @@ -330,12 +330,12 @@ XS(XS__setstat) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: setstat(stat, value)"); + Perl_croak(aTHX_ "Usage: setstat(stat_id, int_value)"); - int stat = (int)SvIV(ST(0)); - int value = (int)SvIV(ST(1)); + int stat_id = (int)SvIV(ST(0)); + int int_value = (int)SvIV(ST(1)); - quest_manager.setstat(stat, value); + quest_manager.setstat(stat_id, int_value); XSRETURN_EMPTY; } @@ -345,12 +345,12 @@ XS(XS__incstat) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: incstat(stat, value)"); + Perl_croak(aTHX_ "Usage: incstat(stat_id, int_value)"); - int stat = (int)SvIV(ST(0)); - int value = (int)SvIV(ST(1)); + int stat_id = (int)SvIV(ST(0)); + int int_value = (int)SvIV(ST(1)); - quest_manager.incstat(stat, value); + quest_manager.incstat(stat_id, int_value); XSRETURN_EMPTY; } @@ -391,7 +391,7 @@ XS(XS__addloot) if(items < 1 || items > 3) Perl_croak(aTHX_ "Usage: addloot(item_id, charges = 0, equipitem = true)"); - uint32 itemid = (uint32)SvUV(ST(0)); + uint32 item_id = (uint32)SvUV(ST(0)); uint16 charges = 0; bool equipitem = true; @@ -400,7 +400,7 @@ XS(XS__addloot) if (items > 2) equipitem = (bool)SvTRUE(ST(2)); - quest_manager.addloot(itemid, charges, equipitem); + quest_manager.addloot(item_id, charges, equipitem); XSRETURN_EMPTY; } @@ -480,11 +480,11 @@ XS(XS__emote) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: emote(str)"); + Perl_croak(aTHX_ "Usage: emote(message)"); - char * str = (char *)SvPV_nolen(ST(0)); + char * message = (char *)SvPV_nolen(ST(0)); - quest_manager.emote(str); + quest_manager.emote(message); XSRETURN_EMPTY; } @@ -494,11 +494,11 @@ XS(XS__shout) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: shout(str)"); + Perl_croak(aTHX_ "Usage: shout(message)"); - char * str = (char *)SvPV_nolen(ST(0)); + char * message = (char *)SvPV_nolen(ST(0)); - quest_manager.shout(str); + quest_manager.shout(message); XSRETURN_EMPTY; } @@ -508,11 +508,11 @@ XS(XS__shout2) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: shout2(str)"); + Perl_croak(aTHX_ "Usage: shout2(message)"); - char * str = (char *)SvPV_nolen(ST(0)); + char * message = (char *)SvPV_nolen(ST(0)); - quest_manager.shout2(str); + quest_manager.shout2(message); XSRETURN_EMPTY; } @@ -522,16 +522,16 @@ XS(XS__gmsay) { dXSARGS; if ((items < 1) || (items > 5)) - Perl_croak(aTHX_ "Usage: gmsay(str, color, send_to_world?)"); + Perl_croak(aTHX_ "Usage: gmsay(message, color_id, send_to_world)"); - char * str = (char *)SvPV_nolen(ST(0)); - int color = 7; + char * message = (char *)SvPV_nolen(ST(0)); + int color_id = 7; bool send_to_world = 0; uint32 to_guilddbid = 0; uint16 to_minstatus = 80; if (items > 1) { - color = (int)SvIV(ST(1)); + color_id = (int)SvIV(ST(1)); } if (items > 2) { @@ -544,7 +544,7 @@ XS(XS__gmsay) if (items > 4) to_minstatus = (int)SvUV(ST(4)); - quest_manager.gmsay(str, color, send_to_world, to_guilddbid, to_minstatus); + quest_manager.gmsay(message, color_id, send_to_world, to_guilddbid, to_minstatus); XSRETURN_EMPTY; } @@ -554,17 +554,17 @@ XS(XS__depop) { dXSARGS; if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: depop(npc_type= 0)"); + Perl_croak(aTHX_ "Usage: depop(npc_type_id = 0)"); - int npc_type; + int npc_type_id; if (items < 1) - npc_type = 0; + npc_type_id = 0; else - npc_type = (int)SvIV(ST(0)); + npc_type_id = (int)SvIV(ST(0)); - quest_manager.depop(npc_type); + quest_manager.depop(npc_type_id); XSRETURN_EMPTY; } @@ -574,17 +574,17 @@ XS(XS__depop_withtimer) { dXSARGS; if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: depop_withtimer(npc_type= 0)"); + Perl_croak(aTHX_ "Usage: depop_withtimer(npc_type_id= 0)"); - int npc_type; + int npc_type_id; if (items < 1) - npc_type = 0; + npc_type_id = 0; else - npc_type = (int)SvIV(ST(0)); + npc_type_id = (int)SvIV(ST(0)); - quest_manager.depop_withtimer(npc_type); + quest_manager.depop_withtimer(npc_type_id); XSRETURN_EMPTY; } @@ -594,17 +594,17 @@ XS(XS__depopall) { dXSARGS; if (items < 0 || items > 1) - Perl_croak(aTHX_ "Usage: depopall(npc_type= 0)"); + Perl_croak(aTHX_ "Usage: depopall(npc_type_id= 0)"); - int npc_type; + int npc_type_id; if (items < 1) - npc_type = 0; + npc_type_id = 0; else - npc_type = (int)SvIV(ST(0)); + npc_type_id = (int)SvIV(ST(0)); - quest_manager.depopall(npc_type); + quest_manager.depopall(npc_type_id); XSRETURN_EMPTY; } @@ -614,12 +614,12 @@ XS(XS__settarget) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: settarget(type, target_id)"); + Perl_croak(aTHX_ "Usage: settarget(target_enum, target_id)"); - char * type = (char *)SvPV_nolen(ST(0)); + char * target_enum = (char *)SvPV_nolen(ST(0)); int target_id = (int)SvIV(ST(1)); - quest_manager.settarget(type, target_id); + quest_manager.settarget(target_enum, target_id); XSRETURN_EMPTY; } @@ -935,18 +935,18 @@ XS(XS__movepc) if (items != 4 && items != 5) Perl_croak(aTHX_ "Usage: movepc(zone_id, x, y, z [,heading])"); - int zoneid = (int)SvIV(ST(0)); + int zone_id = (int)SvIV(ST(0)); float x = (float)SvNV(ST(1)); float y = (float)SvNV(ST(2)); float z = (float)SvNV(ST(3)); if (items == 4) - quest_manager.movepc(zoneid, x, y, z, 0.0f); + quest_manager.movepc(zone_id, x, y, z, 0.0f); else { float heading = (float)SvNV(ST(4)); - quest_manager.movepc(zoneid, x, y, z, heading); + quest_manager.movepc(zone_id, x, y, z, heading); } XSRETURN_EMPTY; @@ -973,14 +973,14 @@ XS(XS__movegrp) { dXSARGS; if (items != 4) - Perl_croak(aTHX_ "Usage: movegrp(zoneid, x, y, z)"); + Perl_croak(aTHX_ "Usage: movegrp(zone_id, x, y, z)"); - int zoneid = (int)SvIV(ST(0)); + int zone_id = (int)SvIV(ST(0)); float x = (float)SvNV(ST(1)); float y = (float)SvNV(ST(2)); float z = (float)SvNV(ST(3)); - quest_manager.movegrp(zoneid, x, y, z); + quest_manager.movegrp(zone_id, x, y, z); XSRETURN_EMPTY; } @@ -1004,12 +1004,12 @@ XS(XS__addskill) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: addskill(skill_id, value)"); + Perl_croak(aTHX_ "Usage: addskill(skill_id, int_value)"); int skill_id = (int)SvIV(ST(0)); - int value = (int)SvIV(ST(1)); + int int_value = (int)SvIV(ST(1)); - quest_manager.addskill(skill_id, value); + quest_manager.addskill(skill_id, int_value); XSRETURN_EMPTY; } @@ -1019,12 +1019,12 @@ XS(XS__setlanguage) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: setlanguage(skill_id, value)"); + Perl_croak(aTHX_ "Usage: setlanguage(skill_id, int_value)"); int skill_id = (int)SvIV(ST(0)); - int value = (int)SvIV(ST(1)); + int int_value = (int)SvIV(ST(1)); - quest_manager.setlanguage(skill_id, value); + quest_manager.setlanguage(skill_id, int_value); XSRETURN_EMPTY; } @@ -1034,12 +1034,12 @@ XS(XS__setskill) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: setskill(skill_id, value)"); + Perl_croak(aTHX_ "Usage: setskill(skill_id, int_value)"); int skill_id = (int)SvIV(ST(0)); - int value = (int)SvIV(ST(1)); + int int_value = (int)SvIV(ST(1)); - quest_manager.setskill(skill_id, value); + quest_manager.setskill(skill_id, int_value); XSRETURN_EMPTY; } @@ -1049,11 +1049,11 @@ XS(XS__setallskill) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: setallskill(value)"); + Perl_croak(aTHX_ "Usage: setallskill(int_value)"); - int value = (int)SvIV(ST(0)); + int int_value = (int)SvIV(ST(0)); - quest_manager.setallskill(value); + quest_manager.setallskill(int_value); XSRETURN_EMPTY; } @@ -1118,10 +1118,10 @@ XS(XS__faction) { dXSARGS; if (items < 2 || items > 3) - Perl_croak(aTHX_ "Usage: faction(faction_id, faction_value, temp)"); + Perl_croak(aTHX_ "Usage: faction(faction_id, int_value, temp)"); int faction_id = (int)SvIV(ST(0)); - int faction_value = (int)SvIV(ST(1)); + int int_value = (int)SvIV(ST(1)); int temp; if(items == 2) @@ -1129,7 +1129,7 @@ XS(XS__faction) else temp = (int)SvIV(ST(2)); - quest_manager.faction(faction_id, faction_value, temp); + quest_manager.faction(faction_id, int_value, temp); XSRETURN_EMPTY; } @@ -1153,12 +1153,12 @@ XS(XS__setguild) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: setguild(new_guild_id, new_rank)"); + Perl_croak(aTHX_ "Usage: setguild(new_guild_id, guild_rank_id)"); unsigned long new_guild_id = (unsigned long)SvUV(ST(0)); - int new_rank = (int)SvIV(ST(1)); + int guild_rank_id = (int)SvIV(ST(1)); - quest_manager.setguild(new_guild_id, new_rank); + quest_manager.setguild(new_guild_id, guild_rank_id); XSRETURN_EMPTY; } @@ -1168,12 +1168,12 @@ XS(XS__createguild) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: createguild(guild_name, leader)"); + Perl_croak(aTHX_ "Usage: createguild(guild_name, leader_name)"); char * guild_name = (char *)SvPV_nolen(ST(0)); - char * leader = (char *)SvPV_nolen(ST(1)); + char * leader_name = (char *)SvPV_nolen(ST(1)); - quest_manager.CreateGuild(guild_name, leader); + quest_manager.CreateGuild(guild_name, leader_name); XSRETURN_EMPTY; } @@ -1265,14 +1265,14 @@ XS(XS__setglobal) { dXSARGS; if (items != 4) - Perl_croak(aTHX_ "Usage: setglobal(varname, newvalue, options, duration)"); + Perl_croak(aTHX_ "Usage: setglobal(key, str_value, options, duration)"); - char * varname = (char *)SvPV_nolen(ST(0)); - char * newvalue = (char *)SvPV_nolen(ST(1)); + char * key = (char *)SvPV_nolen(ST(0)); + char * str_value = (char *)SvPV_nolen(ST(1)); int options = (int)SvIV(ST(2)); char * duration = (char *)SvPV_nolen(ST(3)); - quest_manager.setglobal(varname, newvalue, options, duration); + quest_manager.setglobal(key, str_value, options, duration); XSRETURN_EMPTY; } @@ -1282,16 +1282,16 @@ XS(XS__targlobal) { dXSARGS; if (items != 6) - Perl_croak(aTHX_ "Usage: targlobal(varname, value, duration, npcid, charid, zoneid)"); + Perl_croak(aTHX_ "Usage: targlobal(key, str_value, duration, npc_id, char_id, zone_id)"); - char * varname = (char *)SvPV_nolen(ST(0)); - char * value = (char *)SvPV_nolen(ST(1)); + char * key = (char *)SvPV_nolen(ST(0)); + char * str_value = (char *)SvPV_nolen(ST(1)); char * duration = (char *)SvPV_nolen(ST(2)); - int npcid = (int)SvIV(ST(3)); - int charid = (int)SvIV(ST(4)); - int zoneid = (int)SvIV(ST(5)); + int npc_id = (int)SvIV(ST(3)); + int char_id = (int)SvIV(ST(4)); + int zone_id = (int)SvIV(ST(5)); - quest_manager.targlobal(varname, value, duration, npcid, charid, zoneid); + quest_manager.targlobal(key, str_value, duration, npc_id, char_id, zone_id); XSRETURN_EMPTY; } @@ -1301,11 +1301,11 @@ XS(XS__delglobal) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: delglobal(varname)"); + Perl_croak(aTHX_ "Usage: delglobal(key)"); - char * varname = (char *)SvPV_nolen(ST(0)); + char * key = (char *)SvPV_nolen(ST(0)); - quest_manager.delglobal(varname); + quest_manager.delglobal(key); XSRETURN_EMPTY; } @@ -1328,12 +1328,12 @@ XS(XS__rebind) { dXSARGS; if (items != 4) - Perl_croak(aTHX_ "Usage: rebind(zoneid, x, y, z)"); + Perl_croak(aTHX_ "Usage: rebind(zone_id, x, y, z)"); - int zoneid = (int)SvIV(ST(0)); + int zone_id = (int)SvIV(ST(0)); auto location = glm::vec3((float)SvNV(ST(1)),(float)SvNV(ST(2)),(float)SvNV(ST(3))); - quest_manager.rebind(zoneid, location); + quest_manager.rebind(zone_id, location); XSRETURN_EMPTY; } @@ -1384,7 +1384,7 @@ XS(XS__moveto) { dXSARGS; if (items != 3 && items != 4 && items != 5) - Perl_croak(aTHX_ "Usage: moveto(x, y, z, [mth, saveguard?])"); + Perl_croak(aTHX_ "Usage: moveto(x, y, z, [heading], [saveguard?])"); float x = (float)SvNV(ST(0)); float y = (float)SvNV(ST(1)); @@ -1425,12 +1425,12 @@ XS(XS__addldonpoints) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: addldonpoints(points, theme)"); + Perl_croak(aTHX_ "Usage: addldonpoints(points, theme_id)"); long points = (long)SvIV(ST(0)); - unsigned long theme = (unsigned long)SvUV(ST(1)); + unsigned long theme_id = (unsigned long)SvUV(ST(1)); - quest_manager.addldonpoints(points, theme); + quest_manager.addldonpoints(points, theme_id); XSRETURN_EMPTY; } @@ -1440,12 +1440,12 @@ XS(XS__addldonwin) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: addldonwin(wins, theme)"); + Perl_croak(aTHX_ "Usage: addldonwin(wins, theme_id)"); long wins = (long)SvIV(ST(0)); - unsigned long theme = (unsigned long)SvUV(ST(1)); + unsigned long theme_id = (unsigned long)SvUV(ST(1)); - quest_manager.addldonwin(wins, theme); + quest_manager.addldonwin(wins, theme_id); XSRETURN_EMPTY; } @@ -1455,12 +1455,12 @@ XS(XS__addldonloss) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: addldonloss(losses, theme)"); + Perl_croak(aTHX_ "Usage: addldonloss(losses, theme_id)"); long losses = (long)SvIV(ST(0)); - unsigned long theme = (unsigned long)SvUV(ST(1)); + unsigned long theme_id = (unsigned long)SvUV(ST(1)); - quest_manager.addldonloss(losses, theme); + quest_manager.addldonloss(losses, theme_id); XSRETURN_EMPTY; } @@ -1512,12 +1512,12 @@ XS(XS__respawn) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: respawn(npc_type, grid)"); + Perl_croak(aTHX_ "Usage: respawn(npc_type_id, grid_id)"); - int npc_type = (int)SvIV(ST(0)); - int grid = (int)SvIV(ST(1)); + int npc_type_id = (int)SvIV(ST(0)); + int grid_id = (int)SvIV(ST(1)); - quest_manager.respawn(npc_type, grid); + quest_manager.respawn(npc_type_id, grid_id); XSRETURN_EMPTY; } @@ -1543,19 +1543,19 @@ XS(XS__set_proximity) { dXSARGS; if (items != 4 && items != 6) - Perl_croak(aTHX_ "Usage: set_proximity(minx, maxx, miny, maxy [, minz, maxz])"); + Perl_croak(aTHX_ "Usage: set_proximity(min_x, max_x, min_y, max_y [, min_z, max_z])"); - float minx = (float)SvNV(ST(0)); - float maxx = (float)SvNV(ST(1)); - float miny = (float)SvNV(ST(2)); - float maxy = (float)SvNV(ST(3)); + float min_x = (float)SvNV(ST(0)); + float max_x = (float)SvNV(ST(1)); + float min_y = (float)SvNV(ST(2)); + float max_y = (float)SvNV(ST(3)); if(items == 4) - quest_manager.set_proximity(minx, maxx, miny, maxy); + quest_manager.set_proximity(min_x, max_x, min_y, max_y); else { - float minz = (float)SvNV(ST(4)); - float maxz = (float)SvNV(ST(5)); - quest_manager.set_proximity(minx, maxx, miny, maxy, minz, maxz); + float min_z = (float)SvNV(ST(4)); + float max_z = (float)SvNV(ST(5)); + quest_manager.set_proximity(min_x, max_x, min_y, max_y, min_z, max_z); } XSRETURN_EMPTY; @@ -1602,7 +1602,7 @@ XS(XS__setanim) //Cisyouc: mob->setappearance() addition { dXSARGS; if(items != 2) - Perl_croak(aTHX_ "Usage: quest::setanim(npc_type, animnum);"); + Perl_croak(aTHX_ "Usage: quest::setanim(npc_type_id, anim_num);"); quest_manager.setanim(SvUV(ST(0)), SvUV(ST(1))); @@ -1626,24 +1626,24 @@ XS(XS__spawn_condition) { dXSARGS; if (items < 3 || items > 4) - Perl_croak(aTHX_ "Usage: spawn_condition(zone_short, [instance_id], condition_id, value)"); + Perl_croak(aTHX_ "Usage: spawn_condition(zone_short, [instance_id], condition_id, int_value)"); if(items == 3) { char * zone_short = (char *)SvPV_nolen(ST(0)); - uint16 cond_id = (int)SvUV(ST(1)); - int16 value = (int)SvIV(ST(2)); + uint16 condition_id = (int)SvUV(ST(1)); + int16 int_value = (int)SvIV(ST(2)); - quest_manager.spawn_condition(zone_short, zone->GetInstanceID(), cond_id, value); + quest_manager.spawn_condition(zone_short, zone->GetInstanceID(), condition_id, int_value); } else { char * zone_short = (char *)SvPV_nolen(ST(0)); uint32 instance_id = (int)SvUV(ST(1)); - uint16 cond_id = (int)SvUV(ST(2)); - int16 value = (int)SvIV(ST(3)); + uint16 condition_id = (int)SvUV(ST(2)); + int16 int_value = (int)SvIV(ST(3)); - quest_manager.spawn_condition(zone_short, instance_id, cond_id, value); + quest_manager.spawn_condition(zone_short, instance_id, condition_id, int_value); } XSRETURN_EMPTY; } @@ -1689,14 +1689,14 @@ XS(XS__toggle_spawn_event) { dXSARGS; if (items != 4) - Perl_croak(aTHX_ "Usage: toggle_spawn_event(event_id, enabled?, strict, reset_base)"); + Perl_croak(aTHX_ "Usage: toggle_spawn_event(event_id, is_enabled, is_strict, reset_base)"); uint32 event_id = (int)SvIV(ST(0)); - bool enabled = ((int)SvIV(ST(1))) == 0?false:true; - bool strict = ((int)SvIV(ST(2))) == 0?false:true; + bool is_enabled = ((int)SvIV(ST(1))) == 0?false:true; + bool is_strict = ((int)SvIV(ST(2))) == 0?false:true; bool reset_base = ((int)SvIV(ST(3))) == 0?false:true; - quest_manager.toggle_spawn_event(event_id, enabled, strict, reset_base); + quest_manager.toggle_spawn_event(event_id, is_enabled, is_strict, reset_base); XSRETURN_EMPTY; } @@ -1825,22 +1825,22 @@ XS(XS__forcedooropen) { dXSARGS; if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: forcedooropen(doorid [, altmode=0])"); + Perl_croak(aTHX_ "Usage: forcedooropen(door_id, [alt_mode=0])"); if (items == 1) { - uint32 did = (int)SvIV(ST(0)); + uint32 door_id = (int)SvIV(ST(0)); - quest_manager.forcedooropen(did, false); + quest_manager.forcedooropen(door_id, false); XSRETURN_EMPTY; } else { - uint32 did = (int)SvIV(ST(0)); - bool am = (int)SvIV(ST(1)) == 0?false:true; + uint32 door_id = (int)SvIV(ST(0)); + bool alt_mode = (int)SvIV(ST(1)) == 0?false:true; - quest_manager.forcedooropen(did, am); + quest_manager.forcedooropen(door_id, alt_mode); XSRETURN_EMPTY; } @@ -1851,22 +1851,22 @@ XS(XS__forcedoorclose) { dXSARGS; if (items < 1 || items > 2) - Perl_croak(aTHX_ "Usage: forcedoorclose(doorid [, altmode=0])"); + Perl_croak(aTHX_ "Usage: forcedoorclose(door_id, [alt_mode=0])"); if (items == 1) { - uint32 did = (int)SvIV(ST(0)); + uint32 door_id = (int)SvIV(ST(0)); - quest_manager.forcedoorclose(did, false); + quest_manager.forcedoorclose(door_id, false); XSRETURN_EMPTY; } else { - uint32 did = (int)SvIV(ST(0)); - bool am = (int)SvIV(ST(1)) == 0?false:true; + uint32 door_id = (int)SvIV(ST(0)); + bool alt_mode = (int)SvIV(ST(1)) == 0?false:true; - quest_manager.forcedoorclose(did, am); + quest_manager.forcedoorclose(door_id, alt_mode); XSRETURN_EMPTY; } @@ -1877,11 +1877,11 @@ XS(XS__toggledoorstate) { dXSARGS; if (items !=1) - Perl_croak(aTHX_ "Usage: toggledoorstate(doorid)"); + Perl_croak(aTHX_ "Usage: toggledoorstate(door_id)"); - uint32 did = (int)SvIV(ST(0)); + uint32 door_id = (int)SvIV(ST(0)); - quest_manager.toggledoorstate(did); + quest_manager.toggledoorstate(door_id); XSRETURN_EMPTY; } @@ -1891,14 +1891,14 @@ XS(XS__isdooropen) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: isdooropen(doorid)"); + Perl_croak(aTHX_ "Usage: isdooropen(door_id)"); bool RETVAL; dXSTARG; - uint32 doorid = (int)SvIV(ST(0)); + uint32 door_id = (int)SvIV(ST(0)); - RETVAL = quest_manager.isdooropen(doorid); + RETVAL = quest_manager.isdooropen(door_id); XSprePUSH; PUSHu((IV)RETVAL); XSRETURN(1); @@ -1955,19 +1955,19 @@ XS(XS__AddNode) if (items < 3 || items > 5) Perl_croak(aTHX_ "Usage: AddNode(x, y, z, [best_z], [requested_id])"); - int x = (int)SvIV(ST(0)); - int y = (int)SvIV(ST(1)); - int z = (int)SvIV(ST(2)); + float x = (float)SvNV(ST(0)); + float y = (float)SvNV(ST(1)); + float z = (float)SvNV(ST(2)); int best_z = 0; int requested_id = 0; if (items == 4) { - best_z = (int)SvIV(ST(3)); + best_z = (float)SvNV(ST(3)); } else if (items == 5) { - best_z = (int)SvIV(ST(3)); + best_z = (float)SvNV(ST(3)); requested_id = (int)SvIV(ST(4)); } @@ -2009,11 +2009,11 @@ XS(XS__npcsize) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: npcsize(newsize)"); + Perl_croak(aTHX_ "Usage: npcsize(size)"); - int newsize = (int)SvIV(ST(0)); + int size = (int)SvIV(ST(0)); - quest_manager.npcsize(newsize); + quest_manager.npcsize(size); XSRETURN_EMPTY; } @@ -2023,11 +2023,11 @@ XS(XS__npctexture) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: npctexture(newtexture)"); + Perl_croak(aTHX_ "Usage: npctexture(texture_id)"); - int newtexture = (int)SvIV(ST(0)); + int texture_id = (int)SvIV(ST(0)); - quest_manager.npctexture(newtexture); + quest_manager.npctexture(texture_id); XSRETURN_EMPTY; } @@ -2079,11 +2079,11 @@ XS(XS__playertexture) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: playertexture(newtexture)"); + Perl_croak(aTHX_ "Usage: playertexture(texture_id)"); - int newtexture = (int)SvIV(ST(0)); + int texture_id = (int)SvIV(ST(0)); - quest_manager.playertexture(newtexture); + quest_manager.playertexture(texture_id); XSRETURN_EMPTY; } @@ -2093,12 +2093,12 @@ XS(XS__playerfeature) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: playerfeature(feature, setting)"); + Perl_croak(aTHX_ "Usage: playerfeature(str_value, int_value)"); - char * feature = (char *)SvPV_nolen(ST(0)); - int setting = (int)SvIV(ST(1)); + char * str_value = (char *)SvPV_nolen(ST(0)); + int int_value = (int)SvIV(ST(1)); - quest_manager.playerfeature(feature, setting); + quest_manager.playerfeature(str_value, int_value); XSRETURN_EMPTY; } @@ -2108,12 +2108,12 @@ XS(XS__npcfeature) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: npcfeature(feature, setting)"); + Perl_croak(aTHX_ "Usage: npcfeature(str_value, int_value)"); - char * feature = (char *)SvPV_nolen(ST(0)); - int setting = (int)SvIV(ST(1)); + char * str_value = (char *)SvPV_nolen(ST(0)); + int int_value = (int)SvIV(ST(1)); - quest_manager.npcfeature(feature, setting); + quest_manager.npcfeature(str_value, int_value); XSRETURN_EMPTY; } @@ -2168,17 +2168,17 @@ XS(XS__createBot) if(items != 6) { - Perl_croak(aTHX_ "Usage: createBot(firstname, lastname, level, race, class, gender)"); + Perl_croak(aTHX_ "Usage: createBot(firstname, lastname, level, race_id, class_id, gender_id)"); } char *firstname = (char *)SvPV_nolen(ST(0)); char *lastname = (char *)SvPV_nolen(ST(1)); int level = (int) SvIV(ST(2)); - int race = (int) SvIV(ST(3)); - int botclass = (int) SvIV(ST(4)); - int gender = (int) SvIV(ST(5)); + int race_id = (int) SvIV(ST(3)); + int class_id = (int) SvIV(ST(4)); + int gender_id = (int) SvIV(ST(5)); - RETVAL = quest_manager.createBot(firstname, lastname, level, race, botclass, gender); + RETVAL = quest_manager.createBot(firstname, lastname, level, race_id, class_id, gender_id); XSprePUSH; PUSHu((IV)RETVAL); XSRETURN(1); } @@ -2196,20 +2196,20 @@ XS(XS__taskselector) } quest_manager.taskselector(items, tasks); } else { - Perl_croak(aTHX_ "Usage: taskselector(taskid1, taskid2, ..., taskid%i)", MAXCHOOSERENTRIES); + Perl_croak(aTHX_ "Usage: taskselector(task_id1, task_id2, ..., task_id%i)", MAXCHOOSERENTRIES); } XSRETURN_EMPTY; } -XS(XS__tasksetselector); -XS(XS__tasksetselector) +XS(XS__task_setselector); +XS(XS__task_setselector) { dXSARGS; if(items == 1) { - int tasksetid = (int)SvIV(ST(0)); - quest_manager.tasksetselector(tasksetid); + int task_setid = (int)SvIV(ST(0)); + quest_manager.tasksetselector(task_setid); } else { - Perl_croak(aTHX_ "Usage: tasksetselector(tasksetid)"); + Perl_croak(aTHX_ "Usage: task_setselector(task_setid)"); } XSRETURN_EMPTY; @@ -2225,7 +2225,7 @@ XS(XS__enabletask) } quest_manager.enabletask(items, tasks); } else { - Perl_croak(aTHX_ "Usage: enabletask(taskid1, taskid2, ..., taskid10"); + Perl_croak(aTHX_ "Usage: enabletask(task_id1, task_id2, ..., task_id10"); } XSRETURN_EMPTY; @@ -2241,7 +2241,7 @@ XS(XS__disabletask) } quest_manager.disabletask(items, tasks); } else { - Perl_croak(aTHX_ "Usage: disabletask(taskid1, taskid2, ..., taskid10"); + Perl_croak(aTHX_ "Usage: disabletask(task_id1, task_id2, ..., task_id10"); } XSRETURN_EMPTY; @@ -2255,10 +2255,10 @@ XS(XS__istaskenabled) dXSTARG; if(items == 1) { - unsigned int taskid = (int)SvIV(ST(0)); - RETVAL = quest_manager.istaskenabled(taskid); + unsigned int task_id = (int)SvIV(ST(0)); + RETVAL = quest_manager.istaskenabled(task_id); } else { - Perl_croak(aTHX_ "Usage: istaskenabled(taskid)"); + Perl_croak(aTHX_ "Usage: istaskenabled(task_id)"); } XSprePUSH; PUSHu((IV)RETVAL); @@ -2273,10 +2273,10 @@ XS(XS__istaskactive) dXSTARG; if(items == 1) { - unsigned int task = (int)SvIV(ST(0)); - RETVAL = quest_manager.istaskactive(task); + unsigned int task_id = (int)SvIV(ST(0)); + RETVAL = quest_manager.istaskactive(task_id); } else { - Perl_croak(aTHX_ "Usage: istaskactive(task)"); + Perl_croak(aTHX_ "Usage: istaskactive(task_id)"); } XSprePUSH; PUSHu((IV)RETVAL); @@ -2291,11 +2291,11 @@ XS(XS__istaskactivityactive) dXSTARG; if(items == 2) { - unsigned int task = (int)SvIV(ST(0)); - unsigned int activity = (int)SvIV(ST(1)); - RETVAL = quest_manager.istaskactivityactive(task, activity); + unsigned int task_id = (int)SvIV(ST(0)); + unsigned int activity_id = (int)SvIV(ST(1)); + RETVAL = quest_manager.istaskactivityactive(task_id, activity_id); } else { - Perl_croak(aTHX_ "Usage: istaskactivityactive(task,activity)"); + Perl_croak(aTHX_ "Usage: istaskactivityactive(task_id, activity_id)"); } XSprePUSH; PUSHu((IV)RETVAL); @@ -2310,12 +2310,12 @@ XS(XS__gettaskactivitydonecount) dXSTARG; if(items == 2) { - unsigned int task = (int)SvIV(ST(0)); - unsigned int activity = (int)SvIV(ST(1)); - RETVAL = quest_manager.gettaskactivitydonecount(task, activity); + unsigned int task_id = (int)SvIV(ST(0)); + unsigned int activity_id = (int)SvIV(ST(1)); + RETVAL = quest_manager.gettaskactivitydonecount(task_id, activity_id); XSprePUSH; PUSHu((UV)RETVAL); } else { - Perl_croak(aTHX_ "Usage: gettaskactivitydonecount(task,activity)"); + Perl_croak(aTHX_ "Usage: gettaskactivitydonecount(task_id, activity_id)"); } XSRETURN(1); @@ -2324,24 +2324,24 @@ XS(XS__updatetaskactivity); XS(XS__updatetaskactivity) { dXSARGS; - unsigned int task, activity; + unsigned int task_id, activity_id; int count = 1; bool ignore_quest_update = false; if(items == 2) { - task = (int)SvIV(ST(0)); - activity = (int)SvIV(ST(1)); - quest_manager.updatetaskactivity(task, activity, count, false); + task_id = (int)SvIV(ST(0)); + activity_id = (int)SvIV(ST(1)); + quest_manager.updatetaskactivity(task_id, activity_id, count, false); } else if (items == 3 || items == 4) { - task = (int)SvIV(ST(0)); - activity = (int)SvIV(ST(1)); + task_id = (int)SvIV(ST(0)); + activity_id = (int)SvIV(ST(1)); count = (int)SvIV(ST(2)); if (items == 4){ bool ignore_quest_update = (bool)SvTRUE(ST(3)); } - quest_manager.updatetaskactivity(task, activity, count, ignore_quest_update); + quest_manager.updatetaskactivity(task_id, activity_id, count, ignore_quest_update); } else { - Perl_croak(aTHX_ "Usage: updatetaskactivity(task, activity, [count], [ignore_quest_update])"); + Perl_croak(aTHX_ "Usage: updatetaskactivity(task_id, activity_id, [count], [ignore_quest_update])"); } XSRETURN_EMPTY; @@ -2353,11 +2353,13 @@ XS(XS__resettaskactivity) dXSARGS; unsigned int task, activity; if(items == 2) { - task = (int)SvIV(ST(0)); - activity = (int)SvIV(ST(1)); - quest_manager.resettaskactivity(task, activity); + int task_id = (int)SvIV(ST(0)); + int activity_id = (int)SvIV(ST(1)); + + quest_manager.resettaskactivity(task_id, activity_id); + } else { - Perl_croak(aTHX_ "Usage: resettaskactivity(task, activity)"); + Perl_croak(aTHX_ "Usage: resettaskactivity(task_id, activity_id)"); } XSRETURN_EMPTY; @@ -2367,12 +2369,12 @@ XS(XS__taskexploredarea); XS(XS__taskexploredarea) { dXSARGS; - unsigned int exploreid; + unsigned int explore_id; if(items == 1) { - exploreid = (int)SvIV(ST(0)); - quest_manager.taskexploredarea(exploreid); + explore_id = (int)SvIV(ST(0)); + quest_manager.taskexploredarea(explore_id); } else { - Perl_croak(aTHX_ "Usage: taskexplorearea(exploreid)"); + Perl_croak(aTHX_ "Usage: taskexplorearea(explore_id)"); } XSRETURN_EMPTY; @@ -2382,10 +2384,10 @@ XS(XS__assigntask); XS(XS__assigntask) { dXSARGS; - unsigned int taskid; + unsigned int task_id; bool enforce_level_requirement = false; if(items == 1 || items == 2) { - taskid = (int)SvIV(ST(0)); + task_id = (int)SvIV(ST(0)); if (items == 2) { if ((int)SvIV(ST(1)) == 1) @@ -2393,9 +2395,9 @@ XS(XS__assigntask) enforce_level_requirement = true; } } - quest_manager.assigntask(taskid, enforce_level_requirement); + quest_manager.assigntask(task_id, enforce_level_requirement); } else { - Perl_croak(aTHX_ "Usage: assigntask(taskid, enforce_level_requirement)"); + Perl_croak(aTHX_ "Usage: assigntask(task_id, enforce_level_requirement)"); } XSRETURN_EMPTY; @@ -2405,12 +2407,12 @@ XS(XS__failtask); XS(XS__failtask) { dXSARGS; - unsigned int taskid; + unsigned int task_id; if(items == 1) { - taskid = (int)SvIV(ST(0)); - quest_manager.failtask(taskid); + task_id = (int)SvIV(ST(0)); + quest_manager.failtask(task_id); } else { - Perl_croak(aTHX_ "Usage: failtask(taskid)"); + Perl_croak(aTHX_ "Usage: failtask(task_id)"); } XSRETURN_EMPTY; @@ -2424,10 +2426,10 @@ XS(XS__tasktimeleft) dXSTARG; if(items == 1) { - unsigned int taskid = (int)SvIV(ST(0)); - RETVAL = quest_manager.tasktimeleft(taskid); + unsigned int task_id = (int)SvIV(ST(0)); + RETVAL = quest_manager.tasktimeleft(task_id); } else { - Perl_croak(aTHX_ "Usage: tasktimeleft(taskid)"); + Perl_croak(aTHX_ "Usage: tasktimeleft(task_id)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2443,10 +2445,10 @@ XS(XS__istaskcompleted) dXSTARG; if(items == 1) { - unsigned int taskid = (int)SvIV(ST(0)); - RETVAL = quest_manager.istaskcompleted(taskid); + unsigned int task_id = (int)SvIV(ST(0)); + RETVAL = quest_manager.istaskcompleted(task_id); } else { - Perl_croak(aTHX_ "Usage: istaskcompleted(taskid)"); + Perl_croak(aTHX_ "Usage: istaskcompleted(task_id)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2462,10 +2464,10 @@ XS(XS__enabledtaskcount) dXSTARG; if(items == 1) { - unsigned int taskset = (int)SvIV(ST(0)); - RETVAL = quest_manager.enabledtaskcount(taskset); + unsigned int task_set = (int)SvIV(ST(0)); + RETVAL = quest_manager.enabledtaskcount(task_set); } else { - Perl_croak(aTHX_ "Usage: enabledtaskcount(taskset)"); + Perl_croak(aTHX_ "Usage: enabledtaskcount(task_set)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2481,10 +2483,10 @@ XS(XS__firsttaskinset) dXSTARG; if(items == 1) { - unsigned int taskset = (int)SvIV(ST(0)); - RETVAL = quest_manager.firsttaskinset(taskset); + unsigned int task_set = (int)SvIV(ST(0)); + RETVAL = quest_manager.firsttaskinset(task_set); } else { - Perl_croak(aTHX_ "Usage: firsttaskinset(taskset)"); + Perl_croak(aTHX_ "Usage: firsttaskinset(task_set)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2500,10 +2502,10 @@ XS(XS__lasttaskinset) dXSTARG; if(items == 1) { - unsigned int taskset = (int)SvIV(ST(0)); - RETVAL = quest_manager.lasttaskinset(taskset); + unsigned int task_set = (int)SvIV(ST(0)); + RETVAL = quest_manager.lasttaskinset(task_set); } else { - Perl_croak(aTHX_ "Usage: lasttaskinset(taskset)"); + Perl_croak(aTHX_ "Usage: lasttaskinset(task_set)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2519,11 +2521,11 @@ XS(XS__nexttaskinset) dXSTARG; if(items == 2) { - unsigned int taskset = (int)SvIV(ST(0)); - unsigned int taskid = (int)SvIV(ST(1)); - RETVAL = quest_manager.nexttaskinset(taskset, taskid); + unsigned int task_set = (int)SvIV(ST(0)); + unsigned int task_id = (int)SvIV(ST(1)); + RETVAL = quest_manager.nexttaskinset(task_set, task_id); } else { - Perl_croak(aTHX_ "Usage: nexttaskinset(taskset, taskid)"); + Perl_croak(aTHX_ "Usage: nexttaskinset(task_set, task_id)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2556,10 +2558,10 @@ XS(XS__activespeakactivity) dXSTARG; if(items == 1) { - unsigned int taskid = (int)SvIV(ST(0)); - RETVAL = quest_manager.activespeakactivity(taskid); + unsigned int task_id = (int)SvIV(ST(0)); + RETVAL = quest_manager.activespeakactivity(task_id); } else { - Perl_croak(aTHX_ "Usage: activespeakactivity(taskid)"); + Perl_croak(aTHX_ "Usage: activespeakactivity(task_id)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2575,10 +2577,10 @@ XS(XS__activetasksinset) dXSTARG; if(items == 1) { - unsigned int taskset = (int)SvIV(ST(0)); - RETVAL = quest_manager.activetasksinset(taskset); + unsigned int task_set = (int)SvIV(ST(0)); + RETVAL = quest_manager.activetasksinset(task_set); } else { - Perl_croak(aTHX_ "Usage: activetasksinset(taskset)"); + Perl_croak(aTHX_ "Usage: activetasksinset(task_set)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2594,10 +2596,10 @@ XS(XS__completedtasksinset) dXSTARG; if(items == 1) { - unsigned int taskset = (int)SvIV(ST(0)); - RETVAL = quest_manager.completedtasksinset(taskset); + unsigned int task_set = (int)SvIV(ST(0)); + RETVAL = quest_manager.completedtasksinset(task_set); } else { - Perl_croak(aTHX_ "Usage: completedtasksinset(taskset)"); + Perl_croak(aTHX_ "Usage: completedtasksinset(task_set)"); } XSprePUSH; PUSHi((IV)RETVAL); @@ -2628,15 +2630,15 @@ XS(XS__istaskappropriate) XS(XS__popup); // prototype to pass -Wmissing-prototypes XS(XS__popup) { dXSARGS; - int popupid = 0; + int popup_id = 0; int buttons = 0; int duration = 0; if((items < 2) || (items > 5)) - Perl_croak(aTHX_ "Usage: popup(windowtitle, text, popupid, buttons, duration)"); + Perl_croak(aTHX_ "Usage: popup(window_title, message, popup_id, buttons, duration)"); if(items >= 3) - popupid = (int)SvIV(ST(2)); + popup_id = (int)SvIV(ST(2)); if(items >= 4) buttons = (int)SvIV(ST(3)); @@ -2644,7 +2646,7 @@ XS(XS__istaskappropriate) if(items == 5) duration = (int)SvIV(ST(4)); - quest_manager.popup(SvPV_nolen(ST(0)), SvPV_nolen(ST(1)), popupid, buttons, duration); + quest_manager.popup(SvPV_nolen(ST(0)), SvPV_nolen(ST(1)), popup_id, buttons, duration); XSRETURN_EMPTY; } @@ -2666,12 +2668,12 @@ XS(XS__ze) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: ze(type, str)"); + Perl_croak(aTHX_ "Usage: ze(channel_id, message)"); - int type = (int)SvIV(ST(0)); - char * str = (char *)SvPV_nolen(ST(1)); + int channel_id = (int)SvIV(ST(0)); + char * message = (char *)SvPV_nolen(ST(1)); - quest_manager.ze(type, str); + quest_manager.ze(channel_id, message); XSRETURN_EMPTY; } @@ -2681,12 +2683,12 @@ XS(XS__we) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: we(type, str)"); + Perl_croak(aTHX_ "Usage: we(channel_id, message)"); - int type = (int)SvIV(ST(0)); - char * str = (char *)SvPV_nolen(ST(1)); + int channel_id = (int)SvIV(ST(0)); + char * message = (char *)SvPV_nolen(ST(1)); - quest_manager.we(type, str); + quest_manager.we(channel_id, message); XSRETURN_EMPTY; } @@ -2718,9 +2720,9 @@ XS(XS__CreateGroundObject) { dXSARGS; if (items != 5 && items != 6) - Perl_croak(aTHX_ "Usage: creategroundobject(itemid, x, y, z, heading, [decay_time])"); + Perl_croak(aTHX_ "Usage: creategroundobject(item_id, x, y, z, heading, [decay_time])"); - int itemid = (int)SvIV(ST(0)); + int item_id = (int)SvIV(ST(0)); float x = (float)SvNV(ST(1)); float y = (float)SvNV(ST(2)); float z = (float)SvNV(ST(3)); @@ -2728,10 +2730,10 @@ XS(XS__CreateGroundObject) uint16 id = 0; if(items == 5) - id = quest_manager.CreateGroundObject(itemid, glm::vec4(x, y, z, heading)); + id = quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading)); else{ uint32 decay_time = (uint32)SvIV(ST(5)); - id = quest_manager.CreateGroundObject(itemid, glm::vec4(x, y, z, heading), decay_time); + id = quest_manager.CreateGroundObject(item_id, glm::vec4(x, y, z, heading), decay_time); } XSRETURN_IV(id); @@ -2742,24 +2744,24 @@ XS(XS__CreateGroundObjectFromModel) { dXSARGS; if (items < 5 || items > 7) - Perl_croak(aTHX_ "Usage: creategroundobjectfrommodel(modelname, x, y, z, heading, [type], [decay_time])"); + Perl_croak(aTHX_ "Usage: creategroundobjectfrommodel(modelname, x, y, z, heading, [object_type], [decay_time])"); char * modelname = (char *)SvPV_nolen(ST(0)); float x = (float)SvNV(ST(1)); float y = (float)SvNV(ST(2)); float z = (float)SvNV(ST(3)); float heading = (float)SvNV(ST(4)); - uint32 type = 0; + uint32 object_type = 0; uint32 decay_time = 0; uint16 id = 0; if (items > 5) - type = (uint32)SvIV(ST(5)); + object_type = (uint32)SvIV(ST(5)); if (items > 6) decay_time = (uint32)SvIV(ST(6)); - id = quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), type, decay_time); + id = quest_manager.CreateGroundObjectFromModel(modelname, glm::vec4(x, y, z, heading), object_type, decay_time); XSRETURN_IV(id); } @@ -2768,24 +2770,24 @@ XS(XS__CreateDoor) { dXSARGS; if (items < 5 || items > 7) - Perl_croak(aTHX_ "Usage: createdoor(modelname, x, y, z, heading, [type], [size])"); + Perl_croak(aTHX_ "Usage: createdoor(modelname, x, y, z, heading, [object_type], [size])"); char * modelname = (char *)SvPV_nolen(ST(0)); float x = (float)SvNV(ST(1)); float y = (float)SvNV(ST(2)); float z = (float)SvNV(ST(3)); float heading = (float)SvNV(ST(4)); - uint32 type = 58; + uint32 object_type = 58; uint32 size = 100; uint16 id = 0; if (items > 5) - type = (uint32)SvIV(ST(5)); + object_type = (uint32)SvIV(ST(5)); if (items > 6) size = (uint32)SvIV(ST(6)); - id = quest_manager.CreateDoor(modelname, x, y, z, heading, type, size); + id = quest_manager.CreateDoor(modelname, x, y, z, heading, object_type, size); XSRETURN_IV(id); } @@ -2794,7 +2796,7 @@ XS(XS__ModifyNPCStat) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: ModifyNPCStat(identifier, newValue)"); + Perl_croak(aTHX_ "Usage: ModifyNPCStat(stat_id, str_value)"); quest_manager.ModifyNPCStat(SvPV_nolen(ST(0)), SvPV_nolen(ST(1))); @@ -2806,13 +2808,13 @@ XS(XS__collectitems) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: collectitems(item_id, remove?)"); + Perl_croak(aTHX_ "Usage: collectitems(item_id, remove_item)"); uint32 item_id = (int)SvIV(ST(0)); - bool remove = ((int)SvIV(ST(1))) == 0?false:true; + bool remove_item = ((int)SvIV(ST(1))) == 0?false:true; int quantity = - quest_manager.collectitems(item_id, remove); + quest_manager.collectitems(item_id, remove_item); XSRETURN_IV(quantity); } @@ -2822,12 +2824,12 @@ XS(XS__UpdateSpawnTimer) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: UpdateSpawnTimer(Spawn2_ID, Updated_Time_Till_Repop)"); + Perl_croak(aTHX_ "Usage: UpdateSpawnTimer(spawn2_id, updated_time_till_repop)"); - uint32 id = (int)SvIV(ST(0)); - uint32 duration = (int)SvIV(ST(1)); + uint32 spawn2_id = (int)SvIV(ST(0)); + uint32 updated_time_till_repop = (int)SvIV(ST(1)); - quest_manager.UpdateSpawnTimer(id, duration); + quest_manager.UpdateSpawnTimer(spawn2_id, updated_time_till_repop); XSRETURN_EMPTY; } @@ -2836,15 +2838,15 @@ XS(XS__MerchantSetItem); XS(XS__MerchantSetItem) { dXSARGS; if (items != 2 && items != 3) - Perl_croak(aTHX_ "Usage: MerchantSetItem(NPCid, itemid [, quantity])"); + Perl_croak(aTHX_ "Usage: MerchantSetItem(npc_id, item_id [, quantity])"); - uint32 NPCid = (int)SvUV(ST(0)); - uint32 itemid = (int)SvUV(ST(1)); + uint32 npc_id = (int)SvUV(ST(0)); + uint32 item_id = (int)SvUV(ST(1)); uint32 quantity = 0; if (items == 3) quantity = (int)SvUV(ST(2)); - quest_manager.MerchantSetItem(NPCid, itemid, quantity); + quest_manager.MerchantSetItem(npc_id, item_id, quantity); XSRETURN_EMPTY; } @@ -2853,11 +2855,11 @@ XS(XS__MerchantCountItem); XS(XS__MerchantCountItem) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: MerchantCountItem(NPCid, itemid)"); + Perl_croak(aTHX_ "Usage: MerchantCountItem(npc_id, item_id)"); - uint32 NPCid = (int)SvUV(ST(0)); - uint32 itemid = (int)SvUV(ST(1)); - uint32 quantity = quest_manager.MerchantCountItem(NPCid, itemid); + uint32 npc_id = (int)SvUV(ST(0)); + uint32 item_id = (int)SvUV(ST(1)); + uint32 quantity = quest_manager.MerchantCountItem(npc_id, item_id); XSRETURN_UV(quantity); } @@ -2866,15 +2868,15 @@ XS(XS__varlink); XS(XS__varlink) { dXSARGS; if (items != 1) - Perl_croak(aTHX_ "Usage: varlink(itemID)"); + Perl_croak(aTHX_ "Usage: varlink(item_id)"); dXSTARG; Const_char * RETVAL; char text[250]; - uint32 itemID; - itemID = (int)SvUV(ST(0)); + uint32 item_id; + item_id = (int)SvUV(ST(0)); - RETVAL = quest_manager.varlink(text, itemID); + RETVAL = quest_manager.varlink(text, item_id); sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; XSRETURN(1); @@ -2910,11 +2912,11 @@ XS(XS__UpdateInstanceTimer); XS(XS__UpdateInstanceTimer) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: UpdateInstanceTimer(instance_id, new_duration)"); + Perl_croak(aTHX_ "Usage: UpdateInstanceTimer(instance_id, duration)"); uint16 instance_id = (uint16)SvUV(ST(0)); - uint32 new_duration = (uint32)SvUV(ST(1)); - quest_manager.UpdateInstanceTimer(instance_id, new_duration); + uint32 duration = (uint32)SvUV(ST(1)); + quest_manager.UpdateInstanceTimer(instance_id, duration); XSRETURN_EMPTY; } @@ -2964,29 +2966,29 @@ XS(XS__GetCharactersInInstance) { Const_char * RETVAL; uint16 instance_id = (int)SvUV(ST(0)); - std::list charid_list; - std::string charid_string; + std::list char_id_list; + std::string char_id_string; - database.GetCharactersInInstance(instance_id, charid_list); + database.GetCharactersInInstance(instance_id, char_id_list); - if (charid_list.size() > 0) + if (char_id_list.size() > 0) { - charid_string = itoa(charid_list.size()); - charid_string += " player(s) in instance: "; - auto iter = charid_list.begin(); - while (iter != charid_list.end()) + char_id_string = itoa(char_id_list.size()); + char_id_string += " player(s) in instance: "; + auto iter = char_id_list.begin(); + while (iter != char_id_list.end()) { char char_name[64]; database.GetCharName(*iter, char_name); - charid_string += char_name; - charid_string += "("; - charid_string += itoa(*iter); - charid_string += ")"; + char_id_string += char_name; + char_id_string += "("; + char_id_string += itoa(*iter); + char_id_string += ")"; ++iter; - if (iter != charid_list.end()) - charid_string += ", "; + if (iter != char_id_list.end()) + char_id_string += ", "; } - RETVAL = charid_string.c_str(); + RETVAL = char_id_string.c_str(); } else RETVAL = "No players in that instance."; @@ -3062,7 +3064,7 @@ XS(XS__MovePCInstance) if (items != 5 && items != 6) Perl_croak(aTHX_ "Usage: MovePCInstance(zone_id, instance_id, x, y, z [,heading])"); - int zoneid = (int)SvIV(ST(0)); + int zone_id = (int)SvIV(ST(0)); int instanceid = (int)SvIV(ST(1)); float x = (float)SvNV(ST(2)); float y = (float)SvNV(ST(3)); @@ -3070,12 +3072,12 @@ XS(XS__MovePCInstance) if (items == 4) { - quest_manager.MovePCInstance(zoneid, instanceid, glm::vec4(x, y, z, 0.0f)); + quest_manager.MovePCInstance(zone_id, instanceid, glm::vec4(x, y, z, 0.0f)); } else { float heading = (float)SvNV(ST(5)); - quest_manager.MovePCInstance(zoneid, instanceid, glm::vec4(x, y, z, heading)); + quest_manager.MovePCInstance(zone_id, instanceid, glm::vec4(x, y, z, heading)); } XSRETURN_EMPTY; @@ -3111,23 +3113,23 @@ XS(XS__saylink); XS(XS__saylink) { dXSARGS; if (items < 1 || items > 3) - Perl_croak(aTHX_ "Usage: saylink(phrase,[silent?],[linkname])"); + Perl_croak(aTHX_ "Usage: saylink(message, [silent?], [link_name])"); dXSTARG; Const_char * RETVAL; - char text[250]; - char text2[250]; + char message[250]; + char link_name[250]; bool silent = false; - strcpy(text,(char *)SvPV_nolen(ST(0))); + strcpy(message,(char *)SvPV_nolen(ST(0))); if(items >= 2) { silent = ((int)SvIV(ST(1))) == 0 ? false : true; } if (items == 3) - strcpy(text2,(char *)SvPV_nolen(ST(2))); + strcpy(link_name,(char *)SvPV_nolen(ST(2))); else - strcpy(text2,text); + strcpy(link_name,message); - RETVAL = quest_manager.saylink(text, silent, text2); + RETVAL = quest_manager.saylink(message, silent, link_name); sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; XSRETURN(1); } @@ -3318,21 +3320,21 @@ XS(XS__wearchange) { dXSARGS; if (items < 2) - Perl_croak(aTHX_ "Usage: wearchange(slot, texture, [hero_forge_model], [elite_material])"); + Perl_croak(aTHX_ "Usage: wearchange(slot, texture_id, [hero_forge_model_id], [elite_material_id])"); uint8 slot = (int)SvUV(ST(0)); - uint16 texture = (int)SvUV(ST(1)); + uint16 texture_id = (int)SvUV(ST(1)); - uint32 hero_forge_model = 0; - uint32 elite_material = 0; + uint32 hero_forge_model_id= 0; + uint32 elite_material_id = 0; if (items > 2) - hero_forge_model = (int)SvUV(ST(2)); + hero_forge_model_id= (int)SvUV(ST(2)); if (items > 3) - elite_material = (int)SvUV(ST(3)); + elite_material_id = (int)SvUV(ST(3)); - quest_manager.wearchange(slot, texture, hero_forge_model, elite_material); + quest_manager.wearchange(slot, texture_id, hero_forge_model_id, elite_material_id); XSRETURN_EMPTY; } @@ -3342,14 +3344,14 @@ XS(XS__voicetell) { dXSARGS; if (items != 4) - Perl_croak(aTHX_ "Usage: voicetell(clientname, type, race, gender)"); + Perl_croak(aTHX_ "Usage: voicetell(client_name, macro_id, race_id, gender_id)"); - char * str = (char *)SvPV_nolen(ST(0)); - int macronum = (int)SvIV(ST(1)); - int racenum = (int)SvIV(ST(2)); - int gendernum = (int)SvIV(ST(3)); + char * client_name = (char *)SvPV_nolen(ST(0)); + int macro_id = (int)SvIV(ST(1)); + int race_id = (int)SvIV(ST(2)); + int gender_id = (int)SvIV(ST(3)); - quest_manager.voicetell(str, macronum, racenum, gendernum); + quest_manager.voicetell(client_name, macro_id, race_id, gender_id); XSRETURN_EMPTY; } @@ -3426,20 +3428,20 @@ XS(XS__GetTimeSeconds) XSRETURN_UV(seconds); } -XS(XS__crosszonesignalclientbycharid); -XS(XS__crosszonesignalclientbycharid) +XS(XS__crosszonesignalclientbychar_id); +XS(XS__crosszonesignalclientbychar_id) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: crosszonesignalclientbycharid(char_id, data)"); + Perl_croak(aTHX_ "Usage: crosszonesignalclientbychar_id(char_id, int_value)"); if (items == 2) { int char_id = (int)SvIV(ST(0)); - uint32 data = (uint32)SvIV(ST(1)); - quest_manager.CrossZoneSignalPlayerByCharID(char_id, data); + uint32 int_value = (uint32)SvIV(ST(1)); + quest_manager.CrossZoneSignalPlayerByCharID(char_id, int_value); } else { - Perl_croak(aTHX_ "Usage: crosszonesignalclientbycharid(char_id, data)"); + Perl_croak(aTHX_ "Usage: crosszonesignalclientbychar_id(char_id, int_value)"); } XSRETURN_EMPTY; @@ -3451,14 +3453,14 @@ XS(XS__crosszonesignalclientbyname) dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: crosszonesignalclientbycharid(Name, data)"); + Perl_croak(aTHX_ "Usage: crosszonesignalclientbychar_id(name, int_value)"); if (items == 2) { - char *Name = (char *)SvPV_nolen(ST(0)); - uint32 data = (uint32)SvIV(ST(1)); - quest_manager.CrossZoneSignalPlayerByName(Name, data); + char *name = (char *)SvPV_nolen(ST(0)); + uint32 int_value = (uint32)SvIV(ST(1)); + quest_manager.CrossZoneSignalPlayerByName(name, int_value); } else { - Perl_croak(aTHX_ "Usage: crosszonesignalclientbycharid(Name, data)"); + Perl_croak(aTHX_ "Usage: crosszonesignalclientbychar_id(name, int_value)"); } XSRETURN_EMPTY; @@ -3471,15 +3473,15 @@ XS(XS__crosszonemessageplayerbyname) dXSARGS; if (items != 3) - Perl_croak(aTHX_ "Usage: crosszonemessageplayerbyname(Type, Name, Message)"); + Perl_croak(aTHX_ "Usage: crosszonemessageplayerbyname(channel_id, name, message)"); if (items == 3) { - uint32 Type = (uint32)SvIV(ST(0)); - char *Name = (char *)SvPV_nolen(ST(1)); - char *Message = (char *)SvPV_nolen(ST(2)); - quest_manager.CrossZoneMessagePlayerByName(Type, Name, Message); + uint32 channel_id = (uint32)SvIV(ST(0)); + char *name = (char *)SvPV_nolen(ST(1)); + char *message = (char *)SvPV_nolen(ST(2)); + quest_manager.CrossZoneMessagePlayerByName(channel_id, name, message); } else { - Perl_croak(aTHX_ "Usage: crosszonemessageplayerbyname(Type, Name, Message)"); + Perl_croak(aTHX_ "Usage: crosszonemessageplayerbyname(channel_id, name, message)"); } XSRETURN_EMPTY; @@ -3531,11 +3533,11 @@ XS(XS__clear_npctype_cache) dXSARGS; if (items != 1) { - Perl_croak(aTHX_ "Usage: clear_npctype_cache(npc_id)"); + Perl_croak(aTHX_ "Usage: clear_npctype_cache(npc_type_id)"); } else { - int32 npctype_id = (int32)SvIV(ST(0)); - quest_manager.ClearNPCTypeCache(npctype_id); + int32 npc_type_id = (int32)SvIV(ST(0)); + quest_manager.ClearNPCTypeCache(npc_type_id); } XSRETURN_EMPTY; @@ -3571,12 +3573,12 @@ XS(XS__qs_player_event) { dXSARGS; if (items != 2){ - Perl_croak(aTHX_ "Usage: qs_player_event(char_id, event_desc)"); + Perl_croak(aTHX_ "Usage: qs_player_event(char_id, message)"); } else{ int char_id = (int)SvIV(ST(0)); - std::string event_desc = (std::string)SvPV_nolen(ST(1)); - QServ->PlayerLogEvent(Player_Log_Quest, char_id, event_desc); + std::string message = (std::string)SvPV_nolen(ST(1)); + QServ->PlayerLogEvent(Player_Log_Quest, char_id, message); } XSRETURN_EMPTY; } @@ -3587,31 +3589,31 @@ XS(XS__crosszonesetentityvariablebynpctypeid) dXSARGS; if (items != 3) - Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebynpctypeid(npctype_id, id, m_var)"); + Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebynpctypeid(npc_type_id, key, str_value)"); if (items == 3) { - uint32 npctype_id = (uint32)SvIV(ST(0)); - const char *id = (const char *)SvPV_nolen(ST(1)); - const char *m_var = (const char *)SvPV_nolen(ST(2)); - quest_manager.CrossZoneSetEntityVariableByNPCTypeID(npctype_id, id, m_var); + uint32 npc_type_id = (uint32)SvIV(ST(0)); + const char *key = (const char *)SvPV_nolen(ST(1)); + const char *str_value = (const char *)SvPV_nolen(ST(2)); + quest_manager.CrossZoneSetEntityVariableByNPCTypeID(npc_type_id, key, str_value); } XSRETURN_EMPTY; } -XS(XS__crosszonesetentityvariablebyclientname); -XS(XS__crosszonesetentityvariablebyclientname) +XS(XS__crosszonesetentityvariablebyclient_name); +XS(XS__crosszonesetentityvariablebyclient_name) { dXSARGS; if (items != 3) - Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebyclientname(clientname, id, m_var)"); + Perl_croak(aTHX_ "Usage: crosszonesetentityvariablebyclient_name(client_name, key, str_value)"); 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); + const char *client_name = (const char *)SvPV_nolen(ST(0)); + const char *key = (const char *)SvPV_nolen(ST(1)); + const char *str_value = (const char *)SvPV_nolen(ST(2)); + quest_manager.CrossZoneSetEntityVariableByClientName(client_name, key, str_value); } XSRETURN_EMPTY; @@ -3623,12 +3625,12 @@ XS(XS__crosszonesignalnpcbynpctypeid) dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: crosszonesignalnpcbynpctypeid(npctype_id, data)"); + Perl_croak(aTHX_ "Usage: crosszonesignalnpcbynpctypeid(npc_type_id, int_value)"); if (items == 2) { - uint32 npctype_id = (uint32)SvIV(ST(0)); - uint32 data = (uint32)SvIV(ST(1)); - quest_manager.CrossZoneSignalNPCByNPCTypeID(npctype_id, data); + uint32 npc_type_id = (uint32)SvIV(ST(0)); + uint32 int_value = (uint32)SvIV(ST(1)); + quest_manager.CrossZoneSignalNPCByNPCTypeID(npc_type_id, int_value); } XSRETURN_EMPTY; @@ -3639,16 +3641,16 @@ XS(XS__worldwidemarquee) { dXSARGS; if (items != 6) - Perl_croak(aTHX_ "Usage: worldwidemarquee(type, priority, fadein, fadeout, duration, message)"); + Perl_croak(aTHX_ "Usage: worldwidemarquee(color_id, priority, fade_in, fade_out, duration, message)"); if (items == 6) { - uint32 type = (uint32)SvIV(ST(0)); + uint32 color_id = (uint32)SvIV(ST(0)); uint32 priority = (uint32)SvIV(ST(1)); - uint32 fadein = (uint32)SvIV(ST(2)); - uint32 fadeout = (uint32)SvIV(ST(3)); + uint32 fade_in = (uint32)SvIV(ST(2)); + uint32 fade_out = (uint32)SvIV(ST(3)); uint32 duration = (uint32)SvIV(ST(4)); char* message = (char *)SvPV_nolen(ST(5)); - quest_manager.WorldWideMarquee(type, priority, fadein, fadeout, duration, message); + quest_manager.WorldWideMarquee(color_id, priority, fade_in, fade_out, duration, message); } XSRETURN_EMPTY; @@ -3688,11 +3690,11 @@ XS(XS__UpdateZoneHeader); XS(XS__UpdateZoneHeader) { dXSARGS; if (items != 2) - Perl_croak(aTHX_ "Usage: UpdateZoneHeader(type, value)"); + Perl_croak(aTHX_ "Usage: UpdateZoneHeader(key, str_value)"); - std::string type = (std::string)SvPV_nolen(ST(0)); - std::string value = (std::string)SvPV_nolen(ST(1)); - quest_manager.UpdateZoneHeader(type, value); + std::string key = (std::string)SvPV_nolen(ST(0)); + std::string str_value = (std::string)SvPV_nolen(ST(1)); + quest_manager.UpdateZoneHeader(key, str_value); XSRETURN_EMPTY; } @@ -3784,8 +3786,8 @@ 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, "crosszonesetentityvariablebyclient_name"), XS__crosszonesetentityvariablebyclient_name, file); + newXS(strcpy(buf, "crosszonesignalclientbychar_id"), XS__crosszonesignalclientbychar_id, file); newXS(strcpy(buf, "crosszonesignalclientbyname"), XS__crosszonesignalclientbyname, file); newXS(strcpy(buf, "crosszonesignalnpcbynpctypeid"), XS__crosszonesignalnpcbynpctypeid, file); newXS(strcpy(buf, "worldwidemarquee"), XS__worldwidemarquee, file); @@ -3917,7 +3919,7 @@ EXTERN_C XS(boot_quest) newXS(strcpy(buf, "targlobal"), XS__targlobal, file); newXS(strcpy(buf, "taskexploredarea"), XS__taskexploredarea, file); newXS(strcpy(buf, "taskselector"), XS__taskselector, file); - newXS(strcpy(buf, "tasksetselector"), XS__tasksetselector, file); + newXS(strcpy(buf, "task_setselector"), XS__task_setselector, file); newXS(strcpy(buf, "tasktimeleft"), XS__tasktimeleft, file); newXS(strcpy(buf, "toggle_spawn_event"), XS__toggle_spawn_event, file); newXS(strcpy(buf, "toggledoorstate"), XS__toggledoorstate, file); diff --git a/zone/entity.cpp b/zone/entity.cpp index 0ab10982a..4b0599541 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -3257,7 +3257,7 @@ void EntityList::AddHealAggro(Mob *target, Mob *caster, uint16 hate) for (auto &e : npc_list) { auto &npc = e.second; - if (!npc->CheckAggro(target) || npc->IsFeared()) + if (!npc->CheckAggro(target) || npc->IsFeared() || npc->IsPet()) continue; if (zone->random.Roll(50)) // witness check -- place holder diff --git a/zone/exp.cpp b/zone/exp.cpp index 1fd8ea0a3..be9d01c13 100644 --- a/zone/exp.cpp +++ b/zone/exp.cpp @@ -37,6 +37,49 @@ extern QueryServ* QServ; +static uint32 ScaleAAXPBasedOnCurrentAATotal(int earnedAA, uint32 add_aaxp) +{ + float baseModifier = RuleR(AA, ModernAAScalingStartPercent); + int aaMinimum = RuleI(AA, ModernAAScalingAAMinimum); + int aaLimit = RuleI(AA, ModernAAScalingAALimit); + + // Are we within the scaling window? + if (earnedAA >= aaLimit || earnedAA < aaMinimum) + { + Log(Logs::Detail, Logs::None, "Not within AA scaling window."); + + // At or past the limit. We're done. + return add_aaxp; + } + + // We're not at the limit yet. How close are we? + int remainingAA = aaLimit - earnedAA; + + // We might not always be X - 0 + int scaleRange = aaLimit - aaMinimum; + + // Normalize and get the effectiveness based on the range and the character's + // current spent AA. + float normalizedScale = (float)remainingAA / scaleRange; + + // Scale. + uint32 totalWithExpMod = add_aaxp * (baseModifier / 100) * normalizedScale; + + // Are we so close to the scale limit that we're earning more XP without scaling? This + // will happen when we get very close to the limit. In this case, just grant the unscaled + // amount. + if (totalWithExpMod < add_aaxp) + { + return add_aaxp; + } + + Log(Logs::Detail, + Logs::None, + "Total before the modifier %d :: NewTotal %d :: ScaleRange: %d, SpentAA: %d, RemainingAA: %d, normalizedScale: %0.3f", + add_aaxp, totalWithExpMod, scaleRange, earnedAA, remainingAA, normalizedScale); + + return totalWithExpMod; +} static uint32 MaxBankedGroupLeadershipPoints(int Level) { @@ -174,192 +217,302 @@ uint32 Client::GetExperienceForKill(Mob *against) return 0; } -void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { +float static GetConLevelModifierPercent(uint8 conlevel) +{ + switch (conlevel) + { + case CON_GREEN: + return (float)RuleI(Character, GreenModifier) / 100; + break; + case CON_LIGHTBLUE: + return (float)RuleI(Character, LightBlueModifier) / 100; + break; + case CON_BLUE: + return (float)RuleI(Character, BlueModifier) / 100; + break; + case CON_WHITE: + return (float)RuleI(Character, WhiteModifier) / 100; + break; + case CON_YELLOW: + return (float)RuleI(Character, YellowModifier) / 100; + break; + case CON_RED: + return (float)RuleI(Character, RedModifier) / 100; + break; + default: + return 0; + } +} - this->EVENT_ITEM_ScriptStopReturn(); - - uint32 add_exp = in_add_exp; - - if(!resexp && (XPRate != 0)) - add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); - - if (m_epp.perAA<0 || m_epp.perAA>100) - m_epp.perAA=0; // stop exploit with sanity check - - uint32 add_aaxp; - if(resexp) { +void Client::CalculateNormalizedAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp) +{ + // Functionally this is the same as having the case in the switch, but this is + // cleaner to read. + if (CON_GRAY == conlevel || resexp) + { add_aaxp = 0; - } else { + return; + } + // For this, we ignore the provided value of add_aaxp because it doesn't + // apply. XP per AA is normalized such that there are X white con kills + // per AA. + + uint32 whiteConKillsPerAA = RuleI(AA, NormalizedAANumberOfWhiteConPerAA); + uint32 xpPerAA = RuleI(AA, ExpPerPoint); + + float colorModifier = GetConLevelModifierPercent(conlevel); + float percentToAAXp = (float)m_epp.perAA / 100; + + // Normalize the amount of AA XP we earned for this kill. + add_aaxp = percentToAAXp * (xpPerAA / (whiteConKillsPerAA / colorModifier)); +} + +void Client::CalculateStandardAAExp(uint32 &add_aaxp, uint8 conlevel, bool resexp) +{ + if (!resexp) + { + //if XP scaling is based on the con of a monster, do that now. + if (RuleB(Character, UseXPConScaling)) + { + if (conlevel != 0xFF && !resexp) + { + add_aaxp *= GetConLevelModifierPercent(conlevel); + } + } + } //end !resexp + + float aatotalmod = 1.0; + if (zone->newzone_data.zone_exp_multiplier >= 0) { + aatotalmod *= zone->newzone_data.zone_exp_multiplier; + } + + // Shouldn't race not affect AA XP? + if (RuleB(Character, UseRaceClassExpBonuses)) + { + if (GetBaseRace() == HALFLING) { + aatotalmod *= 1.05; + } + + if (GetClass() == ROGUE || GetClass() == WARRIOR) { + aatotalmod *= 1.05; + } + } + + // why wasn't this here? Where should it be? + if (zone->IsHotzone()) + { + aatotalmod += RuleR(Zone, HotZoneBonus); + } + + if (RuleB(Zone, LevelBasedEXPMods)) { + if (zone->level_exp_mod[GetLevel()].ExpMod) { + add_aaxp *= zone->level_exp_mod[GetLevel()].AAExpMod; + } + } + + add_aaxp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); +} + +void Client::CalculateLeadershipExp(uint32 &add_exp, uint8 conlevel) +{ + if (IsLeadershipEXPOn() && (conlevel == CON_BLUE || conlevel == CON_WHITE || conlevel == CON_YELLOW || conlevel == CON_RED)) + { + add_exp = static_cast(static_cast(add_exp) * 0.8f); + + if (GetGroup()) + { + if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()) + && RuleI(Character, KillsPerGroupLeadershipAA) > 0) + { + uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); + Client *mentoree = GetGroup()->GetMentoree(); + if (GetGroup()->GetMentorPercent() && mentoree && + mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) + { + uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f); + exp -= mentor_exp; + mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down + mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); + } + if (exp > 0) + { + // possible if you mentor 100% to the other client + AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it + Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); + } + } + else + { + Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); + } + } + else + { + Raid *raid = GetRaid(); + // Raid leaders CAN NOT gain group AA XP, other group leaders can though! + if (raid->IsLeader(this)) + { + if (m_pp.raid_leadership_points < MaxBankedRaidLeadershipPoints(GetLevel()) + && RuleI(Character, KillsPerRaidLeadershipAA) > 0) + { + AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA)); + Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP); + } + else + { + Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS); + } + } + else + { + if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()) + && RuleI(Character, KillsPerGroupLeadershipAA) > 0) + { + uint32 group_id = raid->GetGroup(this); + uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); + Client *mentoree = raid->GetMentoree(group_id); + if (raid->GetMentorPercent(group_id) && mentoree && + mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) + { + uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f); + exp -= mentor_exp; + mentoree->AddLeadershipEXP(mentor_exp, 0); + mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); + } + if (exp > 0) + { + AddLeadershipEXP(exp, 0); + Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); + } + } + else + { + Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); + } + } + } + } +} + +void Client::CalculateExp(uint32 in_add_exp, uint32 &add_exp, uint32 &add_aaxp, uint8 conlevel, bool resexp) +{ + add_exp = in_add_exp; + + if (!resexp && (XPRate != 0)) + { + add_exp = static_cast(in_add_exp * (static_cast(XPRate) / 100.0f)); + } + + // Make sure it was initialized. + add_aaxp = 0; + + if (!resexp) + { //figure out how much of this goes to AAs add_aaxp = add_exp * m_epp.perAA / 100; + //take that amount away from regular exp add_exp -= add_aaxp; float totalmod = 1.0; float zemmod = 1.0; + //get modifiers - if(RuleR(Character, ExpMultiplier) >= 0){ + if (RuleR(Character, ExpMultiplier) >= 0) { totalmod *= RuleR(Character, ExpMultiplier); } - if(zone->newzone_data.zone_exp_multiplier >= 0){ + //add the zone exp modifier. + if (zone->newzone_data.zone_exp_multiplier >= 0) { zemmod *= zone->newzone_data.zone_exp_multiplier; } - if(RuleB(Character,UseRaceClassExpBonuses)) + if (RuleB(Character, UseRaceClassExpBonuses)) { - if(GetBaseRace() == HALFLING){ + if (GetBaseRace() == HALFLING) { totalmod *= 1.05; } - if(GetClass() == ROGUE || GetClass() == WARRIOR){ + if (GetClass() == ROGUE || GetClass() == WARRIOR) { totalmod *= 1.05; } } - if(zone->IsHotzone()) + //add hotzone modifier if one has been set. + if (zone->IsHotzone()) { totalmod += RuleR(Zone, HotZoneBonus); } add_exp = uint32(float(add_exp) * totalmod * zemmod); - if(RuleB(Character,UseXPConScaling)) + //if XP scaling is based on the con of a monster, do that now. + if (RuleB(Character, UseXPConScaling)) { - if (conlevel != 0xFF && !resexp) { - switch (conlevel) - { - case CON_GRAY: - add_exp = 0; - add_aaxp = 0; - return; - case CON_GREEN: - add_exp = add_exp * RuleI(Character, GreenModifier) / 100; - add_aaxp = add_aaxp * RuleI(Character, GreenModifier) / 100; - break; - case CON_LIGHTBLUE: - add_exp = add_exp * RuleI(Character, LightBlueModifier)/100; - add_aaxp = add_aaxp * RuleI(Character, LightBlueModifier)/100; - break; - case CON_BLUE: - add_exp = add_exp * RuleI(Character, BlueModifier)/100; - add_aaxp = add_aaxp * RuleI(Character, BlueModifier)/100; - break; - case CON_WHITE: - add_exp = add_exp * RuleI(Character, WhiteModifier)/100; - add_aaxp = add_aaxp * RuleI(Character, WhiteModifier)/100; - break; - case CON_YELLOW: - add_exp = add_exp * RuleI(Character, YellowModifier)/100; - add_aaxp = add_aaxp * RuleI(Character, YellowModifier)/100; - break; - case CON_RED: - add_exp = add_exp * RuleI(Character, RedModifier)/100; - add_aaxp = add_aaxp * RuleI(Character, RedModifier)/100; - break; - } + if (conlevel != 0xFF && !resexp) + { + add_exp = add_exp * GetConLevelModifierPercent(conlevel); } } - if (IsLeadershipEXPOn() && (conlevel == CON_BLUE || conlevel == CON_WHITE || conlevel == CON_YELLOW || conlevel == CON_RED)) { - add_exp = static_cast(static_cast(add_exp) * 0.8f); - - if (GetGroup()) { - if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()) - && RuleI(Character, KillsPerGroupLeadershipAA) > 0) { - uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); - Client *mentoree = GetGroup()->GetMentoree(); - if (GetGroup()->GetMentorPercent() && mentoree && - mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) { - uint32 mentor_exp = exp * (GetGroup()->GetMentorPercent() / 100.0f); - exp -= mentor_exp; - mentoree->AddLeadershipEXP(mentor_exp, 0); // ends up rounded down - mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); - } - if (exp > 0) { // possible if you mentor 100% to the other client - AddLeadershipEXP(exp, 0); // ends up rounded up if mentored, no idea how live actually does it - Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); - } - } else { - Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); - } - } else { - Raid *raid = GetRaid(); - // Raid leaders CAN NOT gain group AA XP, other group leaders can though! - if (raid->IsLeader(this)) { - if (m_pp.raid_leadership_points < MaxBankedRaidLeadershipPoints(GetLevel()) - && RuleI(Character, KillsPerRaidLeadershipAA) > 0) { - AddLeadershipEXP(0, RAID_EXP_PER_POINT / RuleI(Character, KillsPerRaidLeadershipAA)); - Message_StringID(MT_Leadership, GAIN_RAID_LEADERSHIP_EXP); - } else { - Message_StringID(MT_Leadership, MAX_RAID_LEADERSHIP_POINTS); - } - } else { - if (m_pp.group_leadership_points < MaxBankedGroupLeadershipPoints(GetLevel()) - && RuleI(Character, KillsPerGroupLeadershipAA) > 0) { - uint32 group_id = raid->GetGroup(this); - uint32 exp = GROUP_EXP_PER_POINT / RuleI(Character, KillsPerGroupLeadershipAA); - Client *mentoree = raid->GetMentoree(group_id); - if (raid->GetMentorPercent(group_id) && mentoree && - mentoree->GetGroupPoints() < MaxBankedGroupLeadershipPoints(mentoree->GetLevel())) { - uint32 mentor_exp = exp * (raid->GetMentorPercent(group_id) / 100.0f); - exp -= mentor_exp; - mentoree->AddLeadershipEXP(mentor_exp, 0); - mentoree->Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); - } - if (exp > 0) { - AddLeadershipEXP(exp, 0); - Message_StringID(MT_Leadership, GAIN_GROUP_LEADERSHIP_EXP); - } - } else { - Message_StringID(MT_Leadership, MAX_GROUP_LEADERSHIP_POINTS); - } - } - } - - } - + // Calculate any changes to leadership experience. + CalculateLeadershipExp(add_exp, conlevel); } //end !resexp - float aatotalmod = 1.0; - if(zone->newzone_data.zone_exp_multiplier >= 0){ - aatotalmod *= zone->newzone_data.zone_exp_multiplier; - } - - // Shouldn't race not affect AA XP? - if(RuleB(Character,UseRaceClassExpBonuses)) - { - if(GetBaseRace() == HALFLING){ - aatotalmod *= 1.05; - } - - if(GetClass() == ROGUE || GetClass() == WARRIOR){ - aatotalmod *= 1.05; - } - } - - // why wasn't this here? Where should it be? - if(zone->IsHotzone()) - { - aatotalmod += RuleR(Zone, HotZoneBonus); - } - - if(RuleB(Zone, LevelBasedEXPMods)){ - if(zone->level_exp_mod[GetLevel()].ExpMod){ + if (RuleB(Zone, LevelBasedEXPMods)) { + if (zone->level_exp_mod[GetLevel()].ExpMod) { add_exp *= zone->level_exp_mod[GetLevel()].ExpMod; - add_aaxp *= zone->level_exp_mod[GetLevel()].AAExpMod; } } - uint32 exp = GetEXP() + add_exp; + add_exp = GetEXP() + add_exp; +} - uint32 aaexp = (uint32)(RuleR(Character, AAExpMultiplier) * add_aaxp * aatotalmod); +void Client::AddEXP(uint32 in_add_exp, uint8 conlevel, bool resexp) { + + this->EVENT_ITEM_ScriptStopReturn(); + + uint32 exp = 0; + uint32 aaexp = 0; + + if (m_epp.perAA<0 || m_epp.perAA>100) + m_epp.perAA=0; // stop exploit with sanity check + + // Calculate regular XP + CalculateExp(in_add_exp, exp, aaexp, conlevel, resexp); + + // Calculate regular AA XP + if (!RuleB(AA, NormalizedAAEnabled)) + { + CalculateStandardAAExp(aaexp, conlevel, resexp); + } + else + { + CalculateNormalizedAAExp(aaexp, conlevel, resexp); + } + + // Are we also doing linear AA acceleration? + if (RuleB(AA, ModernAAScalingEnabled) && aaexp > 0) + { + aaexp = ScaleAAXPBasedOnCurrentAATotal(GetAAPoints(), aaexp); + } + + // Get current AA XP total uint32 had_aaexp = GetAAXP(); - aaexp += had_aaexp; - if(aaexp < had_aaexp) - aaexp = had_aaexp; //watch for wrap + // Add it to the XP we just earned. + aaexp += had_aaexp; + + // Make sure our new total (existing + just earned) isn't lower than the + // existing total. If it is, we overflowed the bounds of uint32 and wrapped. + // Reset to the existing total. + if (aaexp < had_aaexp) + { + aaexp = had_aaexp; //watch for wrap + } + + // Now update our character's normal and AA xp SetEXP(exp, aaexp, resexp); } diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 08d16e412..d9fa86257 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -336,7 +336,8 @@ void NPC::AddLootDrop(const EQEmu::ItemData *item2, ItemList* itemlist, int16 ch eslot = EQEmu::textures::weaponPrimary; if (item2->Damage > 0) { SendAddPlayerState(PlayerState::PrimaryWeaponEquipped); - SetFacestab(true); + if (!RuleB(Combat, ClassicNPCBackstab)) + SetFacestab(true); } if (item2->IsType2HWeapon()) SetTwoHanderEquipped(true); diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index e42e4f617..a05aa1343 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -127,7 +127,7 @@ bool NPC::AICastSpell(Mob* tar, uint8 iChance, uint32 iSpellTypes) { } case SpellType_Root: { Mob *rootee = GetHateRandom(); - if (rootee && !rootee->IsRooted() && zone->random.Roll(50) + if (rootee && !rootee->IsRooted() && !rootee->IsFeared() && zone->random.Roll(50) && rootee->DontRootMeBefore() < Timer::GetCurrentTime() && rootee->CanBuffStack(AIspells[i].spellid, GetLevel(), true) >= 0 ) { @@ -1391,19 +1391,33 @@ void Mob::AI_Process() { //if(owner->IsClient()) // printf("Pet start pos: (%f, %f, %f)\n", GetX(), GetY(), GetZ()); - float dist = DistanceSquared(m_Position, owner->GetPosition()); - if (dist >= 400) + glm::vec4 ownerPos = owner->GetPosition(); + float dist = DistanceSquared(m_Position, ownerPos); + float distz = ownerPos.z - m_Position.z; + + if (dist >= 400 || distz > 100) { int speed = GetWalkspeed(); if (dist >= 5625) speed = GetRunspeed(); - CalculateNewPosition2(owner->GetX(), owner->GetY(), owner->GetZ(), speed); + if (distz > 100) + { + m_Position = ownerPos; + SendPositionUpdate(); + moved = true; + } + else + { + CalculateNewPosition2(owner->GetX(), + owner->GetY(), owner->GetZ(), speed); + } } else { if(moved) { + this->FixZ(); SetCurrentSpeed(0); moved = false; } @@ -1748,6 +1762,12 @@ void Mob::AI_Event_Engaged(Mob* attacker, bool iYellForHelp) { SetAppearance(eaStanding); + /* + Kick off auto cast timer + */ + if (this->IsNPC()) + this->CastToNPC()->AIautocastspell_timer->Start(300, false); + if (iYellForHelp) { if(IsPet()) { GetOwner()->AI_Event_Engaged(attacker, iYellForHelp); diff --git a/zone/npc.h b/zone/npc.h index c973eb79d..4c67dd1d2 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -420,6 +420,8 @@ public: bool IgnoreDespawn() { return ignore_despawn; } + std::unique_ptr AIautocastspell_timer; + protected: const NPCType* NPCTypedata; @@ -453,7 +455,7 @@ protected: uint32 npc_spells_id; uint8 casting_spell_AIindex; - std::unique_ptr AIautocastspell_timer; + uint32* pDontCastBefore_casting_spell; std::vector AIspells; bool HasAISpell; diff --git a/zone/pets.cpp b/zone/pets.cpp index ef895410b..bbc4f8eea 100644 --- a/zone/pets.cpp +++ b/zone/pets.cpp @@ -655,10 +655,15 @@ void NPC::SetPetState(SpellBuff_Struct *pet_buffs, uint32 *items) { continue; const EQEmu::ItemData* item2 = database.GetItem(items[i]); - if (item2 && item2->NoDrop != 0) { - //dont bother saving item charges for now, NPCs never use them - //and nobody should be able to get them off the corpse..? - AddLootDrop(item2, &itemlist, 0, 1, 255, true, true); + + if (item2) { + bool noDrop=(item2->NoDrop == 0); // Field is reverse logic + bool petCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && + _CLIENTPET(this) && GetPetType() <= petOther); + + if (!noDrop || petCanHaveNoDrop) { + AddLootDrop(item2, &itemlist, 0, 1, 255, true, true); + } } } } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 9f78cb35d..67104a234 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1796,8 +1796,12 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove Message_StringID(4, CORPSE_CANT_SENSE); } } - else if (caster) - caster->Message_StringID(MT_SpellFailure, SPELL_LEVEL_REQ); + else if (caster) { + char level[4]; + ConvertArray(effect_value, level); + caster->Message_StringID(MT_SpellFailure, + SPELL_LEVEL_REQ, level); + } } else { Message_StringID(4, TARGET_NOT_FOUND); diff --git a/zone/trading.cpp b/zone/trading.cpp index 5c069cacd..70d5c85c1 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -523,7 +523,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st else qs_audit->char1_count += detail->charges; - //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { for (uint8 sub_slot = EQEmu::inventory::containerBegin; (sub_slot < EQEmu::inventory::ContainerCount); ++sub_slot) { // this is to catch ALL items const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); @@ -743,7 +742,6 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st qs_audit->char1_count += detail->charges; // 'step 3' should never really see containers..but, just in case... - //for (uint8 sub_slot = SUB_BEGIN; ((sub_slot < inst->GetItem()->BagSlots) && (sub_slot < EmuConstants::ITEM_CONTAINER_SIZE)); ++sub_slot) { for (uint8 sub_slot = EQEmu::inventory::containerBegin; (sub_slot < EQEmu::inventory::ContainerCount); ++sub_slot) { // this is to catch ALL items const EQEmu::ItemInstance* bag_inst = inst->GetItem(sub_slot); @@ -888,8 +886,12 @@ void Client::FinishTrade(Mob* tradingWith, bool finalizer, void* event_entry, st const EQEmu::ItemData* item = inst->GetItem(); if(item && quest_npc == false) { + bool isPetAndCanHaveNoDrop = (RuleB(Pets, CanTakeNoDrop) && + _CLIENTPET(tradingWith) && + tradingWith->GetPetType()<=petOther); // if it was not a NO DROP or Attuned item (or if a GM is trading), let the NPC have it - if(GetGM() || (item->NoDrop != 0 && inst->IsAttuned() == false)) { + if(GetGM() || (inst->IsAttuned() == false && + (item->NoDrop != 0 || isPetAndCanHaveNoDrop))) { // pets need to look inside bags and try to equip items found there if (item->IsClassBag() && item->BagSlots > 0) { for (int16 bslot = EQEmu::inventory::containerBegin; bslot < item->BagSlots; bslot++) { diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 7517b7fb8..9231ccae2 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -884,7 +884,7 @@ void Mob::FixZ(int32 z_find_offset /*= 5*/) glm::vec3 current_loc(m_Position); float new_z = GetFixedZ(current_loc, z_find_offset); - if (new_z != m_Position.z) + if (!IsClient() && new_z != m_Position.z) { if ((new_z > -2000) && new_z != BEST_Z_INVALID) { if (RuleB(Map, MobZVisualDebug)) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 18730bb55..6417b9c1d 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -338,6 +338,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) if (ztz->response <= 0) { zc2->success = ZONE_ERROR_NOTREADY; entity->CastToMob()->SetZone(ztz->current_zone_id, ztz->current_instance_id); + entity->CastToClient()->SetZoning(false); } else { entity->CastToClient()->UpdateWho(1); diff --git a/zone/zone.cpp b/zone/zone.cpp index 3a8f1e938..0e6a50092 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1515,7 +1515,7 @@ void Zone::Repop(uint32 delay) { void Zone::GetTimeSync() { if (worldserver.Connected() && !zone_has_current_time) { - auto pack = new ServerPacket(ServerOP_GetWorldTime, 0); + auto pack = new ServerPacket(ServerOP_GetWorldTime, 1); worldserver.SendPacket(pack); safe_delete(pack); } diff --git a/zone/zone_config.h b/zone/zone_config.h index d67cb5201..43f5b723c 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -49,7 +49,7 @@ class ZoneConfig : public EQEmuConfig { _zone_config=new ZoneConfig; _config=_zone_config; - return _config->ParseFile(EQEmuConfig::ConfigFile.c_str(),"server"); + return _config->parseFile(); } // Accessors for the static private object diff --git a/zone/zoning.cpp b/zone/zoning.cpp index c7be0a37e..cbd928f21 100644 --- a/zone/zoning.cpp +++ b/zone/zoning.cpp @@ -42,7 +42,7 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) { Bot::ProcessClientZoneChange(this); #endif - zoning = true; + bZoning = true; if (app->size != sizeof(ZoneChange_Struct)) { Log(Logs::General, Logs::None, "Wrong size: OP_ZoneChange, size=%d, expected %d", app->size, sizeof(ZoneChange_Struct)); return; @@ -308,6 +308,8 @@ void Client::SendZoneCancel(ZoneChange_Struct *zc) { //reset to unsolicited. zone_mode = ZoneUnsolicited; + // reset since we're not zoning anymore + bZoning = false; } void Client::SendZoneError(ZoneChange_Struct *zc, int8 err) @@ -327,6 +329,8 @@ void Client::SendZoneError(ZoneChange_Struct *zc, int8 err) //reset to unsolicited. zone_mode = ZoneUnsolicited; + // reset since we're not zoning anymore + bZoning = false; } void Client::DoZoneSuccess(ZoneChange_Struct *zc, uint16 zone_id, uint32 instance_id, float dest_x, float dest_y, float dest_z, float dest_h, int8 ignore_r) {