From 38bf73cc08ceb998dfb31eae4206e4953b6d0493 Mon Sep 17 00:00:00 2001 From: Uleat Date: Wed, 9 Jan 2019 20:14:49 -0500 Subject: [PATCH 01/38] Added enum class Expansion --- common/emu_constants.h | 1 + common/emu_versions.cpp | 214 +++++++++++++++++++++++++++---- common/emu_versions.h | 29 +++++ common/eq_limits.cpp | 8 ++ common/eq_limits.h | 3 + common/patches/rof2_limits.h | 1 + common/patches/rof_limits.h | 1 + common/patches/sod_limits.h | 1 + common/patches/sof_limits.h | 1 + common/patches/titanium_limits.h | 1 + common/patches/uf_limits.h | 1 + 11 files changed, 238 insertions(+), 23 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 8d27e74b0..9f24d5c20 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -188,6 +188,7 @@ namespace EQEmu namespace constants { const EQEmu::versions::ClientVersion CHARACTER_CREATION_CLIENT = EQEmu::versions::ClientVersion::Titanium; + using RoF2::constants::EXPANSION; using RoF2::constants::EXPANSION_BIT; using RoF2::constants::EXPANSIONS_MASK; diff --git a/common/emu_versions.cpp b/common/emu_versions.cpp index ba532b8fc..d74835671 100644 --- a/common/emu_versions.cpp +++ b/common/emu_versions.cpp @@ -342,56 +342,224 @@ EQEmu::versions::MobVersion EQEmu::versions::ConvertClientVersionToOfflinePCMobV } } -const char* EQEmu::expansions::ExpansionName(uint32 expansion_bit) +const char* EQEmu::expansions::ExpansionName(Expansion expansion) { - switch (expansion_bit) { - case expansions::bitEverQuest: + switch (expansion) { + case Expansion::EverQuest: return "EverQuest"; - case expansions::bitRoK: + case Expansion::RoK: return "The Ruins of Kunark"; - case expansions::bitSoV: + case Expansion::SoV: return "The Scars of Velious"; - case expansions::bitSoL: + case Expansion::SoL: return "The Shadows of Luclin"; - case expansions::bitPoP: + case Expansion::PoP: return "The Planes of Power"; - case expansions::bitLoY: + case Expansion::LoY: return "The Legacy of Ykesha"; - case expansions::bitLDoN: + case Expansion::LDoN: return "Lost Dungeons of Norrath"; - case expansions::bitGoD: + case Expansion::GoD: return "Gates of Discord"; - case expansions::bitOoW: + case Expansion::OoW: return "Omens of War"; - case expansions::bitDoN: + case Expansion::DoN: return "Dragons of Norrath"; - case expansions::bitDoD: + case Expansion::DoD: return "Depths of Darkhollow"; - case expansions::bitPoR: + case Expansion::PoR: return "Prophecy of Ro"; - case expansions::bitTSS: + case Expansion::TSS: return "The Serpent's Spine"; - case expansions::bitTBS: + case Expansion::TBS: return "The Buried Sea"; - case expansions::bitSoF: + case Expansion::SoF: return "Secrets of Faydwer"; - case expansions::bitSoD: + case Expansion::SoD: return "Seeds of Destruction"; - case expansions::bitUF: + case Expansion::UF: return "Underfoot"; - case expansions::bitHoT: + case Expansion::HoT: return "House of Thule"; - case expansions::bitVoA: + case Expansion::VoA: return "Veil of Alaris"; - case expansions::bitRoF: + case Expansion::RoF: return "Rain of Fear"; - case expansions::bitCotF: + case Expansion::CotF: return "Call of the Forsaken"; default: return "Invalid Expansion"; } } +const char* EQEmu::expansions::ExpansionName(uint32 expansion_bit) +{ + return ExpansionName(ConvertExpansionBitToExpansion(expansion_bit)); +} + +uint32 EQEmu::expansions::ConvertExpansionToExpansionBit(Expansion expansion) +{ + switch (expansion) { + case Expansion::RoK: + return bitRoK; + case Expansion::SoV: + return bitSoV; + case Expansion::SoL: + return bitSoL; + case Expansion::PoP: + return bitPoP; + case Expansion::LoY: + return bitLoY; + case Expansion::LDoN: + return bitLDoN; + case Expansion::GoD: + return bitGoD; + case Expansion::OoW: + return bitOoW; + case Expansion::DoN: + return bitDoN; + case Expansion::DoD: + return bitDoD; + case Expansion::PoR: + return bitPoR; + case Expansion::TSS: + return bitTSS; + case Expansion::TBS: + return bitTBS; + case Expansion::SoF: + return bitSoF; + case Expansion::SoD: + return bitSoD; + case Expansion::UF: + return bitUF; + case Expansion::HoT: + return bitHoT; + case Expansion::VoA: + return bitVoA; + case Expansion::RoF: + return bitRoF; + case Expansion::CotF: + return bitCotF; + default: + return bitEverQuest; + } +} + +EQEmu::expansions::Expansion EQEmu::expansions::ConvertExpansionBitToExpansion(uint32 expansion_bit) +{ + switch (expansion_bit) { + case bitRoK: + return Expansion::RoK; + case bitSoV: + return Expansion::SoV; + case bitSoL: + return Expansion::SoL; + case bitPoP: + return Expansion::PoP; + case bitLoY: + return Expansion::LoY; + case bitLDoN: + return Expansion::LDoN; + case bitGoD: + return Expansion::GoD; + case bitOoW: + return Expansion::OoW; + case bitDoN: + return Expansion::DoN; + case bitDoD: + return Expansion::DoD; + case bitPoR: + return Expansion::PoR; + case bitTSS: + return Expansion::TSS; + case bitTBS: + return Expansion::TBS; + case bitSoF: + return Expansion::SoF; + case bitSoD: + return Expansion::SoD; + case bitUF: + return Expansion::UF; + case bitHoT: + return Expansion::HoT; + case bitVoA: + return Expansion::VoA; + case bitRoF: + return Expansion::RoF; + case bitCotF: + return Expansion::CotF; + default: + return Expansion::EverQuest; + } +} + +uint32 EQEmu::expansions::ConvertExpansionToExpansionMask(Expansion expansion) +{ + switch (expansion) { + case Expansion::RoK: + return maskRoK; + case Expansion::SoV: + return maskSoV; + case Expansion::SoL: + return maskSoL; + case Expansion::PoP: + return maskPoP; + case Expansion::LoY: + return maskLoY; + case Expansion::LDoN: + return maskLDoN; + case Expansion::GoD: + return maskGoD; + case Expansion::OoW: + return maskOoW; + case Expansion::DoN: + return maskDoN; + case Expansion::DoD: + return maskDoD; + case Expansion::PoR: + return maskPoR; + case Expansion::TSS: + return maskTSS; + case Expansion::TBS: + return maskTBS; + case Expansion::SoF: + return maskSoF; + case Expansion::SoD: + return maskSoD; + case Expansion::UF: + return maskUF; + case Expansion::HoT: + return maskHoT; + case Expansion::VoA: + return maskVoA; + case Expansion::RoF: + return maskRoF; + case Expansion::CotF: + return maskCotF; + default: + return maskEverQuest; + } +} + +EQEmu::expansions::Expansion EQEmu::expansions::ConvertClientVersionToExpansion(versions::ClientVersion client_version) +{ + switch (client_version) { + case versions::ClientVersion::Titanium: + return expansions::Expansion::PoR; + case versions::ClientVersion::SoF: + return expansions::Expansion::SoF; + case versions::ClientVersion::SoD: + return expansions::Expansion::SoD; + case versions::ClientVersion::UF: + return expansions::Expansion::UF; + case versions::ClientVersion::RoF: + case versions::ClientVersion::RoF2: + return expansions::Expansion::RoF; + default: + return expansions::Expansion::EverQuest; + } +} + uint32 EQEmu::expansions::ConvertClientVersionToExpansionBit(versions::ClientVersion client_version) { switch (client_version) { diff --git a/common/emu_versions.h b/common/emu_versions.h index 20bfd6dbc..17ea82b9f 100644 --- a/common/emu_versions.h +++ b/common/emu_versions.h @@ -137,6 +137,30 @@ namespace EQEmu } /*versions*/ namespace expansions { + enum class Expansion : uint32 { + EverQuest = 0, + RoK, + SoV, + SoL, + PoP, + LoY, + LDoN, + GoD, + OoW, + DoN, + DoD, + PoR, + TSS, + TBS, + SoF, + SoD, + UF, + HoT, + VoA, + RoF, + CotF + }; + enum ExpansionBitmask : uint32 { bitEverQuest = 0x00000000, bitRoK = 0x00000001, @@ -182,7 +206,12 @@ namespace EQEmu maskCotF = 0x000FFFFF }; + const char* ExpansionName(Expansion expansion); const char* ExpansionName(uint32 expansion_bit); + uint32 ConvertExpansionToExpansionBit(Expansion expansion); + Expansion ConvertExpansionBitToExpansion(uint32 expansion_bit); + uint32 ConvertExpansionToExpansionMask(Expansion expansion); + Expansion ConvertClientVersionToExpansion(versions::ClientVersion client_version); uint32 ConvertClientVersionToExpansionBit(versions::ClientVersion client_version); uint32 ConvertClientVersionToExpansionMask(versions::ClientVersion client_version); diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 025ec4f95..f07b5cf0f 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -25,6 +25,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi { /*[ClientVersion::Unknown] =*/ EQEmu::constants::LookupEntry( + EQEmu::expansions::Expansion::EverQuest, ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, @@ -39,6 +40,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::Client62] =*/ EQEmu::constants::LookupEntry( + EQEmu::expansions::Expansion::EverQuest, Client62::INULL, Client62::INULL, Client62::INULL, @@ -53,6 +55,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::Titanium] =*/ EQEmu::constants::LookupEntry( + Titanium::constants::EXPANSION, Titanium::constants::EXPANSION_BIT, Titanium::constants::EXPANSIONS_MASK, Titanium::constants::CHARACTER_CREATION_LIMIT, @@ -67,6 +70,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::SoF] =*/ EQEmu::constants::LookupEntry( + SoF::constants::EXPANSION, SoF::constants::EXPANSION_BIT, SoF::constants::EXPANSIONS_MASK, SoF::constants::CHARACTER_CREATION_LIMIT, @@ -81,6 +85,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::SoD] =*/ EQEmu::constants::LookupEntry( + SoD::constants::EXPANSION, SoD::constants::EXPANSION_BIT, SoD::constants::EXPANSIONS_MASK, SoD::constants::CHARACTER_CREATION_LIMIT, @@ -95,6 +100,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::UF] =*/ EQEmu::constants::LookupEntry( + UF::constants::EXPANSION, UF::constants::EXPANSION_BIT, UF::constants::EXPANSIONS_MASK, UF::constants::CHARACTER_CREATION_LIMIT, @@ -109,6 +115,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::RoF] =*/ EQEmu::constants::LookupEntry( + RoF::constants::EXPANSION, RoF::constants::EXPANSION_BIT, RoF::constants::EXPANSIONS_MASK, RoF::constants::CHARACTER_CREATION_LIMIT, @@ -123,6 +130,7 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ), /*[ClientVersion::RoF2] =*/ EQEmu::constants::LookupEntry( + RoF2::constants::EXPANSION, RoF2::constants::EXPANSION_BIT, RoF2::constants::EXPANSIONS_MASK, RoF2::constants::CHARACTER_CREATION_LIMIT, diff --git a/common/eq_limits.h b/common/eq_limits.h index f18edd212..21bc2459b 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -35,6 +35,7 @@ namespace EQEmu { namespace constants { struct LookupEntry { + EQEmu::expansions::Expansion Expansion; uint32 ExpansionBit; uint32 ExpansionsMask; int16 CharacterCreationLimit; @@ -48,6 +49,7 @@ namespace EQEmu int MercBuffs; LookupEntry( + EQEmu::expansions::Expansion Expansion, uint32 ExpansionBit, uint32 ExpansionsMask, int16 CharacterCreationLimit, @@ -60,6 +62,7 @@ namespace EQEmu int PetBuffs, int MercBuffs ) : + Expansion(Expansion), ExpansionBit(ExpansionBit), ExpansionsMask(ExpansionsMask), CharacterCreationLimit(CharacterCreationLimit), diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index ecfd6de4b..8b83e885c 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -259,6 +259,7 @@ namespace RoF2 namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF2; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::RoF; const uint32 EXPANSION_BIT = EQEmu::expansions::bitRoF; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskRoF; diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 6bb59c14c..42cffc5bf 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -250,6 +250,7 @@ namespace RoF namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::RoF; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::RoF; const uint32 EXPANSION_BIT = EQEmu::expansions::bitRoF; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskRoF; diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index cb7e3e21a..eb6ce1daa 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -277,6 +277,7 @@ namespace SoD namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoD; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::SoD; const uint32 EXPANSION_BIT = EQEmu::expansions::bitSoD; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskSoD; diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index a3ff9bc2d..22b6995c8 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -277,6 +277,7 @@ namespace SoF namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::SoF; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::SoF; const uint32 EXPANSION_BIT = EQEmu::expansions::bitSoF; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskSoF; diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 01cbe0b09..8bfebe319 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -276,6 +276,7 @@ namespace Titanium namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::PoR; const uint32 EXPANSION_BIT = EQEmu::expansions::bitPoR; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskPoR; diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 0232a1b85..ce1f9c770 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -278,6 +278,7 @@ namespace UF namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::UF; } + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::UF; const uint32 EXPANSION_BIT = EQEmu::expansions::bitUF; const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskUF; From 93acbf524141f48d82931aaf5e702551a8cc26a2 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 10 Jan 2019 19:09:27 -0500 Subject: [PATCH 02/38] Reimplemented pre-nerf Ranger stationary damage bonus. This will allow Developers to disable/enable the stationary requirement. --- zone/attack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/attack.cpp b/zone/attack.cpp index 013f0fa5b..4c13f6362 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -5038,7 +5038,7 @@ void Mob::CommonOutgoingHitSuccess(Mob* defender, DamageHitInfo &hit, ExtraAttac hit.damage_done = headshot; } else if (GetClass() == RANGER && GetLevel() > 50) { // no double dmg on headshot - if (defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) { + if ((defender->IsNPC() && !defender->IsMoving() && !defender->IsRooted()) || !RuleB(Combat, ArcheryBonusRequiresStationary)) { hit.damage_done *= 2; Message_StringID(MT_CritMelee, BOW_DOUBLE_DAMAGE); } From d8c88aac96ab2cf7ce582159917ed73971c973db Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Thu, 10 Jan 2019 19:55:59 -0500 Subject: [PATCH 03/38] Added multi-version capabilities to NPCs. Setting a spawn2 row's 'version' column to -1 will make that spawn appear in all versions of the zone. This is similar to how doors/objects/groundspawns use version -1. --- common/version.h | 2 +- utils/sql/db_update_manifest.txt | 1 + utils/sql/git/required/2019_01_10_multi_version_spawns.sql | 1 + zone/npc.cpp | 2 +- zone/spawn2.cpp | 4 ++-- 5 files changed, 6 insertions(+), 4 deletions(-) create mode 100644 utils/sql/git/required/2019_01_10_multi_version_spawns.sql diff --git a/common/version.h b/common/version.h index ba57cf898..c45ef76d8 100644 --- a/common/version.h +++ b/common/version.h @@ -30,7 +30,7 @@ Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9134 +#define CURRENT_BINARY_DATABASE_VERSION 9135 #ifdef BOTS #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9021 #else diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 7a7523c94..9e3a7190f 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -388,6 +388,7 @@ 9132|2018_12_16_global_base_scaling.sql|SHOW TABLES LIKE 'npc_scale_global_base'|empty| 9133|2018_11_25_StuckBehavior.sql|SHOW COLUMNS FROM `npc_types` LIKE 'stuck_behavior'|empty| 9134|2019_01_04_update_global_base_scaling.sql|SELECT * FROM db_version WHERE version >= 9134|empty| +9135|2019_01_10_multi_version_spawns.sql|SELECT * FROM db_version WHERE version >= 9135|empty| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not diff --git a/utils/sql/git/required/2019_01_10_multi_version_spawns.sql b/utils/sql/git/required/2019_01_10_multi_version_spawns.sql new file mode 100644 index 000000000..c15bd0146 --- /dev/null +++ b/utils/sql/git/required/2019_01_10_multi_version_spawns.sql @@ -0,0 +1 @@ +ALTER TABLE `spawn2` MODIFY `version` SMALLINT(5) SIGNED NOT NULL DEFAULT '0'; \ No newline at end of file diff --git a/zone/npc.cpp b/zone/npc.cpp index 8de819e0c..16a508d1f 100644 --- a/zone/npc.cpp +++ b/zone/npc.cpp @@ -1388,7 +1388,7 @@ uint32 ZoneDatabase::DeleteSpawnRemoveFromNPCTypeTable(const char *zone, uint32 uint32 spawngroupID = 0; std::string query = StringFormat("SELECT id, spawngroupID FROM spawn2 WHERE zone = '%s' " - "AND version = %u AND spawngroupID = %i", + "AND (version = %u OR version = -1) AND spawngroupID = %i", zone, zone_version, spawn->GetSp2()); auto results = QueryDatabase(query); if (!results.Success()) diff --git a/zone/spawn2.cpp b/zone/spawn2.cpp index 3a6142c42..e004faa4a 100644 --- a/zone/spawn2.cpp +++ b/zone/spawn2.cpp @@ -488,7 +488,7 @@ bool ZoneDatabase::PopulateZoneSpawnListClose(uint32 zoneid, LinkedList "animation " "FROM " "spawn2 " - "WHERE zone = '%s' AND version = %u", + "WHERE zone = '%s' AND (version = %u OR version = -1) ", zone_name, version ); @@ -592,7 +592,7 @@ bool ZoneDatabase::PopulateZoneSpawnList(uint32 zoneid, LinkedList &spa "animation " "FROM " "spawn2 " - "WHERE zone = '%s' AND version = %u", + "WHERE zone = '%s' AND (version = %u OR version = -1)", zone_name, version ); From 7857bc45fbd3ff4702b575b737550a83bac0b656 Mon Sep 17 00:00:00 2001 From: Uleat Date: Fri, 11 Jan 2019 05:01:44 -0500 Subject: [PATCH 04/38] Excluded runtime modification of expansion-based rules 'World:ExpansionSettings' and 'World:UseClientBasedExpansionSettings' --- changelog.txt | 8 ++++++++ common/rulesys.cpp | 39 +++++++++++++++++++++++++++++++++------ common/rulesys.h | 6 +++--- ucs/ucs.cpp | 5 +++-- world/net.cpp | 6 +++--- world/zoneserver.cpp | 4 ++-- zone/command.cpp | 14 +++++++------- zone/net.cpp | 4 ++-- zone/worldserver.cpp | 2 +- zone/zone.cpp | 2 +- 10 files changed, 63 insertions(+), 27 deletions(-) diff --git a/changelog.txt b/changelog.txt index 3e2c4f671..51b8821a0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,14 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 1/11/2019 == +Uleat: Modified rules system to ignore all runtime modifications of 'World:ExpansionSettings' and 'World:UseClientBasedExpansionSettings' fields. + - These fields are no longer allowed to be changed during server runtime through the command system + - Major syncronization issues between server and clients result when these fields are altered in-game + - It is not recommended to update these fields via sql queries while the server is in operation + - Failure to observe these warnings will result in abhorant behavior and loss of items + - Modify these fields during server operation at your own risk! + == 1/4/2019 == Akkadius: [Scaling] Global base scaling data has been updated in new database binary revision diff --git a/common/rulesys.cpp b/common/rulesys.cpp index 61bb72357..d4ff3d4d9 100644 --- a/common/rulesys.cpp +++ b/common/rulesys.cpp @@ -61,7 +61,7 @@ RuleManager::RuleManager() : m_activeRuleset(0), m_activeName("default") { - ResetRules(); + ResetRules(false); } RuleManager::CategoryType RuleManager::FindCategory(const char *catname) { @@ -126,7 +126,7 @@ bool RuleManager::GetRule(const char *rule_name, std::string &return_value) { return true; } -bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save) { +bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save, bool reload) { if(rule_name == nullptr || rule_value == nullptr) return(false); @@ -135,6 +135,13 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas if(!_FindRule(rule_name, type, index)) return(false); + if (reload) { + if (strcasecmp(rule_name, "World:ExpansionSettings") == 0) + return(false); + if (strcasecmp(rule_name, "World:UseClientBasedExpansionSettings") == 0) + return(false); + } + switch(type) { case IntRule: m_RuleIntValues[index] = atoi(rule_value); @@ -160,7 +167,16 @@ bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Databas return(true); } -void RuleManager::ResetRules() { +void RuleManager::ResetRules(bool reload) { + std::string expansion1; + std::string expansion2; + + // these rules must not change during server runtime + if (reload) { + GetRule("World:ExpansionSettings", expansion1); + GetRule("World:UseClientBasedExpansionSettings", expansion2); + } + Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values"); #define RULE_INT(cat, rule, default_value) \ m_RuleIntValues[ Int__##rule ] = default_value; @@ -169,6 +185,12 @@ void RuleManager::ResetRules() { #define RULE_BOOL(cat, rule, default_value) \ m_RuleBoolValues[ Bool__##rule ] = default_value; #include "ruletypes.h" + + // restore these rules to their pre-reset values + if (reload) { + SetRule("World:ExpansionSettings", expansion1.c_str(), nullptr, false, false); + SetRule("World:UseClientBasedExpansionSettings", expansion2.c_str(), nullptr, false, false); + } } bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) { @@ -235,7 +257,7 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) { } } -bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { +bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) { int ruleset_id = this->GetRulesetID(database, ruleset_name); if (ruleset_id < 0) { @@ -269,7 +291,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { return false; for (auto row = results.begin(); row != results.end(); ++row) - if (!SetRule(row[0], row[1], nullptr, false)) + if (!SetRule(row[0], row[1], nullptr, false, reload)) Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]); } @@ -279,7 +301,7 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { return false; for (auto row = results.begin(); row != results.end(); ++row) - if (!SetRule(row[0], row[1], nullptr, false)) + if (!SetRule(row[0], row[1], nullptr, false, reload)) Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]); return true; @@ -288,6 +310,11 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name) { void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) { char value_string[100]; + if (type == IntRule && strcasecmp(_GetRuleName(type, index), "World:ExpansionSettings") == 0) + return; + if (type == BoolRule && strcasecmp(_GetRuleName(type, index), "World:UseClientBasedExpansionSettings") == 0) + return; + switch (type) { case IntRule: sprintf(value_string, "%d", m_RuleIntValues[index]); diff --git a/common/rulesys.h b/common/rulesys.h index 25c3a4019..710c6d612 100644 --- a/common/rulesys.h +++ b/common/rulesys.h @@ -102,7 +102,7 @@ public: bool ListRules(const char *catname, std::vector &into); bool ListCategories(std::vector &into); bool GetRule(const char *rule_name, std::string &ret_val); - bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false); + bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false, bool reload = false); int GetActiveRulesetID() const { return(m_activeRuleset); } const char *GetActiveRuleset() const { return(m_activeName.c_str()); } @@ -110,8 +110,8 @@ public: static std::string GetRulesetName(Database *db, int id); static bool ListRulesets(Database *db, std::map &into); - void ResetRules(); - bool LoadRules(Database *db, const char *ruleset = nullptr); + void ResetRules(bool reload = false); + bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false); void SaveRules(Database *db, const char *ruleset = nullptr); private: diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index b9e7f41b4..21e525cbe 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -102,13 +102,14 @@ int main() { char tmp[64]; + // ucs has no 'reload rules' handler if (database.GetVariable("RuleSet", tmp, sizeof(tmp)-1)) { Log(Logs::General, Logs::UCS_Server, "Loading rule set '%s'", tmp); - if(!RuleManager::Instance()->LoadRules(&database, tmp)) { + if(!RuleManager::Instance()->LoadRules(&database, tmp, false)) { Log(Logs::General, Logs::UCS_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp); } } else { - if(!RuleManager::Instance()->LoadRules(&database, "default")) { + if(!RuleManager::Instance()->LoadRules(&database, "default", false)) { Log(Logs::General, Logs::UCS_Server, "No rule set configured, using default rules"); } else { Log(Logs::General, Logs::UCS_Server, "Loaded default rule set 'default'", tmp); diff --git a/world/net.cpp b/world/net.cpp index 7065ea6c3..77deec265 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -336,12 +336,12 @@ int main(int argc, char** argv) { std::string tmp; if (database.GetVariable("RuleSet", tmp)) { Log(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str()); - if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) { + if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { Log(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { - if (!RuleManager::Instance()->LoadRules(&database, "default")) { + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { Log(Logs::General, Logs::World_Server, "No rule set configured, using default rules"); } else { @@ -622,4 +622,4 @@ void CheckForServerScript(bool force_download) { 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/zoneserver.cpp b/world/zoneserver.cpp index 7d638d100..7eaa7e3c1 100644 --- a/world/zoneserver.cpp +++ b/world/zoneserver.cpp @@ -814,12 +814,12 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) { } case ServerOP_ReloadRules: { zoneserver_list.SendPacket(pack); - RuleManager::Instance()->LoadRules(&database, "default"); + RuleManager::Instance()->LoadRules(&database, "default", true); break; } case ServerOP_ReloadRulesWorld: { - RuleManager::Instance()->LoadRules(&database, "default"); + RuleManager::Instance()->LoadRules(&database, "default", true); break; } case ServerOP_ReloadPerlExportSettings: diff --git a/zone/command.cpp b/zone/command.cpp index bccf0747a..f65a4cd11 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -8345,7 +8345,7 @@ void command_rules(Client *c, const Seperator *sep) { c->Message(0, "(%d) %s", cur->first, cur->second.c_str()); } } else if(!strcasecmp(sep->arg[1], "reload")) { - RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset()); + RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); c->Message(0, "The active ruleset (%s (%d)) has been reloaded", RuleManager::Instance()->GetActiveRuleset(), RuleManager::Instance()->GetActiveRulesetID()); } else if(!strcasecmp(sep->arg[1], "switch")) { @@ -8361,7 +8361,7 @@ void command_rules(Client *c, const Seperator *sep) { } //TODO: we likely want to reload this ruleset everywhere... - RuleManager::Instance()->LoadRules(&database, sep->arg[2]); + RuleManager::Instance()->LoadRules(&database, sep->arg[2], true); c->Message(0, "The selected ruleset has been changed to (%s (%d)) and reloaded locally", sep->arg[2], rsid); } else if(!strcasecmp(sep->arg[1], "load")) { @@ -8371,7 +8371,7 @@ void command_rules(Client *c, const Seperator *sep) { c->Message(13, "Unknown rule set '%s'", sep->arg[2]); return; } - RuleManager::Instance()->LoadRules(&database, sep->arg[2]); + RuleManager::Instance()->LoadRules(&database, sep->arg[2], true); c->Message(0, "Loaded ruleset '%s' (%d) locally", sep->arg[2], rsid); } else if(!strcasecmp(sep->arg[1], "store")) { if(sep->argnum == 1) { @@ -8395,9 +8395,9 @@ void command_rules(Client *c, const Seperator *sep) { return; } } else if(!strcasecmp(sep->arg[1], "reset")) { - RuleManager::Instance()->ResetRules(); + RuleManager::Instance()->ResetRules(true); c->Message(0, "The running ruleset has been set to defaults"); - + } else if(!strcasecmp(sep->arg[1], "get")) { if(sep->argnum != 2) { c->Message(13, "Invalid argument count, see help."); @@ -8414,7 +8414,7 @@ void command_rules(Client *c, const Seperator *sep) { c->Message(13, "Invalid argument count, see help."); return; } - if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3])) { + if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], nullptr, false, true)) { c->Message(13, "Failed to modify rule"); } else { c->Message(0, "Rule modified locally."); @@ -8424,7 +8424,7 @@ void command_rules(Client *c, const Seperator *sep) { c->Message(13, "Invalid argument count, see help."); return; } - if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true)) { + if(!RuleManager::Instance()->SetRule(sep->arg[2], sep->arg[3], &database, true, true)) { c->Message(13, "Failed to modify rule"); } else { c->Message(0, "Rule modified locally and in the database."); diff --git a/zone/net.cpp b/zone/net.cpp index 641c69248..9e896fead 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -362,12 +362,12 @@ int main(int argc, char** argv) { std::string tmp; if (database.GetVariable("RuleSet", tmp)) { Log(Logs::General, Logs::Zone_Server, "Loading rule set '%s'", tmp.c_str()); - if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str())) { + if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) { Log(Logs::General, Logs::Error, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str()); } } else { - if (!RuleManager::Instance()->LoadRules(&database, "default")) { + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { Log(Logs::General, Logs::Zone_Server, "No rule set configured, using default rules"); } else { diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 7b5524605..e187a3144 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -1772,7 +1772,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) zone->GetLongName(), zone->GetInstanceID() ); - RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset()); + RuleManager::Instance()->LoadRules(&database, RuleManager::Instance()->GetActiveRuleset(), true); break; } case ServerOP_ReloadLogs: { diff --git a/zone/zone.cpp b/zone/zone.cpp index 3fa3e5370..923e37a39 100755 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -904,7 +904,7 @@ bool Zone::Init(bool iStaticZone) { std::string r_name = RuleManager::Instance()->GetRulesetName(&database, default_ruleset); if(r_name.size() > 0) { - RuleManager::Instance()->LoadRules(&database, r_name.c_str()); + RuleManager::Instance()->LoadRules(&database, r_name.c_str(), false); } } From bcf271c30f0cbae0c751dd2d27027e1a8a8f5785 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 12 Jan 2019 20:03:52 -0500 Subject: [PATCH 05/38] Added dynamic entries to eqdictionary --- common/emu_constants.h | 3 + common/emu_limits.h | 5 +- common/eq_limits.cpp | 238 +++++++++++++++++++++++++++++-- common/eq_limits.h | 29 +++- common/inventory_profile.cpp | 6 +- common/inventory_profile.h | 2 +- common/patches/rof2_limits.h | 8 +- common/patches/rof_limits.h | 8 +- common/patches/sod_limits.h | 8 +- common/patches/sof_limits.h | 8 +- common/patches/titanium_limits.h | 14 +- common/patches/uf_limits.h | 8 +- ucs/ucs.cpp | 3 + world/client.cpp | 4 +- world/net.cpp | 3 + world/worlddb.cpp | 2 +- zone/client_mods.cpp | 2 +- zone/corpse.cpp | 2 +- zone/net.cpp | 3 + zone/spells.cpp | 4 +- zone/zonedb.cpp | 2 +- 21 files changed, 319 insertions(+), 43 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 9f24d5c20..805bc6516 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -131,6 +131,9 @@ namespace EQEmu const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = CORPSE_BEGIN + invslot::slotCursor; + using RoF2::invslot::EQUIPMENT_BITMASK; + using RoF2::invslot::GENERAL_BITMASK; + using RoF2::invslot::CURSOR_BITMASK; using RoF2::invslot::POSSESSIONS_BITMASK; using RoF2::invslot::CORPSE_BITMASK; diff --git a/common/emu_limits.h b/common/emu_limits.h index 36d4a67b7..c855f44ab 100644 --- a/common/emu_limits.h +++ b/common/emu_limits.h @@ -70,7 +70,10 @@ namespace EntityLimits } // namespace invtype namespace invslot { - const uint64 POSSESSIONS_BITMASK = 0x00000000007FFFFF; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x0000000000000000; + const uint64 CURSOR_BITMASK = 0x0000000000000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) } // namespace invslot diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index f07b5cf0f..aad77efc1 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -19,9 +19,25 @@ #include "emu_constants.h" #include "emu_limits.h" +#include "rulesys.h" + +#include -static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versions::ClientVersionCount] = +static bool global_dictionary_init = false; +void EQEmu::InitializeDynamicLookups() { + if (global_dictionary_init == true) + return; + + constants::InitializeDynamicLookups(); + inventory::InitializeDynamicLookups(); + behavior::InitializeDynamicLookups(); + + global_dictionary_init = true; +} + +static std::unique_ptr constants_dynamic_lookup_entries[EQEmu::versions::ClientVersionCount]; +static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu::versions::ClientVersionCount] = { /*[ClientVersion::Unknown] =*/ EQEmu::constants::LookupEntry( @@ -145,12 +161,34 @@ static const EQEmu::constants::LookupEntry constants_lookup_entries[EQEmu::versi ) }; -const EQEmu::constants::LookupEntry* EQEmu::constants::Lookup(versions::ClientVersion client_version) -{ - return &constants_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; +static bool constants_dictionary_init = false; +void EQEmu::constants::InitializeDynamicLookups() { + if (constants_dictionary_init == true) + return; + constants_dictionary_init = true; + + if (RuleB(World, UseClientBasedExpansionSettings)) + return; + + // use static references for now } -static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versions::MobVersionCount] = +const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (constants_dynamic_lookup_entries[static_cast(client_version)]) + return constants_dynamic_lookup_entries[static_cast(client_version)].get(); + + return &constants_static_lookup_entries[static_cast(client_version)]; +} + +const EQEmu::constants::LookupEntry* EQEmu::constants::StaticLookup(versions::ClientVersion client_version) +{ + return &constants_static_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; +} + +static std::unique_ptr inventory_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; +static const EQEmu::inventory::LookupEntry inventory_static_lookup_entries[EQEmu::versions::MobVersionCount] = { /*[MobVersion::Unknown] =*/ EQEmu::inventory::LookupEntry( @@ -166,6 +204,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi ClientUnknown::INULL ), + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, @@ -190,6 +231,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi Client62::INULL ), + Client62::INULL, + Client62::INULL, + Client62::INULL, Client62::INULL, Client62::INULL, Client62::INULL, @@ -214,6 +258,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi Titanium::invtype::OTHER_SIZE ), + Titanium::invslot::EQUIPMENT_BITMASK, + Titanium::invslot::GENERAL_BITMASK, + Titanium::invslot::CURSOR_BITMASK, Titanium::invslot::POSSESSIONS_BITMASK, Titanium::invslot::CORPSE_BITMASK, Titanium::invbag::SLOT_COUNT, @@ -238,6 +285,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi SoF::invtype::OTHER_SIZE ), + SoF::invslot::EQUIPMENT_BITMASK, + SoF::invslot::GENERAL_BITMASK, + SoF::invslot::CURSOR_BITMASK, SoF::invslot::POSSESSIONS_BITMASK, SoF::invslot::CORPSE_BITMASK, SoF::invbag::SLOT_COUNT, @@ -262,6 +312,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi SoD::invtype::OTHER_SIZE ), + SoD::invslot::EQUIPMENT_BITMASK, + SoD::invslot::GENERAL_BITMASK, + SoD::invslot::CURSOR_BITMASK, SoD::invslot::POSSESSIONS_BITMASK, SoD::invslot::CORPSE_BITMASK, SoD::invbag::SLOT_COUNT, @@ -286,6 +339,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi UF::invtype::OTHER_SIZE ), + UF::invslot::EQUIPMENT_BITMASK, + UF::invslot::GENERAL_BITMASK, + UF::invslot::CURSOR_BITMASK, UF::invslot::POSSESSIONS_BITMASK, UF::invslot::CORPSE_BITMASK, UF::invbag::SLOT_COUNT, @@ -310,6 +366,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi RoF::invtype::OTHER_SIZE ), + RoF::invslot::EQUIPMENT_BITMASK, + RoF::invslot::GENERAL_BITMASK, + RoF::invslot::CURSOR_BITMASK, RoF::invslot::POSSESSIONS_BITMASK, RoF::invslot::CORPSE_BITMASK, RoF::invbag::SLOT_COUNT, @@ -334,6 +393,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi RoF2::invtype::OTHER_SIZE ), + RoF2::invslot::EQUIPMENT_BITMASK, + RoF2::invslot::GENERAL_BITMASK, + RoF2::invslot::CURSOR_BITMASK, RoF2::invslot::POSSESSIONS_BITMASK, RoF2::invslot::CORPSE_BITMASK, RoF2::invbag::SLOT_COUNT, @@ -358,6 +420,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::NPC::INULL ), + EntityLimits::NPC::INULL, + EntityLimits::NPC::INULL, + EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, EntityLimits::NPC::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -382,6 +447,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::NPCMerchant::INULL ), + EntityLimits::NPCMerchant::INULL, + EntityLimits::NPCMerchant::INULL, + EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, EntityLimits::NPCMerchant::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -406,6 +474,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::Merc::INULL ), + EntityLimits::Merc::INULL, + EntityLimits::Merc::INULL, + EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, EntityLimits::Merc::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -430,6 +501,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::Bot::INULL ), + EntityLimits::Bot::invslot::EQUIPMENT_BITMASK, + EntityLimits::Bot::invslot::GENERAL_BITMASK, + EntityLimits::Bot::invslot::CURSOR_BITMASK, EntityLimits::Bot::invslot::POSSESSIONS_BITMASK, EntityLimits::Bot::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -454,6 +528,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::ClientPet::INULL ), + EntityLimits::ClientPet::INULL, + EntityLimits::ClientPet::INULL, + EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, EntityLimits::ClientPet::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -478,6 +555,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::NPCPet::INULL ), + EntityLimits::NPCPet::INULL, + EntityLimits::NPCPet::INULL, + EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, EntityLimits::NPCPet::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -502,6 +582,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::MercPet::INULL ), + EntityLimits::MercPet::INULL, + EntityLimits::MercPet::INULL, + EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, EntityLimits::MercPet::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -526,6 +609,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi EntityLimits::BotPet::INULL ), + EntityLimits::BotPet::INULL, + EntityLimits::BotPet::INULL, + EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, EntityLimits::BotPet::INULL, 0, //EQEmu::inventory::ContainerCount, /*ItemBagSize,*/ @@ -550,6 +636,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi Titanium::INULL ), + Titanium::INULL, + Titanium::INULL, + Titanium::INULL, Titanium::INULL, Titanium::INULL, Titanium::invbag::SLOT_COUNT, @@ -574,6 +663,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi SoF::INULL ), + SoF::INULL, + SoF::INULL, + SoF::INULL, SoF::INULL, SoF::INULL, SoF::invbag::SLOT_COUNT, @@ -598,6 +690,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi SoD::INULL ), + SoD::INULL, + SoD::INULL, + SoD::INULL, SoD::INULL, SoD::INULL, SoD::invbag::SLOT_COUNT, @@ -622,6 +717,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi UF::INULL ), + UF::INULL, + UF::INULL, + UF::INULL, UF::INULL, UF::INULL, UF::invbag::SLOT_COUNT, @@ -646,6 +744,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi RoF::INULL ), + RoF::INULL, + RoF::INULL, + RoF::INULL, RoF::INULL, RoF::INULL, RoF::invbag::SLOT_COUNT, @@ -670,6 +771,9 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi RoF2::INULL ), + RoF2::INULL, + RoF2::INULL, + RoF2::INULL, RoF2::INULL, RoF2::INULL, RoF2::invbag::SLOT_COUNT, @@ -682,12 +786,101 @@ static const EQEmu::inventory::LookupEntry inventory_lookup_entries[EQEmu::versi ) }; -const EQEmu::inventory::LookupEntry* EQEmu::inventory::Lookup(versions::MobVersion mob_version) -{ - return &inventory_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; +static bool inventory_dictionary_init = false; +void EQEmu::inventory::InitializeDynamicLookups() { + if (inventory_dictionary_init == true) + return; + inventory_dictionary_init = true; + + // server is configured for static definitions + if (RuleB(World, UseClientBasedExpansionSettings)) + return; + + // Notes: + // Currently, there are only 3 known expansions that affect inventory-related settings in the clients.. + // - Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots + // - Expansion::TBS "The Buried Sea" - toggles slotPowerSource enabled (set) and disabled (clear) + // - Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 enabled (set) and disabled (clear) + // Obviously, the client must support the expansion to allow any (set) condition + + const uint32 current_expansions = RuleI(World, ExpansionSettings); + const uint32 dynamic_check_mask = (EQEmu::expansions::bitPoR | EQEmu::expansions::bitTBS | EQEmu::expansions::bitHoT); // the only known expansions that affect inventory + + // if all of the above expansion bits are present, then static references will suffice + if ((current_expansions & dynamic_check_mask) == dynamic_check_mask) + return; + + for (uint32 iter = static_cast(EQEmu::versions::ClientVersion::Unknown); iter <= static_cast(EQEmu::versions::LastClientVersion); ++iter) { + // no need to dynamic this condition since it is the lowest compatibility standard at this time + if (iter <= static_cast(EQEmu::versions::ClientVersion::Titanium)) + continue; + + // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: + inventory_dynamic_lookup_entries[iter] = std::make_unique(new LookupEntry(inventory_static_lookup_entries[iter])); + + // clamp affected fields to the lowest standard + inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size + inventory_dynamic_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK; // power source + inventory_dynamic_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK; // general size + inventory_dynamic_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later + inventory_dynamic_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later + + if (current_expansions & EQEmu::expansions::bitPoR) { + // update bank size + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR) + inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = SoF::invtype::BANK_SIZE; + } + + if (current_expansions & EQEmu::expansions::bitTBS) { + // update power source + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitTBS) + inventory_dynamic_lookup_entries[iter]->EquipmentBitmask = SoF::invslot::EQUIPMENT_BITMASK; + } + + if (current_expansions & EQEmu::expansions::bitHoT) { + // update general size + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitHoT) + inventory_dynamic_lookup_entries[iter]->GeneralBitmask = RoF::invslot::GENERAL_BITMASK; + } + + // fixup possessions bitmask + inventory_dynamic_lookup_entries[iter]->PossessionsBitmask = + ( + inventory_dynamic_lookup_entries[iter]->EquipmentBitmask | + inventory_dynamic_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_lookup_entries[iter]->CursorBitmask + ); + + // fixup corpse bitmask + inventory_dynamic_lookup_entries[iter]->CorpseBitmask = + ( + inventory_dynamic_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_lookup_entries[iter]->CursorBitmask | + (inventory_dynamic_lookup_entries[iter]->EquipmentBitmask << 34) + ); + + // expansion-related fields are now updated and all other fields reflect the static entry values + } + + // only client versions that require a change from their static definitions have been given a dynamic lookup entry } -static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::versions::MobVersionCount] = +const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (inventory_dynamic_lookup_entries[static_cast(mob_version)]) + return inventory_dynamic_lookup_entries[static_cast(mob_version)].get(); + + return &inventory_static_lookup_entries[static_cast(mob_version)]; +} + +const EQEmu::inventory::LookupEntry* EQEmu::inventory::StaticLookup(versions::MobVersion mob_version) +{ + return &inventory_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; +} + +static std::unique_ptr behavior_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; +static const EQEmu::behavior::LookupEntry behavior_static_lookup_entries[EQEmu::versions::MobVersionCount] = { /*[MobVersion::Unknown] =*/ EQEmu::behavior::LookupEntry( @@ -779,7 +972,28 @@ static const EQEmu::behavior::LookupEntry behavior_lookup_entries[EQEmu::version ) }; -const EQEmu::behavior::LookupEntry* EQEmu::behavior::Lookup(versions::MobVersion mob_version) -{ - return &behavior_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; +static bool behavior_dictionary_init = false; +void EQEmu::behavior::InitializeDynamicLookups() { + if (behavior_dictionary_init == true) + return; + behavior_dictionary_init = true; + + if (RuleB(World, UseClientBasedExpansionSettings)) + return; + + // use static references for now +} + +const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (behavior_dynamic_lookup_entries[static_cast(mob_version)]) + return behavior_dynamic_lookup_entries[static_cast(mob_version)].get(); + + return &behavior_static_lookup_entries[static_cast(mob_version)]; +} + +const EQEmu::behavior::LookupEntry* EQEmu::behavior::StaticLookup(versions::MobVersion mob_version) +{ + return &behavior_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } diff --git a/common/eq_limits.h b/common/eq_limits.h index 21bc2459b..117b529c4 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -33,6 +33,8 @@ namespace EQEmu { + void InitializeDynamicLookups(); + namespace constants { struct LookupEntry { EQEmu::expansions::Expansion Expansion; @@ -48,6 +50,7 @@ namespace EQEmu int PetBuffs; int MercBuffs; + LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry( EQEmu::expansions::Expansion Expansion, uint32 ExpansionBit, @@ -77,7 +80,10 @@ namespace EQEmu { } }; - const LookupEntry* Lookup(versions::ClientVersion client_version); + void InitializeDynamicLookups(); + + const LookupEntry* DynamicLookup(versions::ClientVersion client_version); + const LookupEntry* StaticLookup(versions::ClientVersion client_version); } /*constants*/ @@ -127,6 +133,9 @@ namespace EQEmu int16 InventoryTypeSizeArray[25]; // should reflect EQEmu::invtype::TYPE_COUNT referenced in emu_constants.h }; + uint64 EquipmentBitmask; + uint64 GeneralBitmask; + uint64 CursorBitmask; uint64 PossessionsBitmask; uint64 CorpseBitmask; int16 BagSlotCount; @@ -137,8 +146,12 @@ namespace EQEmu bool ConcatenateInvTypeLimbo; bool AllowOverLevelEquipment; + LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry( InventoryTypeSize_Struct InventoryTypeSize, + uint64 EquipmentBitmask, + uint64 GeneralBitmask, + uint64 CursorBitmask, uint64 PossessionsBitmask, uint64 CorpseBitmask, int16 BagSlotCount, @@ -149,6 +162,9 @@ namespace EQEmu bool AllowOverLevelEquipment ) : InventoryTypeSize(InventoryTypeSize), + EquipmentBitmask(EquipmentBitmask), + GeneralBitmask(GeneralBitmask), + CursorBitmask(CursorBitmask), PossessionsBitmask(PossessionsBitmask), CorpseBitmask(CorpseBitmask), BagSlotCount(BagSlotCount), @@ -160,7 +176,10 @@ namespace EQEmu { } }; - const LookupEntry* Lookup(versions::MobVersion mob_version); + void InitializeDynamicLookups(); + + const LookupEntry* DynamicLookup(versions::MobVersion mob_version); + const LookupEntry* StaticLookup(versions::MobVersion mob_version); } /*inventory*/ @@ -168,6 +187,7 @@ namespace EQEmu struct LookupEntry { bool CoinHasWeight; + LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry( bool CoinHasWeight ) : @@ -175,7 +195,10 @@ namespace EQEmu { } }; - const LookupEntry* Lookup(versions::MobVersion mob_version); + void InitializeDynamicLookups(); + + const LookupEntry* DynamicLookup(versions::MobVersion mob_version); + const LookupEntry* StaticLookup(versions::MobVersion mob_version); } /*behavior*/ diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index f353aa673..4f9a49448 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -122,12 +122,12 @@ EQEmu::InventoryProfile::~InventoryProfile() bool EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory_version) { if (!m_mob_version_set) { m_mob_version = versions::ValidateMobVersion(inventory_version); - m_lookup = inventory::Lookup(m_mob_version); + m_lookup = inventory::StaticLookup(m_mob_version); m_mob_version_set = true; return true; } else { - m_lookup = inventory::Lookup(versions::MobVersion::Unknown); + m_lookup = inventory::StaticLookup(versions::MobVersion::Unknown); Log(Logs::General, Logs::Error, "InventoryVersion set request after initial set (old: %u, new: %u)", static_cast(m_mob_version), static_cast(inventory_version)); return false; @@ -1092,7 +1092,7 @@ bool EQEmu::InventoryProfile::SupportsClickCasting(int16 slot_id) return true; } else if (slot_id >= invbag::GENERAL_BAGS_BEGIN && slot_id <= invbag::GENERAL_BAGS_END) { - if (inventory::Lookup(m_mob_version)->AllowClickCastFromBag) + if (inventory::StaticLookup(m_mob_version)->AllowClickCastFromBag) return true; } diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 3a90e847d..36cb2b38b 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -88,7 +88,7 @@ namespace EQEmu InventoryProfile() { m_mob_version = versions::MobVersion::Unknown; m_mob_version_set = false; - m_lookup = inventory::Lookup(versions::MobVersion::Unknown); + m_lookup = inventory::StaticLookup(versions::MobVersion::Unknown); } ~InventoryProfile(); diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 8b83e885c..3316c01c5 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -183,8 +183,12 @@ namespace RoF2 const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x00000003FFFFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x01FFFFFFFF800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x00000001FF800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvSlotName(int16 inv_type, int16 inv_slot); diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 42cffc5bf..f82e86408 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -181,8 +181,12 @@ namespace RoF const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x00000003FFFFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x01FFFFFFFF800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x00000001FF800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvSlotName(int16 inv_type, int16 inv_slot); diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index eb6ce1daa..c883524e7 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -191,8 +191,12 @@ namespace SoD const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x000000007F800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvCorpseSlotName(int16 inv_slot); diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 22b6995c8..5f8922148 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -191,8 +191,12 @@ namespace SoF const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x000000007F800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvCorpseSlotName(int16 inv_slot); diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 8bfebe319..77aab1c49 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -190,8 +190,12 @@ namespace Titanium const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x000000027FDFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x017FFFFE7F800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000005FFFFF; + const uint64 GENERAL_BITMASK = 0x000000007F800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvCorpseSlotName(int16 inv_slot); @@ -276,9 +280,9 @@ namespace Titanium namespace constants { inline EQEmu::versions::ClientVersion GetConstantsRef() { return EQEmu::versions::ClientVersion::Titanium; } - const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::PoR; - const uint32 EXPANSION_BIT = EQEmu::expansions::bitPoR; - const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskPoR; + const EQEmu::expansions::Expansion EXPANSION = EQEmu::expansions::Expansion::DoD; // Someone had this as PoR in another section... + const uint32 EXPANSION_BIT = EQEmu::expansions::bitDoD; + const uint32 EXPANSIONS_MASK = EQEmu::expansions::maskDoD; const size_t CHARACTER_CREATION_LIMIT = 8; // Hard-coded in client - DO NOT ALTER diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index ce1f9c770..87752a91e 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -191,8 +191,12 @@ namespace UF const int16 CORPSE_BEGIN = invslot::slotGeneral1; const int16 CORPSE_END = invslot::slotGeneral1 + invslot::slotCursor; - const uint64 POSSESSIONS_BITMASK = 0x000000027FFFFFFF; // based on 34-slot count (RoF+) - const uint64 CORPSE_BITMASK = 0x01FFFFFE7F800000; // based on 34-slot count (RoF+) + const uint64 EQUIPMENT_BITMASK = 0x00000000007FFFFF; + const uint64 GENERAL_BITMASK = 0x000000007F800000; + const uint64 CURSOR_BITMASK = 0x0000000200000000; + const uint64 POSSESSIONS_BITMASK = (EQUIPMENT_BITMASK | GENERAL_BITMASK | CURSOR_BITMASK); // based on 34-slot count (RoF+) + const uint64 CORPSE_BITMASK = (GENERAL_BITMASK | CURSOR_BITMASK | (EQUIPMENT_BITMASK << 34)); // based on 34-slot count (RoF+) + const char* GetInvPossessionsSlotName(int16 inv_slot); const char* GetInvCorpseSlotName(int16 inv_slot); diff --git a/ucs/ucs.cpp b/ucs/ucs.cpp index 21e525cbe..bd36c47e6 100644 --- a/ucs/ucs.cpp +++ b/ucs/ucs.cpp @@ -116,6 +116,9 @@ int main() { } } + EQEmu::InitializeDynamicLookups(); + Log(Logs::General, Logs::UCS_Server, "Initialized dynamic dictionary entries"); + database.ExpireMail(); if(Config->ChatPort != Config->MailPort) diff --git a/world/client.cpp b/world/client.cpp index fba31d5cd..d439758cf 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -211,7 +211,7 @@ void Client::SendMaxCharCreate() { auto outapp = new EQApplicationPacket(OP_SendMaxCharacters, sizeof(MaxCharacters_Struct)); MaxCharacters_Struct* mc = (MaxCharacters_Struct*)outapp->pBuffer; - mc->max_chars = EQEmu::constants::Lookup(m_ClientVersion)->CharacterCreationLimit; + mc->max_chars = EQEmu::constants::StaticLookup(m_ClientVersion)->CharacterCreationLimit; if (mc->max_chars > EQEmu::constants::CHARACTER_CREATION_LIMIT) mc->max_chars = EQEmu::constants::CHARACTER_CREATION_LIMIT; @@ -765,7 +765,7 @@ bool Client::HandleEnterWorldPacket(const EQApplicationPacket *app) { // This can probably be moved outside and have another method return requested info (don't forget to remove the #include "../common/shareddb.h" above) // (This is a literal translation of the original process..I don't see why it can't be changed to a single-target query over account iteration) if (!is_player_zoning) { - size_t character_limit = EQEmu::constants::Lookup(eqs->ClientVersion())->CharacterCreationLimit; + size_t character_limit = EQEmu::constants::StaticLookup(eqs->ClientVersion())->CharacterCreationLimit; if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) { character_limit = EQEmu::constants::CHARACTER_CREATION_LIMIT; } if (eqs->ClientVersion() == EQEmu::versions::ClientVersion::Titanium) { character_limit = Titanium::constants::CHARACTER_CREATION_LIMIT; } diff --git a/world/net.cpp b/world/net.cpp index 77deec265..c9bdde4b3 100644 --- a/world/net.cpp +++ b/world/net.cpp @@ -348,6 +348,9 @@ int main(int argc, char** argv) { Log(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str()); } } + + EQEmu::InitializeDynamicLookups(); + Log(Logs::General, Logs::World_Server, "Initialized dynamic dictionary entries"); } if (RuleB(World, ClearTempMerchantlist)) { diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 830f0bfc3..59cbb188a 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -36,7 +36,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou { /* Set Character Creation Limit */ EQEmu::versions::ClientVersion client_version = EQEmu::versions::ConvertClientVersionBitToClientVersion(clientVersionBit); - size_t character_limit = EQEmu::constants::Lookup(client_version)->CharacterCreationLimit; + size_t character_limit = EQEmu::constants::StaticLookup(client_version)->CharacterCreationLimit; // Validate against absolute server max if (character_limit > EQEmu::constants::CHARACTER_CREATION_LIMIT) diff --git a/zone/client_mods.cpp b/zone/client_mods.cpp index 299aa3f0b..1f9049262 100644 --- a/zone/client_mods.cpp +++ b/zone/client_mods.cpp @@ -838,7 +838,7 @@ uint32 Client::CalcCurrentWeight() This is the ONLY instance I have seen where the client is hard coded to particular Item IDs to set a certain property for an item. It is very odd. */ // SoD+ client has no weight for coin - if (EQEmu::behavior::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) { + if (EQEmu::behavior::StaticLookup(EQEmu::versions::ConvertClientVersionToMobVersion(ClientVersion()))->CoinHasWeight) { Total += (m_pp.platinum + m_pp.gold + m_pp.silver + m_pp.copper) / 4; } float Packrat = (float)spellbonuses.Packrat + (float)aabonuses.Packrat + (float)itembonuses.Packrat; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 681f6d17a..5ceaa8019 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1374,7 +1374,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::Lookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize.Corpse; + int corpselootlimit = EQEmu::inventory::StaticLookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize.Corpse; for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; diff --git a/zone/net.cpp b/zone/net.cpp index 9e896fead..5dec87474 100644 --- a/zone/net.cpp +++ b/zone/net.cpp @@ -374,6 +374,9 @@ int main(int argc, char** argv) { Log(Logs::General, Logs::Zone_Server, "Loaded default rule set 'default'", tmp.c_str()); } } + + EQEmu::InitializeDynamicLookups(); + Log(Logs::General, Logs::Zone_Server, "Initialized dynamic dictionary entries"); } #ifdef BOTS diff --git a/zone/spells.cpp b/zone/spells.cpp index b6ee17b18..b24d21725 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5619,12 +5619,12 @@ int Client::GetCurrentBuffSlots() const numbuffs++; if (GetLevel() > 74) numbuffs++; - return EQEmu::ClampUpper(numbuffs, EQEmu::constants::Lookup(m_ClientVersion)->LongBuffs); + return EQEmu::ClampUpper(numbuffs, EQEmu::constants::StaticLookup(m_ClientVersion)->LongBuffs); } int Client::GetCurrentSongSlots() const { - return EQEmu::constants::Lookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this + return EQEmu::constants::StaticLookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this } void Client::InitializeBuffSlots() diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index b30c037b7..81e2ee9c4 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3646,7 +3646,7 @@ void ZoneDatabase::LoadBuffs(Client *client) } // We load up to the most our client supports - max_slots = EQEmu::constants::Lookup(client->ClientVersion())->LongBuffs; + max_slots = EQEmu::constants::StaticLookup(client->ClientVersion())->LongBuffs; for (int index = 0; index < max_slots; ++index) { if (!IsValidSpell(buffs[index].spellid)) continue; From 26ed51f32a82e15f9e4e11b5340c9c533e72fb80 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 12 Jan 2019 20:59:27 -0500 Subject: [PATCH 06/38] Fix for linux builds --- common/eq_limits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index aad77efc1..e5aee9c17 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -816,7 +816,7 @@ void EQEmu::inventory::InitializeDynamicLookups() { continue; // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: - inventory_dynamic_lookup_entries[iter] = std::make_unique(new LookupEntry(inventory_static_lookup_entries[iter])); + inventory_dynamic_lookup_entries[iter] = std::unique_ptr(new LookupEntry(inventory_static_lookup_entries[iter])); // clamp affected fields to the lowest standard inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size From 182b7e984350d92e828011e6d56417de6edeed13 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sat, 12 Jan 2019 20:19:21 -0800 Subject: [PATCH 07/38] Small change to gmmove to always force an update --- zone/mob.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/zone/mob.cpp b/zone/mob.cpp index 4ef43c4e0..b193e8bcb 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -1663,15 +1663,10 @@ void Mob::ShowBuffList(Client* client) { } void Mob::GMMove(float x, float y, float z, float heading, bool SendUpdate) { - if (IsCorpse() || (IsClient() && !IsAIControlled())) { - m_Position.x = x; - m_Position.y = y; - m_Position.z = z; - mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); - } - else { - Teleport(glm::vec4(x, y, z, heading)); - } + m_Position.x = x; + m_Position.y = y; + m_Position.z = z; + mMovementManager->SendCommandToClients(this, 0.0, 0.0, 0.0, 0.0, 0, ClientRangeAny); if (IsNPC()) { CastToNPC()->SaveGuardSpot(glm::vec4(x, y, z, heading)); From 703cbc6727c1dd57760754980b839acb7c3641ee Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 15 Jan 2019 00:50:58 -0500 Subject: [PATCH 08/38] Activated per-expansion support for active inventory slot addressing --- changelog.txt | 5 ++ common/eq_limits.cpp | 158 +++++++++++++++++++++++++++++++---- common/eq_limits.h | 3 + common/inventory_profile.cpp | 25 +++--- common/inventory_profile.h | 13 +-- common/patches/rof.cpp | 3 +- common/shareddb.cpp | 9 +- world/client.cpp | 12 ++- world/worlddb.cpp | 3 + zone/bot.cpp | 2 + zone/client.cpp | 1 + zone/client_packet.cpp | 18 +++- zone/corpse.cpp | 2 +- 13 files changed, 209 insertions(+), 45 deletions(-) diff --git a/changelog.txt b/changelog.txt index 51b8821a0..52e6b59de 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 1/15/2019 == +Uleat: Activated per-expansion support for active inventory slot addressing + - Server honors expansions that alter bank size and power source, general9 and general10 slots + - Server honors gm flag behaviors for the active inventory slots of each client + == 1/11/2019 == Uleat: Modified rules system to ignore all runtime modifications of 'World:ExpansionSettings' and 'World:UseClientBasedExpansionSettings' fields. - These fields are no longer allowed to be changed during server runtime through the command system diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index e5aee9c17..299e504a9 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -36,6 +36,7 @@ void EQEmu::InitializeDynamicLookups() { global_dictionary_init = true; } +static std::unique_ptr constants_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount]; static std::unique_ptr constants_dynamic_lookup_entries[EQEmu::versions::ClientVersionCount]; static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu::versions::ClientVersionCount] = { @@ -173,6 +174,15 @@ void EQEmu::constants::InitializeDynamicLookups() { // use static references for now } +const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicGMLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (constants_dynamic_gm_lookup_entries[static_cast(client_version)]) + return constants_dynamic_gm_lookup_entries[static_cast(client_version)].get(); + + return &constants_static_lookup_entries[static_cast(client_version)]; +} + const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicLookup(versions::ClientVersion client_version) { client_version = versions::ValidateClientVersion(client_version); @@ -187,6 +197,7 @@ const EQEmu::constants::LookupEntry* EQEmu::constants::StaticLookup(versions::Cl return &constants_static_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; } +static std::unique_ptr inventory_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount]; static std::unique_ptr inventory_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; static const EQEmu::inventory::LookupEntry inventory_static_lookup_entries[EQEmu::versions::MobVersionCount] = { @@ -797,25 +808,123 @@ void EQEmu::inventory::InitializeDynamicLookups() { return; // Notes: - // Currently, there are only 3 known expansions that affect inventory-related settings in the clients.. - // - Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots - // - Expansion::TBS "The Buried Sea" - toggles slotPowerSource enabled (set) and disabled (clear) - // - Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 enabled (set) and disabled (clear) - // Obviously, the client must support the expansion to allow any (set) condition + // - Currently, there are only 3 known expansions that affect inventory-related settings in the clients.. + // -- Expansion::PoR "Prophecy of Ro" - toggles between 24 (set) and 16 (clear) bank slots + // -- Expansion::TBS "The Buried Sea" - toggles slotPowerSource activated (set) and deactivated (clear) + // -- Expansion::HoT "House of Thule" - toggles slotGeneral9/slotGeneral10 activated (set) and deactivated (clear) + // - Corspe size does not appear to reflect loss of active possessions slots + // - Inspect size does not appear to reflect loss of active equipment slots + // - Bank size is not overridden by GM flag when expansion bit is (clear) + // - Power Source slot is enabled, but not activated, by GM flag when expansion bit is (clear) + // - General9 and General10 slots are activated by GM flag when expansion bit is (clear) + // - Obviously, the client must support the expansion to allow any (set) or override condition - const uint32 current_expansions = RuleI(World, ExpansionSettings); - const uint32 dynamic_check_mask = (EQEmu::expansions::bitPoR | EQEmu::expansions::bitTBS | EQEmu::expansions::bitHoT); // the only known expansions that affect inventory + const uint32 dynamic_check_mask = + ( + EQEmu::expansions::bitPoR | + EQEmu::expansions::bitTBS | + EQEmu::expansions::bitHoT + ); // if all of the above expansion bits are present, then static references will suffice - if ((current_expansions & dynamic_check_mask) == dynamic_check_mask) + if ((dynamic_check_mask & RuleI(World, ExpansionSettings)) == dynamic_check_mask) return; - for (uint32 iter = static_cast(EQEmu::versions::ClientVersion::Unknown); iter <= static_cast(EQEmu::versions::LastClientVersion); ++iter) { - // no need to dynamic this condition since it is the lowest compatibility standard at this time - if (iter <= static_cast(EQEmu::versions::ClientVersion::Titanium)) + // Dynamic GM Lookups (demotive methodology) (client-linked mob versions only) + for (uint32 iter = static_cast(EQEmu::versions::MobVersion::Unknown); iter <= static_cast(EQEmu::versions::LastPCMobVersion); ++iter) { + // no need to dynamic this condition since it is the lowest compatibility standard + if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask) continue; + // only client versions whose supported expansions are affected need to be considered + if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask) + continue; + + // special case gm exclusions based on known behaviors + switch (iter) { + case static_cast(versions::MobVersion::RoF2) : + case static_cast(versions::MobVersion::RoF) : + // if bank size is not altered on these clients, then static will suffice + // (we already know these clients support this expansion...) + if (RuleI(World, ExpansionSettings) & expansions::bitPoR) + continue; + break; + default: + break; + } + // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: + inventory_dynamic_gm_lookup_entries[iter] = std::unique_ptr(new LookupEntry(inventory_static_lookup_entries[iter])); + + inventory_dynamic_gm_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later + inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later + + if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) { + // update bank size + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR) + inventory_dynamic_gm_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; + } + + if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) { + // update power source + switch (iter) { + case versions::bitUF: + case versions::bitSoD: + case versions::bitSoF: + // gm flag does not override expansion-based behavior + // (we already know that only these clients support this behavior) + inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK; + break; + default: + break; + } + } + + if (~RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) { + // update general size + switch (iter) { + case versions::bitUF: + case versions::bitSoD: + case versions::bitSoF: + // gm flag does not override expansion-based behavior + // (we already know that only these clients support this behavior) + inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK; + break; + default: + break; + } + } + + // fixup possessions bitmask + inventory_dynamic_gm_lookup_entries[iter]->PossessionsBitmask = + ( + inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask | + inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask + ); + + // fixup corpse bitmask + inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask = + ( + inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask | + (inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask << 34) + ); + + // expansion-related fields are now updated and all other fields reflect the static entry values + } + + // Dynamic Lookups (promotive methodology) (all mob versions allowed) + for (uint32 iter = static_cast(EQEmu::versions::MobVersion::Unknown); iter <= static_cast(EQEmu::versions::LastPCMobVersion); ++iter) { + // no need to dynamic this condition since it is the lowest compatibility standard + if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask) + continue; + + // only client versions whose supported expansions are affected need to be considered + if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask) + continue; + + // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: inventory_dynamic_lookup_entries[iter] = std::unique_ptr(new LookupEntry(inventory_static_lookup_entries[iter])); // clamp affected fields to the lowest standard @@ -825,19 +934,19 @@ void EQEmu::inventory::InitializeDynamicLookups() { inventory_dynamic_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later inventory_dynamic_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later - if (current_expansions & EQEmu::expansions::bitPoR) { + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) { // update bank size if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR) inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = SoF::invtype::BANK_SIZE; } - if (current_expansions & EQEmu::expansions::bitTBS) { + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) { // update power source if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitTBS) inventory_dynamic_lookup_entries[iter]->EquipmentBitmask = SoF::invslot::EQUIPMENT_BITMASK; } - if (current_expansions & EQEmu::expansions::bitHoT) { + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) { // update general size if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitHoT) inventory_dynamic_lookup_entries[iter]->GeneralBitmask = RoF::invslot::GENERAL_BITMASK; @@ -862,7 +971,16 @@ void EQEmu::inventory::InitializeDynamicLookups() { // expansion-related fields are now updated and all other fields reflect the static entry values } - // only client versions that require a change from their static definitions have been given a dynamic lookup entry + // only client versions that require a change from their static definitions have been given a dynamic (gm) lookup entry +} + +const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicGMLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (inventory_dynamic_gm_lookup_entries[static_cast(mob_version)]) + return inventory_dynamic_gm_lookup_entries[static_cast(mob_version)].get(); + + return &inventory_static_lookup_entries[static_cast(mob_version)]; } const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicLookup(versions::MobVersion mob_version) @@ -879,6 +997,7 @@ const EQEmu::inventory::LookupEntry* EQEmu::inventory::StaticLookup(versions::Mo return &inventory_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } +static std::unique_ptr behavior_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount]; static std::unique_ptr behavior_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; static const EQEmu::behavior::LookupEntry behavior_static_lookup_entries[EQEmu::versions::MobVersionCount] = { @@ -984,6 +1103,15 @@ void EQEmu::behavior::InitializeDynamicLookups() { // use static references for now } +const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicGMLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (behavior_dynamic_gm_lookup_entries[static_cast(mob_version)]) + return behavior_dynamic_gm_lookup_entries[static_cast(mob_version)].get(); + + return &behavior_static_lookup_entries[static_cast(mob_version)]; +} + const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicLookup(versions::MobVersion mob_version) { mob_version = versions::ValidateMobVersion(mob_version); diff --git a/common/eq_limits.h b/common/eq_limits.h index 117b529c4..5a37917cc 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -82,6 +82,7 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version); const LookupEntry* DynamicLookup(versions::ClientVersion client_version); const LookupEntry* StaticLookup(versions::ClientVersion client_version); @@ -178,6 +179,7 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version); const LookupEntry* DynamicLookup(versions::MobVersion mob_version); const LookupEntry* StaticLookup(versions::MobVersion mob_version); @@ -197,6 +199,7 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version); const LookupEntry* DynamicLookup(versions::MobVersion mob_version); const LookupEntry* StaticLookup(versions::MobVersion mob_version); diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 4f9a49448..2fe73ee19 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -119,19 +119,18 @@ EQEmu::InventoryProfile::~InventoryProfile() m_trade.clear(); } -bool EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory_version) { - if (!m_mob_version_set) { - m_mob_version = versions::ValidateMobVersion(inventory_version); - m_lookup = inventory::StaticLookup(m_mob_version); - m_mob_version_set = true; - return true; - } - else { - m_lookup = inventory::StaticLookup(versions::MobVersion::Unknown); - Log(Logs::General, Logs::Error, "InventoryVersion set request after initial set (old: %u, new: %u)", - static_cast(m_mob_version), static_cast(inventory_version)); - return false; - } +void EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory_version) { + m_mob_version = versions::ValidateMobVersion(inventory_version); + SetGMInventory(m_gm_inventory); +} + +void EQEmu::InventoryProfile::SetGMInventory(bool gmi_flag) { + m_gm_inventory = gmi_flag; + + if (m_gm_inventory) + m_lookup = inventory::DynamicGMLookup(m_mob_version); + else + m_lookup = inventory::DynamicLookup(m_mob_version); } void EQEmu::InventoryProfile::CleanDirty() { diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 36cb2b38b..5a19a2550 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -87,15 +87,18 @@ namespace EQEmu InventoryProfile() { m_mob_version = versions::MobVersion::Unknown; - m_mob_version_set = false; + m_gm_inventory = false; m_lookup = inventory::StaticLookup(versions::MobVersion::Unknown); } ~InventoryProfile(); - bool SetInventoryVersion(versions::MobVersion inventory_version); - bool SetInventoryVersion(versions::ClientVersion client_version) { return SetInventoryVersion(versions::ConvertClientVersionToMobVersion(client_version)); } + void SetInventoryVersion(versions::MobVersion inventory_version); + void SetInventoryVersion(versions::ClientVersion client_version) { SetInventoryVersion(versions::ConvertClientVersionToMobVersion(client_version)); } - versions::MobVersion InventoryVersion() { return m_mob_version; } + void SetGMInventory(bool gmi_flag); + bool GMInventory() const { return m_gm_inventory; } + + versions::MobVersion InventoryVersion() const { return m_mob_version; } const inventory::LookupEntry* GetLookup() const { return m_lookup; } @@ -222,7 +225,7 @@ namespace EQEmu private: // Active mob version versions::MobVersion m_mob_version; - bool m_mob_version_set; + bool m_gm_inventory; const inventory::LookupEntry* m_lookup; }; } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index d0fa44773..8d9f5f641 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2334,7 +2334,8 @@ namespace RoF outapp->WriteUInt32(emu->lastlogin); outapp->WriteUInt32(emu->timePlayedMin); outapp->WriteUInt32(emu->timeentitledonaccount); - outapp->WriteUInt32(0x0007ffff); // Expansion bitmask + outapp->WriteUInt32(emu->expansions); + //outapp->WriteUInt32(0x0007ffff); // Expansion bitmask outapp->WriteUInt32(structs::MAX_PP_LANGUAGE); diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 97a071448..46e3a7512 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -720,9 +720,12 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv) if (cv_conflict) { char char_name[64] = ""; GetCharName(char_id, char_name); - Log(Logs::Moderate, Logs::Client_Login, - "ClientVersion conflict during inventory load at zone entry for '%s' (charid: %u, inver: %s)", - char_name, char_id, EQEmu::versions::MobVersionName(inv->InventoryVersion()) + Log(Logs::General, Logs::Error, + "ClientVersion/Expansion conflict during inventory load at zone entry for '%s' (charid: %u, inver: %s, gmi: %s)", + char_name, + char_id, + EQEmu::versions::MobVersionName(inv->InventoryVersion()), + (inv->GMInventory() ? "true" : "false") ); } diff --git a/world/client.cpp b/world/client.cpp index d439758cf..30c57db5d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -171,10 +171,13 @@ void Client::SendEnterWorld(std::string name) void Client::SendExpansionInfo() { auto outapp = new EQApplicationPacket(OP_ExpansionInfo, sizeof(ExpansionInfo_Struct)); ExpansionInfo_Struct *eis = (ExpansionInfo_Struct*)outapp->pBuffer; - if(RuleB(World, UseClientBasedExpansionSettings)) { + + // need to rework .. not until full scope of change is accounted for, though + if (RuleB(World, UseClientBasedExpansionSettings)) { eis->Expansions = EQEmu::expansions::ConvertClientVersionToExpansionMask(eqs->ClientVersion()); - } else { - eis->Expansions = (RuleI(World, ExpansionSettings)); + } + else { + eis->Expansions = RuleI(World, ExpansionSettings); } QueuePacket(outapp); @@ -1442,7 +1445,10 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) PlayerProfile_Struct pp; ExtendedProfile_Struct ext; EQEmu::InventoryProfile inv; + inv.SetInventoryVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)); + inv.SetGMInventory(false); // character cannot have gm flag at this point + time_t bday = time(nullptr); char startzone[50]={0}; uint32 i; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 59cbb188a..4daa7fa77 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -97,7 +97,10 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou CharacterSelectEntry_Struct *cse = (CharacterSelectEntry_Struct *)buff_ptr; PlayerProfile_Struct pp; EQEmu::InventoryProfile inv; + inv.SetInventoryVersion(client_version); + inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support + uint32 character_id = (uint32)atoi(row[0]); uint8 has_home = 0; uint8 has_bind = 0; diff --git a/zone/bot.cpp b/zone/bot.cpp index 5876ebed3..125d933b1 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -39,6 +39,7 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm } m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot); + m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static) _guildRank = 0; _guildId = 0; @@ -113,6 +114,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to auto bot_owner = GetBotOwner(); m_inv.SetInventoryVersion(EQEmu::versions::MobVersion::Bot); + m_inv.SetGMInventory(false); // bot expansions are not currently implemented (defaults to static) _guildRank = 0; _guildId = 0; diff --git a/zone/client.cpp b/zone/client.cpp index 3327f2633..da5430ff7 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2077,6 +2077,7 @@ bool Client::ChangeFirstName(const char* in_firstname, const char* gmname) void Client::SetGM(bool toggle) { m_pp.gm = toggle ? 1 : 0; + m_inv.SetGMInventory((bool)m_pp.gm); Message(13, "You are %s a GM.", m_pp.gm ? "now" : "no longer"); SendAppearancePacket(AT_GM, m_pp.gm); Save(); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7dc36771f..541eb2e81 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1144,8 +1144,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) SetClientVersion(Connection()->ClientVersion()); m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(Connection()->ClientVersion()); - bool siv = m_inv.SetInventoryVersion(m_ClientVersion); - Log(Logs::General, Logs::None, "%s inventory version to %s(%i)", (siv ? "Succeeded in setting" : "Failed to set"), ClientVersionName(m_ClientVersion), m_ClientVersion); + m_inv.SetInventoryVersion(m_ClientVersion); /* Antighost code tmp var is so the search doesnt find this object @@ -1185,7 +1184,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) uint32 cid = CharacterID(); character_id = cid; /* Global character_id reference */ - /* Flush and reload factions */ + /* Flush and reload factions */ database.RemoveTempFactions(this); database.LoadCharacterFactionValues(cid, factionvalues); @@ -1222,6 +1221,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.platinum_shared = database.GetSharedPlatinum(this->AccountID()); database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */ + // set to full support in case they're a gm with items in disabled expansion slots..but, have their gm flag off... + // item loss will occur when they use the 'empty' slots, if this is not done + m_inv.SetGMInventory(true); loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */ database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */ database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */ @@ -1238,7 +1240,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) database.LoadCharacterLeadershipAA(cid, &m_pp); /* Load Character Leadership AA's */ database.LoadCharacterTribute(cid, &m_pp); /* Load CharacterTribute */ - /* Load AdventureStats */ + /* Load AdventureStats */ AdventureStats_Struct as; if (database.GetAdventureStats(cid, &as)) { @@ -1397,6 +1399,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if (m_pp.ldon_points_tak < 0 || m_pp.ldon_points_tak > 2000000000) { m_pp.ldon_points_tak = 0; } if (m_pp.ldon_points_available < 0 || m_pp.ldon_points_available > 2000000000) { m_pp.ldon_points_available = 0; } + // need to rework .. not until full scope of change is accounted for, though if (RuleB(World, UseClientBasedExpansionSettings)) { m_pp.expansions = EQEmu::expansions::ConvertClientVersionToExpansionMask(ClientVersion()); } @@ -1516,6 +1519,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) Bot::LoadAndSpawnAllZonedBots(this); #endif + m_inv.SetGMInventory((bool)m_pp.gm); // set to current gm state for calc CalcBonuses(); if (RuleB(Zone, EnableLoggedOffReplenishments) && time(nullptr) - m_pp.lastlogin >= RuleI(Zone, MinOfflineTimeToReplenishments)) { @@ -1639,6 +1643,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) this is not quite where live sends inventory, they do it after tribute */ if (loaditems) { /* Dont load if a length error occurs */ + if (admin >= minStatusToBeGM) + m_inv.SetGMInventory(true); // set to true to allow expansion-restricted packets through + BulkSendInventoryItems(); /* Send stuff on the cursor which isnt sent in bulk */ for (auto iter = m_inv.cursor_cbegin(); iter != m_inv.cursor_cend(); ++iter) { @@ -1648,6 +1655,9 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) const EQEmu::ItemInstance *inst = *iter; SendItemPacket(EQEmu::invslot::slotCursor, inst, ItemPacketLimbo); } + + // this is kinda hackish atm..this process needs to be realigned to allow a contiguous flow + m_inv.SetGMInventory((bool)m_pp.gm); // reset back to current gm state } /* Task Packets */ diff --git a/zone/corpse.cpp b/zone/corpse.cpp index 5ceaa8019..fbb319cb5 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1374,7 +1374,7 @@ void Corpse::QueryLoot(Client* to) { cur = itemlist.begin(); end = itemlist.end(); - int corpselootlimit = EQEmu::inventory::StaticLookup(EQEmu::versions::ConvertClientVersionToMobVersion(to->ClientVersion()))->InventoryTypeSize.Corpse; + int corpselootlimit = to->GetInv().GetLookup()->InventoryTypeSize.Corpse; for(; cur != end; ++cur) { ServerLootItem_Struct* sitem = *cur; From c9ef66ae2d52c1ec84176792f79af51fc9fa44b2 Mon Sep 17 00:00:00 2001 From: Uleat Date: Tue, 15 Jan 2019 20:11:29 -0500 Subject: [PATCH 09/38] Added note for inventory::InitializeDynamicLookups() [ci skip] --- common/eq_limits.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 299e504a9..d7863fcb9 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -815,7 +815,7 @@ void EQEmu::inventory::InitializeDynamicLookups() { // - Corspe size does not appear to reflect loss of active possessions slots // - Inspect size does not appear to reflect loss of active equipment slots // - Bank size is not overridden by GM flag when expansion bit is (clear) - // - Power Source slot is enabled, but not activated, by GM flag when expansion bit is (clear) + // - Power Source slot is enabled, but not activated, by GM flag when expansion bit is (clear) (RoF+ only) // - General9 and General10 slots are activated by GM flag when expansion bit is (clear) // - Obviously, the client must support the expansion to allow any (set) or override condition From 14a4f58c0b28e98a3d374ebba403969c13530bfa Mon Sep 17 00:00:00 2001 From: "Michael Cook (mackal)" Date: Wed, 16 Jan 2019 13:18:33 -0500 Subject: [PATCH 10/38] Remove duplicate waypoint code from a merge --- zone/waypoints.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index e7b4298d5..60a85449e 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -537,9 +537,6 @@ void NPC::AssignWaypoints(int32 grid) if (wandertype == 1 || wandertype == 2 || wandertype == 5) CalculateNewWaypoint(); - - if (wandertype == 1 || wandertype == 2 || wandertype == 5) - CalculateNewWaypoint(); } void Mob::SendTo(float new_x, float new_y, float new_z) { From 585c6322bf40fe6f2d9d279e104c371a7f88abc0 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Jan 2019 08:24:21 -0500 Subject: [PATCH 11/38] Added 'spells' entry to EQDictionary --- changelog.txt | 3 + common/database_conversions.cpp | 10 +- common/emu_constants.h | 49 ++++++---- common/eq_limits.cpp | 90 +++++++++++++++++ common/eq_limits.h | 28 +++++- common/eq_packet_structs.h | 12 +-- common/patches/rof.cpp | 154 +++++++++++++++--------------- common/patches/rof.h | 18 ---- common/patches/rof2.cpp | 154 +++++++++++++++--------------- common/patches/rof2.h | 18 ---- common/patches/rof2_limits.h | 28 ++++++ common/patches/rof2_structs.h | 7 +- common/patches/rof_limits.h | 28 ++++++ common/patches/rof_structs.h | 7 +- common/patches/sod.cpp | 130 ++++++++++++------------- common/patches/sod.h | 16 ---- common/patches/sod_limits.h | 26 +++++ common/patches/sod_structs.h | 11 +-- common/patches/sof.cpp | 132 ++++++++++++------------- common/patches/sof.h | 17 ---- common/patches/sof_limits.h | 27 ++++++ common/patches/sof_structs.h | 11 +-- common/patches/titanium.cpp | 132 ++++++++++++------------- common/patches/titanium.h | 17 ---- common/patches/titanium_limits.h | 27 ++++++ common/patches/titanium_structs.h | 11 +-- common/patches/uf.cpp | 144 ++++++++++++++-------------- common/patches/uf.h | 18 ---- common/patches/uf_limits.h | 28 ++++++ common/patches/uf_structs.h | 11 +-- world/client.cpp | 4 +- zone/aa.cpp | 4 +- zone/attack.cpp | 4 +- zone/bot.cpp | 20 ++-- zone/bot.h | 12 +-- zone/bot_command.cpp | 2 +- zone/client.cpp | 6 +- zone/client_packet.cpp | 20 ++-- zone/command.cpp | 12 +-- zone/effects.cpp | 6 +- zone/lua_mob.cpp | 22 ++--- zone/merc.cpp | 4 +- zone/mob.cpp | 40 ++++---- zone/mob.h | 16 ++-- zone/mob_ai.cpp | 8 +- zone/perl_mob.cpp | 8 +- zone/questmgr.cpp | 6 +- zone/special_attacks.cpp | 4 +- zone/spell_effects.cpp | 12 +-- zone/spells.cpp | 22 ++--- zone/trap.cpp | 2 +- zone/zonedb.cpp | 8 +- 52 files changed, 891 insertions(+), 715 deletions(-) diff --git a/changelog.txt b/changelog.txt index 52e6b59de..60330e137 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,9 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 1/20/2019 == +Uleat: Added 'spells' entry to EQDictionary + == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing - Server honors expansions that alter bank size and power source, general9 and general10 slots diff --git a/common/database_conversions.cpp b/common/database_conversions.cpp index 0e6c40a6f..9850dfac1 100644 --- a/common/database_conversions.cpp +++ b/common/database_conversions.cpp @@ -217,7 +217,7 @@ namespace Convert { /*0245*/ uint8 guildbanker; /*0246*/ uint8 unknown0246[6]; // /*0252*/ uint32 intoxication; - /*0256*/ uint32 spellSlotRefresh[MAX_PP_REF_MEMSPELL]; //in ms + /*0256*/ uint32 spellSlotRefresh[9]; //in ms /*0292*/ uint32 abilitySlotRefresh; /*0296*/ uint8 haircolor; // Player hair color /*0297*/ uint8 beardcolor; // Player beard color @@ -256,9 +256,9 @@ namespace Convert { /*2505*/ uint8 unknown2541[47]; // ? /*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2580*/ uint8 unknown2616[4]; - /*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; + /*2584*/ uint32 spell_book[480]; /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff - /*4632*/ uint32 mem_spells[MAX_PP_REF_MEMSPELL]; + /*4632*/ uint32 mem_spells[9]; /*4668*/ uint8 unknown4704[32]; // /*4700*/ float y; // Player y position /*4704*/ float x; // Player x position @@ -1360,7 +1360,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Spell Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++){ + for (i = 0; i < 480; i++){ if (pp->spell_book[i] > 0 && pp->spell_book[i] != 4294967295 && pp->spell_book[i] < 40000 && pp->spell_book[i] != 1){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->spell_book[i]); @@ -1372,7 +1372,7 @@ bool Database::CheckDatabaseConvertPPDeblob(){ if (rquery != ""){ results = QueryDatabase(rquery); } /* Run Max Memmed Spell Convert */ first_entry = 0; rquery = ""; - for (i = 0; i < MAX_PP_REF_MEMSPELL; i++){ + for (i = 0; i < 9; i++){ if (pp->mem_spells[i] > 0 && pp->mem_spells[i] != 65535 && pp->mem_spells[i] != 4294967295){ if (first_entry != 1){ rquery = StringFormat("REPLACE INTO `character_memmed_spells` (id, slot_id, spell_id) VALUES (%u, %u, %u)", character_id, i, pp->mem_spells[i]); diff --git a/common/emu_constants.h b/common/emu_constants.h index 805bc6516..9e265753a 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -228,6 +228,34 @@ namespace EQEmu } // namespace behavior + namespace spells { + enum class CastingSlot : uint32 { // hybrid declaration + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + MaxGems = 12, + Ability = 20, // HT/LoH for Tit + PotionBelt = 21, // Tit uses a different slot for PB + Item = 22, + Discipline = 23, + AltAbility = 0xFF + }; + + using RoF2::spells::SPELL_ID_MAX; + using SoD::spells::SPELLBOOK_SIZE; + using UF::spells::SPELL_GEM_COUNT; // RoF+ clients define more than UF client..but, they are not valid beyond UF + + } // namespace spells + namespace bug { enum CategoryID : uint32 { catOther = 0, @@ -259,27 +287,6 @@ namespace EQEmu } // namespace bug - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Gem10 = 9, - Gem11 = 10, - Gem12 = 11, - MaxGems = 12, - Ability = 20, // HT/LoH for Tit - PotionBelt = 21, // Tit uses a different slot for PB - Item = 22, - Discipline = 23, - AltAbility = 0xFF - }; - } /*EQEmu*/ #endif /*COMMON_EMU_CONSTANTS_H*/ diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index d7863fcb9..09ba6712a 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -32,6 +32,7 @@ void EQEmu::InitializeDynamicLookups() { constants::InitializeDynamicLookups(); inventory::InitializeDynamicLookups(); behavior::InitializeDynamicLookups(); + spells::InitializeDynamicLookups(); global_dictionary_init = true; } @@ -1125,3 +1126,92 @@ const EQEmu::behavior::LookupEntry* EQEmu::behavior::StaticLookup(versions::MobV { return &behavior_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } + +static std::unique_ptr spells_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount]; +static std::unique_ptr spells_dynamic_lookup_entries[EQEmu::versions::ClientVersionCount]; +static const EQEmu::spells::LookupEntry spells_static_lookup_entries[EQEmu::versions::ClientVersionCount] = +{ + /*[ClientVersion::Unknown] =*/ + EQEmu::spells::LookupEntry( + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL + ), + /*[ClientVersion::Client62] =*/ + EQEmu::spells::LookupEntry( + Client62::INULL, + Client62::INULL, + Client62::INULL + ), + /*[ClientVersion::Titanium] =*/ + EQEmu::spells::LookupEntry( + Titanium::spells::SPELL_ID_MAX, + Titanium::spells::SPELLBOOK_SIZE, + Titanium::spells::SPELL_GEM_COUNT + ), + /*[ClientVersion::SoF] =*/ + EQEmu::spells::LookupEntry( + SoF::spells::SPELL_ID_MAX, + SoF::spells::SPELLBOOK_SIZE, + SoF::spells::SPELL_GEM_COUNT + ), + /*[ClientVersion::SoD] =*/ + EQEmu::spells::LookupEntry( + SoD::spells::SPELL_ID_MAX, + SoD::spells::SPELLBOOK_SIZE, + SoD::spells::SPELL_GEM_COUNT + ), + /*[ClientVersion::UF] =*/ + EQEmu::spells::LookupEntry( + UF::spells::SPELL_ID_MAX, + SoD::spells::SPELLBOOK_SIZE, + UF::spells::SPELL_GEM_COUNT + ), + /*[ClientVersion::RoF] =*/ + EQEmu::spells::LookupEntry( + RoF::spells::SPELL_ID_MAX, + SoD::spells::SPELLBOOK_SIZE, + UF::spells::SPELL_GEM_COUNT // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + ), + /*[ClientVersion::RoF2] =*/ + EQEmu::spells::LookupEntry( + RoF2::spells::SPELL_ID_MAX, + SoD::spells::SPELLBOOK_SIZE, + UF::spells::SPELL_GEM_COUNT // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + ) +}; + +static bool spells_dictionary_init = false; +void EQEmu::spells::InitializeDynamicLookups() { + if (spells_dictionary_init == true) + return; + spells_dictionary_init = true; + + if (RuleB(World, UseClientBasedExpansionSettings)) + return; + + // use static references for now +} + +const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicGMLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (spells_dynamic_gm_lookup_entries[static_cast(client_version)]) + return spells_dynamic_gm_lookup_entries[static_cast(client_version)].get(); + + return &spells_static_lookup_entries[static_cast(client_version)]; +} + +const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (spells_dynamic_lookup_entries[static_cast(client_version)]) + return spells_dynamic_lookup_entries[static_cast(client_version)].get(); + + return &spells_static_lookup_entries[static_cast(client_version)]; +} + +const EQEmu::spells::LookupEntry* EQEmu::spells::StaticLookup(versions::ClientVersion client_version) +{ + return &spells_static_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; +} diff --git a/common/eq_limits.h b/common/eq_limits.h index 5a37917cc..c27bc1eb8 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -93,7 +93,7 @@ namespace EQEmu // note: 'PossessionsBitmask' needs to be attuned to the client version with the highest number // of possessions slots and 'InventoryTypeSize[typePossessions]' should reflect the same count // with translators adjusting for valid slot indices. Server-side validations will be performed - // against 'PossessionsBitmask' (note: the same applies to Corpse type size and bitmask) + // against 'PossessionsBitmask' (note: the same applies to CorpseBitmask..size is not dependent) struct InventoryTypeSize_Struct { // should reflect count and naming conventions referenced in emu_constants.h int16 Possessions, Bank, SharedBank; @@ -205,6 +205,32 @@ namespace EQEmu } /*behavior*/ + namespace spells { + struct LookupEntry { + int SpellIdMax; + int SpellbookSize; + int SpellGemCount; + + LookupEntry(const LookupEntry *lookup_entry) { } + LookupEntry( + int SpellIdMax, + int SpellbookSize, + int SpellGemCount + ) : + SpellIdMax(SpellIdMax), + SpellbookSize(SpellbookSize), + SpellGemCount(SpellGemCount) + { } + }; + + void InitializeDynamicLookups(); + + const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version); + const LookupEntry* DynamicLookup(versions::ClientVersion client_version); + const LookupEntry* StaticLookup(versions::ClientVersion client_version); + + } /*spells*/ + } /*EQEmu*/ namespace ClientUnknown diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 5ae2c1a93..8e0d4d0d1 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -852,10 +852,6 @@ struct SuspendedMinion_Struct ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 480; // Set for all functions -static const uint32 MAX_PP_MEMSPELL = static_cast(EQEmu::CastingSlot::MaxGems); // Set to latest client so functions can work right -- 12 -static const uint32 MAX_PP_REF_SPELLBOOK = 480; // Set for Player Profile size retain -static const uint32 MAX_PP_REF_MEMSPELL = 9; // Set for Player Profile size retain static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; @@ -935,7 +931,7 @@ struct PlayerProfile_Struct /*0245*/ uint8 guildbanker; /*0246*/ uint8 unknown0246[6]; // /*0252*/ uint32 intoxication; -/*0256*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; //in ms +/*0256*/ uint32 spellSlotRefresh[EQEmu::spells::SPELL_GEM_COUNT]; //in ms /*0292*/ uint32 abilitySlotRefresh; /*0296*/ uint8 haircolor; // Player hair color /*0297*/ uint8 beardcolor; // Player beard color @@ -974,9 +970,9 @@ struct PlayerProfile_Struct /*2505*/ uint8 unknown2541[47]; // ? /*2552*/ uint8 languages[MAX_PP_LANGUAGE]; /*2580*/ uint8 unknown2616[4]; -/*2584*/ uint32 spell_book[MAX_PP_REF_SPELLBOOK]; +/*2584*/ uint32 spell_book[EQEmu::spells::SPELLBOOK_SIZE]; /*4504*/ uint8 unknown4540[128]; // Was [428] all 0xff -/*4632*/ uint32 mem_spells[MAX_PP_MEMSPELL]; +/*4632*/ uint32 mem_spells[EQEmu::spells::SPELL_GEM_COUNT]; /*4668*/ uint8 unknown4704[32]; // /*4700*/ float y; // Player y position /*4704*/ float x; // Player x position @@ -4373,7 +4369,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint32 spell[MAX_PP_MEMSPELL]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 + uint32 spell[EQEmu::spells::SPELL_GEM_COUNT]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 uint32 unknown; //there seems to be an extra field in this packet... }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 8d9f5f641..a539282bf 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -65,8 +65,8 @@ namespace RoF // client to server say link converter static inline void RoFToServerSayLink(std::string& serverSayLink, const std::string& rofSayLink); - static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot); + static inline spells::CastingSlot ServerToRoFCastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot RoFToServerCastingSlot(spells::CastingSlot slot); static inline int ServerToRoFBuffSlot(int index); static inline int RoFToServerBuffSlot(int index); @@ -502,7 +502,7 @@ namespace RoF ENCODE_LENGTH_EXACT(CastSpell_Struct); SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); - eq->slot = static_cast(ServerToRoFCastingSlot(static_cast(emu->slot))); + eq->slot = static_cast(ServerToRoFCastingSlot(static_cast(emu->slot))); OUT(spell_id); eq->inventory_slot = ServerToRoFSlot(emu->inventoryslot); @@ -2124,33 +2124,33 @@ namespace RoF outapp->WriteUInt32(0); } - outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots + outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots - for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++) + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { outapp->WriteUInt32(emu->spell_book[r]); } // zeroes for the rest of the spellbook slots - for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++) + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE; r++) { outapp->WriteUInt32(0xFFFFFFFFU); } - outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots + outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // first 12 + for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) // first 12 { outapp->WriteUInt32(emu->mem_spells[r]); } // zeroes for the rest of the slots -- the other 4 which don't work at all! - for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < spells::SPELL_GEM_COUNT - EQEmu::spells::SPELL_GEM_COUNT; r++) { outapp->WriteUInt32(0xFFFFFFFFU); } outapp->WriteUInt32(13); // gem refresh count - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) { outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh } @@ -4221,7 +4221,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(RoFToServerCastingSlot(static_cast(eq->slot))); + emu->slot = static_cast(RoFToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = RoFToServerSlot(eq->inventory_slot); @@ -4738,7 +4738,7 @@ namespace RoF DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) { if (eq->spell[i] == 0) emu->spell[i] = 0xFFFFFFFF; @@ -6087,80 +6087,80 @@ namespace RoF } } - static inline CastingSlot ServerToRoFCastingSlot(EQEmu::CastingSlot slot) + static inline spells::CastingSlot ServerToRoFCastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Gem10: - return CastingSlot::Gem10; - case EQEmu::CastingSlot::Gem11: - return CastingSlot::Gem11; - case EQEmu::CastingSlot::Gem12: - return CastingSlot::Gem12; - case EQEmu::CastingSlot::Item: - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::Item; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Gem10: + return spells::CastingSlot::Gem10; + case EQEmu::spells::CastingSlot::Gem11: + return spells::CastingSlot::Gem11; + case EQEmu::spells::CastingSlot::Gem12: + return spells::CastingSlot::Gem12; + case EQEmu::spells::CastingSlot::Item: + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot RoFToServerCastingSlot(CastingSlot slot) + static inline EQEmu::spells::CastingSlot RoFToServerCastingSlot(spells::CastingSlot slot) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Gem10: - return EQEmu::CastingSlot::Gem10; - case CastingSlot::Gem11: - return EQEmu::CastingSlot::Gem11; - case CastingSlot::Gem12: - return EQEmu::CastingSlot::Gem12; - case CastingSlot::Discipline: - return EQEmu::CastingSlot::Discipline; - case CastingSlot::Item: - return EQEmu::CastingSlot::Item; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Gem10: + return EQEmu::spells::CastingSlot::Gem10; + case spells::CastingSlot::Gem11: + return EQEmu::spells::CastingSlot::Gem11; + case spells::CastingSlot::Gem12: + return EQEmu::spells::CastingSlot::Gem12; + case spells::CastingSlot::Discipline: + return EQEmu::spells::CastingSlot::Discipline; + case spells::CastingSlot::Item: + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/rof.h b/common/patches/rof.h index 146b34f1f..205998b32 100644 --- a/common/patches/rof.h +++ b/common/patches/rof.h @@ -50,24 +50,6 @@ namespace RoF #include "rof_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Gem10 = 9, - Gem11 = 10, - Gem12 = 11, - Item = 12, - Discipline = 13, - AltAbility = 0xFF - }; - }; /*RoF*/ #endif /*COMMON_ROF_H*/ diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index a062033fc..7aa1411b6 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -65,8 +65,8 @@ namespace RoF2 // client to server say link converter static inline void RoF2ToServerSayLink(std::string &server_saylink, const std::string &rof2_saylink); - static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot); + static inline spells::CastingSlot ServerToRoF2CastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot RoF2ToServerCastingSlot(spells::CastingSlot slot); static inline int ServerToRoF2BuffSlot(int index); static inline int RoF2ToServerBuffSlot(int index); @@ -570,7 +570,7 @@ namespace RoF2 ENCODE_LENGTH_EXACT(CastSpell_Struct); SETUP_DIRECT_ENCODE(CastSpell_Struct, structs::CastSpell_Struct); - eq->slot = static_cast(ServerToRoF2CastingSlot(static_cast(emu->slot))); + eq->slot = static_cast(ServerToRoF2CastingSlot(static_cast(emu->slot))); OUT(spell_id); eq->inventory_slot = ServerToRoF2Slot(emu->inventoryslot); @@ -2200,33 +2200,33 @@ namespace RoF2 outapp->WriteUInt32(0); } - outapp->WriteUInt32(structs::MAX_PP_SPELLBOOK); // Spellbook slots + outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots - for (uint32 r = 0; r < MAX_PP_SPELLBOOK; r++) + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { outapp->WriteUInt32(emu->spell_book[r]); } // zeroes for the rest of the spellbook slots - for (uint32 r = 0; r < structs::MAX_PP_SPELLBOOK - MAX_PP_SPELLBOOK; r++) + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE; r++) { outapp->WriteUInt32(0xFFFFFFFFU); } - outapp->WriteUInt32(structs::MAX_PP_MEMSPELL); // Memorised spell slots + outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) // write first 12 + for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) // write first 12 { outapp->WriteUInt32(emu->mem_spells[r]); } // zeroes for the rest of the slots the other 4, which actually don't work on the client at all :D - for (uint32 r = 0; r < structs::MAX_PP_MEMSPELL - MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < spells::SPELL_GEM_COUNT - EQEmu::spells::SPELL_GEM_COUNT; r++) { outapp->WriteUInt32(0xFFFFFFFFU); } outapp->WriteUInt32(13); // gem refresh counts - for (uint32 r = 0; r < MAX_PP_MEMSPELL; r++) + for (uint32 r = 0; r < EQEmu::spells::SPELL_GEM_COUNT; r++) { outapp->WriteUInt32(emu->spellSlotRefresh[r]); // spell gem refresh } @@ -4460,7 +4460,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(RoF2ToServerCastingSlot(static_cast(eq->slot))); + emu->slot = static_cast(RoF2ToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = RoF2ToServerSlot(eq->inventory_slot); @@ -4976,7 +4976,7 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) { if (eq->spell[i] == 0) emu->spell[i] = 0xFFFFFFFF; @@ -6342,80 +6342,80 @@ namespace RoF2 } } - static inline CastingSlot ServerToRoF2CastingSlot(EQEmu::CastingSlot slot) + static inline spells::CastingSlot ServerToRoF2CastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Gem10: - return CastingSlot::Gem10; - case EQEmu::CastingSlot::Gem11: - return CastingSlot::Gem11; - case EQEmu::CastingSlot::Gem12: - return CastingSlot::Gem12; - case EQEmu::CastingSlot::Item: - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::Item; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Gem10: + return spells::CastingSlot::Gem10; + case EQEmu::spells::CastingSlot::Gem11: + return spells::CastingSlot::Gem11; + case EQEmu::spells::CastingSlot::Gem12: + return spells::CastingSlot::Gem12; + case EQEmu::spells::CastingSlot::Item: + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot RoF2ToServerCastingSlot(CastingSlot slot) + static inline EQEmu::spells::CastingSlot RoF2ToServerCastingSlot(spells::CastingSlot slot) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Gem10: - return EQEmu::CastingSlot::Gem10; - case CastingSlot::Gem11: - return EQEmu::CastingSlot::Gem11; - case CastingSlot::Gem12: - return EQEmu::CastingSlot::Gem12; - case CastingSlot::Discipline: - return EQEmu::CastingSlot::Discipline; - case CastingSlot::Item: - return EQEmu::CastingSlot::Item; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Gem10: + return EQEmu::spells::CastingSlot::Gem10; + case spells::CastingSlot::Gem11: + return EQEmu::spells::CastingSlot::Gem11; + case spells::CastingSlot::Gem12: + return EQEmu::spells::CastingSlot::Gem12; + case spells::CastingSlot::Discipline: + return EQEmu::spells::CastingSlot::Discipline; + case spells::CastingSlot::Item: + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/rof2.h b/common/patches/rof2.h index 4fb94a1d4..9eef8e596 100644 --- a/common/patches/rof2.h +++ b/common/patches/rof2.h @@ -50,24 +50,6 @@ namespace RoF2 #include "rof2_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Gem10 = 9, - Gem11 = 10, - Gem12 = 11, - Item = 12, - Discipline = 13, - AltAbility = 0xFF - }; - }; /*RoF2*/ #endif /*COMMON_ROF2_H*/ diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 3316c01c5..6f741a9bc 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -295,6 +295,34 @@ namespace RoF2 } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF2; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + MaxGems = 16, // fallacy..only 12 slot are useable... + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 45000; + const int SPELLBOOK_SIZE = 720; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*RoF2*/ #endif /*COMMON_ROF2_LIMITS_H*/ diff --git a/common/patches/rof2_structs.h b/common/patches/rof2_structs.h index f53675f83..f36906df0 100644 --- a/common/patches/rof2_structs.h +++ b/common/patches/rof2_structs.h @@ -128,8 +128,7 @@ static const uint32 MAX_NUMBER_GUILDS = 1500; // Used primarily in the Player Profile: static const uint32 MAX_PP_LANGUAGE = 32; // was 25 -static const uint32 MAX_PP_SPELLBOOK = 720; // was 480 -static const uint32 MAX_PP_MEMSPELL = 16; // was 12 + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 300; @@ -1167,9 +1166,9 @@ union /*06092*/ uint32 timestamp2_count; // Seen 100 /*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related? /*06496*/ uint32 spell_book_count; // Seen 720 -/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] +/*06500*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] /*09380*/ uint32 mem_spell_count; // Seen 16 -/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s +/*09384*/ int32 mem_spells[spells::SPELL_GEM_COUNT]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s /*09448*/ uint32 unknown16_count; // Seen 13 /*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related /*09504*/ uint8 unknown_rof17; // Seen 0 or 8 diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index f82e86408..739c19898 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -286,6 +286,34 @@ namespace RoF } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::RoF; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + MaxGems = 16, // fallacy..only 12 slots are useable + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 45000; + const int SPELLBOOK_SIZE = 720; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*RoF*/ #endif /*COMMON_ROF_LIMITS_H*/ diff --git a/common/patches/rof_structs.h b/common/patches/rof_structs.h index 885a9aa80..e9122a156 100644 --- a/common/patches/rof_structs.h +++ b/common/patches/rof_structs.h @@ -128,8 +128,7 @@ static const uint32 MAX_NUMBER_GUILDS = 1500; // Used primarily in the Player Profile: static const uint32 MAX_PP_LANGUAGE = 32; // was 25 -static const uint32 MAX_PP_SPELLBOOK = 720; // was 480 -static const uint32 MAX_PP_MEMSPELL = 16; // was 12 + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 300; @@ -1108,9 +1107,9 @@ union /*06092*/ uint32 timestamp2_count; // Seen 100 /*06096*/ uint32 timestamps2[100]; // Unknown Unix Timestamps - maybe Skill related? /*06496*/ uint32 spell_book_count; // Seen 720 -/*06500*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] +/*06500*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880 bytes] /*09380*/ uint32 mem_spell_count; // Seen 16 -/*09384*/ int32 mem_spells[MAX_PP_MEMSPELL]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s +/*09384*/ int32 mem_spells[spells::SPELL_GEM_COUNT]; // [16] List of spells memorized - First 12 are set or -1 and last 4 are 0s /*09448*/ uint32 unknown16_count; // Seen 13 /*09452*/ uint32 unknown_rof16[13]; // Possibly spell or buff related /*09504*/ uint8 unknown_rof17; // Seen 0 or 8 diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 112312afd..34e724960 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -59,8 +59,8 @@ namespace SoD // client to server say link converter static inline void SoDToServerSayLink(std::string &server_saylink, const std::string &sod_saylink); - static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot); + static inline spells::CastingSlot ServerToSoDCastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot SoDToServerCastingSlot(spells::CastingSlot slot); static inline int ServerToSoDBuffSlot(int index); static inline int SoDToServerBuffSlot(int index); @@ -1452,7 +1452,7 @@ namespace SoD } OUT(deity); OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); OUT(abilitySlotRefresh); OUT(points); // Relocation Test // OUT(unknown0166[4]); @@ -1492,9 +1492,9 @@ namespace SoD OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + OUT_array(spell_book, spells::SPELLBOOK_SIZE); // OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); OUT(platinum); OUT(gold); @@ -2842,7 +2842,7 @@ namespace SoD DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(SoDToServerCastingSlot(static_cast(eq->slot))); + emu->slot = static_cast(SoDToServerCastingSlot(static_cast(eq->slot))); IN(slot); IN(spell_id); emu->inventoryslot = SoDToServerSlot(eq->inventoryslot); @@ -3136,9 +3136,9 @@ namespace SoD DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) + for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i) emu->spell[i] = eq->spell[i]; - for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) emu->spell[i] = 0xFFFFFFFF; FINISH_DIRECT_DECODE(); @@ -4021,72 +4021,72 @@ namespace SoD } } - static inline CastingSlot ServerToSoDCastingSlot(EQEmu::CastingSlot slot) + static inline spells::CastingSlot ServerToSoDCastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Gem10: - return CastingSlot::Gem10; - case EQEmu::CastingSlot::Item: - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::Item; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Gem10: + return spells::CastingSlot::Gem10; + case EQEmu::spells::CastingSlot::Item: + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot SoDToServerCastingSlot(CastingSlot slot) + static inline EQEmu::spells::CastingSlot SoDToServerCastingSlot(spells::CastingSlot slot) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Gem10: - return EQEmu::CastingSlot::Gem10; - case CastingSlot::Discipline: - return EQEmu::CastingSlot::Discipline; - case CastingSlot::Item: - return EQEmu::CastingSlot::Item; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Gem10: + return EQEmu::spells::CastingSlot::Gem10; + case spells::CastingSlot::Discipline: + return EQEmu::spells::CastingSlot::Discipline; + case spells::CastingSlot::Item: + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/sod.h b/common/patches/sod.h index 5c29e36c0..977645231 100644 --- a/common/patches/sod.h +++ b/common/patches/sod.h @@ -50,22 +50,6 @@ namespace SoD #include "sod_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Gem10 = 9, - Item = 10, - Discipline = 11, - AltAbility = 0xFF - }; - }; /*SoD*/ #endif /*COMMON_SOD_H*/ diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index c883524e7..a26075cdb 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -313,6 +313,32 @@ namespace SoD } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoD; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + MaxGems = 10, + Item = 10, + Discipline = 11, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 23000; + const int SPELLBOOK_SIZE = 480; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*SoD*/ #endif /*COMMON_SOD_LIMITS_H*/ diff --git a/common/patches/sod_structs.h b/common/patches/sod_structs.h index 57e37c957..0d201e13a 100644 --- a/common/patches/sod_structs.h +++ b/common/patches/sod_structs.h @@ -815,8 +815,7 @@ struct BindStruct { ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 25; // -static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now -static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 300; //was 299 @@ -885,7 +884,7 @@ struct PlayerProfile_Struct /*00060*/ BindStruct binds[5]; // Bind points (primary is first) /*00160*/ uint32 deity; // deity /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) -/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each +/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each /*00208*/ uint32 abilitySlotRefresh; /*00212*/ uint8 haircolor; // Player hair color /*00213*/ uint8 beardcolor; // Player beard color @@ -911,9 +910,9 @@ struct PlayerProfile_Struct /*04172*/ uint8 unknown04172[28]; // /*04200*/ uint8 face; // Player face /*04201*/ uint8 unknown02264[147]; // was [175] -/*04348*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 480 = 60 pages [1920] +/*04348*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages [1920] /*06268*/ uint8 unknown4184[128]; // was [164] Seen -1 -/*06396*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized +/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized /*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*06464*/ uint32 platinum; // Platinum Pieces on player /*06468*/ uint32 gold; // Gold Pieces on player @@ -3846,7 +3845,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint32 spell[MAX_PP_MEMSPELL]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 + uint32 spell[spells::SPELL_GEM_COUNT]; // 0xFFFFFFFF if no action, slot number if to unmem starting at 0 uint32 unknown; //there seems to be an extra field in this packet... }; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 52af1244f..1b1d9dc28 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -59,8 +59,8 @@ namespace SoF // client to server say link converter static inline void SoFToServerSayLink(std::string &server_saylink, const std::string &sof_saylink); - static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 item_location); + static inline spells::CastingSlot ServerToSoFCastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot SoFToServerCastingSlot(spells::CastingSlot slot, uint32 item_location); static inline int ServerToSoFBuffSlot(int index); static inline int SoFToServerBuffSlot(int index); @@ -956,7 +956,7 @@ namespace SoF // Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case if (emu->scribing == 3) - eq->slot = static_cast(ServerToSoFCastingSlot(static_cast(emu->slot))); + eq->slot = static_cast(ServerToSoFCastingSlot(static_cast(emu->slot))); else OUT(slot); OUT(spell_id); @@ -1116,7 +1116,7 @@ namespace SoF } OUT(deity); OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); OUT(abilitySlotRefresh); OUT(points); // Relocation Test // OUT(unknown0166[4]); @@ -1156,9 +1156,9 @@ namespace SoF OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + OUT_array(spell_book, spells::SPELLBOOK_SIZE); // OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); OUT(platinum); OUT(gold); @@ -2298,7 +2298,7 @@ namespace SoF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(SoFToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); + emu->slot = static_cast(SoFToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); IN(spell_id); emu->inventoryslot = SoFToServerSlot(eq->inventoryslot); IN(target_id); @@ -2540,9 +2540,9 @@ namespace SoF DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) + for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i) IN(spell[i]); - for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) emu->spell[i] = 0xFFFFFFFF; IN(unknown); @@ -3419,73 +3419,73 @@ namespace SoF } } - static inline CastingSlot ServerToSoFCastingSlot(EQEmu::CastingSlot slot) { + static inline spells::CastingSlot ServerToSoFCastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Item: - return CastingSlot::Item; - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::PotionBelt; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Item: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::PotionBelt; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot SoFToServerCastingSlot(CastingSlot slot, uint32 item_location) { + static inline EQEmu::spells::CastingSlot SoFToServerCastingSlot(spells::CastingSlot slot, uint32 item_location) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Ability: - return EQEmu::CastingSlot::Ability; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Ability: + return EQEmu::spells::CastingSlot::Ability; // Tit uses 10 for item and discipline casting, but items have a valid location - case CastingSlot::Item: + case spells::CastingSlot::Item: if (item_location == INVALID_INDEX) - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; else - return EQEmu::CastingSlot::Item; - case CastingSlot::PotionBelt: - return EQEmu::CastingSlot::PotionBelt; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::PotionBelt: + return EQEmu::spells::CastingSlot::PotionBelt; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/sof.h b/common/patches/sof.h index 47c023471..dde55f9a3 100644 --- a/common/patches/sof.h +++ b/common/patches/sof.h @@ -50,23 +50,6 @@ namespace SoF #include "sof_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Ability = 9, - Item = 10, - Discipline = 10, - PotionBelt = 11, - AltAbility = 0xFF - }; - }; /*SoF*/ #endif /*COMMON_SOF_H*/ diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 5f8922148..8f682c8c1 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -313,6 +313,33 @@ namespace SoF } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::SoF; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + MaxGems = 9, + Ability = 9, + Item = 10, + Discipline = 10, + PotionBelt = 11, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 15999; + const int SPELLBOOK_SIZE = 480; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*SoF*/ #endif /*COMMON_SOF_LIMITS_H*/ diff --git a/common/patches/sof_structs.h b/common/patches/sof_structs.h index 527341c93..93b185e23 100644 --- a/common/patches/sof_structs.h +++ b/common/patches/sof_structs.h @@ -816,8 +816,7 @@ struct BindStruct { ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 25; // -static const uint32 MAX_PP_SPELLBOOK = 480; // Confirmed 60 pages on Live now -static const uint32 MAX_PP_MEMSPELL = 10; //was 9 now 10 on Live + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 300; //was 299 @@ -886,7 +885,7 @@ struct PlayerProfile_Struct //23576 Octets /*00060*/ BindStruct binds[5]; // Bind points (primary is first) /*00160*/ uint32 deity; // deity /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) -/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each +/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each /*00208*/ uint32 abilitySlotRefresh; /*00212*/ uint8 haircolor; // Player hair color /*00213*/ uint8 beardcolor; // Player beard color @@ -911,9 +910,9 @@ struct PlayerProfile_Struct //23576 Octets /*04168*/ uint32 WIS; // Wisdom - 46 00 00 00 - 70 /*04172*/ uint8 face; // Player face /*04173*/ uint8 unknown02264[147]; // was [139] -/*04312*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 480 = 60 pages +/*04312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 480 = 60 pages /*06232*/ uint8 unknown4184[128]; // was [136] -/*06396*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized +/*06396*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized /*06436*/ uint8 unknown04396[28]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*06464*/ uint32 platinum; // Platinum Pieces on player /*06468*/ uint32 gold; // Gold Pieces on player @@ -3769,7 +3768,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint32 spell[MAX_PP_MEMSPELL]; + uint32 spell[spells::SPELL_GEM_COUNT]; uint32 unknown; }; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 2a1345ad0..05357e3af 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -58,8 +58,8 @@ namespace Titanium // client to server say link converter static inline void TitaniumToServerSayLink(std::string &server_saylink, const std::string &titanium_saylink); - static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 item_location); + static inline spells::CastingSlot ServerToTitaniumCastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot TitaniumToServerCastingSlot(spells::CastingSlot slot, uint32 item_location); static inline int ServerToTitaniumBuffSlot(int index); static inline int TitaniumToServerBuffSlot(int index); @@ -890,7 +890,7 @@ namespace Titanium // Since HT/LoH are translated up, we need to translate down only for memSpellSpellbar case if (emu->scribing == 3) - eq->slot = static_cast(ServerToTitaniumCastingSlot(static_cast(emu->slot))); + eq->slot = static_cast(ServerToTitaniumCastingSlot(static_cast(emu->slot))); else OUT(slot); OUT(spell_id); @@ -981,7 +981,7 @@ namespace Titanium } OUT(deity); OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); OUT(abilitySlotRefresh); OUT(haircolor); OUT(beardcolor); @@ -1012,9 +1012,9 @@ namespace Titanium OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, structs::MAX_PP_SPELLBOOK); + OUT_array(spell_book, spells::SPELLBOOK_SIZE); // OUT(unknown4184[448]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); OUT(platinum); OUT(gold); @@ -1815,7 +1815,7 @@ namespace Titanium DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(TitaniumToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); + emu->slot = static_cast(TitaniumToServerCastingSlot(static_cast(eq->slot), eq->inventoryslot)); IN(spell_id); emu->inventoryslot = TitaniumToServerSlot(eq->inventoryslot); IN(target_id); @@ -2003,9 +2003,9 @@ namespace Titanium DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (int i = 0; i < structs::MAX_PP_MEMSPELL; ++i) + for (int i = 0; i < spells::SPELL_GEM_COUNT; ++i) IN(spell[i]); - for (int i = structs::MAX_PP_MEMSPELL; i < MAX_PP_MEMSPELL; ++i) + for (int i = spells::SPELL_GEM_COUNT; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) emu->spell[i] = 0xFFFFFFFF; IN(unknown); @@ -2721,73 +2721,73 @@ namespace Titanium } } - static inline CastingSlot ServerToTitaniumCastingSlot(EQEmu::CastingSlot slot) { + static inline spells::CastingSlot ServerToTitaniumCastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Item: - return CastingSlot::Item; - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::PotionBelt; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Item: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::PotionBelt; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot TitaniumToServerCastingSlot(CastingSlot slot, uint32 item_location) { + static inline EQEmu::spells::CastingSlot TitaniumToServerCastingSlot(spells::CastingSlot slot, uint32 item_location) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Ability: - return EQEmu::CastingSlot::Ability; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Ability: + return EQEmu::spells::CastingSlot::Ability; // Tit uses 10 for item and discipline casting, but items have a valid location - case CastingSlot::Item: + case spells::CastingSlot::Item: if (item_location == INVALID_INDEX) - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; else - return EQEmu::CastingSlot::Item; - case CastingSlot::PotionBelt: - return EQEmu::CastingSlot::PotionBelt; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::PotionBelt: + return EQEmu::spells::CastingSlot::PotionBelt; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/titanium.h b/common/patches/titanium.h index ea68dd59a..2f063c9ad 100644 --- a/common/patches/titanium.h +++ b/common/patches/titanium.h @@ -50,23 +50,6 @@ namespace Titanium #include "titanium_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Ability = 9, - Item = 10, - Discipline = 10, - PotionBelt = 11, - AltAbility = 0xFF - }; - }; /*Titanium*/ #endif /*COMMON_TITANIUM_H*/ diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 77aab1c49..28eb414e3 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -312,6 +312,33 @@ namespace Titanium } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::Titanium; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + MaxGems = 9, + Ability = 9, + Item = 10, + Discipline = 10, + PotionBelt = 11, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 9999; + const int SPELLBOOK_SIZE = 400; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*Titanium*/ #endif /*COMMON_TITANIUM_LIMITS_H*/ diff --git a/common/patches/titanium_structs.h b/common/patches/titanium_structs.h index 8cf202e31..6ffee7ddf 100644 --- a/common/patches/titanium_structs.h +++ b/common/patches/titanium_structs.h @@ -754,8 +754,7 @@ struct BindStruct { ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 28; -static const uint32 MAX_PP_SPELLBOOK = 400; -static const uint32 MAX_PP_MEMSPELL = 9; + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 240; @@ -824,7 +823,7 @@ struct PlayerProfile_Struct /*00024*/ BindStruct binds[5]; // Bind points (primary is first) /*00124*/ uint32 deity; // deity /*00128*/ uint32 intoxication; // Alcohol level (in ticks till sober?) -/*00132*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) +/*00132*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) /*00168*/ uint32 abilitySlotRefresh; /*00172*/ uint8 haircolor; // Player hair color /*00173*/ uint8 beardcolor; // Player beard color @@ -849,9 +848,9 @@ struct PlayerProfile_Struct /*02260*/ uint32 WIS; // Wisdom /*02264*/ uint8 face; // Player face /*02265*/ uint8 unknown02264[47]; -/*02312*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook +/*02312*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook /*03912*/ uint8 unknown4184[448]; // all 0xff after last spell -/*04360*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized +/*04360*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized /*04396*/ uint8 unknown04396[32]; /*04428*/ uint32 platinum; // Platinum Pieces on player /*04432*/ uint32 gold; // Gold Pieces on player @@ -3271,7 +3270,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint32 spell[MAX_PP_MEMSPELL]; + uint32 spell[spells::SPELL_GEM_COUNT]; uint32 unknown; }; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index b199197a2..47d6bb4ff 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -59,8 +59,8 @@ namespace UF // client to server say link converter static inline void UFToServerSayLink(std::string& serverSayLink, const std::string& ufSayLink); - static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot); - static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot); + static inline spells::CastingSlot ServerToUFCastingSlot(EQEmu::spells::CastingSlot slot); + static inline EQEmu::spells::CastingSlot UFToServerCastingSlot(spells::CastingSlot slot); static inline int ServerToUFBuffSlot(int index); static inline int UFToServerBuffSlot(int index); @@ -1682,7 +1682,7 @@ namespace UF } OUT(deity); OUT(intoxication); - OUT_array(spellSlotRefresh, structs::MAX_PP_MEMSPELL); + OUT_array(spellSlotRefresh, spells::SPELL_GEM_COUNT); OUT(abilitySlotRefresh); OUT(points); // Relocation Test // OUT(unknown0166[4]); @@ -1724,10 +1724,10 @@ namespace UF OUT(WIS); OUT(face); // OUT(unknown02264[47]); - memset(eq->spell_book, 0xFF, sizeof(uint32)* structs::MAX_PP_SPELLBOOK); + memset(eq->spell_book, 0xFF, sizeof(uint32)* spells::SPELLBOOK_SIZE); OUT_array(spell_book, 480U); // OUT(unknown4184[128]); - OUT_array(mem_spells, structs::MAX_PP_MEMSPELL); + OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); OUT(platinum); OUT(gold); @@ -3142,7 +3142,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::CastSpell_Struct); SETUP_DIRECT_DECODE(CastSpell_Struct, structs::CastSpell_Struct); - emu->slot = static_cast(UFToServerCastingSlot(static_cast(eq->slot))); + emu->slot = static_cast(UFToServerCastingSlot(static_cast(eq->slot))); IN(spell_id); emu->inventoryslot = UFToServerSlot(eq->inventoryslot); @@ -3491,7 +3491,7 @@ namespace UF DECODE_LENGTH_EXACT(structs::LoadSpellSet_Struct); SETUP_DIRECT_DECODE(LoadSpellSet_Struct, structs::LoadSpellSet_Struct); - for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) if (eq->spell[i] == 0) emu->spell[i] = 0xFFFFFFFF; else @@ -4380,80 +4380,80 @@ namespace UF } } - static inline CastingSlot ServerToUFCastingSlot(EQEmu::CastingSlot slot) + static inline spells::CastingSlot ServerToUFCastingSlot(EQEmu::spells::CastingSlot slot) { switch (slot) { - case EQEmu::CastingSlot::Gem1: - return CastingSlot::Gem1; - case EQEmu::CastingSlot::Gem2: - return CastingSlot::Gem2; - case EQEmu::CastingSlot::Gem3: - return CastingSlot::Gem3; - case EQEmu::CastingSlot::Gem4: - return CastingSlot::Gem4; - case EQEmu::CastingSlot::Gem5: - return CastingSlot::Gem5; - case EQEmu::CastingSlot::Gem6: - return CastingSlot::Gem6; - case EQEmu::CastingSlot::Gem7: - return CastingSlot::Gem7; - case EQEmu::CastingSlot::Gem8: - return CastingSlot::Gem8; - case EQEmu::CastingSlot::Gem9: - return CastingSlot::Gem9; - case EQEmu::CastingSlot::Gem10: - return CastingSlot::Gem10; - case EQEmu::CastingSlot::Gem11: - return CastingSlot::Gem11; - case EQEmu::CastingSlot::Gem12: - return CastingSlot::Gem12; - case EQEmu::CastingSlot::Item: - case EQEmu::CastingSlot::PotionBelt: - return CastingSlot::Item; - case EQEmu::CastingSlot::Discipline: - return CastingSlot::Discipline; - case EQEmu::CastingSlot::AltAbility: - return CastingSlot::AltAbility; + case EQEmu::spells::CastingSlot::Gem1: + return spells::CastingSlot::Gem1; + case EQEmu::spells::CastingSlot::Gem2: + return spells::CastingSlot::Gem2; + case EQEmu::spells::CastingSlot::Gem3: + return spells::CastingSlot::Gem3; + case EQEmu::spells::CastingSlot::Gem4: + return spells::CastingSlot::Gem4; + case EQEmu::spells::CastingSlot::Gem5: + return spells::CastingSlot::Gem5; + case EQEmu::spells::CastingSlot::Gem6: + return spells::CastingSlot::Gem6; + case EQEmu::spells::CastingSlot::Gem7: + return spells::CastingSlot::Gem7; + case EQEmu::spells::CastingSlot::Gem8: + return spells::CastingSlot::Gem8; + case EQEmu::spells::CastingSlot::Gem9: + return spells::CastingSlot::Gem9; + case EQEmu::spells::CastingSlot::Gem10: + return spells::CastingSlot::Gem10; + case EQEmu::spells::CastingSlot::Gem11: + return spells::CastingSlot::Gem11; + case EQEmu::spells::CastingSlot::Gem12: + return spells::CastingSlot::Gem12; + case EQEmu::spells::CastingSlot::Item: + case EQEmu::spells::CastingSlot::PotionBelt: + return spells::CastingSlot::Item; + case EQEmu::spells::CastingSlot::Discipline: + return spells::CastingSlot::Discipline; + case EQEmu::spells::CastingSlot::AltAbility: + return spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return CastingSlot::Discipline; + return spells::CastingSlot::Discipline; } } - static inline EQEmu::CastingSlot UFToServerCastingSlot(CastingSlot slot) + static inline EQEmu::spells::CastingSlot UFToServerCastingSlot(spells::CastingSlot slot) { switch (slot) { - case CastingSlot::Gem1: - return EQEmu::CastingSlot::Gem1; - case CastingSlot::Gem2: - return EQEmu::CastingSlot::Gem2; - case CastingSlot::Gem3: - return EQEmu::CastingSlot::Gem3; - case CastingSlot::Gem4: - return EQEmu::CastingSlot::Gem4; - case CastingSlot::Gem5: - return EQEmu::CastingSlot::Gem5; - case CastingSlot::Gem6: - return EQEmu::CastingSlot::Gem6; - case CastingSlot::Gem7: - return EQEmu::CastingSlot::Gem7; - case CastingSlot::Gem8: - return EQEmu::CastingSlot::Gem8; - case CastingSlot::Gem9: - return EQEmu::CastingSlot::Gem9; - case CastingSlot::Gem10: - return EQEmu::CastingSlot::Gem10; - case CastingSlot::Gem11: - return EQEmu::CastingSlot::Gem11; - case CastingSlot::Gem12: - return EQEmu::CastingSlot::Gem12; - case CastingSlot::Discipline: - return EQEmu::CastingSlot::Discipline; - case CastingSlot::Item: - return EQEmu::CastingSlot::Item; - case CastingSlot::AltAbility: - return EQEmu::CastingSlot::AltAbility; + case spells::CastingSlot::Gem1: + return EQEmu::spells::CastingSlot::Gem1; + case spells::CastingSlot::Gem2: + return EQEmu::spells::CastingSlot::Gem2; + case spells::CastingSlot::Gem3: + return EQEmu::spells::CastingSlot::Gem3; + case spells::CastingSlot::Gem4: + return EQEmu::spells::CastingSlot::Gem4; + case spells::CastingSlot::Gem5: + return EQEmu::spells::CastingSlot::Gem5; + case spells::CastingSlot::Gem6: + return EQEmu::spells::CastingSlot::Gem6; + case spells::CastingSlot::Gem7: + return EQEmu::spells::CastingSlot::Gem7; + case spells::CastingSlot::Gem8: + return EQEmu::spells::CastingSlot::Gem8; + case spells::CastingSlot::Gem9: + return EQEmu::spells::CastingSlot::Gem9; + case spells::CastingSlot::Gem10: + return EQEmu::spells::CastingSlot::Gem10; + case spells::CastingSlot::Gem11: + return EQEmu::spells::CastingSlot::Gem11; + case spells::CastingSlot::Gem12: + return EQEmu::spells::CastingSlot::Gem12; + case spells::CastingSlot::Discipline: + return EQEmu::spells::CastingSlot::Discipline; + case spells::CastingSlot::Item: + return EQEmu::spells::CastingSlot::Item; + case spells::CastingSlot::AltAbility: + return EQEmu::spells::CastingSlot::AltAbility; default: // we shouldn't have any issues with other slots ... just return something - return EQEmu::CastingSlot::Discipline; + return EQEmu::spells::CastingSlot::Discipline; } } diff --git a/common/patches/uf.h b/common/patches/uf.h index 1dc5046c3..c36d9e851 100644 --- a/common/patches/uf.h +++ b/common/patches/uf.h @@ -50,24 +50,6 @@ namespace UF #include "uf_ops.h" }; - enum class CastingSlot : uint32 { - Gem1 = 0, - Gem2 = 1, - Gem3 = 2, - Gem4 = 3, - Gem5 = 4, - Gem6 = 5, - Gem7 = 6, - Gem8 = 7, - Gem9 = 8, - Gem10 = 9, - Gem11 = 10, - Gem12 = 11, - Item = 12, - Discipline = 13, - AltAbility = 0xFF - }; - }; /*UF*/ #endif /*COMMON_UF_H*/ diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 87752a91e..5f5d5e199 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -314,6 +314,34 @@ namespace UF } /*skills*/ + namespace spells { + inline EQEmu::versions::ClientVersion GetSkillsRef() { return EQEmu::versions::ClientVersion::UF; } + + enum class CastingSlot : uint32 { + Gem1 = 0, + Gem2 = 1, + Gem3 = 2, + Gem4 = 3, + Gem5 = 4, + Gem6 = 5, + Gem7 = 6, + Gem8 = 7, + Gem9 = 8, + Gem10 = 9, + Gem11 = 10, + Gem12 = 11, + MaxGems = 12, + Item = 12, + Discipline = 13, + AltAbility = 0xFF + }; + + const int SPELL_ID_MAX = 28000; + const int SPELLBOOK_SIZE = 720; + const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + + } /*spells*/ + }; /*UF*/ #endif /*COMMON_UF_LIMITS_H*/ diff --git a/common/patches/uf_structs.h b/common/patches/uf_structs.h index fe58b73b2..8e3309734 100644 --- a/common/patches/uf_structs.h +++ b/common/patches/uf_structs.h @@ -845,8 +845,7 @@ struct BindStruct { ** OpCode: 0x006a */ static const uint32 MAX_PP_LANGUAGE = 25; // -static const uint32 MAX_PP_SPELLBOOK = 720; // Confirmed 60 pages on Underfoot now -static const uint32 MAX_PP_MEMSPELL = 12; //was 9 now 10 on Underfoot + static const uint32 MAX_PP_SKILL = PACKET_SKILL_ARRAY_SIZE; // 100 - actual skills buffer size static const uint32 MAX_PP_INNATE_SKILL = 25; static const uint32 MAX_PP_AA_ARRAY = 300; //was 299 @@ -916,7 +915,7 @@ struct PlayerProfile_Struct /*00060*/ BindStruct binds[5]; // Bind points (primary is first) /*00160*/ uint32 deity; // deity /*00164*/ uint32 intoxication; // Alcohol level (in ticks till sober?) -/*00168*/ uint32 spellSlotRefresh[MAX_PP_MEMSPELL]; // Refresh time (millis) - 4 Octets Each +/*00168*/ uint32 spellSlotRefresh[spells::SPELL_GEM_COUNT]; // Refresh time (millis) - 4 Octets Each /*00208*/ uint8 unknown00208[6]; // Seen 00 00 00 00 00 00 00 00 00 00 00 00 02 01 /*00222*/ uint32 abilitySlotRefresh; /*00226*/ uint8 haircolor; // Player hair color @@ -943,8 +942,8 @@ struct PlayerProfile_Struct /*04188*/ uint8 unknown04188[28]; // /*04216*/ uint8 face; // Player face - Actually uint32? /*04217*/ uint8 unknown04217[147]; // was [175] -/*04364*/ uint32 spell_book[MAX_PP_SPELLBOOK]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920] -/*07244*/ uint32 mem_spells[MAX_PP_MEMSPELL]; // List of spells memorized +/*04364*/ uint32 spell_book[spells::SPELLBOOK_SIZE]; // List of the Spells in spellbook 720 = 90 pages [2880] was [1920] +/*07244*/ uint32 mem_spells[spells::SPELL_GEM_COUNT]; // List of spells memorized /*07284*/ uint8 unknown07284[20]; //#### uint8 unknown04396[32]; in Titanium ####[28] /*07312*/ uint32 platinum; // Platinum Pieces on player /*07316*/ uint32 gold; // Gold Pieces on player @@ -3907,7 +3906,7 @@ struct AnnoyingZoneUnknown_Struct { }; struct LoadSpellSet_Struct { - uint8 spell[MAX_PP_MEMSPELL]; // 0 if no action + uint8 spell[spells::SPELL_GEM_COUNT]; // 0 if no action uint32 unknown; // there seems to be an extra field in this packet... }; diff --git a/world/client.cpp b/world/client.cpp index 30c57db5d..822b648b6 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1529,10 +1529,10 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) // strcpy(pp.servername, WorldConfig::get()->ShortName.c_str()); - for (i = 0; i < MAX_PP_REF_SPELLBOOK; i++) + for (i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) pp.spell_book[i] = 0xFFFFFFFF; - for(i = 0; i < MAX_PP_MEMSPELL; i++) + for(i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) pp.mem_spells[i] = 0xFFFFFFFF; for(i = 0; i < BUFF_COUNT; i++) diff --git a/zone/aa.cpp b/zone/aa.cpp index dfbf9de12..48ee715f7 100644 --- a/zone/aa.cpp +++ b/zone/aa.cpp @@ -1221,12 +1221,12 @@ void Client::ActivateAlternateAdvancementAbility(int rank_id, int target_id) { // Bards can cast instant cast AAs while they are casting another song if(spells[rank->spell].cast_time == 0 && GetClass() == BARD && IsBardSong(casting_spell_id)) { - if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { + if(!SpellFinished(rank->spell, entity_list.GetMob(target_id), EQEmu::spells::CastingSlot::AltAbility, spells[rank->spell].mana, -1, spells[rank->spell].ResistDiff, false)) { return; } ExpendAlternateAdvancementCharge(ability->id); } else { - if(!CastSpell(rank->spell, target_id, EQEmu::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { + if(!CastSpell(rank->spell, target_id, EQEmu::spells::CastingSlot::AltAbility, -1, -1, 0, -1, rank->spell_type + pTimerAAStart, cooldown, nullptr, rank->id)) { return; } } diff --git a/zone/attack.cpp b/zone/attack.cpp index 4c13f6362..483cce368 100644 --- a/zone/attack.cpp +++ b/zone/attack.cpp @@ -1526,7 +1526,7 @@ bool Client::Attack(Mob* other, int Hand, bool bRiposte, bool IsStrikethrough, b IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } other->Damage(this, my_hit.damage_done, SPELL_UNKNOWN, my_hit.skill, true, -1, false, m_specialattacks); @@ -2130,7 +2130,7 @@ void NPC::Damage(Mob* other, int32 damage, uint16 spell_id, EQEmu::skills::Skill if (IsLDoNTrapped()) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); + SpellFinished(GetLDoNTrapSpellID(), other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[GetLDoNTrapSpellID()].ResistDiff, false); SetLDoNTrapSpellID(0); SetLDoNTrapped(false); SetLDoNTrapDetected(false); diff --git a/zone/bot.cpp b/zone/bot.cpp index 125d933b1..4076eafef 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6263,7 +6263,7 @@ void Bot::DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster) { Mob::DoBuffTic(buff, slot, caster); } -bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, +bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, int16 *resist_adjust, uint32 aa_id) { bool Result = false; if(zone && !zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { @@ -6303,7 +6303,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, return false; } - if(slot < EQEmu::CastingSlot::MaxGems && !CheckFizzle(spell_id)) { + if(slot < EQEmu::spells::CastingSlot::MaxGems && !CheckFizzle(spell_id)) { int fizzle_msg = IsBardSong(spell_id) ? MISS_NOTE : SPELL_FIZZLE; InterruptSpell(fizzle_msg, 0x121, spell_id); @@ -6317,7 +6317,7 @@ bool Bot::CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, Log(Logs::Detail, Logs::Spells, "Casting a new spell/song while singing a song. Killing old song %d.", bardsong); bardsong = 0; bardsong_target_id = 0; - bardsong_slot = EQEmu::CastingSlot::Gem1; + bardsong_slot = EQEmu::spells::CastingSlot::Gem1; bardsong_timer.Disable(); } @@ -6447,7 +6447,7 @@ bool Bot::IsImmuneToSpell(uint16 spell_id, Mob *caster) { return Result; } -bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot) { +bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot) { bool Result = false; SpellTargetType targetType = spells[spell_id].targettype; if(targetType == ST_GroupClientAndPet) { @@ -6460,7 +6460,7 @@ bool Bot::DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_ce return Result; } -bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { +bool Bot::DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot, int32 cast_time, int32 mana_cost, uint32* oSpellWillFinish, uint32 item_slot, uint32 aa_id) { bool Result = false; if(GetClass() == BARD) cast_time = 0; @@ -6564,7 +6564,7 @@ void Bot::GenerateSpecialAttacks() { SetSpecialAbility(SPECATK_TRIPLE, 1); } -bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { +bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) { if(GetClass() == BARD) { if(!ApplyNextBardPulse(bardsong, this, bardsong_slot)) InterruptSpell(SONG_ENDS_ABRUPTLY, 0x121, bardsong); @@ -6574,7 +6574,7 @@ bool Bot::DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::Cast return true; } -bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { +bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) { if(spellTarget) { if(IsGrouped() && (spellTarget->IsBot() || spellTarget->IsClient()) && RuleB(Bots, GroupBuffing)) { bool noGroupSpell = false; @@ -6586,7 +6586,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu:: bool spelltypeequal = ((spelltype == 2) || (spelltype == 16) || (spelltype == 32)); bool spelltypetargetequal = ((spelltype == 8) && (spells[thespell].targettype == ST_Self)); bool spelltypeclassequal = ((spelltype == 1024) && (GetClass() == SHAMAN)); - bool slotequal = (slot == EQEmu::CastingSlot::Item); + bool slotequal = (slot == EQEmu::spells::CastingSlot::Item); if(spellequal || slotequal) { if((spelltypeequal || spelltypetargetequal) || spelltypeclassequal || slotequal) { if(((spells[thespell].effectid[0] == 0) && (spells[thespell].base[0] < 0)) && @@ -6625,7 +6625,7 @@ bool Bot::DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu:: return true; } -bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool& stopLogic) { +bool Bot::DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool& stopLogic) { bool isMainGroupMGB = false; if(isMainGroupMGB && (GetClass() != BARD)) { BotGroupSay(this, "MGB %s", spells[spell_id].name); @@ -8708,7 +8708,7 @@ bool Bot::UseDiscipline(uint32 spell_id, uint32 target) { if(IsCasting()) InterruptSpell(); - CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); + CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline); return true; } diff --git a/zone/bot.h b/zone/bot.h index d80ac5ad6..6a528a4e7 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -322,9 +322,9 @@ public: virtual void SetAttackTimer(); uint32 GetClassHPFactor(); virtual int32 CalcMaxHP(); - bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); - bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); - bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::CastingSlot slot, bool &stopLogic); + bool DoFinishedSpellAETarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic); + bool DoFinishedSpellSingleTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic); + bool DoFinishedSpellGroupTarget(uint16 spell_id, Mob* spellTarget, EQEmu::spells::CastingSlot slot, bool &stopLogic); void SendBotArcheryWearChange(uint8 material_slot, uint32 material, uint32 color); void Camp(bool databaseSave = true); virtual void AddToHateList(Mob* other, uint32 hate = 0, int32 damage = 0, bool iYellForHelp = true, bool bFrenzy = false, bool iBuffTic = false, bool pet_command = false); @@ -425,12 +425,12 @@ public: virtual float GetAOERange(uint16 spell_id); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100); virtual void DoBuffTic(const Buffs_Struct &buff, int slot, Mob* caster = nullptr); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, + virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, int16 *resist_adjust = nullptr, uint32 aa_id = 0); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); - virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::CastingSlot slot); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); + virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, CastAction_type &CastAction, EQEmu::spells::CastingSlot slot); + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 aa_id = 0); // Bot Equipment & Inventory Class Methods void BotTradeSwapItem(Client* client, int16 lootSlot, const EQEmu::ItemInstance* inst, const EQEmu::ItemInstance* inst_swap, uint32 equipableSlots, std::string* errorMessage, bool swap = true); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index fe5dcd69f..b44681341 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7774,7 +7774,7 @@ bool helper_cast_standard_spell(Bot* casting_bot, Mob* target_mob, int spell_id, if (annouce_cast) Bot::BotGroupSay(casting_bot, "Attempting to cast '%s' on %s", spells[spell_id].name, target_mob->GetCleanName()); - return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::CastingSlot::Gem2, -1, -1, dont_root_before); + return casting_bot->CastSpell(spell_id, target_mob->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, -1, dont_root_before); } bool helper_command_alias_fail(Client *bot_owner, const char* command_handler, const char *alias, const char *command) diff --git a/zone/client.cpp b/zone/client.cpp index da5430ff7..b625210ee 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -4950,7 +4950,7 @@ void Client::HandleLDoNOpen(NPC *target) if(target->GetLDoNTrapSpellID() != 0) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); @@ -5072,7 +5072,7 @@ void Client::HandleLDoNDisarm(NPC *target, uint16 skill, uint8 type) break; case -1: Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); @@ -5091,7 +5091,7 @@ void Client::HandleLDoNPickLock(NPC *target, uint16 skill, uint8 type) if(target->IsLDoNTrapped()) { Message_StringID(13, LDON_ACCIDENT_SETOFF2); - target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); + target->SpellFinished(target->GetLDoNTrapSpellID(), this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[target->GetLDoNTrapSpellID()].ResistDiff); target->SetLDoNTrapSpellID(0); target->SetLDoNTrapped(false); target->SetLDoNTrapDetected(false); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 541eb2e81..797075108 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -530,7 +530,7 @@ void Client::CompleteConnect() SendAppearancePacket(AT_GuildID, GuildID(), false); SendAppearancePacket(AT_GuildRank, rank, false); } - for (uint32 spellInt = 0; spellInt < MAX_PP_REF_SPELLBOOK; spellInt++) { + for (uint32 spellInt = 0; spellInt < EQEmu::spells::SPELLBOOK_SIZE; spellInt++) { if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000) m_pp.spell_book[spellInt] = 0xFFFFFFFF; } @@ -1412,7 +1412,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } if (SPDAT_RECORDS > 0) { - for (uint32 z = 0; z= (uint32)SPDAT_RECORDS) UnmemSpell(z, false); } @@ -1544,7 +1544,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) } /* Load Spell Slot Refresh from Currently Memoried Spells */ - for (unsigned int i = 0; i < MAX_PP_MEMSPELL; ++i) + for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) if (IsValidSpell(m_pp.mem_spells[i])) m_pp.spellSlotRefresh[i] = p_timers.GetRemainingTime(pTimerSpellStart + m_pp.mem_spells[i]) * 1000; @@ -4006,7 +4006,7 @@ void Client::Handle_OP_CancelTrade(const EQApplicationPacket *app) void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) { - using EQEmu::CastingSlot; + using EQEmu::spells::CastingSlot; if (app->size != sizeof(CastSpell_Struct)) { std::cout << "Wrong size: OP_CastSpell, size=" << app->size << ", expected " << sizeof(CastSpell_Struct) << std::endl; return; @@ -4027,14 +4027,14 @@ void Client::Handle_OP_CastSpell(const EQApplicationPacket *app) /* Memorized Spell */ if (m_pp.mem_spells[castspell->slot] && m_pp.mem_spells[castspell->slot] == castspell->spell_id) { uint16 spell_to_cast = 0; - if (castspell->slot < MAX_PP_MEMSPELL) { + if (castspell->slot < EQEmu::spells::SPELL_GEM_COUNT) { spell_to_cast = m_pp.mem_spells[castspell->slot]; if (spell_to_cast != castspell->spell_id) { InterruptSpell(castspell->spell_id); //CHEATER!!! return; } } - else if (castspell->slot >= MAX_PP_MEMSPELL) { + else if (castspell->slot >= EQEmu::spells::SPELL_GEM_COUNT) { InterruptSpell(); return; } @@ -5253,7 +5253,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); DeleteSpell_Struct* dss = (DeleteSpell_Struct*)outapp->pBuffer; - if (dss->spell_slot < 0 || dss->spell_slot > int(MAX_PP_SPELLBOOK)) + if (dss->spell_slot < 0 || dss->spell_slot > int(EQEmu::spells::SPELLBOOK_SIZE)) return; if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) { @@ -8451,7 +8451,7 @@ void Client::Handle_OP_ItemPreview(const EQApplicationPacket *app) void Client::Handle_OP_ItemVerifyRequest(const EQApplicationPacket *app) { - using EQEmu::CastingSlot; + using EQEmu::spells::CastingSlot; if (app->size != sizeof(ItemVerifyRequest_Struct)) { Log(Logs::General, Logs::Error, "OP size error: OP_ItemVerifyRequest expected:%i got:%i", sizeof(ItemVerifyRequest_Struct), app->size); @@ -9177,7 +9177,7 @@ void Client::Handle_OP_LoadSpellSet(const EQApplicationPacket *app) } int i; LoadSpellSet_Struct* ss = (LoadSpellSet_Struct*)app->pBuffer; - for (i = 0; ispell[i] != 0xFFFFFFFF) UnmemSpell(i, true); } @@ -13327,7 +13327,7 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app) const SwapSpell_Struct* swapspell = (const SwapSpell_Struct*)app->pBuffer; int swapspelltemp; - if (swapspell->from_slot < 0 || swapspell->from_slot > MAX_PP_SPELLBOOK || swapspell->to_slot < 0 || swapspell->to_slot > MAX_PP_SPELLBOOK) + if (swapspell->from_slot < 0 || swapspell->from_slot > EQEmu::spells::SPELLBOOK_SIZE || swapspell->to_slot < 0 || swapspell->to_slot > EQEmu::spells::SPELLBOOK_SIZE) return; swapspelltemp = m_pp.spell_book[swapspell->from_slot]; diff --git a/zone/command.cpp b/zone/command.cpp index f65a4cd11..c2b36c6e6 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -2609,14 +2609,14 @@ void command_castspell(Client *c, const Seperator *sep) else if (c->GetTarget() == 0) if(c->Admin() >= commandInstacast) - c->SpellFinished(spellid, 0, EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); + c->SpellFinished(spellid, 0, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, 0, EQEmu::CastingSlot::Item, 0); + c->CastSpell(spellid, 0, EQEmu::spells::CastingSlot::Item, 0); else if(c->Admin() >= commandInstacast) - c->SpellFinished(spellid, c->GetTarget(), EQEmu::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); + c->SpellFinished(spellid, c->GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellid].ResistDiff); else - c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::CastingSlot::Item, 0); + c->CastSpell(spellid, c->GetTarget()->GetID(), EQEmu::spells::CastingSlot::Item, 0); } } @@ -4620,7 +4620,7 @@ void command_memspell(Client *c, const Seperator *sep) { slot = atoi(sep->arg[1]) - 1; spell_id = atoi(sep->arg[2]); - if (slot > MAX_PP_MEMSPELL || spell_id >= SPDAT_RECORDS) + if (slot > EQEmu::spells::SPELL_GEM_COUNT || spell_id >= SPDAT_RECORDS) { c->Message(0, "Error: #MemSpell: Arguement out of range"); } @@ -6301,7 +6301,7 @@ void command_scribespells(Client *c, const Seperator *sep) c->Message(0, "Scribing spells for %s.", t->GetName()); Log(Logs::General, Logs::Normal, "Scribe spells request for %s from %s, levels: %u -> %u", t->GetName(), c->GetName(), min_level, max_level); - for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot)) + for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot)) { if ( diff --git a/zone/effects.cpp b/zone/effects.cpp index 6b0c2a2ad..7887eb652 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -643,9 +643,9 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { } if (reduced_recast > 0) - CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast); + CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline, -1, -1, 0, -1, (uint32)DiscTimer, reduced_recast); else{ - CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); + CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline); return true; } @@ -653,7 +653,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) { } else { - CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); + CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline); } return(true); } diff --git a/zone/lua_mob.cpp b/zone/lua_mob.cpp index 33d786b11..59d50508e 100644 --- a/zone/lua_mob.cpp +++ b/zone/lua_mob.cpp @@ -770,28 +770,28 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id) { bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, static_cast(slot)); + return self->CastSpell(spell_id, target_id, static_cast(slot)); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot)); + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot)); } bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, int mana_cost, int item_slot, int timer, int timer_duration) { Lua_Safe_Call_Bool(); - return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), static_cast(timer), static_cast(timer_duration)); } @@ -800,7 +800,7 @@ bool Lua_Mob::CastSpell(int spell_id, int target_id, int slot, int cast_time, in Lua_Safe_Call_Bool(); int16 res = resist_adjust; - return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), + return self->CastSpell(spell_id, target_id, static_cast(slot), cast_time, mana_cost, nullptr, static_cast(item_slot), static_cast(timer), static_cast(timer_duration), &res); } @@ -811,27 +811,27 @@ bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target) { bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, static_cast(slot)); + return self->SpellFinished(spell_id, target, static_cast(slot)); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, static_cast(slot), mana_used); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust); } bool Lua_Mob::SpellFinished(int spell_id, Lua_Mob target, int slot, int mana_used, uint32 inventory_slot, int resist_adjust, bool proc) { Lua_Safe_Call_Bool(); - return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust, proc); + return self->SpellFinished(spell_id, target, static_cast(slot), mana_used, inventory_slot, resist_adjust, proc); } void Lua_Mob::SendBeginCast(int spell_id, int cast_time) { diff --git a/zone/merc.cpp b/zone/merc.cpp index b33cade34..1825a23eb 100644 --- a/zone/merc.cpp +++ b/zone/merc.cpp @@ -1993,7 +1993,7 @@ bool Merc::AIDoSpellCast(uint16 spellid, Mob* tar, int32 mana_cost, uint32* oDon SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); SetMoving(false); - result = CastSpell(spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0); + result = CastSpell(spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, 0); if(IsCasting() && IsSitting()) Stand(); @@ -4045,7 +4045,7 @@ bool Merc::UseDiscipline(int32 spell_id, int32 target) { if(IsCasting()) InterruptSpell(); - CastSpell(spell_id, target, EQEmu::CastingSlot::Discipline); + CastSpell(spell_id, target, EQEmu::spells::CastingSlot::Discipline); return(true); } diff --git a/zone/mob.cpp b/zone/mob.cpp index b193e8bcb..773c53767 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -3123,12 +3123,12 @@ void Mob::ExecWeaponProc(const EQEmu::ItemInstance *inst, uint16 spell_id, Mob * twinproc = true; if (IsBeneficialSpell(spell_id) && (!IsNPC() || (IsNPC() && CastToNPC()->GetInnateProcSpellID() != spell_id))) { // NPC innate procs don't take this path ever - SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); + SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) SpellOnTarget(spell_id, this, false, false, 0, true, level_override); } else if(!(on->IsClient() && on->CastToClient()->dead)) { //dont proc on dead clients - SpellFinished(spell_id, on, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); + SpellFinished(spell_id, on, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff, true, level_override); if(twinproc) SpellOnTarget(spell_id, on, false, false, 0, true, level_override); } @@ -3465,7 +3465,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) trigger_spell_id = CastToClient()->CalcAAFocus(focusTriggerOnCast, *rank, spell_id); if (IsValidSpell(trigger_spell_id) && GetTarget()) - SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1, + SpellFinished(trigger_spell_id, GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1, spells[trigger_spell_id].ResistDiff); } @@ -3473,7 +3473,7 @@ void Mob::TriggerOnCast(uint32 focus_spell, uint32 spell_id, bool aa_trigger) trigger_spell_id = CalcFocusEffect(focusTriggerOnCast, focus_spell, spell_id); if (IsValidSpell(trigger_spell_id) && GetTarget()) { - SpellFinished(trigger_spell_id, GetTarget(), EQEmu::CastingSlot::Item, 0, -1, + SpellFinished(trigger_spell_id, GetTarget(), EQEmu::spells::CastingSlot::Item, 0, -1, spells[trigger_spell_id].ResistDiff); CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); } @@ -3504,7 +3504,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) { // If we trigger an effect then its over. if (IsValidSpell(spells[spell_id].base2[i])){ - SpellFinished(spells[spell_id].base2[i], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + SpellFinished(spells[spell_id].base2[i], target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); return true; } } @@ -3523,7 +3523,7 @@ bool Mob::TrySpellTrigger(Mob *target, uint32 spell_id, int effect) if(zone->random.Int(0, 100) <= spells[spell_id].base[effect]) { if (IsValidSpell(spells[spell_id].base2[effect])){ - SpellFinished(spells[spell_id].base2[effect], target, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff); + SpellFinished(spells[spell_id].base2[effect], target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[effect]].ResistDiff); return true; //Only trigger once of these per spell effect. } } @@ -3600,7 +3600,7 @@ void Mob::TryTriggerOnValueAmount(bool IsHP, bool IsMana, bool IsEndur, bool IsP } if (use_spell){ - SpellFinished(spells[spell_id].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spells[spell_id].base[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); if(!TryFadeEffect(e)) BuffFadeBySlot(e); @@ -3628,7 +3628,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) if(zone->random.Roll(focus)) { Message(MT_Spells,"You twincast %s!",spells[spell_id].name); - SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } @@ -3646,7 +3646,7 @@ void Mob::TryTwincast(Mob *caster, Mob *target, uint32 spell_id) { if(zone->random.Roll(focus)) { - SpellFinished(spell_id, target, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } @@ -3774,10 +3774,10 @@ bool Mob::TryFadeEffect(int slot) if(IsValidSpell(spell_id)) { if (IsBeneficialSpell(spell_id)) { - SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } else if(!(IsClient() && CastToClient()->dead)) { - SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } return true; } @@ -3811,7 +3811,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, target); else - SpellFinished(focus_trigger, this, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); + SpellFinished(focus_trigger, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); } // For detrimental spells, if the triggered spell is beneficial, then it will land on the caster // if the triggered spell is also detrimental, then it will land on the target @@ -3821,7 +3821,7 @@ void Mob::TrySympatheticProc(Mob *target, uint32 spell_id) SpellFinished(focus_trigger, this); else - SpellFinished(focus_trigger, target, EQEmu::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); + SpellFinished(focus_trigger, target, EQEmu::spells::CastingSlot::Item, 0, -1, spells[focus_trigger].ResistDiff); } CheckNumHitsRemaining(NumHit::MatchingSpells, -1, focus_spell); @@ -4470,7 +4470,7 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) if (IsValidSpell(spells[spell_id].base2[i]) && spells[spell_id].max[i] <= level) { if(zone->random.Roll(spells[spell_id].base[i])) - SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + SpellFinished(spells[spell_id].base2[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); } } } @@ -4485,17 +4485,17 @@ void Mob::TrySpellOnKill(uint8 level, uint16 spell_id) if(aabonuses.SpellOnKill[i] && IsValidSpell(aabonuses.SpellOnKill[i]) && (level >= aabonuses.SpellOnKill[i + 2])) { if(zone->random.Roll(static_cast(aabonuses.SpellOnKill[i + 1]))) - SpellFinished(aabonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(aabonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } if(itembonuses.SpellOnKill[i] && IsValidSpell(itembonuses.SpellOnKill[i]) && (level >= itembonuses.SpellOnKill[i + 2])){ if(zone->random.Roll(static_cast(itembonuses.SpellOnKill[i + 1]))) - SpellFinished(itembonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(itembonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } if(spellbonuses.SpellOnKill[i] && IsValidSpell(spellbonuses.SpellOnKill[i]) && (level >= spellbonuses.SpellOnKill[i + 2])) { if(zone->random.Roll(static_cast(spellbonuses.SpellOnKill[i + 1]))) - SpellFinished(spellbonuses.SpellOnKill[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); + SpellFinished(spellbonuses.SpellOnKill[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnKill[i]].ResistDiff); } } @@ -4512,19 +4512,19 @@ bool Mob::TrySpellOnDeath() for(int i = 0; i < MAX_SPELL_TRIGGER*2; i+=2) { if(IsClient() && aabonuses.SpellOnDeath[i] && IsValidSpell(aabonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(aabonuses.SpellOnDeath[i + 1]))) { - SpellFinished(aabonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(aabonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SpellOnDeath[i]].ResistDiff); } } if(itembonuses.SpellOnDeath[i] && IsValidSpell(itembonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(itembonuses.SpellOnDeath[i + 1]))) { - SpellFinished(itembonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(itembonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[itembonuses.SpellOnDeath[i]].ResistDiff); } } if(spellbonuses.SpellOnDeath[i] && IsValidSpell(spellbonuses.SpellOnDeath[i])) { if(zone->random.Roll(static_cast(spellbonuses.SpellOnDeath[i + 1]))) { - SpellFinished(spellbonuses.SpellOnDeath[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); + SpellFinished(spellbonuses.SpellOnDeath[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spellbonuses.SpellOnDeath[i]].ResistDiff); } } } diff --git a/zone/mob.h b/zone/mob.h index 56d6e5e4f..40e1a0dfd 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -278,7 +278,7 @@ public: //Song bool UseBardSpellLogic(uint16 spell_id = 0xffff, int slot = -1); - bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::CastingSlot slot); + bool ApplyNextBardPulse(uint16 spell_id, Mob *spell_target, EQEmu::spells::CastingSlot slot); void BardPulse(uint16 spell_id, Mob *caster); //Spell @@ -309,24 +309,24 @@ public: void SendSpellBarEnable(uint16 spellid); void ZeroCastingVars(); virtual void SpellProcess(); - virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, + virtual bool CastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 *resist_adjust = nullptr, uint32 aa_id = 0); - virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, int32 casttime = -1, + virtual bool DoCastSpell(uint16 spell_id, uint16 target_id, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, int32 casttime = -1, int32 mana_cost = -1, uint32* oSpellWillFinish = 0, uint32 item_slot = 0xFFFFFFFF, uint32 timer = 0xFFFFFFFF, uint32 timer_duration = 0, int16 resist_adjust = 0, uint32 aa_id = 0); - void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::CastingSlot slot, uint16 mana_used, + void CastedSpellFinished(uint16 spell_id, uint32 target_id, EQEmu::spells::CastingSlot slot, uint16 mana_used, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0); - bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::CastingSlot slot = EQEmu::CastingSlot::Item, uint16 mana_used = 0, + bool SpellFinished(uint16 spell_id, Mob *target, EQEmu::spells::CastingSlot slot = EQEmu::spells::CastingSlot::Item, uint16 mana_used = 0, uint32 inventory_slot = 0xFFFFFFFF, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); void SendBeginCast(uint16 spell_id, uint32 casttime); virtual bool SpellOnTarget(uint16 spell_id, Mob* spelltar, bool reflect = false, bool use_resist_adjust = false, int16 resist_adjust = 0, bool isproc = false, int level_override = -1); virtual bool SpellEffect(Mob* caster, uint16 spell_id, float partial = 100, int level_override = -1); virtual bool DetermineSpellTargets(uint16 spell_id, Mob *&spell_target, Mob *&ae_center, - CastAction_type &CastAction, EQEmu::CastingSlot slot, bool isproc = false); + CastAction_type &CastAction, EQEmu::spells::CastingSlot slot, bool isproc = false); virtual bool CheckFizzle(uint16 spell_id); virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual bool IsImmuneToSpell(uint16 spell_id, Mob *caster); @@ -1375,7 +1375,7 @@ protected: int attacked_count; bool delaytimer; uint16 casting_spell_targetid; - EQEmu::CastingSlot casting_spell_slot; + EQEmu::spells::CastingSlot casting_spell_slot; uint16 casting_spell_mana; uint32 casting_spell_inventory_slot; uint32 casting_spell_timer; @@ -1385,7 +1385,7 @@ protected: uint32 casting_spell_aa_id; bool casting_spell_checks; uint16 bardsong; - EQEmu::CastingSlot bardsong_slot; + EQEmu::spells::CastingSlot bardsong_slot; uint32 bardsong_target_id; bool ActiveProjectileATK; diff --git a/zone/mob_ai.cpp b/zone/mob_ai.cpp index e44a1246c..37fbb7814 100644 --- a/zone/mob_ai.cpp +++ b/zone/mob_ai.cpp @@ -375,7 +375,7 @@ bool NPC::AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgain #endif casting_spell_AIindex = i; - return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); + return CastSpell(AIspells[i].spellid, tar->GetID(), EQEmu::spells::CastingSlot::Gem2, AIspells[i].manacost == -2 ? 0 : -1, mana_cost, oDontDoAgainBefore, -1, -1, 0, &(AIspells[i].resist_adjust)); } bool EntityList::AICheckCloseBeneficialSpells(NPC* caster, uint8 iChance, float iRange, uint32 iSpellTypes) { @@ -688,11 +688,11 @@ void Client::AI_SpellCast() } uint32 spell_to_cast = 0xFFFFFFFF; - EQEmu::CastingSlot slot_to_use = EQEmu::CastingSlot::Item; + EQEmu::spells::CastingSlot slot_to_use = EQEmu::spells::CastingSlot::Item; if(valid_spells.size() == 1) { spell_to_cast = valid_spells[0]; - slot_to_use = static_cast(slots[0]); + slot_to_use = static_cast(slots[0]); } else if(valid_spells.empty()) { @@ -702,7 +702,7 @@ void Client::AI_SpellCast() { uint32 idx = zone->random.Int(0, (valid_spells.size()-1)); spell_to_cast = valid_spells[idx]; - slot_to_use = static_cast(slots[idx]); + slot_to_use = static_cast(slots[idx]); } if(IsMezSpell(spell_to_cast) || IsFearSpell(spell_to_cast)) diff --git a/zone/perl_mob.cpp b/zone/perl_mob.cpp index b9884b2a0..334aeaf0b 100644 --- a/zone/perl_mob.cpp +++ b/zone/perl_mob.cpp @@ -3737,7 +3737,7 @@ XS(XS_Mob_CastSpell) { Mob *THIS; uint16 spell_id = (uint16) SvUV(ST(1)); uint16 target_id = (uint16) SvUV(ST(2)); - EQEmu::CastingSlot slot; + EQEmu::spells::CastingSlot slot; int32 casttime; int32 mana_cost; int16 resist_adjust; @@ -3751,9 +3751,9 @@ XS(XS_Mob_CastSpell) { Perl_croak(aTHX_ "THIS is nullptr, avoiding crash."); if (items < 4) - slot = EQEmu::CastingSlot::Item; + slot = EQEmu::spells::CastingSlot::Item; else { - slot = static_cast(SvUV(ST(3))); + slot = static_cast(SvUV(ST(3))); } if (items < 5) @@ -3827,7 +3827,7 @@ XS(XS_Mob_SpellFinished) { resist_diff = spells[spell_id].ResistDiff; } - THIS->SpellFinished(spell_id, spell_target, EQEmu::CastingSlot::Item, mana_cost, -1, resist_diff); + THIS->SpellFinished(spell_id, spell_target, EQEmu::spells::CastingSlot::Item, mana_cost, -1, resist_diff); } XSRETURN_EMPTY; } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index dad4ebd26..660ac3273 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -371,14 +371,14 @@ void QuestManager::castspell(int spell_id, int target_id) { if (owner) { Mob *tgt = entity_list.GetMob(target_id); if(tgt != nullptr) - owner->SpellFinished(spell_id, tgt, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + owner->SpellFinished(spell_id, tgt, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } void QuestManager::selfcast(int spell_id) { QuestManagerCurrentQuestVars(); if (initiator) - initiator->SpellFinished(spell_id, initiator, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + initiator->SpellFinished(spell_id, initiator, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } void QuestManager::addloot(int item_id, int charges, bool equipitem, int aug1, int aug2, int aug3, int aug4, int aug5, int aug6) { @@ -985,7 +985,7 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { bool SpellBucketCheckResult = 0; - for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < MAX_PP_SPELLBOOK; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot)) + for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot)) { if ( diff --git a/zone/special_attacks.cpp b/zone/special_attacks.cpp index ff3559db9..1e38b481b 100644 --- a/zone/special_attacks.cpp +++ b/zone/special_attacks.cpp @@ -197,7 +197,7 @@ void Mob::DoSpecialAttackDamage(Mob *who, EQEmu::skills::SkillType skill, int32 IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::CastingSlot::Item, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], who, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } @@ -2156,7 +2156,7 @@ void Mob::DoMeleeSkillAttackDmg(Mob *other, uint16 weapon_damage, EQEmu::skills: IsValidSpell(aabonuses.SkillAttackProc[2])) { float chance = aabonuses.SkillAttackProc[0] / 1000.0f; if (zone->random.Roll(chance)) - SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::CastingSlot::Item, 0, -1, + SpellFinished(aabonuses.SkillAttackProc[2], other, EQEmu::spells::CastingSlot::Item, 0, -1, spells[aabonuses.SkillAttackProc[2]].ResistDiff); } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 82fef55cf..e4c0badd5 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -2470,7 +2470,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove case SE_FcTimerRefresh: { if(IsClient()) { - for(unsigned int i =0 ; i < MAX_PP_MEMSPELL; ++i) { + for (unsigned int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; ++i) { if(IsValidSpell(CastToClient()->m_pp.mem_spells[i])) { if (CalcFocusEffect(focusFcTimerRefresh, spell_id, CastToClient()->m_pp.mem_spells[i])){ CastToClient()->m_pp.spellSlotRefresh[i] = 1; @@ -2739,7 +2739,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial, int level_ove if (caster && IsValidSpell(spells[spell_id].base2[i])){ if(zone->random.Roll(spells[spell_id].base[i])) - caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); + caster->SpellFinished(spells[spell_id].base2[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[spell_id].base2[i]].ResistDiff); } break; } @@ -3662,7 +3662,7 @@ void Mob::DoBuffTic(const Buffs_Struct &buff, int slot, Mob *caster) case SE_CastOnFadeEffectNPC: case SE_CastOnFadeEffectAlways: { if (buff.ticsremaining == 0) { - SpellFinished(spells[buff.spellid].base[i], this, EQEmu::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff); + SpellFinished(spells[buff.spellid].base[i], this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spells[buff.spellid].base[i]].ResistDiff); } break; } @@ -5100,7 +5100,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo if (Caston_spell_id) { if (IsValidSpell(Caston_spell_id) && (Caston_spell_id != spell_id)) - SpellFinished(Caston_spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff); + SpellFinished(Caston_spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[Caston_spell_id].ResistDiff); } return (value * lvlModifier / 100); @@ -6663,10 +6663,10 @@ void Mob::TryTriggerThreshHold(int32 damage, int effect_id, Mob* attacker){ if (IsValidSpell(spell_id)) { if (IsBeneficialSpell(spell_id)) - SpellFinished(spell_id, this, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, this, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); else if(attacker) - SpellFinished(spell_id, attacker, EQEmu::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); + SpellFinished(spell_id, attacker, EQEmu::spells::CastingSlot::Item, 0, -1, spells[spell_id].ResistDiff); } } } diff --git a/zone/spells.cpp b/zone/spells.cpp index b24d21725..9e3c11b6b 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -107,7 +107,7 @@ extern volatile bool is_zone_loaded; extern WorldServer worldserver; extern FastMath g_Math; -using EQEmu::CastingSlot; +using EQEmu::spells::CastingSlot; // this is run constantly for every mob void Mob::SpellProcess() @@ -4968,7 +4968,7 @@ void Client::MakeBuffFadePacket(uint16 spell_id, int slot_id, bool send_message) void Client::MemSpell(uint16 spell_id, int slot, bool update_client) { - if(slot >= MAX_PP_MEMSPELL || slot < 0) + if(slot >= EQEmu::spells::SPELL_GEM_COUNT || slot < 0) return; if(update_client) @@ -4990,7 +4990,7 @@ void Client::MemSpell(uint16 spell_id, int slot, bool update_client) void Client::UnmemSpell(int slot, bool update_client) { - if(slot > MAX_PP_MEMSPELL || slot < 0) + if(slot > EQEmu::spells::SPELL_GEM_COUNT || slot < 0) return; Log(Logs::Detail, Logs::Spells, "Spell %d forgotten from slot %d", m_pp.mem_spells[slot], slot); @@ -5006,7 +5006,7 @@ void Client::UnmemSpell(int slot, bool update_client) void Client::UnmemSpellBySpellID(int32 spell_id) { - for(int i = 0; i < MAX_PP_MEMSPELL; i++) { + for(int i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) { if(m_pp.mem_spells[i] == spell_id) { UnmemSpell(i, true); break; @@ -5018,14 +5018,14 @@ void Client::UnmemSpellAll(bool update_client) { int i; - for(i = 0; i < MAX_PP_MEMSPELL; i++) + for(i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) if(m_pp.mem_spells[i] != 0xFFFFFFFF) UnmemSpell(i, update_client); } void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client) { - if(slot >= MAX_PP_SPELLBOOK || slot < 0) + if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0) return; if(update_client) @@ -5046,7 +5046,7 @@ void Client::ScribeSpell(uint16 spell_id, int slot, bool update_client) void Client::UnscribeSpell(int slot, bool update_client) { - if(slot >= MAX_PP_SPELLBOOK || slot < 0) + if(slot >= EQEmu::spells::SPELLBOOK_SIZE || slot < 0) return; Log(Logs::Detail, Logs::Spells, "Spell %d erased from spell book slot %d", m_pp.spell_book[slot], slot); @@ -5068,7 +5068,7 @@ void Client::UnscribeSpellAll(bool update_client) { int i; - for(i = 0; i < MAX_PP_SPELLBOOK; i++) + for(i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { if(m_pp.spell_book[i] != 0xFFFFFFFF) UnscribeSpell(i, update_client); @@ -5102,7 +5102,7 @@ void Client::UntrainDiscAll(bool update_client) } int Client::GetNextAvailableSpellBookSlot(int starting_slot) { - for (int i = starting_slot; i < MAX_PP_SPELLBOOK; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells + for (int i = starting_slot; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { //using starting_slot should help speed this up when we're iterating through a bunch of spells if (!IsValidSpell(GetSpellByBookSlot(i))) return i; } @@ -5111,7 +5111,7 @@ int Client::GetNextAvailableSpellBookSlot(int starting_slot) { } int Client::FindSpellBookSlotBySpellID(uint16 spellid) { - for(int i = 0; i < MAX_PP_SPELLBOOK; i++) { + for(int i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { if(m_pp.spell_book[i] == spellid) return i; } @@ -5410,7 +5410,7 @@ bool Mob::UseBardSpellLogic(uint16 spell_id, int slot) spell_id != SPELL_UNKNOWN && slot != -1 && GetClass() == BARD && - slot <= MAX_PP_MEMSPELL && + slot <= EQEmu::spells::SPELL_GEM_COUNT && IsBardSong(spell_id) ); } diff --git a/zone/trap.cpp b/zone/trap.cpp index 5e4198e5b..29314f568 100644 --- a/zone/trap.cpp +++ b/zone/trap.cpp @@ -135,7 +135,7 @@ void Trap::Trigger(Mob* trigger) entity_list.MessageClose(trigger,false,100,13,"%s",message.c_str()); } if(hiddenTrigger){ - hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff); + hiddenTrigger->SpellFinished(effectvalue, trigger, EQEmu::spells::CastingSlot::Item, 0, -1, spells[effectvalue].ResistDiff); } break; case trapTypeAlarm: diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 81e2ee9c4..29873a38e 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1204,12 +1204,12 @@ bool ZoneDatabase::LoadCharacterMemmedSpells(uint32 character_id, PlayerProfile_ auto results = database.QueryDatabase(query); int i = 0; /* Initialize Spells */ - for (i = 0; i < MAX_PP_MEMSPELL; i++){ + for (i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++){ pp->mem_spells[i] = 0xFFFFFFFF; } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - if (i < MAX_PP_MEMSPELL && atoi(row[1]) <= SPDAT_RECORDS){ + if (i < EQEmu::spells::SPELL_GEM_COUNT && atoi(row[1]) <= SPDAT_RECORDS){ pp->mem_spells[i] = atoi(row[1]); } } @@ -1227,12 +1227,12 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str auto results = database.QueryDatabase(query); int i = 0; /* Initialize Spells */ - for (i = 0; i < MAX_PP_SPELLBOOK; i++){ + for (i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++){ pp->spell_book[i] = 0xFFFFFFFF; } for (auto row = results.begin(); row != results.end(); ++row) { i = atoi(row[0]); - if (i < MAX_PP_SPELLBOOK && atoi(row[1]) <= SPDAT_RECORDS){ + if (i < EQEmu::spells::SPELLBOOK_SIZE && atoi(row[1]) <= SPDAT_RECORDS){ pp->spell_book[i] = atoi(row[1]); } } From f690c64f9e9916a65057b8e19bdb4fdb386a5d94 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Jan 2019 20:04:07 -0500 Subject: [PATCH 12/38] Moved buff definitions into 'spells' lookup --- common/emu_constants.h | 16 ++-- common/eq_limits.cpp | 136 +++++++++++++++---------------- common/eq_limits.h | 53 ++++++------ common/patches/rof.cpp | 20 ++--- common/patches/rof2.cpp | 20 ++--- common/patches/rof2_limits.h | 16 ++-- common/patches/rof_limits.h | 16 ++-- common/patches/sod.cpp | 20 ++--- common/patches/sod_limits.h | 16 ++-- common/patches/sof.cpp | 20 ++--- common/patches/sof_limits.h | 16 ++-- common/patches/titanium.cpp | 20 ++--- common/patches/titanium_limits.h | 16 ++-- common/patches/uf.cpp | 20 ++--- common/patches/uf_limits.h | 16 ++-- zone/client.h | 8 +- zone/mob.h | 2 +- zone/spells.cpp | 4 +- zone/zonedb.cpp | 2 +- 19 files changed, 219 insertions(+), 218 deletions(-) diff --git a/common/emu_constants.h b/common/emu_constants.h index 9e265753a..6fe6f8ec6 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -203,14 +203,6 @@ namespace EQEmu const size_t SAY_LINK_CLOSER_SIZE = 1; const size_t SAY_LINK_MAXIMUM_SIZE = (SAY_LINK_OPENER_SIZE + SAY_LINK_BODY_SIZE + SAY_LINK_TEXT_SIZE + SAY_LINK_CLOSER_SIZE); - const int LongBuffs = RoF2::constants::LongBuffs; - const int ShortBuffs = RoF2::constants::ShortBuffs; - const int DiscBuffs = RoF2::constants::DiscBuffs; - const int TotalBuffs = RoF2::constants::TotalBuffs; - const int NPCBuffs = RoF2::constants::NPCBuffs; - const int PetBuffs = RoF2::constants::PetBuffs; - const int MercBuffs = RoF2::constants::MercBuffs; - } /*constants*/ namespace profile { @@ -254,6 +246,14 @@ namespace EQEmu using SoD::spells::SPELLBOOK_SIZE; using UF::spells::SPELL_GEM_COUNT; // RoF+ clients define more than UF client..but, they are not valid beyond UF + using RoF2::spells::LONG_BUFFS; + using RoF2::spells::SHORT_BUFFS; + using RoF2::spells::DISC_BUFFS; + using RoF2::spells::TOTAL_BUFFS; + using RoF2::spells::NPC_BUFFS; + using RoF2::spells::PET_BUFFS; + using RoF2::spells::MERC_BUFFS; + } // namespace spells namespace bug { diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 09ba6712a..8727ba24b 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -47,13 +47,6 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, - ClientUnknown::INULL, ClientUnknown::INULL ), /*[ClientVersion::Client62] =*/ @@ -62,13 +55,6 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu Client62::INULL, Client62::INULL, Client62::INULL, - Client62::INULL, - Client62::INULL, - Client62::INULL, - Client62::INULL, - Client62::INULL, - Client62::INULL, - Client62::INULL, Client62::INULL ), /*[ClientVersion::Titanium] =*/ @@ -77,14 +63,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu Titanium::constants::EXPANSION_BIT, Titanium::constants::EXPANSIONS_MASK, Titanium::constants::CHARACTER_CREATION_LIMIT, - Titanium::constants::SAY_LINK_BODY_SIZE, - Titanium::constants::LongBuffs, - Titanium::constants::ShortBuffs, - Titanium::constants::DiscBuffs, - Titanium::constants::TotalBuffs, - Titanium::constants::NPCBuffs, - Titanium::constants::PetBuffs, - Titanium::constants::MercBuffs + Titanium::constants::SAY_LINK_BODY_SIZE ), /*[ClientVersion::SoF] =*/ EQEmu::constants::LookupEntry( @@ -92,14 +71,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu SoF::constants::EXPANSION_BIT, SoF::constants::EXPANSIONS_MASK, SoF::constants::CHARACTER_CREATION_LIMIT, - SoF::constants::SAY_LINK_BODY_SIZE, - SoF::constants::LongBuffs, - SoF::constants::ShortBuffs, - SoF::constants::DiscBuffs, - SoF::constants::TotalBuffs, - SoF::constants::NPCBuffs, - SoF::constants::PetBuffs, - SoF::constants::MercBuffs + SoF::constants::SAY_LINK_BODY_SIZE ), /*[ClientVersion::SoD] =*/ EQEmu::constants::LookupEntry( @@ -107,14 +79,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu SoD::constants::EXPANSION_BIT, SoD::constants::EXPANSIONS_MASK, SoD::constants::CHARACTER_CREATION_LIMIT, - SoD::constants::SAY_LINK_BODY_SIZE, - SoD::constants::LongBuffs, - SoD::constants::ShortBuffs, - SoD::constants::DiscBuffs, - SoD::constants::TotalBuffs, - SoD::constants::NPCBuffs, - SoD::constants::PetBuffs, - SoD::constants::MercBuffs + SoD::constants::SAY_LINK_BODY_SIZE ), /*[ClientVersion::UF] =*/ EQEmu::constants::LookupEntry( @@ -122,14 +87,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu UF::constants::EXPANSION_BIT, UF::constants::EXPANSIONS_MASK, UF::constants::CHARACTER_CREATION_LIMIT, - UF::constants::SAY_LINK_BODY_SIZE, - UF::constants::LongBuffs, - UF::constants::ShortBuffs, - UF::constants::DiscBuffs, - UF::constants::TotalBuffs, - UF::constants::NPCBuffs, - UF::constants::PetBuffs, - UF::constants::MercBuffs + UF::constants::SAY_LINK_BODY_SIZE ), /*[ClientVersion::RoF] =*/ EQEmu::constants::LookupEntry( @@ -137,14 +95,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu RoF::constants::EXPANSION_BIT, RoF::constants::EXPANSIONS_MASK, RoF::constants::CHARACTER_CREATION_LIMIT, - RoF::constants::SAY_LINK_BODY_SIZE, - RoF::constants::LongBuffs, - RoF::constants::ShortBuffs, - RoF::constants::DiscBuffs, - RoF::constants::TotalBuffs, - RoF::constants::NPCBuffs, - RoF::constants::PetBuffs, - RoF::constants::MercBuffs + RoF::constants::SAY_LINK_BODY_SIZE ), /*[ClientVersion::RoF2] =*/ EQEmu::constants::LookupEntry( @@ -152,14 +103,7 @@ static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu RoF2::constants::EXPANSION_BIT, RoF2::constants::EXPANSIONS_MASK, RoF2::constants::CHARACTER_CREATION_LIMIT, - RoF2::constants::SAY_LINK_BODY_SIZE, - RoF2::constants::LongBuffs, - RoF2::constants::ShortBuffs, - RoF2::constants::DiscBuffs, - RoF2::constants::TotalBuffs, - RoF2::constants::NPCBuffs, - RoF2::constants::PetBuffs, - RoF2::constants::MercBuffs + RoF2::constants::SAY_LINK_BODY_SIZE ) }; @@ -1133,12 +1077,26 @@ static const EQEmu::spells::LookupEntry spells_static_lookup_entries[EQEmu::vers { /*[ClientVersion::Unknown] =*/ EQEmu::spells::LookupEntry( + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, + ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL, ClientUnknown::INULL ), /*[ClientVersion::Client62] =*/ EQEmu::spells::LookupEntry( + Client62::INULL, + Client62::INULL, + Client62::INULL, + Client62::INULL, + Client62::INULL, + Client62::INULL, + Client62::INULL, Client62::INULL, Client62::INULL, Client62::INULL @@ -1147,37 +1105,79 @@ static const EQEmu::spells::LookupEntry spells_static_lookup_entries[EQEmu::vers EQEmu::spells::LookupEntry( Titanium::spells::SPELL_ID_MAX, Titanium::spells::SPELLBOOK_SIZE, - Titanium::spells::SPELL_GEM_COUNT + Titanium::spells::SPELL_GEM_COUNT, + Titanium::spells::LONG_BUFFS, + Titanium::spells::SHORT_BUFFS, + Titanium::spells::DISC_BUFFS, + Titanium::spells::TOTAL_BUFFS, + Titanium::spells::NPC_BUFFS, + Titanium::spells::PET_BUFFS, + Titanium::spells::MERC_BUFFS ), /*[ClientVersion::SoF] =*/ EQEmu::spells::LookupEntry( SoF::spells::SPELL_ID_MAX, SoF::spells::SPELLBOOK_SIZE, - SoF::spells::SPELL_GEM_COUNT + SoF::spells::SPELL_GEM_COUNT, + SoF::spells::LONG_BUFFS, + SoF::spells::SHORT_BUFFS, + SoF::spells::DISC_BUFFS, + SoF::spells::TOTAL_BUFFS, + SoF::spells::NPC_BUFFS, + SoF::spells::PET_BUFFS, + SoF::spells::MERC_BUFFS ), /*[ClientVersion::SoD] =*/ EQEmu::spells::LookupEntry( SoD::spells::SPELL_ID_MAX, SoD::spells::SPELLBOOK_SIZE, - SoD::spells::SPELL_GEM_COUNT + SoD::spells::SPELL_GEM_COUNT, + SoD::spells::LONG_BUFFS, + SoD::spells::SHORT_BUFFS, + SoD::spells::DISC_BUFFS, + SoD::spells::TOTAL_BUFFS, + SoD::spells::NPC_BUFFS, + SoD::spells::PET_BUFFS, + SoD::spells::MERC_BUFFS ), /*[ClientVersion::UF] =*/ EQEmu::spells::LookupEntry( UF::spells::SPELL_ID_MAX, SoD::spells::SPELLBOOK_SIZE, - UF::spells::SPELL_GEM_COUNT + UF::spells::SPELL_GEM_COUNT, + UF::spells::LONG_BUFFS, + UF::spells::SHORT_BUFFS, + UF::spells::DISC_BUFFS, + UF::spells::TOTAL_BUFFS, + UF::spells::NPC_BUFFS, + UF::spells::PET_BUFFS, + UF::spells::MERC_BUFFS ), /*[ClientVersion::RoF] =*/ EQEmu::spells::LookupEntry( RoF::spells::SPELL_ID_MAX, SoD::spells::SPELLBOOK_SIZE, - UF::spells::SPELL_GEM_COUNT // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + RoF::spells::LONG_BUFFS, + RoF::spells::SHORT_BUFFS, + RoF::spells::DISC_BUFFS, + RoF::spells::TOTAL_BUFFS, + RoF::spells::NPC_BUFFS, + RoF::spells::PET_BUFFS, + RoF::spells::MERC_BUFFS ), /*[ClientVersion::RoF2] =*/ EQEmu::spells::LookupEntry( RoF2::spells::SPELL_ID_MAX, SoD::spells::SPELLBOOK_SIZE, - UF::spells::SPELL_GEM_COUNT // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + UF::spells::SPELL_GEM_COUNT, // client translators are setup to allow the max value a client supports..however, the top 4 indices are not valid in this case + RoF2::spells::LONG_BUFFS, + RoF2::spells::SHORT_BUFFS, + RoF2::spells::DISC_BUFFS, + RoF2::spells::TOTAL_BUFFS, + RoF2::spells::NPC_BUFFS, + RoF2::spells::PET_BUFFS, + RoF2::spells::MERC_BUFFS ) }; diff --git a/common/eq_limits.h b/common/eq_limits.h index c27bc1eb8..0c862fe38 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -42,41 +42,20 @@ namespace EQEmu uint32 ExpansionsMask; int16 CharacterCreationLimit; size_t SayLinkBodySize; - int LongBuffs; - int ShortBuffs; - int DiscBuffs; - int TotalBuffs; - int NPCBuffs; - int PetBuffs; - int MercBuffs; - + LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry( EQEmu::expansions::Expansion Expansion, uint32 ExpansionBit, uint32 ExpansionsMask, int16 CharacterCreationLimit, - size_t SayLinkBodySize, - int LongBuffs, - int ShortBuffs, - int DiscBuffs, - int TotalBuffs, - int NPCBuffs, - int PetBuffs, - int MercBuffs + size_t SayLinkBodySize ) : Expansion(Expansion), ExpansionBit(ExpansionBit), ExpansionsMask(ExpansionsMask), CharacterCreationLimit(CharacterCreationLimit), - SayLinkBodySize(SayLinkBodySize), - LongBuffs(LongBuffs), - ShortBuffs(ShortBuffs), - DiscBuffs(DiscBuffs), - TotalBuffs(TotalBuffs), - NPCBuffs(NPCBuffs), - PetBuffs(PetBuffs), - MercBuffs(MercBuffs) + SayLinkBodySize(SayLinkBodySize) { } }; @@ -210,16 +189,38 @@ namespace EQEmu int SpellIdMax; int SpellbookSize; int SpellGemCount; + + int LongBuffs; + int ShortBuffs; + int DiscBuffs; + int TotalBuffs; + int NPCBuffs; + int PetBuffs; + int MercBuffs; LookupEntry(const LookupEntry *lookup_entry) { } LookupEntry( int SpellIdMax, int SpellbookSize, - int SpellGemCount + int SpellGemCount, + int LongBuffs, + int ShortBuffs, + int DiscBuffs, + int TotalBuffs, + int NPCBuffs, + int PetBuffs, + int MercBuffs ) : SpellIdMax(SpellIdMax), SpellbookSize(SpellbookSize), - SpellGemCount(SpellGemCount) + SpellGemCount(SpellGemCount), + LongBuffs(LongBuffs), + ShortBuffs(ShortBuffs), + DiscBuffs(DiscBuffs), + TotalBuffs(TotalBuffs), + NPCBuffs(NPCBuffs), + PetBuffs(PetBuffs), + MercBuffs(MercBuffs) { } }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index a539282bf..5a87748a4 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -6169,12 +6169,12 @@ namespace RoF static inline int ServerToRoFBuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -6182,12 +6182,12 @@ namespace RoF static inline int RoFToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 7aa1411b6..74453f1ff 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -6424,12 +6424,12 @@ namespace RoF2 static inline int ServerToRoF2BuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -6437,12 +6437,12 @@ namespace RoF2 static inline int RoF2ToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/rof2_limits.h b/common/patches/rof2_limits.h index 6f741a9bc..b3a1a4962 100644 --- a/common/patches/rof2_limits.h +++ b/common/patches/rof2_limits.h @@ -271,14 +271,6 @@ namespace RoF2 const size_t SAY_LINK_BODY_SIZE = 56; - const int LongBuffs = 42; - const int ShortBuffs = 20; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 97; - const int PetBuffs = NPCBuffs; - const int MercBuffs = LongBuffs; - } /*constants*/ namespace behavior { @@ -321,6 +313,14 @@ namespace RoF2 const int SPELLBOOK_SIZE = 720; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 42; + const int SHORT_BUFFS = 20; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 97; + const int PET_BUFFS = NPC_BUFFS; + const int MERC_BUFFS = LONG_BUFFS; + } /*spells*/ }; /*RoF2*/ diff --git a/common/patches/rof_limits.h b/common/patches/rof_limits.h index 739c19898..460ebfddb 100644 --- a/common/patches/rof_limits.h +++ b/common/patches/rof_limits.h @@ -262,14 +262,6 @@ namespace RoF const size_t SAY_LINK_BODY_SIZE = 55; - const int LongBuffs = 42; - const int ShortBuffs = 20; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 97; - const int PetBuffs = NPCBuffs; - const int MercBuffs = LongBuffs; - } /*constants*/ namespace behavior { @@ -312,6 +304,14 @@ namespace RoF const int SPELLBOOK_SIZE = 720; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 42; + const int SHORT_BUFFS = 20; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 97; + const int PET_BUFFS = NPC_BUFFS; + const int MERC_BUFFS = LONG_BUFFS; + } /*spells*/ }; /*RoF*/ diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 34e724960..e64510d06 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -4093,12 +4093,12 @@ namespace SoD static inline int ServerToSoDBuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -4106,12 +4106,12 @@ namespace SoD static inline int SoDToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/sod_limits.h b/common/patches/sod_limits.h index a26075cdb..7927a255b 100644 --- a/common/patches/sod_limits.h +++ b/common/patches/sod_limits.h @@ -289,14 +289,6 @@ namespace SoD const size_t SAY_LINK_BODY_SIZE = 50; - const int LongBuffs = 25; - const int ShortBuffs = 15; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 85; - const int PetBuffs = NPCBuffs; - const int MercBuffs = LongBuffs; - } /*constants*/ namespace behavior { @@ -337,6 +329,14 @@ namespace SoD const int SPELLBOOK_SIZE = 480; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 25; + const int SHORT_BUFFS = 15; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 85; + const int PET_BUFFS = NPC_BUFFS; + const int MERC_BUFFS = LONG_BUFFS; + } /*spells*/ }; /*SoD*/ diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 1b1d9dc28..a1141f99c 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -3491,12 +3491,12 @@ namespace SoF static inline int ServerToSoFBuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -3504,12 +3504,12 @@ namespace SoF static inline int SoFToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/sof_limits.h b/common/patches/sof_limits.h index 8f682c8c1..399ff8c1a 100644 --- a/common/patches/sof_limits.h +++ b/common/patches/sof_limits.h @@ -289,14 +289,6 @@ namespace SoF const size_t SAY_LINK_BODY_SIZE = 50; - const int LongBuffs = 25; - const int ShortBuffs = 15; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 60; - const int PetBuffs = 30; - const int MercBuffs = 0; - } /*constants*/ namespace behavior { @@ -338,6 +330,14 @@ namespace SoF const int SPELLBOOK_SIZE = 480; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 25; + const int SHORT_BUFFS = 15; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 60; + const int PET_BUFFS = 30; + const int MERC_BUFFS = 0; + } /*spells*/ }; /*SoF*/ diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 05357e3af..9220875a8 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -2794,12 +2794,12 @@ namespace Titanium static inline int ServerToTitaniumBuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -2807,12 +2807,12 @@ namespace Titanium static inline int TitaniumToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/titanium_limits.h b/common/patches/titanium_limits.h index 28eb414e3..5a804defb 100644 --- a/common/patches/titanium_limits.h +++ b/common/patches/titanium_limits.h @@ -288,14 +288,6 @@ namespace Titanium const size_t SAY_LINK_BODY_SIZE = 45; - const int LongBuffs = 25; - const int ShortBuffs = 12; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 60; - const int PetBuffs = 30; - const int MercBuffs = 0; - } /*constants*/ namespace behavior { @@ -337,6 +329,14 @@ namespace Titanium const int SPELLBOOK_SIZE = 400; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 25; + const int SHORT_BUFFS = 12; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 60; + const int PET_BUFFS = 30; + const int MERC_BUFFS = 0; + } /*spells*/ }; /*Titanium*/ diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 47d6bb4ff..9e87a7579 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -4460,12 +4460,12 @@ namespace UF static inline int ServerToUFBuffSlot(int index) { // we're a disc - if (index >= EQEmu::constants::LongBuffs + EQEmu::constants::ShortBuffs) - return index - EQEmu::constants::LongBuffs - EQEmu::constants::ShortBuffs + - constants::LongBuffs + constants::ShortBuffs; + if (index >= EQEmu::spells::LONG_BUFFS + EQEmu::spells::SHORT_BUFFS) + return index - EQEmu::spells::LONG_BUFFS - EQEmu::spells::SHORT_BUFFS + + spells::LONG_BUFFS + spells::SHORT_BUFFS; // we're a song - if (index >= EQEmu::constants::LongBuffs) - return index - EQEmu::constants::LongBuffs + constants::LongBuffs; + if (index >= EQEmu::spells::LONG_BUFFS) + return index - EQEmu::spells::LONG_BUFFS + spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } @@ -4473,12 +4473,12 @@ namespace UF static inline int UFToServerBuffSlot(int index) { // we're a disc - if (index >= constants::LongBuffs + constants::ShortBuffs) - return index - constants::LongBuffs - constants::ShortBuffs + EQEmu::constants::LongBuffs + - EQEmu::constants::ShortBuffs; + if (index >= spells::LONG_BUFFS + spells::SHORT_BUFFS) + return index - spells::LONG_BUFFS - spells::SHORT_BUFFS + EQEmu::spells::LONG_BUFFS + + EQEmu::spells::SHORT_BUFFS; // we're a song - if (index >= constants::LongBuffs) - return index - constants::LongBuffs + EQEmu::constants::LongBuffs; + if (index >= spells::LONG_BUFFS) + return index - spells::LONG_BUFFS + EQEmu::spells::LONG_BUFFS; // we're a normal buff return index; // as long as we guard against bad slots server side, we should be fine } diff --git a/common/patches/uf_limits.h b/common/patches/uf_limits.h index 5f5d5e199..429d57cd5 100644 --- a/common/patches/uf_limits.h +++ b/common/patches/uf_limits.h @@ -290,14 +290,6 @@ namespace UF const size_t SAY_LINK_BODY_SIZE = 50; - const int LongBuffs = 30; - const int ShortBuffs = 20; - const int DiscBuffs = 1; - const int TotalBuffs = LongBuffs + ShortBuffs + DiscBuffs; - const int NPCBuffs = 85; - const int PetBuffs = NPCBuffs; - const int MercBuffs = LongBuffs; - } /*constants*/ namespace behavior { @@ -340,6 +332,14 @@ namespace UF const int SPELLBOOK_SIZE = 720; const int SPELL_GEM_COUNT = static_cast(CastingSlot::MaxGems); + const int LONG_BUFFS = 30; + const int SHORT_BUFFS = 20; + const int DISC_BUFFS = 1; + const int TOTAL_BUFFS = LONG_BUFFS + SHORT_BUFFS + DISC_BUFFS; + const int NPC_BUFFS = 85; + const int PET_BUFFS = NPC_BUFFS; + const int MERC_BUFFS = LONG_BUFFS; + } /*spells*/ }; /*UF*/ diff --git a/zone/client.h b/zone/client.h index 854786efc..d1ccbb399 100644 --- a/zone/client.h +++ b/zone/client.h @@ -557,10 +557,10 @@ public: virtual int GetCurrentBuffSlots() const; virtual int GetCurrentSongSlots() const; virtual int GetCurrentDiscSlots() const { return 1; } - virtual int GetMaxBuffSlots() const { return EQEmu::constants::LongBuffs; } - virtual int GetMaxSongSlots() const { return EQEmu::constants::ShortBuffs; } - virtual int GetMaxDiscSlots() const { return EQEmu::constants::DiscBuffs; } - virtual int GetMaxTotalSlots() const { return EQEmu::constants::TotalBuffs; } + virtual int GetMaxBuffSlots() const { return EQEmu::spells::LONG_BUFFS; } + virtual int GetMaxSongSlots() const { return EQEmu::spells::SHORT_BUFFS; } + virtual int GetMaxDiscSlots() const { return EQEmu::spells::DISC_BUFFS; } + virtual int GetMaxTotalSlots() const { return EQEmu::spells::TOTAL_BUFFS; } virtual uint32 GetFirstBuffSlot(bool disc, bool song); virtual uint32 GetLastBuffSlot(bool disc, bool song); virtual void InitializeBuffSlots(); diff --git a/zone/mob.h b/zone/mob.h index 40e1a0dfd..ad65bab39 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -1538,7 +1538,7 @@ protected: glm::vec3 m_TargetRing; // we might want to do this differently, we gotta do max NPC buffs ... which is 97 - uint32 m_spellHitsLeft[EQEmu::constants::TotalBuffs]; // Used to track which spells will have their numhits incremented when spell finishes casting + uint32 m_spellHitsLeft[EQEmu::spells::TOTAL_BUFFS]; // Used to track which spells will have their numhits incremented when spell finishes casting GravityBehavior flymode; bool m_targetable; int QGVarDuration(const char *fmt); diff --git a/zone/spells.cpp b/zone/spells.cpp index 9e3c11b6b..c88522a57 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5619,12 +5619,12 @@ int Client::GetCurrentBuffSlots() const numbuffs++; if (GetLevel() > 74) numbuffs++; - return EQEmu::ClampUpper(numbuffs, EQEmu::constants::StaticLookup(m_ClientVersion)->LongBuffs); + return EQEmu::ClampUpper(numbuffs, EQEmu::spells::StaticLookup(m_ClientVersion)->LongBuffs); } int Client::GetCurrentSongSlots() const { - return EQEmu::constants::StaticLookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this + return EQEmu::spells::StaticLookup(m_ClientVersion)->ShortBuffs; // AAs dont affect this } void Client::InitializeBuffSlots() diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 29873a38e..420e9ec7d 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -3646,7 +3646,7 @@ void ZoneDatabase::LoadBuffs(Client *client) } // We load up to the most our client supports - max_slots = EQEmu::constants::StaticLookup(client->ClientVersion())->LongBuffs; + max_slots = EQEmu::spells::StaticLookup(client->ClientVersion())->LongBuffs; for (int index = 0; index < max_slots; ++index) { if (!IsValidSpell(buffs[index].spellid)) continue; From 40b2366346c405122b50a741cafa095215a76cb2 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Sun, 20 Jan 2019 21:33:56 -0600 Subject: [PATCH 13/38] Implement and extended #goto via #goto - this will work cross zone, cross instance, in zone etc. It works on top of the original #goto (target) and #goto x y z --- changelog.txt | 2 ++ common/database_instances.cpp | 13 +++++-- zone/client.cpp | 52 ++++++++++++++++++++++++++++ zone/client.h | 2 ++ zone/command.cpp | 64 +++++++++++++++++++++++++++++++---- 5 files changed, 124 insertions(+), 9 deletions(-) diff --git a/changelog.txt b/changelog.txt index 60330e137..9917b0e2d 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,6 +3,8 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 1/20/2019 == Uleat: Added 'spells' entry to EQDictionary +Akkadius: Implement and extended #goto via #goto - this will work cross zone, cross instance, in zone etc. + It works on top of the original #goto (target) and #goto x y z == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing diff --git a/common/database_instances.cpp b/common/database_instances.cpp index 5350d71f9..548a84bdb 100644 --- a/common/database_instances.cpp +++ b/common/database_instances.cpp @@ -38,16 +38,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #endif +/** + * @param instance_id + * @param char_id + * @return + */ bool Database::AddClientToInstance(uint16 instance_id, uint32 char_id) { std::string query = StringFormat( "REPLACE INTO `instance_list_player` (id, charid) " "VALUES " "(%lu, %lu)", - (unsigned long)instance_id, - (unsigned long)char_id - ); + (unsigned long) instance_id, + (unsigned long) char_id + ); + auto results = QueryDatabase(query); + return results.Success(); } diff --git a/zone/client.cpp b/zone/client.cpp index b625210ee..b0eca3c43 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -9075,3 +9075,55 @@ void Client::SetSecondaryWeaponOrnamentation(uint32 model_id) Message(15, "Your secondary weapon appearance has been modified"); } } + +/** + * Used in #goto + * + * @param player_name + */ +bool Client::GotoPlayer(std::string player_name) +{ + std::string query = StringFormat( + "SELECT" + " character_data.zone_id," + " character_data.zone_instance," + " character_data.x," + " character_data.y," + " character_data.z," + " character_data.heading " + "FROM" + " character_data " + "WHERE" + " TRUE" + " AND character_data.name = '%s'" + " AND character_data.last_login > (UNIX_TIMESTAMP() - 600) LIMIT 1", player_name.c_str()); + + auto results = database.QueryDatabase(query); + if (!results.Success()) { + return false; + } + + for (auto row = results.begin(); row != results.end(); ++row) { + auto zone_id = static_cast(atoi(row[0])); + auto instance_id = static_cast(atoi(row[1])); + auto x = static_cast(atof(row[2])); + auto y = static_cast(atof(row[3])); + auto z = static_cast(atof(row[4])); + auto heading = static_cast(atof(row[5])); + + if (instance_id > 0 && !database.CheckInstanceExists(instance_id)) { + this->Message(15, "Instance no longer exists..."); + return false; + } + + if (instance_id > 0) { + database.AddClientToInstance(instance_id, this->CharacterID()); + } + + this->MovePC(zone_id, instance_id, x, y, z, heading); + + return true; + } + + return false; +} \ No newline at end of file diff --git a/zone/client.h b/zone/client.h index d1ccbb399..fb9cd2e31 100644 --- a/zone/client.h +++ b/zone/client.h @@ -255,6 +255,8 @@ public: void SetPrimaryWeaponOrnamentation(uint32 model_id); void SetSecondaryWeaponOrnamentation(uint32 model_id); + bool GotoPlayer(std::string player_name); + //abstract virtual function implementations required by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); virtual void Damage(Mob* from, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill, bool avoidable = true, int8 buffslot = -1, bool iBuffTic = false, eSpecialAttacks special = eSpecialAttacks::None); diff --git a/zone/command.cpp b/zone/command.cpp index c2b36c6e6..d6e28ddf3 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5349,13 +5349,65 @@ void command_loc(Client *c, const Seperator *sep) void command_goto(Client *c, const Seperator *sep) { - // goto function - if (sep->arg[1][0] == '\0' && c->GetTarget()) - c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), c->GetTarget()->GetX(), c->GetTarget()->GetY(), c->GetTarget()->GetZ(), c->GetTarget()->GetHeading()); - else if (!(sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3))) + /** + * Goto via target and no args + */ + if (sep->arg[1][0] == '\0' && c->GetTarget()) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + c->GetTarget()->GetX(), + c->GetTarget()->GetY(), + c->GetTarget()->GetZ(), + c->GetTarget()->GetHeading()); + } + + /** + * Goto via player name + */ + else if (!sep->IsNumber(1) && sep->arg[1]) { + + /** + * Find them in zone first + */ + const char *player_name = sep->arg[1]; + std::string player_name_string = sep->arg[1]; + Client *client = entity_list.GetClientByName(player_name); + if (client) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + client->GetX(), + client->GetY(), + client->GetZ(), + client->GetHeading()); + + c->Message(15, "Goto player '%s' same zone", player_name_string.c_str()); + } + else if (c->GotoPlayer(player_name_string)) { + c->Message(15, "Goto player '%s' different zone", player_name_string.c_str()); + } + else { + c->Message(15, "Player '%s' not found", player_name_string.c_str()); + } + } + + /** + * Goto via x y z + */ + else if (sep->IsNumber(1) && sep->IsNumber(2) && sep->IsNumber(3)) { + c->MovePC( + zone->GetZoneID(), + zone->GetInstanceID(), + atof(sep->arg[1]), + atof(sep->arg[2]), + atof(sep->arg[3]), + c->GetHeading()); + } + else { c->Message(0, "Usage: #goto [x y z]"); - else - c->MovePC(zone->GetZoneID(), zone->GetInstanceID(), atof(sep->arg[1]), atof(sep->arg[2]), atof(sep->arg[3]), c->GetHeading()); + c->Message(0, "Usage: #goto [player_name]"); + } } void command_iteminfo(Client *c, const Seperator *sep) From 7b2c87c7edfd042de4bcc6532e446ee0a0596adb Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 20 Jan 2019 23:40:40 -0500 Subject: [PATCH 14/38] Added bi-state dynamic lookup return --- common/eq_limits.cpp | 228 ++++++++++++++++++++--------------- common/eq_limits.h | 12 +- common/inventory_profile.cpp | 5 +- 3 files changed, 139 insertions(+), 106 deletions(-) diff --git a/common/eq_limits.cpp b/common/eq_limits.cpp index 8727ba24b..b6e47ea36 100644 --- a/common/eq_limits.cpp +++ b/common/eq_limits.cpp @@ -37,8 +37,8 @@ void EQEmu::InitializeDynamicLookups() { global_dictionary_init = true; } +static std::unique_ptr constants_dynamic_nongm_lookup_entries[EQEmu::versions::ClientVersionCount]; static std::unique_ptr constants_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount]; -static std::unique_ptr constants_dynamic_lookup_entries[EQEmu::versions::ClientVersionCount]; static const EQEmu::constants::LookupEntry constants_static_lookup_entries[EQEmu::versions::ClientVersionCount] = { /*[ClientVersion::Unknown] =*/ @@ -119,6 +119,23 @@ void EQEmu::constants::InitializeDynamicLookups() { // use static references for now } +const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicLookup(versions::ClientVersion client_version, bool gm_flag) +{ + if (gm_flag) + return DynamicGMLookup(client_version); + else + return DynamicNonGMLookup(client_version); +} + +const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicNonGMLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (constants_dynamic_nongm_lookup_entries[static_cast(client_version)]) + return constants_dynamic_nongm_lookup_entries[static_cast(client_version)].get(); + + return &constants_static_lookup_entries[static_cast(client_version)]; +} + const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicGMLookup(versions::ClientVersion client_version) { client_version = versions::ValidateClientVersion(client_version); @@ -128,22 +145,13 @@ const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicGMLookup(versions: return &constants_static_lookup_entries[static_cast(client_version)]; } -const EQEmu::constants::LookupEntry* EQEmu::constants::DynamicLookup(versions::ClientVersion client_version) -{ - client_version = versions::ValidateClientVersion(client_version); - if (constants_dynamic_lookup_entries[static_cast(client_version)]) - return constants_dynamic_lookup_entries[static_cast(client_version)].get(); - - return &constants_static_lookup_entries[static_cast(client_version)]; -} - const EQEmu::constants::LookupEntry* EQEmu::constants::StaticLookup(versions::ClientVersion client_version) { return &constants_static_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; } +static std::unique_ptr inventory_dynamic_nongm_lookup_entries[EQEmu::versions::MobVersionCount]; static std::unique_ptr inventory_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount]; -static std::unique_ptr inventory_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; static const EQEmu::inventory::LookupEntry inventory_static_lookup_entries[EQEmu::versions::MobVersionCount] = { /*[MobVersion::Unknown] =*/ @@ -775,6 +783,63 @@ void EQEmu::inventory::InitializeDynamicLookups() { if ((dynamic_check_mask & RuleI(World, ExpansionSettings)) == dynamic_check_mask) return; + // Dynamic Lookups (promotive methodology) (all mob versions allowed) + for (uint32 iter = static_cast(EQEmu::versions::MobVersion::Unknown); iter <= static_cast(EQEmu::versions::LastPCMobVersion); ++iter) { + // no need to dynamic this condition since it is the lowest compatibility standard + if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask) + continue; + + // only client versions whose supported expansions are affected need to be considered + if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask) + continue; + + // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: + inventory_dynamic_nongm_lookup_entries[iter] = std::unique_ptr(new LookupEntry(inventory_static_lookup_entries[iter])); + + // clamp affected fields to the lowest standard + inventory_dynamic_nongm_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size + inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK; // power source + inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK; // general size + inventory_dynamic_nongm_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later + inventory_dynamic_nongm_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later + + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) { + // update bank size + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR) + inventory_dynamic_nongm_lookup_entries[iter]->InventoryTypeSize.Bank = SoF::invtype::BANK_SIZE; + } + + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) { + // update power source + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitTBS) + inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask = SoF::invslot::EQUIPMENT_BITMASK; + } + + if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) { + // update general size + if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitHoT) + inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask = RoF::invslot::GENERAL_BITMASK; + } + + // fixup possessions bitmask + inventory_dynamic_nongm_lookup_entries[iter]->PossessionsBitmask = + ( + inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask | + inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_nongm_lookup_entries[iter]->CursorBitmask + ); + + // fixup corpse bitmask + inventory_dynamic_nongm_lookup_entries[iter]->CorpseBitmask = + ( + inventory_dynamic_nongm_lookup_entries[iter]->GeneralBitmask | + inventory_dynamic_nongm_lookup_entries[iter]->CursorBitmask | + (inventory_dynamic_nongm_lookup_entries[iter]->EquipmentBitmask << 34) + ); + + // expansion-related fields are now updated and all other fields reflect the static entry values + } + // Dynamic GM Lookups (demotive methodology) (client-linked mob versions only) for (uint32 iter = static_cast(EQEmu::versions::MobVersion::Unknown); iter <= static_cast(EQEmu::versions::LastPCMobVersion); ++iter) { // no need to dynamic this condition since it is the lowest compatibility standard @@ -846,7 +911,7 @@ void EQEmu::inventory::InitializeDynamicLookups() { inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask | inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask | inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask - ); + ); // fixup corpse bitmask inventory_dynamic_gm_lookup_entries[iter]->CorpseBitmask = @@ -854,63 +919,6 @@ void EQEmu::inventory::InitializeDynamicLookups() { inventory_dynamic_gm_lookup_entries[iter]->GeneralBitmask | inventory_dynamic_gm_lookup_entries[iter]->CursorBitmask | (inventory_dynamic_gm_lookup_entries[iter]->EquipmentBitmask << 34) - ); - - // expansion-related fields are now updated and all other fields reflect the static entry values - } - - // Dynamic Lookups (promotive methodology) (all mob versions allowed) - for (uint32 iter = static_cast(EQEmu::versions::MobVersion::Unknown); iter <= static_cast(EQEmu::versions::LastPCMobVersion); ++iter) { - // no need to dynamic this condition since it is the lowest compatibility standard - if ((dynamic_check_mask & ~constants_static_lookup_entries[iter].ExpansionsMask) == dynamic_check_mask) - continue; - - // only client versions whose supported expansions are affected need to be considered - if ((constants_static_lookup_entries[iter].ExpansionsMask & RuleI(World, ExpansionSettings)) == constants_static_lookup_entries[iter].ExpansionsMask) - continue; - - // direct manipulation of lookup indices is safe so long as (int)ClientVersion:: == (int)MobVersion:: - inventory_dynamic_lookup_entries[iter] = std::unique_ptr(new LookupEntry(inventory_static_lookup_entries[iter])); - - // clamp affected fields to the lowest standard - inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = Titanium::invtype::BANK_SIZE; // bank size - inventory_dynamic_lookup_entries[iter]->EquipmentBitmask = Titanium::invslot::EQUIPMENT_BITMASK; // power source - inventory_dynamic_lookup_entries[iter]->GeneralBitmask = Titanium::invslot::GENERAL_BITMASK; // general size - inventory_dynamic_lookup_entries[iter]->PossessionsBitmask = 0; // we'll fix later - inventory_dynamic_lookup_entries[iter]->CorpseBitmask = 0; // we'll fix later - - if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitPoR) { - // update bank size - if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitPoR) - inventory_dynamic_lookup_entries[iter]->InventoryTypeSize.Bank = SoF::invtype::BANK_SIZE; - } - - if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitTBS) { - // update power source - if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitTBS) - inventory_dynamic_lookup_entries[iter]->EquipmentBitmask = SoF::invslot::EQUIPMENT_BITMASK; - } - - if (RuleI(World, ExpansionSettings) & EQEmu::expansions::bitHoT) { - // update general size - if (constants_static_lookup_entries[iter].ExpansionsMask & EQEmu::expansions::bitHoT) - inventory_dynamic_lookup_entries[iter]->GeneralBitmask = RoF::invslot::GENERAL_BITMASK; - } - - // fixup possessions bitmask - inventory_dynamic_lookup_entries[iter]->PossessionsBitmask = - ( - inventory_dynamic_lookup_entries[iter]->EquipmentBitmask | - inventory_dynamic_lookup_entries[iter]->GeneralBitmask | - inventory_dynamic_lookup_entries[iter]->CursorBitmask - ); - - // fixup corpse bitmask - inventory_dynamic_lookup_entries[iter]->CorpseBitmask = - ( - inventory_dynamic_lookup_entries[iter]->GeneralBitmask | - inventory_dynamic_lookup_entries[iter]->CursorBitmask | - (inventory_dynamic_lookup_entries[iter]->EquipmentBitmask << 34) ); // expansion-related fields are now updated and all other fields reflect the static entry values @@ -919,6 +927,23 @@ void EQEmu::inventory::InitializeDynamicLookups() { // only client versions that require a change from their static definitions have been given a dynamic (gm) lookup entry } +const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicLookup(versions::MobVersion mob_version, bool gm_flag) +{ + if (gm_flag) + return DynamicGMLookup(mob_version); + else + return DynamicNonGMLookup(mob_version); +} + +const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicNonGMLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (inventory_dynamic_nongm_lookup_entries[static_cast(mob_version)]) + return inventory_dynamic_nongm_lookup_entries[static_cast(mob_version)].get(); + + return &inventory_static_lookup_entries[static_cast(mob_version)]; +} + const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicGMLookup(versions::MobVersion mob_version) { mob_version = versions::ValidateMobVersion(mob_version); @@ -928,22 +953,13 @@ const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicGMLookup(versions: return &inventory_static_lookup_entries[static_cast(mob_version)]; } -const EQEmu::inventory::LookupEntry* EQEmu::inventory::DynamicLookup(versions::MobVersion mob_version) -{ - mob_version = versions::ValidateMobVersion(mob_version); - if (inventory_dynamic_lookup_entries[static_cast(mob_version)]) - return inventory_dynamic_lookup_entries[static_cast(mob_version)].get(); - - return &inventory_static_lookup_entries[static_cast(mob_version)]; -} - const EQEmu::inventory::LookupEntry* EQEmu::inventory::StaticLookup(versions::MobVersion mob_version) { return &inventory_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } +static std::unique_ptr behavior_dynamic_nongm_lookup_entries[EQEmu::versions::MobVersionCount]; static std::unique_ptr behavior_dynamic_gm_lookup_entries[EQEmu::versions::MobVersionCount]; -static std::unique_ptr behavior_dynamic_lookup_entries[EQEmu::versions::MobVersionCount]; static const EQEmu::behavior::LookupEntry behavior_static_lookup_entries[EQEmu::versions::MobVersionCount] = { /*[MobVersion::Unknown] =*/ @@ -1048,6 +1064,23 @@ void EQEmu::behavior::InitializeDynamicLookups() { // use static references for now } +const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicLookup(versions::MobVersion mob_version, bool gm_flag) +{ + if (gm_flag) + return DynamicGMLookup(mob_version); + else + return DynamicNonGMLookup(mob_version); +} + +const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicNonGMLookup(versions::MobVersion mob_version) +{ + mob_version = versions::ValidateMobVersion(mob_version); + if (behavior_dynamic_nongm_lookup_entries[static_cast(mob_version)]) + return behavior_dynamic_nongm_lookup_entries[static_cast(mob_version)].get(); + + return &behavior_static_lookup_entries[static_cast(mob_version)]; +} + const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicGMLookup(versions::MobVersion mob_version) { mob_version = versions::ValidateMobVersion(mob_version); @@ -1057,22 +1090,13 @@ const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicGMLookup(versions::M return &behavior_static_lookup_entries[static_cast(mob_version)]; } -const EQEmu::behavior::LookupEntry* EQEmu::behavior::DynamicLookup(versions::MobVersion mob_version) -{ - mob_version = versions::ValidateMobVersion(mob_version); - if (behavior_dynamic_lookup_entries[static_cast(mob_version)]) - return behavior_dynamic_lookup_entries[static_cast(mob_version)].get(); - - return &behavior_static_lookup_entries[static_cast(mob_version)]; -} - const EQEmu::behavior::LookupEntry* EQEmu::behavior::StaticLookup(versions::MobVersion mob_version) { return &behavior_static_lookup_entries[static_cast(versions::ValidateMobVersion(mob_version))]; } +static std::unique_ptr spells_dynamic_nongm_lookup_entries[EQEmu::versions::ClientVersionCount]; static std::unique_ptr spells_dynamic_gm_lookup_entries[EQEmu::versions::ClientVersionCount]; -static std::unique_ptr spells_dynamic_lookup_entries[EQEmu::versions::ClientVersionCount]; static const EQEmu::spells::LookupEntry spells_static_lookup_entries[EQEmu::versions::ClientVersionCount] = { /*[ClientVersion::Unknown] =*/ @@ -1193,6 +1217,23 @@ void EQEmu::spells::InitializeDynamicLookups() { // use static references for now } +const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicLookup(versions::ClientVersion client_version, bool gm_flag) +{ + if (gm_flag) + return DynamicGMLookup(client_version); + else + return DynamicNonGMLookup(client_version); +} + +const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicNonGMLookup(versions::ClientVersion client_version) +{ + client_version = versions::ValidateClientVersion(client_version); + if (spells_dynamic_nongm_lookup_entries[static_cast(client_version)]) + return spells_dynamic_nongm_lookup_entries[static_cast(client_version)].get(); + + return &spells_static_lookup_entries[static_cast(client_version)]; +} + const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicGMLookup(versions::ClientVersion client_version) { client_version = versions::ValidateClientVersion(client_version); @@ -1202,15 +1243,6 @@ const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicGMLookup(versions::Clien return &spells_static_lookup_entries[static_cast(client_version)]; } -const EQEmu::spells::LookupEntry* EQEmu::spells::DynamicLookup(versions::ClientVersion client_version) -{ - client_version = versions::ValidateClientVersion(client_version); - if (spells_dynamic_lookup_entries[static_cast(client_version)]) - return spells_dynamic_lookup_entries[static_cast(client_version)].get(); - - return &spells_static_lookup_entries[static_cast(client_version)]; -} - const EQEmu::spells::LookupEntry* EQEmu::spells::StaticLookup(versions::ClientVersion client_version) { return &spells_static_lookup_entries[static_cast(versions::ValidateClientVersion(client_version))]; diff --git a/common/eq_limits.h b/common/eq_limits.h index 0c862fe38..1f83c4606 100644 --- a/common/eq_limits.h +++ b/common/eq_limits.h @@ -61,8 +61,9 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag); + const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version); const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version); - const LookupEntry* DynamicLookup(versions::ClientVersion client_version); const LookupEntry* StaticLookup(versions::ClientVersion client_version); } /*constants*/ @@ -158,8 +159,9 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag); + const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version); const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version); - const LookupEntry* DynamicLookup(versions::MobVersion mob_version); const LookupEntry* StaticLookup(versions::MobVersion mob_version); } /*inventory*/ @@ -178,8 +180,9 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicLookup(versions::MobVersion mob_version, bool gm_flag); + const LookupEntry* DynamicNonGMLookup(versions::MobVersion mob_version); const LookupEntry* DynamicGMLookup(versions::MobVersion mob_version); - const LookupEntry* DynamicLookup(versions::MobVersion mob_version); const LookupEntry* StaticLookup(versions::MobVersion mob_version); } /*behavior*/ @@ -226,8 +229,9 @@ namespace EQEmu void InitializeDynamicLookups(); + const LookupEntry* DynamicLookup(versions::ClientVersion client_version, bool gm_flag); + const LookupEntry* DynamicNonGMLookup(versions::ClientVersion client_version); const LookupEntry* DynamicGMLookup(versions::ClientVersion client_version); - const LookupEntry* DynamicLookup(versions::ClientVersion client_version); const LookupEntry* StaticLookup(versions::ClientVersion client_version); } /*spells*/ diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index 2fe73ee19..826c84fb4 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -127,10 +127,7 @@ void EQEmu::InventoryProfile::SetInventoryVersion(versions::MobVersion inventory void EQEmu::InventoryProfile::SetGMInventory(bool gmi_flag) { m_gm_inventory = gmi_flag; - if (m_gm_inventory) - m_lookup = inventory::DynamicGMLookup(m_mob_version); - else - m_lookup = inventory::DynamicLookup(m_mob_version); + m_lookup = inventory::DynamicLookup(m_mob_version, gmi_flag); } void EQEmu::InventoryProfile::CleanDirty() { From 48564a5789f6a19e3c25e0c7e504523ea231d92e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 00:29:58 -0600 Subject: [PATCH 15/38] Implemented server side #who --- changelog.txt | 17 +- common/classes.cpp | 1052 ++++++++++++++++++++++------------------ zone/client_packet.cpp | 10 + zone/command.cpp | 127 ++++- zone/command.h | 1 + 5 files changed, 728 insertions(+), 479 deletions(-) diff --git a/changelog.txt b/changelog.txt index 9917b0e2d..54c61f19f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -3,8 +3,21 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) == 1/20/2019 == Uleat: Added 'spells' entry to EQDictionary -Akkadius: Implement and extended #goto via #goto - this will work cross zone, cross instance, in zone etc. - It works on top of the original #goto (target) and #goto x y z +Akkadius: + - [Command] Extended #goto via #goto - + - This will work cross zone, cross instance, in zone etc. + - It works on top of the original #goto (target) and #goto x y z + - [Command] Implemented server side #who Example: https://bit.ly/2TZ2hvI + - Searches can be filtered by + - Account Name + - Base Class Name + - Guild Name + - IP + - Player Name + - Race Name + - Zone Short Name + - Features a clickable (Goto) saylink that will bring you directly to a player regardless of + whether or not they are in an instance == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing diff --git a/common/classes.cpp b/common/classes.cpp index 58aa56602..be683fbd1 100644 --- a/common/classes.cpp +++ b/common/classes.cpp @@ -18,280 +18,382 @@ #include "../common/global_define.h" #include "../common/classes.h" -const char* GetClassIDName(uint8 class_id, uint8 level) +const char *GetClassIDName(uint8 class_id, uint8 level) { switch (class_id) { - case WARRIOR: - if (level >= 70) - return "Vanquisher"; - else if (level >= 65) - return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE. - else if (level >= 60) - return "Warlord"; - else if (level >= 55) - return "Myrmidon"; - else if (level >= 51) - return "Champion"; - else - return "Warrior"; - case CLERIC: - if (level >= 70) - return "Prelate"; - else if (level >= 65) - return "Archon"; - else if (level >= 60) - return "High Priest"; - else if (level >= 55) - return "Templar"; - else if (level >= 51) - return "Vicar"; - else - return "Cleric"; - case PALADIN: - if (level >= 70) - return "Lord"; - else if (level >= 65) - return "Lord Protector"; - else if (level >= 60) - return "Crusader"; - else if (level >= 55) - return "Knight"; - else if (level >= 51) - return "Cavalier"; - else - return "Paladin"; - case RANGER: - if (level >= 70) - return "Plainswalker"; - else if (level >= 65) - return "Forest Stalker"; - else if (level >= 60) - return "Warder"; - else if (level >= 55) - return "Outrider"; - else if (level >= 51) - return "Pathfinder"; - else - return "Ranger"; - case SHADOWKNIGHT: - if (level >= 70) - return "Scourge Knight"; - else if (level >= 65) - return "Dread Lord"; - else if (level >= 60) - return "Grave Lord"; - else if (level >= 55) - return "Revenant"; - else if (level >= 51) - return "Reaver"; - else - return "Shadowknight"; - case DRUID: - if (level >= 70) - return "Natureguard"; - else if (level >= 65) - return "Storm Warden"; - else if (level >= 60) - return "Hierophant"; - else if (level >= 55) - return "Preserver"; - else if (level >= 51) - return "Wanderer"; - else - return "Druid"; - case MONK: - if (level >= 70) - return "Stone Fist"; - else if (level >= 65) - return "Transcendent"; - else if (level >= 60) - return "Grandmaster"; - else if (level >= 55) - return "Master"; - else if (level >= 51) - return "Disciple"; - else - return "Monk"; - case BARD: - if (level >= 70) - return "Performer"; - else if (level >= 65) - return "Maestro"; - else if (level >= 60) - return "Virtuoso"; - else if (level >= 55) - return "Troubadour"; - else if (level >= 51) - return "Minstrel"; - else - return "Bard"; - case ROGUE: - if (level >= 70) - return "Nemesis"; - else if (level >= 65) - return "Deceiver"; - else if (level >= 60) - return "Assassin"; - else if (level >= 55) - return "Blackguard"; - else if (level >= 51) - return "Rake"; - else - return "Rogue"; - case SHAMAN: - if (level >= 70) - return "Soothsayer"; - else if (level >= 65) - return "Prophet"; - else if (level >= 60) - return "Oracle"; - else if (level >= 55) - return "Luminary"; - else if (level >= 51) - return "Mystic"; - else - return "Shaman"; - case NECROMANCER: - if (level >= 70) - return "Wraith"; - else if (level >= 65) - return "Arch Lich"; - else if (level >= 60) - return "Warlock"; - else if (level >= 55) - return "Defiler"; - else if (level >= 51) - return "Heretic"; - else - return "Necromancer"; - case WIZARD: - if (level >= 70) - return "Grand Arcanist"; - else if (level >= 65) - return "Arcanist"; - else if (level >= 60) - return "Sorcerer"; - else if (level >= 55) - return "Evoker"; - else if (level >= 51) - return "Channeler"; - else - return "Wizard"; - case MAGICIAN: - if (level >= 70) - return "Arch Magus"; - else if (level >= 65) - return "Arch Convoker"; - else if (level >= 60) - return "Arch Mage"; - else if (level >= 55) - return "Conjurer"; - if (level >= 51) - return "Elementalist"; - else - return "Magician"; - case ENCHANTER: - if (level >= 70) - return "Bedazzler"; - else if (level >= 65) - return "Coercer"; - else if (level >= 60) - return "Phantasmist"; - else if (level >= 55) - return "Beguiler"; - else if (level >= 51) - return "Illusionist"; - else - return "Enchanter"; - case BEASTLORD: - if (level >= 70) - return "Wildblood"; - else if (level >= 65) - return "Feral Lord"; - else if (level >= 60) - return "Savage Lord"; - else if (level >= 55) - return "Animist"; - else if (level >= 51) - return "Primalist"; - else - return "Beastlord"; - case BERSERKER: - if (level >= 70) - return "Ravager"; - else if (level >= 65) - return "Fury"; - else if (level >= 60) - return "Rager"; - else if (level >= 55) - return "Vehement"; - else if (level >= 51) - return "Brawler"; - else - return "Berserker"; - case BANKER: - if (level >= 70) - return "Master Banker"; - else if (level >= 65) - return "Elder Banker"; - else if (level >= 60) - return "Oldest Banker"; - else if (level >= 55) - return "Older Banker"; - else if (level >= 51) - return "Old Banker"; - else - return "Banker"; - case WARRIORGM: - return "Warrior Guildmaster"; - case CLERICGM: - return "Cleric Guildmaster"; - case PALADINGM: - return "Paladin Guildmaster"; - case RANGERGM: - return "Ranger Guildmaster"; - case SHADOWKNIGHTGM: - return "Shadowknight Guildmaster"; - case DRUIDGM: - return "Druid Guildmaster"; - case MONKGM: - return "Monk Guildmaster"; - case BARDGM: - return "Bard Guildmaster"; - case ROGUEGM: - return "Rogue Guildmaster"; - case SHAMANGM: - return "Shaman Guildmaster"; - case NECROMANCERGM: - return "Necromancer Guildmaster"; - case WIZARDGM: - return "Wizard Guildmaster"; - case MAGICIANGM: - return "Magician Guildmaster"; - case ENCHANTERGM: - return "Enchanter Guildmaster"; - case BEASTLORDGM: - return "Beastlord Guildmaster"; - case BERSERKERGM: - return "Berserker Guildmaster"; - case MERCHANT: - return "Merchant"; - case ADVENTURERECRUITER: - return "Adventure Recruiter"; - case ADVENTUREMERCHANT: - return "Adventure Merchant"; - case CORPSE_CLASS: - return "Corpse Class"; - case TRIBUTE_MASTER: - return "Tribute Master"; - case GUILD_TRIBUTE_MASTER: - return "Guild Tribute Master"; - default: - return "Unknown"; + case WARRIOR: + if (level >= 70) { + return "Vanquisher"; + } + else if (level >= 65) { + return "Overlord"; //Baron-Sprite: LEAVE MY CLASSES ALONE. + } + else if (level >= 60) { + return "Warlord"; + } + else if (level >= 55) { + return "Myrmidon"; + } + else if (level >= 51) { + return "Champion"; + } + else { + return "Warrior"; + } + case CLERIC: + if (level >= 70) { + return "Prelate"; + } + else if (level >= 65) { + return "Archon"; + } + else if (level >= 60) { + return "High Priest"; + } + else if (level >= 55) { + return "Templar"; + } + else if (level >= 51) { + return "Vicar"; + } + else { + return "Cleric"; + } + case PALADIN: + if (level >= 70) { + return "Lord"; + } + else if (level >= 65) { + return "Lord Protector"; + } + else if (level >= 60) { + return "Crusader"; + } + else if (level >= 55) { + return "Knight"; + } + else if (level >= 51) { + return "Cavalier"; + } + else { + return "Paladin"; + } + case RANGER: + if (level >= 70) { + return "Plainswalker"; + } + else if (level >= 65) { + return "Forest Stalker"; + } + else if (level >= 60) { + return "Warder"; + } + else if (level >= 55) { + return "Outrider"; + } + else if (level >= 51) { + return "Pathfinder"; + } + else { + return "Ranger"; + } + case SHADOWKNIGHT: + if (level >= 70) { + return "Scourge Knight"; + } + else if (level >= 65) { + return "Dread Lord"; + } + else if (level >= 60) { + return "Grave Lord"; + } + else if (level >= 55) { + return "Revenant"; + } + else if (level >= 51) { + return "Reaver"; + } + else { + return "Shadowknight"; + } + case DRUID: + if (level >= 70) { + return "Natureguard"; + } + else if (level >= 65) { + return "Storm Warden"; + } + else if (level >= 60) { + return "Hierophant"; + } + else if (level >= 55) { + return "Preserver"; + } + else if (level >= 51) { + return "Wanderer"; + } + else { + return "Druid"; + } + case MONK: + if (level >= 70) { + return "Stone Fist"; + } + else if (level >= 65) { + return "Transcendent"; + } + else if (level >= 60) { + return "Grandmaster"; + } + else if (level >= 55) { + return "Master"; + } + else if (level >= 51) { + return "Disciple"; + } + else { + return "Monk"; + } + case BARD: + if (level >= 70) { + return "Performer"; + } + else if (level >= 65) { + return "Maestro"; + } + else if (level >= 60) { + return "Virtuoso"; + } + else if (level >= 55) { + return "Troubadour"; + } + else if (level >= 51) { + return "Minstrel"; + } + else { + return "Bard"; + } + case ROGUE: + if (level >= 70) { + return "Nemesis"; + } + else if (level >= 65) { + return "Deceiver"; + } + else if (level >= 60) { + return "Assassin"; + } + else if (level >= 55) { + return "Blackguard"; + } + else if (level >= 51) { + return "Rake"; + } + else { + return "Rogue"; + } + case SHAMAN: + if (level >= 70) { + return "Soothsayer"; + } + else if (level >= 65) { + return "Prophet"; + } + else if (level >= 60) { + return "Oracle"; + } + else if (level >= 55) { + return "Luminary"; + } + else if (level >= 51) { + return "Mystic"; + } + else { + return "Shaman"; + } + case NECROMANCER: + if (level >= 70) { + return "Wraith"; + } + else if (level >= 65) { + return "Arch Lich"; + } + else if (level >= 60) { + return "Warlock"; + } + else if (level >= 55) { + return "Defiler"; + } + else if (level >= 51) { + return "Heretic"; + } + else { + return "Necromancer"; + } + case WIZARD: + if (level >= 70) { + return "Grand Arcanist"; + } + else if (level >= 65) { + return "Arcanist"; + } + else if (level >= 60) { + return "Sorcerer"; + } + else if (level >= 55) { + return "Evoker"; + } + else if (level >= 51) { + return "Channeler"; + } + else { + return "Wizard"; + } + case MAGICIAN: + if (level >= 70) { + return "Arch Magus"; + } + else if (level >= 65) { + return "Arch Convoker"; + } + else if (level >= 60) { + return "Arch Mage"; + } + else if (level >= 55) { + return "Conjurer"; + } + if (level >= 51) { + return "Elementalist"; + } + else { + return "Magician"; + } + case ENCHANTER: + if (level >= 70) { + return "Bedazzler"; + } + else if (level >= 65) { + return "Coercer"; + } + else if (level >= 60) { + return "Phantasmist"; + } + else if (level >= 55) { + return "Beguiler"; + } + else if (level >= 51) { + return "Illusionist"; + } + else { + return "Enchanter"; + } + case BEASTLORD: + if (level >= 70) { + return "Wildblood"; + } + else if (level >= 65) { + return "Feral Lord"; + } + else if (level >= 60) { + return "Savage Lord"; + } + else if (level >= 55) { + return "Animist"; + } + else if (level >= 51) { + return "Primalist"; + } + else { + return "Beastlord"; + } + case BERSERKER: + if (level >= 70) { + return "Ravager"; + } + else if (level >= 65) { + return "Fury"; + } + else if (level >= 60) { + return "Rager"; + } + else if (level >= 55) { + return "Vehement"; + } + else if (level >= 51) { + return "Brawler"; + } + else { + return "Berserker"; + } + case BANKER: + if (level >= 70) { + return "Master Banker"; + } + else if (level >= 65) { + return "Elder Banker"; + } + else if (level >= 60) { + return "Oldest Banker"; + } + else if (level >= 55) { + return "Older Banker"; + } + else if (level >= 51) { + return "Old Banker"; + } + else { + return "Banker"; + } + case WARRIORGM: + return "Warrior Guildmaster"; + case CLERICGM: + return "Cleric Guildmaster"; + case PALADINGM: + return "Paladin Guildmaster"; + case RANGERGM: + return "Ranger Guildmaster"; + case SHADOWKNIGHTGM: + return "Shadowknight Guildmaster"; + case DRUIDGM: + return "Druid Guildmaster"; + case MONKGM: + return "Monk Guildmaster"; + case BARDGM: + return "Bard Guildmaster"; + case ROGUEGM: + return "Rogue Guildmaster"; + case SHAMANGM: + return "Shaman Guildmaster"; + case NECROMANCERGM: + return "Necromancer Guildmaster"; + case WIZARDGM: + return "Wizard Guildmaster"; + case MAGICIANGM: + return "Magician Guildmaster"; + case ENCHANTERGM: + return "Enchanter Guildmaster"; + case BEASTLORDGM: + return "Beastlord Guildmaster"; + case BERSERKERGM: + return "Berserker Guildmaster"; + case MERCHANT: + return "Merchant"; + case ADVENTURERECRUITER: + return "Adventure Recruiter"; + case ADVENTUREMERCHANT: + return "Adventure Merchant"; + case CORPSE_CLASS: + return "Corpse Class"; + case TRIBUTE_MASTER: + return "Tribute Master"; + case GUILD_TRIBUTE_MASTER: + return "Guild Tribute Master"; + default: + return "Unknown"; } } -const char* GetPlayerClassName(uint32 player_class_value, uint8 level) +const char *GetPlayerClassName(uint32 player_class_value, uint8 level) { return GetClassIDName(GetClassIDFromPlayerClassValue(player_class_value), level); } @@ -299,295 +401,295 @@ const char* GetPlayerClassName(uint32 player_class_value, uint8 level) uint32 GetPlayerClassValue(uint8 class_id) { switch (class_id) { - case WARRIOR: - case CLERIC: - case PALADIN: - case RANGER: - case SHADOWKNIGHT: - case DRUID: - case MONK: - case BARD: - case ROGUE: - case SHAMAN: - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - case BEASTLORD: - case BERSERKER: - return class_id; - default: - return PLAYER_CLASS_UNKNOWN; // watch + case WARRIOR: + case CLERIC: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case DRUID: + case MONK: + case BARD: + case ROGUE: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + case BEASTLORD: + case BERSERKER: + return class_id; + default: + return PLAYER_CLASS_UNKNOWN; // watch } } uint32 GetPlayerClassBit(uint8 class_id) { switch (class_id) { - case WARRIOR: - return PLAYER_CLASS_WARRIOR_BIT; - case CLERIC: - return PLAYER_CLASS_CLERIC_BIT; - case PALADIN: - return PLAYER_CLASS_PALADIN_BIT; - case RANGER: - return PLAYER_CLASS_RANGER_BIT; - case SHADOWKNIGHT: - return PLAYER_CLASS_SHADOWKNIGHT_BIT; - case DRUID: - return PLAYER_CLASS_DRUID_BIT; - case MONK: - return PLAYER_CLASS_MONK_BIT; - case BARD: - return PLAYER_CLASS_BARD_BIT; - case ROGUE: - return PLAYER_CLASS_ROGUE_BIT; - case SHAMAN: - return PLAYER_CLASS_SHAMAN_BIT; - case NECROMANCER: - return PLAYER_CLASS_NECROMANCER_BIT; - case WIZARD: - return PLAYER_CLASS_WIZARD_BIT; - case MAGICIAN: - return PLAYER_CLASS_MAGICIAN_BIT; - case ENCHANTER: - return PLAYER_CLASS_ENCHANTER_BIT; - case BEASTLORD: - return PLAYER_CLASS_BEASTLORD_BIT; - case BERSERKER: - return PLAYER_CLASS_BERSERKER_BIT; - default: - return PLAYER_CLASS_UNKNOWN_BIT; + case WARRIOR: + return PLAYER_CLASS_WARRIOR_BIT; + case CLERIC: + return PLAYER_CLASS_CLERIC_BIT; + case PALADIN: + return PLAYER_CLASS_PALADIN_BIT; + case RANGER: + return PLAYER_CLASS_RANGER_BIT; + case SHADOWKNIGHT: + return PLAYER_CLASS_SHADOWKNIGHT_BIT; + case DRUID: + return PLAYER_CLASS_DRUID_BIT; + case MONK: + return PLAYER_CLASS_MONK_BIT; + case BARD: + return PLAYER_CLASS_BARD_BIT; + case ROGUE: + return PLAYER_CLASS_ROGUE_BIT; + case SHAMAN: + return PLAYER_CLASS_SHAMAN_BIT; + case NECROMANCER: + return PLAYER_CLASS_NECROMANCER_BIT; + case WIZARD: + return PLAYER_CLASS_WIZARD_BIT; + case MAGICIAN: + return PLAYER_CLASS_MAGICIAN_BIT; + case ENCHANTER: + return PLAYER_CLASS_ENCHANTER_BIT; + case BEASTLORD: + return PLAYER_CLASS_BEASTLORD_BIT; + case BERSERKER: + return PLAYER_CLASS_BERSERKER_BIT; + default: + return PLAYER_CLASS_UNKNOWN_BIT; } } uint8 GetClassIDFromPlayerClassValue(uint32 player_class_value) { switch (player_class_value) { - case PLAYER_CLASS_WARRIOR: - case PLAYER_CLASS_CLERIC: - case PLAYER_CLASS_PALADIN: - case PLAYER_CLASS_RANGER: - case PLAYER_CLASS_SHADOWKNIGHT: - case PLAYER_CLASS_DRUID: - case PLAYER_CLASS_MONK: - case PLAYER_CLASS_BARD: - case PLAYER_CLASS_ROGUE: - case PLAYER_CLASS_SHAMAN: - case PLAYER_CLASS_NECROMANCER: - case PLAYER_CLASS_WIZARD: - case PLAYER_CLASS_MAGICIAN: - case PLAYER_CLASS_ENCHANTER: - case PLAYER_CLASS_BEASTLORD: - case PLAYER_CLASS_BERSERKER: - return player_class_value; - default: - return PLAYER_CLASS_UNKNOWN; // watch + case PLAYER_CLASS_WARRIOR: + case PLAYER_CLASS_CLERIC: + case PLAYER_CLASS_PALADIN: + case PLAYER_CLASS_RANGER: + case PLAYER_CLASS_SHADOWKNIGHT: + case PLAYER_CLASS_DRUID: + case PLAYER_CLASS_MONK: + case PLAYER_CLASS_BARD: + case PLAYER_CLASS_ROGUE: + case PLAYER_CLASS_SHAMAN: + case PLAYER_CLASS_NECROMANCER: + case PLAYER_CLASS_WIZARD: + case PLAYER_CLASS_MAGICIAN: + case PLAYER_CLASS_ENCHANTER: + case PLAYER_CLASS_BEASTLORD: + case PLAYER_CLASS_BERSERKER: + return player_class_value; + default: + return PLAYER_CLASS_UNKNOWN; // watch } } uint8 GetClassIDFromPlayerClassBit(uint32 player_class_bit) { switch (player_class_bit) { - case PLAYER_CLASS_WARRIOR_BIT: - return WARRIOR; - case PLAYER_CLASS_CLERIC_BIT: - return CLERIC; - case PLAYER_CLASS_PALADIN_BIT: - return PALADIN; - case PLAYER_CLASS_RANGER_BIT: - return RANGER; - case PLAYER_CLASS_SHADOWKNIGHT_BIT: - return SHADOWKNIGHT; - case PLAYER_CLASS_DRUID_BIT: - return DRUID; - case PLAYER_CLASS_MONK_BIT: - return MONK; - case PLAYER_CLASS_BARD_BIT: - return BARD; - case PLAYER_CLASS_ROGUE_BIT: - return ROGUE; - case PLAYER_CLASS_SHAMAN_BIT: - return SHAMAN; - case PLAYER_CLASS_NECROMANCER_BIT: - return NECROMANCER; - case PLAYER_CLASS_WIZARD_BIT: - return WIZARD; - case PLAYER_CLASS_MAGICIAN_BIT: - return MAGICIAN; - case PLAYER_CLASS_ENCHANTER_BIT: - return ENCHANTER; - case PLAYER_CLASS_BEASTLORD_BIT: - return BEASTLORD; - case PLAYER_CLASS_BERSERKER_BIT: - return BERSERKER; - default: - return PLAYER_CLASS_UNKNOWN; // watch + case PLAYER_CLASS_WARRIOR_BIT: + return WARRIOR; + case PLAYER_CLASS_CLERIC_BIT: + return CLERIC; + case PLAYER_CLASS_PALADIN_BIT: + return PALADIN; + case PLAYER_CLASS_RANGER_BIT: + return RANGER; + case PLAYER_CLASS_SHADOWKNIGHT_BIT: + return SHADOWKNIGHT; + case PLAYER_CLASS_DRUID_BIT: + return DRUID; + case PLAYER_CLASS_MONK_BIT: + return MONK; + case PLAYER_CLASS_BARD_BIT: + return BARD; + case PLAYER_CLASS_ROGUE_BIT: + return ROGUE; + case PLAYER_CLASS_SHAMAN_BIT: + return SHAMAN; + case PLAYER_CLASS_NECROMANCER_BIT: + return NECROMANCER; + case PLAYER_CLASS_WIZARD_BIT: + return WIZARD; + case PLAYER_CLASS_MAGICIAN_BIT: + return MAGICIAN; + case PLAYER_CLASS_ENCHANTER_BIT: + return ENCHANTER; + case PLAYER_CLASS_BEASTLORD_BIT: + return BEASTLORD; + case PLAYER_CLASS_BERSERKER_BIT: + return BERSERKER; + default: + return PLAYER_CLASS_UNKNOWN; // watch } } bool IsFighterClass(uint8 class_id) { switch (class_id) { - case WARRIOR: - case PALADIN: - case RANGER: - case SHADOWKNIGHT: - case MONK: - case BARD: - case ROGUE: - case BEASTLORD: - case BERSERKER: - return true; - default: - return false; + case WARRIOR: + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case MONK: + case BARD: + case ROGUE: + case BEASTLORD: + case BERSERKER: + return true; + default: + return false; } } bool IsSpellFighterClass(uint8 class_id) { switch (class_id) { - case PALADIN: - case RANGER: - case SHADOWKNIGHT: - case BEASTLORD: - return true; - default: - return false; + case PALADIN: + case RANGER: + case SHADOWKNIGHT: + case BEASTLORD: + return true; + default: + return false; } } bool IsNonSpellFighterClass(uint8 class_id) { switch (class_id) { - case WARRIOR: - case MONK: - case BARD: - case ROGUE: - case BERSERKER: - return true; - default: - return false; + case WARRIOR: + case MONK: + case BARD: + case ROGUE: + case BERSERKER: + return true; + default: + return false; } } bool IsCasterClass(uint8 class_id) { switch (class_id) { - case CLERIC: - case DRUID: - case SHAMAN: - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - return true; - default: - return false; + case CLERIC: + case DRUID: + case SHAMAN: + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; } } bool IsINTCasterClass(uint8 class_id) { switch (class_id) { - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - return true; - default: - return false; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; } } bool IsWISCasterClass(uint8 class_id) { switch (class_id) { - case CLERIC: - case DRUID: - case SHAMAN: - return true; - default: - return false; + case CLERIC: + case DRUID: + case SHAMAN: + return true; + default: + return false; } } bool IsPlateClass(uint8 class_id) { switch (class_id) { - case WARRIOR: - case CLERIC: - case PALADIN: - case SHADOWKNIGHT: - case BARD: - return true; - default: - return false; + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case BARD: + return true; + default: + return false; } } bool IsChainClass(uint8 class_id) { switch (class_id) { - case RANGER: - case ROGUE: - case SHAMAN: - case BERSERKER: - return true; - default: - return false; + case RANGER: + case ROGUE: + case SHAMAN: + case BERSERKER: + return true; + default: + return false; } } bool IsLeatherClass(uint8 class_id) { switch (class_id) { - case DRUID: - case MONK: - case BEASTLORD: - return true; - default: - return false; + case DRUID: + case MONK: + case BEASTLORD: + return true; + default: + return false; } } bool IsClothClass(uint8 class_id) { switch (class_id) { - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - return true; - default: - return false; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return true; + default: + return false; } } uint8 ClassArmorType(uint8 class_id) { switch (class_id) { - case WARRIOR: - case CLERIC: - case PALADIN: - case SHADOWKNIGHT: - case BARD: - return ARMOR_TYPE_PLATE; - case RANGER: - case ROGUE: - case SHAMAN: - case BERSERKER: - return ARMOR_TYPE_CHAIN; - case DRUID: - case MONK: - case BEASTLORD: - return ARMOR_TYPE_LEATHER; - case NECROMANCER: - case WIZARD: - case MAGICIAN: - case ENCHANTER: - return ARMOR_TYPE_CLOTH; - default: - return ARMOR_TYPE_UNKNOWN; + case WARRIOR: + case CLERIC: + case PALADIN: + case SHADOWKNIGHT: + case BARD: + return ARMOR_TYPE_PLATE; + case RANGER: + case ROGUE: + case SHAMAN: + case BERSERKER: + return ARMOR_TYPE_CHAIN; + case DRUID: + case MONK: + case BEASTLORD: + return ARMOR_TYPE_LEATHER; + case NECROMANCER: + case WIZARD: + case MAGICIAN: + case ENCHANTER: + return ARMOR_TYPE_CLOTH; + default: + return ARMOR_TYPE_UNKNOWN; } } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 797075108..7485d7451 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -809,6 +809,16 @@ void Client::CompleteConnect() std::string event_desc = StringFormat("Connect :: Logged into zoneid:%i instid:%i", this->GetZoneID(), this->GetInstanceID()); QServ->PlayerLogEvent(Player_Log_Connect_State, this->CharacterID(), event_desc); } + + /** + * Update last login since this doesn't get updated until a late save later so we can update online status + */ + database.QueryDatabase( + StringFormat( + "UPDATE `character_data` SET `last_login` = UNIX_TIMESTAMP() WHERE id = %u", + this->CharacterID() + ) + ); } if (zone) { diff --git a/zone/command.cpp b/zone/command.cpp index d6e28ddf3..5224d4c83 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -413,6 +413,7 @@ int command_init(void) command_add("viewpetition", "[petition number] - View a petition", 20, command_viewpetition) || command_add("wc", "[wear slot] [material] - Sends an OP_WearChange for your target", 200, command_wc) || command_add("weather", "[0/1/2/3] (Off/Rain/Snow/Manual) - Change the weather", 80, command_weather) || + command_add("who", "[search]", 20, command_who) || command_add("worldshutdown", "- Shut down world and all zones", 200, command_worldshutdown) || command_add("wp", "[add/delete] [grid_num] [pause] [wp_num] [-h] - Add/delete a waypoint to/from a wandering grid", 170, command_wp) || command_add("wpadd", "[pause] [-h] - Add your current location as a waypoint to your NPC target's AI path", 170, command_wpadd) || @@ -2262,10 +2263,12 @@ void command_sendzonespawns(Client *c, const Seperator *sep) void command_zsave(Client *c, const Seperator *sep) { - if(zone->SaveZoneCFG()) + if (zone->SaveZoneCFG()) { c->Message(13, "Zone header saved successfully."); - else + } + else { c->Message(13, "ERROR: Zone header data was NOT saved."); + } } void command_dbspawn2(Client *c, const Seperator *sep) @@ -11837,6 +11840,126 @@ void command_scale(Client *c, const Seperator *sep) } } +void command_who(Client *c, const Seperator *sep) +{ + std::string query = + "SELECT\n" + " character_data.account_id,\n" + " character_data.name,\n" + " character_data.zone_id,\n" + " COALESCE((select zone.short_name from zone where zoneidnumber = character_data.zone_id LIMIT 1), \"Not Found\") as zone_name,\n" + " character_data.zone_instance,\n" + " COALESCE((select guilds.name from guilds where id = ((select guild_id from guild_members where char_id = character_data.id))), \"\") as guild_name,\n" + " character_data.level,\n" + " character_data.race,\n" + " character_data.class,\n" + " COALESCE((select account.status from account where account.id = character_data.account_id LIMIT 1), 0) as account_status,\n" + " COALESCE((select account.name from account where account.id = character_data.account_id LIMIT 1), \"\") as account_name,\n" + " COALESCE((select account_ip.ip from account_ip where account_ip.accid = character_data.account_id ORDER BY account_ip.lastused DESC LIMIT 1), \"\") as account_ip\n" + "FROM\n" + " character_data\n" + "WHERE\n" + " last_login > (UNIX_TIMESTAMP() - 600)\n" + "ORDER BY character_data.name;"; + + auto results = database.QueryDatabase(query); + if (!results.Success()) + return; + + if (results.RowCount() == 0) { + c->Message(15, "No results found"); + return; + } + + std::string search_string; + + if (sep->arg[1]) { + search_string = str_tolower(sep->arg[1]); + } + + int found_count = 0; + + c->Message(5, "Players in EverQuest"); + c->Message(5, "--------------------"); + + for (auto row = results.begin(); row != results.end(); ++row) { + auto account_id = static_cast(atoi(row[0])); + std::string player_name = row[1]; + auto zone_id = static_cast(atoi(row[2])); + std::string zone_short_name = row[3]; + auto zone_instance = static_cast(atoi(row[4])); + std::string guild_name = row[5]; + auto player_level = static_cast(atoi(row[6])); + auto player_race = static_cast(atoi(row[7])); + auto player_class = static_cast(atoi(row[8])); + auto account_status = static_cast(atoi(row[9])); + std::string account_name = row[10]; + std::string account_ip = row[11]; + + std::string base_class_name = GetClassIDName(static_cast(player_class), 1); + std::string displayed_race_name = GetRaceIDName(static_cast(player_race)); + + if (search_string.length() > 0) { + bool found_search_term = + ( + str_tolower(player_name).find(search_string) != std::string::npos || + str_tolower(zone_short_name).find(search_string) != std::string::npos || + str_tolower(displayed_race_name).find(search_string) != std::string::npos || + str_tolower(base_class_name).find(search_string) != std::string::npos || + str_tolower(guild_name).find(search_string) != std::string::npos || + str_tolower(account_name).find(search_string) != std::string::npos || + str_tolower(account_ip).find(search_string) != std::string::npos + ); + + if (!found_search_term) { + continue; + } + } + + std::string displayed_guild_name; + if (guild_name.length() > 0) { + displayed_guild_name = EQEmu::SayLinkEngine::GenerateQuestSaylink( + StringFormat( + "#who \"%s\"", + guild_name.c_str()), + false, + StringFormat("<%s>", guild_name.c_str()) + ); + } + + std::string goto_saylink = EQEmu::SayLinkEngine::GenerateQuestSaylink( + StringFormat("#goto %s", player_name.c_str()), false, "Goto" + ); + + std::string display_class_name = GetClassIDName(static_cast(player_class), static_cast(player_level)); + + c->Message( + 5, "%s[%u %s] %s (%s) %s ZONE: %s (%u) (%s) (%s) (%s)", + (account_status > 0 ? "* GM * " : ""), + player_level, + EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", base_class_name.c_str()), false, display_class_name).c_str(), + player_name.c_str(), + EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", displayed_race_name.c_str()), false, displayed_race_name).c_str(), + displayed_guild_name.c_str(), + EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", zone_short_name.c_str()), false, zone_short_name).c_str(), + zone_instance, + goto_saylink.c_str(), + EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_name.c_str()), false, account_name).c_str(), + EQEmu::SayLinkEngine::GenerateQuestSaylink(StringFormat("#who %s", account_ip.c_str()), false, account_ip).c_str() + ); + + found_count++; + } + + std::string message = ( + found_count > 0 ? + StringFormat("There is %i player(s) in EverQuest", found_count).c_str() : + "There are no players in EverQuest that match those who filters." + ); + + c->Message(5, message.c_str()); +} + // All new code added to command.cpp should be BEFORE this comment line. Do no append code to this file below the BOTS code block. #ifdef BOTS #include "bot_command.h" diff --git a/zone/command.h b/zone/command.h index 0a4eec014..ae029cc9d 100644 --- a/zone/command.h +++ b/zone/command.h @@ -325,6 +325,7 @@ void command_viewnpctype(Client *c, const Seperator *sep); void command_viewpetition(Client *c, const Seperator *sep); void command_wc(Client *c, const Seperator *sep); void command_weather(Client *c, const Seperator *sep); +void command_who(Client *c, const Seperator *sep); void command_worldshutdown(Client *c, const Seperator *sep); void command_wp(Client *c, const Seperator *sep); void command_wpadd(Client *c, const Seperator *sep); From 7c15d332c5b15da3b1b5aa79b2b767edd9fabe43 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 01:33:38 -0600 Subject: [PATCH 16/38] Implemented: #gmzone [zone_short_name] [zone_version=0] [identifier=gmzone] - Zones to a private GM instance --- changelog.txt | 4 +- zone/command.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++----- zone/command.h | 1 + 3 files changed, 90 insertions(+), 10 deletions(-) diff --git a/changelog.txt b/changelog.txt index 54c61f19f..e2c0463cf 100644 --- a/changelog.txt +++ b/changelog.txt @@ -18,7 +18,9 @@ Akkadius: - Zone Short Name - Features a clickable (Goto) saylink that will bring you directly to a player regardless of whether or not they are in an instance - + - [Command] Implemented: #gmzone [zone_short_name] [zone_version=0] [identifier=gmzone] + - Zones to a private GM instance + - Example: https://i.imgur.com/qswdrzO.gif == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing - Server honors expansions that alter bank size and power source, general9 and general10 slots diff --git a/zone/command.cpp b/zone/command.cpp index 5224d4c83..196a97463 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -219,6 +219,7 @@ int command_init(void) command_add("globalview", "Lists all qglobals in cache if you were to do a quest with this target.", 80, command_globalview) || command_add("gm", "- Turn player target's or your GM flag on or off", 80, command_gm) || command_add("gmspeed", "[on/off] - Turn GM speed hack on/off for you or your player target", 100, command_gmspeed) || + command_add("gmzone", "[zone_short_name] [zone_version=0] [identifier=gmzone] - Zones to a private GM instance", 100, command_gmzone) || command_add("goto", "[x] [y] [z] - Teleport to the provided coordinates or to your target", 10, command_goto) || command_add("grid", "[add/delete] [grid_num] [wandertype] [pausetype] - Create/delete a wandering grid", 170, command_grid) || command_add("guild", "- Guild manipulation commands. Use argument help for more info.", 10, command_guild) || @@ -4429,18 +4430,94 @@ void command_fixmob(Client *c, const Seperator *sep) void command_gmspeed(Client *c, const Seperator *sep) { - bool state=atobool(sep->arg[1]); - Client *t=c; + bool state = atobool(sep->arg[1]); + Client *t = c; - if(c->GetTarget() && c->GetTarget()->IsClient()) - t=c->GetTarget()->CastToClient(); - - if(sep->arg[1][0] != 0) { - database.SetGMSpeed(t->AccountID(), state?1:0); - c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state?"On":"Off", t->GetName()); + if (c->GetTarget() && c->GetTarget()->IsClient()) { + t = c->GetTarget()->CastToClient(); } - else + + if (sep->arg[1][0] != 0) { + database.SetGMSpeed(t->AccountID(), state ? 1 : 0); + c->Message(0, "Turning GMSpeed %s for %s (zone to take effect)", state ? "On" : "Off", t->GetName()); + } + else { c->Message(0, "Usage: #gmspeed [on/off]"); + } +} + +void command_gmzone(Client *c, const Seperator *sep) +{ + if (!sep->arg[1]) { + c->Message(0, "Usage"); + c->Message(0, "-------"); + c->Message(0, "#gmzone [zone_short_name] [zone_version=0]"); + return; + } + + std::string zone_short_name_string = sep->arg[1]; + const char *zone_short_name = sep->arg[1]; + auto zone_version = static_cast(sep->arg[2] ? atoi(sep->arg[2]) : 0); + std::string identifier = "gmzone"; + uint32 zone_id = database.GetZoneID(zone_short_name); + uint32 duration = 100000000; + uint16 instance_id = 0; + + if (zone_id == 0) { + c->Message(13, "Invalid zone specified"); + return; + } + + if (sep->arg[3] && sep->arg[3][0]) { + identifier = sep->arg[3]; + } + + std::string bucket_key = StringFormat("%s-%s-instance", zone_short_name, identifier.c_str()); + std::string existing_zone_instance = DataBucket::GetData(bucket_key); + + if (existing_zone_instance.length() > 0) { + instance_id = std::stoi(existing_zone_instance); + + c->Message(15, "Found already created instance (%s) (%u)", zone_short_name, instance_id); + } + + if (instance_id == 0) { + if (!database.GetUnusedInstanceID(instance_id)) { + c->Message(13, "Server was unable to find a free instance id."); + return; + } + + if (!database.CreateInstance(instance_id, zone_id, zone_version, duration)) { + c->Message(13, "Server was unable to create a new instance."); + return; + } + + c->Message(15, "New private GM instance %s was created with id %lu.", zone_short_name, (unsigned long) instance_id); + DataBucket::SetData(bucket_key, std::to_string(instance_id)); + } + + if (instance_id > 0) { + float target_x = -1, target_y = -1, target_z = -1; + int16 min_status = 0; + uint8 min_level = 0; + + if (!database.GetSafePoints( + zone_short_name, + zone_version, + &target_x, + &target_y, + &target_z, + &min_status, + &min_level + )) { + c->Message(13, "Failed to find safe coordinates for specified zone"); + } + + c->Message(15, "Zoning to private GM instance (%s) (%u)", zone_short_name, instance_id); + + c->AssignToInstance(instance_id); + c->MovePC(zone_id, instance_id, target_x, target_y, target_z, 0, 1); + } } void command_title(Client *c, const Seperator *sep) diff --git a/zone/command.h b/zone/command.h index ae029cc9d..21ea58919 100644 --- a/zone/command.h +++ b/zone/command.h @@ -117,6 +117,7 @@ void command_givemoney(Client *c, const Seperator *sep); void command_globalview(Client* c, const Seperator *sep); void command_gm(Client *c, const Seperator *sep); void command_gmspeed(Client *c, const Seperator *sep); +void command_gmzone(Client *c, const Seperator *sep); void command_goto(Client *c, const Seperator *sep); void command_grid(Client *c, const Seperator *sep); void command_guild(Client *c, const Seperator *sep); From 90b9e51f70580666d9091ed95f5b5e364c098173 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 01:37:38 -0600 Subject: [PATCH 17/38] Fix issue where NPC's clip into the world and the client interprets them at 0,0,0 --- zone/entity.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/zone/entity.cpp b/zone/entity.cpp index 9b31abc2b..7b8e0880c 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -650,8 +650,6 @@ void EntityList::AddNPC(NPC *npc, bool SendSpawnPacket, bool dontqueue) parse->EventNPC(EVENT_SPAWN, npc, nullptr, "", 0); - npc->FixZ(); - uint16 emoteid = npc->GetEmoteID(); if (emoteid != 0) npc->DoNPCEmote(ONSPAWN, emoteid); From fdae56e89fc489f0f033c23c4cc29da5c399b8c4 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 01:39:13 -0600 Subject: [PATCH 18/38] Update changelog.txt [skip ci] --- changelog.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.txt b/changelog.txt index e2c0463cf..d6bae58d2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -21,6 +21,9 @@ Akkadius: - [Command] Implemented: #gmzone [zone_short_name] [zone_version=0] [identifier=gmzone] - Zones to a private GM instance - Example: https://i.imgur.com/qswdrzO.gif + - [NPC] Fix issue where NPC's clip into the world and the client interprets them at 0,0,0 + - This issue would show itself when NPC's would bunch up by a zone-in + == 1/15/2019 == Uleat: Activated per-expansion support for active inventory slot addressing - Server honors expansions that alter bank size and power source, general9 and general10 slots From e5fce0fd4dafb711425c7d48470e0760c18ce143 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 01:44:35 -0600 Subject: [PATCH 19/38] Remove debug std::cout [skip ci] --- zone/mob_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/mob_info.cpp b/zone/mob_info.cpp index 2de8e68ec..1382e5c97 100644 --- a/zone/mob_info.cpp +++ b/zone/mob_info.cpp @@ -817,7 +817,7 @@ void Mob::DisplayInfo(Mob *mob) NPCCommandsMenu(client, npc); } - std::cout << "Window Length: " << window_text.length() << std::endl; + // std::cout << "Window Length: " << window_text.length() << std::endl; if (client->GetDisplayMobInfoWindow()) { client->SendFullPopup( From f5b28a0b243be251678d6fa510520376ac5fe67f Mon Sep 17 00:00:00 2001 From: Akkadius Date: Mon, 21 Jan 2019 02:30:05 -0600 Subject: [PATCH 20/38] Filter invis NPC's in #killallnpcs --- zone/command.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/zone/command.cpp b/zone/command.cpp index 196a97463..8c64c44a4 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -5260,7 +5260,15 @@ void command_killallnpcs(Client *c, const Seperator *sep) continue; } - if (entity->IsInvisible() || !entity->IsAttackAllowed(c)) { + bool is_not_attackable = + ( + entity->IsInvisible() || + !entity->IsAttackAllowed(c) || + entity->GetRace() == 127 || + entity->GetRace() == 240 + ); + + if (is_not_attackable) { continue; } From 32b161fd57b7643a9cf63804c576baa0ce6cdd19 Mon Sep 17 00:00:00 2001 From: Kinglykrab Date: Mon, 21 Jan 2019 19:10:48 -0500 Subject: [PATCH 21/38] Adds dynamic rule capabilities to quests in LUA/Perl. - quest::set_rule(string rule_name, string rule_value) Example: quest::set_rule("Zone:UseZoneController", "false") - Sets the rule "Zone:UseZoneController" to "false" for the current zone. - quest::get_rule(string rule_name) Example: quest::get_rule("Zone:UseZoneController") - Returns true/false depending upon if it's enabled/disabled. - Example NPC script here: https://pastebin.com/akKKN2NS --- zone/embparser_api.cpp | 32 ++++++++++++++++++++++++++++++++ zone/lua_general.cpp | 12 ++++++++++++ 2 files changed, 44 insertions(+) diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index 86b72e1b8..154e28566 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -3622,6 +3622,36 @@ XS(XS__UpdateZoneHeader) { XSRETURN_EMPTY; } +XS(XS__set_rule); +XS(XS__set_rule) { + dXSARGS; + if (items != 2) + Perl_croak(aTHX_ "Usage: quest::set_rule(string rule_name, string rule_value)"); + + std::string rule_name = (std::string) SvPV_nolen(ST(0)); + std::string rule_value = (std::string) SvPV_nolen(ST(1)); + RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str()); + + XSRETURN_EMPTY; +} + +XS(XS__get_rule); +XS(XS__get_rule) { + dXSARGS; + if (items != 1) + Perl_croak(aTHX_ "Usage: quest::get_rule(string rule_name)"); + + dXSTARG; + std::string rule_name = (std::string) SvPV_nolen(ST(0)); + std::string rule_value; + RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value); + + sv_setpv(TARG, rule_value.c_str()); + XSprePUSH; + PUSHTARG; + XSRETURN(1); +} + XS(XS__get_data); XS(XS__get_data) { dXSARGS; @@ -3734,6 +3764,8 @@ EXTERN_C XS(boot_quest) { newXS(strcpy(buf, "GetTimeSeconds"), XS__GetTimeSeconds, file); newXS(strcpy(buf, "GetZoneID"), XS__GetZoneID, file); newXS(strcpy(buf, "GetZoneLongName"), XS__GetZoneLongName, file); + newXS(strcpy(buf, "set_rule"), XS__set_rule, file); + newXS(strcpy(buf, "get_rule"), XS__get_rule, file); newXS(strcpy(buf, "get_data"), XS__get_data, file); newXS(strcpy(buf, "get_data_expires"), XS__get_data_expires, file); newXS(strcpy(buf, "set_data"), XS__set_data, file); diff --git a/zone/lua_general.cpp b/zone/lua_general.cpp index fdb3facc9..9dd1d8c9b 100644 --- a/zone/lua_general.cpp +++ b/zone/lua_general.cpp @@ -814,6 +814,16 @@ std::string lua_say_link(const char *phrase) { return quest_manager.saylink(text, false, text); } +void lua_set_rule(std::string rule_name, std::string rule_value) { + RuleManager::Instance()->SetRule(rule_name.c_str(), rule_value.c_str()); +} + +std::string lua_get_rule(std::string rule_name) { + std::string rule_value; + RuleManager::Instance()->GetRule(rule_name.c_str(), rule_value); + return rule_value; +} + std::string lua_get_data(std::string bucket_key) { return DataBucket::GetData(bucket_key); } @@ -1687,6 +1697,8 @@ luabind::scope lua_register_general() { luabind::def("say_link", (std::string(*)(const char*,bool,const char*))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*,bool))&lua_say_link), luabind::def("say_link", (std::string(*)(const char*))&lua_say_link), + luabind::def("set_rule", (void(*)(std::string, std::string))&lua_set_rule), + luabind::def("get_rule", (std::string(*)(std::string))&lua_get_rule), luabind::def("get_data", (std::string(*)(std::string))&lua_get_data), luabind::def("get_data_expires", (std::string(*)(std::string))&lua_get_data_expires), luabind::def("set_data", (void(*)(std::string, std::string))&lua_set_data), From ce610db166bae7dedb582b8ea76361a8b12ae62a Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 02:16:02 -0600 Subject: [PATCH 22/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index f4adff7a2..61d3ccce2 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -2161,7 +2161,7 @@ sub run_database_check{ } #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $revision_check; $i < $binary_database_version; $i++){ + for($i = $revision_check; $i <= $binary_database_version; $i++){ if(!defined($m_d{$i}[0])){ next; } $file_name = trim($m_d{$i}[1]); From a6638104ac7079f919e668822da2330674b1c9de Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 02:38:01 -0600 Subject: [PATCH 23/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 3832 +++++++++++++++++---------------- 1 file changed, 1955 insertions(+), 1877 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 61d3ccce2..90a75b724 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -24,32 +24,32 @@ $eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/ #::: Globals $time_stamp = strftime('%m-%d-%Y', gmtime()); $db_run_stage = 0; #::: Sets database run stage check -if($Config{osname}=~/freebsd|linux/i){ - $OS = "Linux"; - $os_flavor = ""; - if(-e "/etc/debian_version"){ - $os_flavor = "debian"; - } - elsif(-e "/etc/fedora-release"){ - $os_flavor = "fedora_core"; - } - elsif(-e "/etc/redhat-release"){ - $os_flavor = "red_hat"; - } +if ($Config{osname} =~ /freebsd|linux/i) { + $OS = "Linux"; + $os_flavor = ""; + if (-e "/etc/debian_version") { + $os_flavor = "debian"; + } + elsif (-e "/etc/fedora-release") { + $os_flavor = "fedora_core"; + } + elsif (-e "/etc/redhat-release") { + $os_flavor = "red_hat"; + } } -if($Config{osname}=~/Win|MS/i){ - $OS = "Windows"; +if ($Config{osname} =~ /Win|MS/i) { + $OS = "Windows"; } $has_internet_connection = check_internet_connection(); -if(-e "skip_internet_connection_check.txt"){ - $has_internet_connection = 1; +if (-e "skip_internet_connection_check.txt") { + $has_internet_connection = 1; } ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(); -if(-e "eqemu_server_skip_update.txt"){ - $skip_self_update_check = 1; +if (-e "eqemu_server_skip_update.txt") { + $skip_self_update_check = 1; } #::: Check for script self update @@ -57,19 +57,19 @@ 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(); -if(-e "eqemu_config.json") { - read_eqemu_config_json(); +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(); + #::: 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 -if(-e "eqemu_update.pl"){ - unlink("eqemu_update.pl"); +if (-e "eqemu_update.pl") { + unlink("eqemu_update.pl"); } print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if $ARGV[0] eq "ran_from_world"; @@ -77,1391 +77,1463 @@ print "[Info] For EQEmu Server management utilities - run eqemu_server.pl\n" if check_db_version_table(); #::: Check if db_version table exists... -if(trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db){ - print get_mysql_result("DROP TABLE db_version"); - print "[Database] Old db_version table present, dropping...\n\n"; +if (trim(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'Revision'")) ne "" && $db) { + print get_mysql_result("DROP TABLE db_version"); + print "[Database] Old db_version table present, dropping...\n\n"; } check_for_world_bootup_database_update(); sub urlencode { - my ($rv) = @_; - $rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge; - return $rv; + my ($rv) = @_; + $rv =~ s/([^A-Za-z0-9])/sprintf("%%%2.2X", ord($1))/ge; + return $rv; } sub urldecode { - my ($rv) = @_; - $rv =~ s/\+/ /g; - $rv =~ s/%(..)/pack("c",hex($1))/ge; - return $rv; + my ($rv) = @_; + $rv =~ s/\+/ /g; + $rv =~ s/%(..)/pack("c", hex($1))/ge; + return $rv; } sub analytics_insertion { - $event_name = urlencode($_[0]); - $event_data = urlencode($_[1]); + $event_name = urlencode($_[0]); + $event_data = urlencode($_[1]); - #::: Check for internet connection before doing analytics - if(!$has_internet_connection || $can_see_analytics_server == -1){ - return; - } + #::: Check for internet connection before doing analytics + if (!$has_internet_connection || $can_see_analytics_server == -1) { + return; + } - #::: Check for analytics server connectivity so that the script doesn't break when its offline - if(!$can_see_analytics_server){ - if($OS eq "Linux"){ - $count = "c"; - } - if($OS eq "Windows"){ - $count = "n"; - } + #::: Check for analytics server connectivity so that the script doesn't break when its offline + if (!$can_see_analytics_server) { + if ($OS eq "Linux") { + $count = "c"; + } + if ($OS eq "Windows") { + $count = "n"; + } - if (`ping analytics.akkadius.com -$count 1 -w 500`=~/Reply from|1 received/i) { - $can_see_analytics_server = 1; - } - else { - $can_see_analytics_server = -1; - } - } + if (`ping analytics.akkadius.com -$count 1 -w 500` =~ /Reply from|1 received/i) { + $can_see_analytics_server = 1; + } + else { + $can_see_analytics_server = -1; + } + } - $server_name = ""; - if($long_name){ - $server_name = "&server_name=" . urlencode($long_name); - } + $server_name = ""; + if ($long_name) { + $server_name = "&server_name=" . urlencode($long_name); + } - if(!$extended_os){ - if($OS eq "Linux"){ - $extended_os = `cat /proc/version`; - $extended_os = trim($extended_os); - } - if($OS eq "Windows"){ - my $output = `ver`; - my @os_version = split("\n", $output); - foreach my $val (@os_version){ - if($val=~/Windows/i){ - $extended_os = trim($val); - } - } - } - } + if (!$extended_os) { + if ($OS eq "Linux") { + $extended_os = `cat /proc/version`; + $extended_os = trim($extended_os); + } + if ($OS eq "Windows") { + my $output = `ver`; + my @os_version = split("\n", $output); + foreach my $val (@os_version) { + if ($val =~ /Windows/i) { + $extended_os = trim($val); + } + } + } + } - $url = "http://analytics.akkadius.com/"; - $url .= "?api_key=24a0bde2e5bacd65bcab06a9ac40b62c"; - $url .= "&event=" . $event_name; - $url .= "&event_data=" . $event_data; - $url .= "&OS=" . urlencode($OS); - $url .= "&extended_os=" . urlencode($extended_os); - $url .= $server_name; + $url = "http://analytics.akkadius.com/"; + $url .= "?api_key=24a0bde2e5bacd65bcab06a9ac40b62c"; + $url .= "&event=" . $event_name; + $url .= "&event_data=" . $event_data; + $url .= "&OS=" . urlencode($OS); + $url .= "&extended_os=" . urlencode($extended_os); + $url .= $server_name; - # print "Calling url :: '" . $url . "'\n"; + # print "Calling url :: '" . $url . "'\n"; - if($OS eq "Windows"){ - eval('require LWP::UserAgent;'); - my $ua = LWP::UserAgent->new; - $ua->timeout(1); - $ua->env_proxy; - my $response = $ua->get($url); - } - if($OS eq "Linux"){ - $api_call = `curl -s "$url"`; - } + if ($OS eq "Windows") { + eval('require LWP::UserAgent;'); + my $ua = LWP::UserAgent->new; + $ua->timeout(1); + $ua->env_proxy; + my $response = $ua->get($url); + } + if ($OS eq "Linux") { + $api_call = `curl -s "$url"`; + } } sub show_install_summary_info { - print "[Install] Installation complete...\n"; - print "[Install] Server Info (Save somewhere if needed):\n"; + print "[Install] Installation complete...\n"; + print "[Install] Server Info (Save somewhere if needed):\n"; - if (-e "install_variables.txt") { - $file_to_open = "install_variables.txt"; - } - elsif (-e "../install_variables.txt") { - $file_to_open = "../install_variables.txt"; - } - open(INSTALL_VARS, $file_to_open); - while () { - chomp; - $o = $_; - @data = split(":", $o); - print " - " . $data[0] . "\t" . $data[1] . "\n"; - } - close(INSTALL_VARS); + if (-e "install_variables.txt") { + $file_to_open = "install_variables.txt"; + } + elsif (-e "../install_variables.txt") { + $file_to_open = "../install_variables.txt"; + } + open(INSTALL_VARS, $file_to_open); + while () { + chomp; + $o = $_; + @data = split(":", $o); + print " - " . $data[0] . "\t" . $data[1] . "\n"; + } + close(INSTALL_VARS); - if ($OS eq "Windows") { - print "[Install] Windows Utility Scripts:\n"; - print " - t_start_server.bat Starts EQEmu server with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; - print " - t_start_server_with_loginserver.bat Starts EQEmu server with 30 zones with loginserver\n"; - print " - t_stop_server.bat Stops EQEmu Server (No warning)\n"; - print " - t_database_backup.bat Backs up the Database to backups/ folder - do not run during server is online\n"; - print " - t_server_crash_report.pl Will parse any zone crashes for reporting to developers\n"; - } - if ($OS eq "Linux") { - print "[Install] Linux Utility Scripts:\n"; - print " - server_start.sh Starts EQEmu server (Quiet) with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; - print " - server_start_dev.sh Starts EQEmu server with 10 dynamic zones, UCS & Queryserv, dynamic zones all verbose\n"; - print " - server_stop.sh Stops EQEmu Server (No warning)\n"; - print " - server_status.sh Prints the status of the EQEmu Server processes\n"; - } + if ($OS eq "Windows") { + print "[Install] Windows Utility Scripts:\n"; + print " - t_start_server.bat Starts EQEmu server with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; + print " - t_start_server_with_loginserver.bat Starts EQEmu server with 30 zones with loginserver\n"; + print " - t_stop_server.bat Stops EQEmu Server (No warning)\n"; + print " - t_database_backup.bat Backs up the Database to backups/ folder - do not run during server is online\n"; + print " - t_server_crash_report.pl Will parse any zone crashes for reporting to developers\n"; + } + if ($OS eq "Linux") { + print "[Install] Linux Utility Scripts:\n"; + print " - server_start.sh Starts EQEmu server (Quiet) with 30 dynamic zones, UCS & Queryserv, dynamic zones\n"; + print " - server_start_dev.sh Starts EQEmu server with 10 dynamic zones, UCS & Queryserv, dynamic zones all verbose\n"; + print " - server_stop.sh Stops EQEmu Server (No warning)\n"; + print " - server_status.sh Prints the status of the EQEmu Server processes\n"; + } - print "[Configure] eqemu_config.xml Edit to change server settings and name\n"; + print "[Configure] eqemu_config.xml Edit to change server settings and name\n"; - analytics_insertion("install_complete", "null"); + analytics_insertion("install_complete", "null"); } sub new_server { - $file_count = 0; - opendir(DIR, ".") or die $!; - while (my $file = readdir(DIR)) { - next if ($file =~ m/^\./); - $file_count++; - } - closedir(DIR); + $file_count = 0; + opendir(DIR, ".") or die $!; + while (my $file = readdir(DIR)) { + next if ($file =~ m/^\./); + $file_count++; + } + closedir(DIR); - if($file_count > 4 && (!-e "install_variables.txt" && !-e "../install_variables.txt")){ - print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; - <>; - exit; - } + if ($file_count > 4 && (!-e "install_variables.txt" && !-e "../install_variables.txt")) { + print "[New Server] ERROR: You must run eqemu_server.pl in an empty directory\n"; + <>; + exit; + } - if(-e "install_variables.txt" || -e "../install_variables.txt"){ - get_installation_variables(); - } + if (-e "install_variables.txt" || -e "../install_variables.txt") { + get_installation_variables(); + } - while(1){ + while (1) { - $database_name = $installation_variables{"mysql_eqemu_db_name"}; - $database_user = $installation_variables{"mysql_eqemu_user"}; - $database_password = $installation_variables{"mysql_eqemu_password"}; + $database_name = $installation_variables{"mysql_eqemu_db_name"}; + $database_user = $installation_variables{"mysql_eqemu_user"}; + $database_password = $installation_variables{"mysql_eqemu_password"}; - if($database_name ne ""){ - $mysql_pass = 1; - } - else { + if ($database_name ne "") { + $mysql_pass = 1; + } + else { - print "\n"; - print "[New Server] For a new server folder install, we assume Perl and MySQL are configured\n"; - print "[New Server] This will install a fresh PEQ Database, with all server assets\n"; - print "[New Server] You will need to supply database credentials to get started...\n\n"; + print "\n"; + print "[New Server] For a new server folder install, we assume Perl and MySQL are configured\n"; + print "[New Server] This will install a fresh PEQ Database, with all server assets\n"; + print "[New Server] You will need to supply database credentials to get started...\n\n"; - check_for_input("MySQL User: "); - $database_user = trim($input); + check_for_input("MySQL User: "); + $database_user = trim($input); - check_for_input("MySQL Password: "); - $database_password = trim($input); + check_for_input("MySQL Password: "); + $database_password = trim($input); - $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; - $mysql_pass = 0; - open (MYSQL_CHECK, "mysqlcheck.txt"); - while (){ - chomp; - $o = $_; - if($o=~/Error/i){ $mysql_pass = 0;} - if($o=~/SHOW PROCESSLIST/i){ $mysql_pass = 1; } - } - close (MYSQL_CHECK); - unlink("mysqlcheck.txt"); - } + $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; + $mysql_pass = 0; + open(MYSQL_CHECK, "mysqlcheck.txt"); + while () { + chomp; + $o = $_; + if ($o =~ /Error/i) {$mysql_pass = 0;} + if ($o =~ /SHOW PROCESSLIST/i) {$mysql_pass = 1;} + } + close(MYSQL_CHECK); + unlink("mysqlcheck.txt"); + } - if($mysql_pass == 1){ + if ($mysql_pass == 1) { - if((!-e "install_variables.txt" && !-e "../install_variables.txt")){ - print "[New Server] Success! We have a database connection\n"; + if ((!-e "install_variables.txt" && !-e "../install_variables.txt")) { + print "[New Server] Success! We have a database connection\n"; - check_for_input("Specify a NEW database name that PEQ will be installed to: "); - $database_name = trim($input); + check_for_input("Specify a NEW database name that PEQ will be installed to: "); + $database_name = trim($input); - #::: Write install vars - open (INSTALL_VARS, '>', 'install_variables.txt'); - print INSTALL_VARS ""; - print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n"; - print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n"; - print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n"; - close (INSTALL_VARS); - } - analytics_insertion("new_server::install", $database_name); + #::: Write install vars + open(INSTALL_VARS, '>', 'install_variables.txt'); + print INSTALL_VARS ""; + print INSTALL_VARS "mysql_eqemu_db_name:" . $database_name . "\n"; + print INSTALL_VARS "mysql_eqemu_user:" . $database_user . "\n"; + print INSTALL_VARS "mysql_eqemu_password:" . $database_password . "\n"; + close(INSTALL_VARS); + } + analytics_insertion("new_server::install", $database_name); - if($OS eq "Linux"){ - build_linux_source("login"); - } + if ($OS eq "Linux") { + build_linux_source("login"); + } - do_installer_routines(); + do_installer_routines(); - if($OS eq "Linux"){ - print `chmod 755 *.sh`; - } + if ($OS eq "Linux") { + print `chmod 755 *.sh`; + } - analytics_insertion("new_server::install_complete", $database_name . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + analytics_insertion("new_server::install_complete", $database_name . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); - print "[New Server] New server folder install complete\n"; - print "[New Server] Below is your installation info:\n"; + print "[New Server] New server folder install complete\n"; + print "[New Server] Below is your installation info:\n"; - show_install_summary_info(); + show_install_summary_info(); - if($OS eq "Linux") { - unlink('/home/eqemu/install_variables.txt'); - } + if ($OS eq "Linux") { + unlink('/home/eqemu/install_variables.txt'); + } - rmtree('updates_staged'); + rmtree('updates_staged'); - return; - } - else { - print "[New Server] MySQL authorization failed or no MySQL installed\n"; - } - } + return; + } + else { + print "[New Server] MySQL authorization failed or no MySQL installed\n"; + } + } } sub check_xml_to_json_conversion { - if(-e "eqemu_config.xml" && !-e "eqemu_config.json") { + 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`; - } + 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(); + #::: 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); + 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); + $result = $json->decode($content); + $json->canonical(1); - print $json->pretty->indent_length(5)->utf8->encode($result),"\n"; + 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; + 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'); + 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"; + 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; - } + exit; + } } sub build_linux_source { - $build_options = $_[0]; + $build_options = $_[0]; - $cmake_options = ""; - $source_folder_post_fix = ""; + $cmake_options = ""; + $source_folder_post_fix = ""; - if($build_options =~/bots/i){ - $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; - $source_folder_post_fix = "_bots"; - } + if ($build_options =~ /bots/i) { + $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; + $source_folder_post_fix = "_bots"; + } - $current_directory = `pwd`; - @directories = split('/', $current_directory); - foreach my $val (@directories){ - if(trim($val) ne ""){ - $last_directory = trim($val); - } - } - my $eqemu_server_directory = "/home/eqemu"; - my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix; + $current_directory = `pwd`; + @directories = split('/', $current_directory); + foreach my $val (@directories) { + if (trim($val) ne "") { + $last_directory = trim($val); + } + } + my $eqemu_server_directory = "/home/eqemu"; + my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix; - $current_directory = trim($current_directory); + $current_directory = trim($current_directory); - mkdir($source_dir) if (!-e $source_dir); + mkdir($source_dir) if (!-e $source_dir); - # print 'server_dir: ' . $eqemu_server_directory . "\n"; - # print 'source_dir: ' . $source_dir . "\n"; - # print 'current_dir: \'' . $current_directory . "'\n"; + # print 'server_dir: ' . $eqemu_server_directory . "\n"; + # print 'source_dir: ' . $source_dir . "\n"; + # print 'current_dir: \'' . $current_directory . "'\n"; - chdir($source_dir); + chdir($source_dir); - print `git clone https://github.com/EQEmu/Server.git`; + print `git clone https://github.com/EQEmu/Server.git`; - mkdir ($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build"); - chdir ($source_dir . "/Server/build"); + mkdir($source_dir . "/Server/build") if (!-e $source_dir . "/Server/build"); + chdir($source_dir . "/Server/build"); - print "Generating CMake build files...\n"; - if($os_flavor eq "fedora_core"){ - 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_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; - } - print "Building EQEmu Server code. This will take a while."; + print "Generating CMake build files...\n"; + if ($os_flavor eq "fedora_core") { + 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_LOGIN=ON -DEQEMU_BUILD_LUA=ON -G "Unix Makefiles" ..`; + } + print "Building EQEmu Server code. This will take a while."; - #::: Build - print `make`; + #::: Build + print `make`; - chdir ($current_directory); + chdir($current_directory); - print `ln -s -f $source_dir/Server/build/bin/eqlaunch .`; - print `ln -s -f $source_dir/Server/build/bin/export_client_files .`; - print `ln -s -f $source_dir/Server/build/bin/import_client_files .`; - print `ln -s -f $source_dir/Server/build/bin/libcommon.a .`; - print `ln -s -f $source_dir/Server/build/bin/libluabind.a .`; - print `ln -s -f $source_dir/Server/build/bin/queryserv .`; - print `ln -s -f $source_dir/Server/build/bin/shared_memory .`; - 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 .`; + print `ln -s -f $source_dir/Server/build/bin/eqlaunch .`; + print `ln -s -f $source_dir/Server/build/bin/export_client_files .`; + print `ln -s -f $source_dir/Server/build/bin/import_client_files .`; + print `ln -s -f $source_dir/Server/build/bin/libcommon.a .`; + print `ln -s -f $source_dir/Server/build/bin/libluabind.a .`; + print `ln -s -f $source_dir/Server/build/bin/queryserv .`; + print `ln -s -f $source_dir/Server/build/bin/shared_memory .`; + 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 { - print "[Install] EQEmu Server Installer... LOADING... PLEASE WAIT...\n"; + print "[Install] EQEmu Server Installer... LOADING... PLEASE WAIT...\n"; - #::: Make some local server directories... - mkdir('logs'); - mkdir('updates_staged'); - mkdir('shared'); + #::: Make some local server directories... + mkdir('logs'); + mkdir('updates_staged'); + mkdir('shared'); - do_install_config_json(); - read_eqemu_config_json(); - get_installation_variables(); + do_install_config_json(); + read_eqemu_config_json(); + get_installation_variables(); - $db_name = "peq"; - if($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } + $db_name = "peq"; + if ($installation_variables{"mysql_eqemu_db_name"}) { + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } - #::: Download assets - if($OS eq "Windows"){ - # fetch_latest_windows_binaries(); - fetch_latest_windows_appveyor(); - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); - } + #::: Download assets + if ($OS eq "Windows") { + # fetch_latest_windows_binaries(); + fetch_latest_windows_appveyor(); + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); + } - map_files_fetch_bulk(); - opcodes_fetch(); - plugins_fetch(); - quest_files_fetch(); - lua_modules_fetch(); - fetch_utility_scripts(); + map_files_fetch_bulk(); + opcodes_fetch(); + plugins_fetch(); + quest_files_fetch(); + lua_modules_fetch(); + fetch_utility_scripts(); - #::: Database Routines - print "[Database] Creating Database '" . $db_name . "'\n"; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; - print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; + #::: Database Routines + print "[Database] Creating Database '" . $db_name . "'\n"; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "DROP DATABASE IF EXISTS $db_name;"`; + print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; - #::: Get Binary DB version - if($OS eq "Windows"){ @db_version = split(': ', `world db_version`); } - if($OS eq "Linux"){ @db_version = split(': ', `./world db_version`); } - $binary_database_version = trim($db_version[1]); + #::: Get Binary DB version + if ($OS eq "Windows") {@db_version = split(': ', `world db_version`);} + if ($OS eq "Linux") {@db_version = split(': ', `./world db_version`);} + $binary_database_version = trim($db_version[1]); - #::: Local DB Version - check_db_version_table(); - $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + #::: Local DB Version + check_db_version_table(); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - #::: Download PEQ latest - fetch_peq_db_full(); - print "[Database] Fetching Latest Database Updates...\n"; - main_db_management(); - print "[Database] Applying Latest Database Updates...\n"; - main_db_management(); + #::: Download PEQ latest + fetch_peq_db_full(); + print "[Database] Fetching Latest Database Updates...\n"; + main_db_management(); + print "[Database] Applying Latest Database Updates...\n"; + main_db_management(); - remove_duplicate_rule_values(); + remove_duplicate_rule_values(); - if($OS eq "Windows"){ - check_windows_firewall_rules(); - do_windows_login_server_setup(); - } - if($OS eq "Linux"){ - do_linux_login_server_setup(); - } + if ($OS eq "Windows") { + check_windows_firewall_rules(); + do_windows_login_server_setup(); + } + if ($OS eq "Linux") { + do_linux_login_server_setup(); + } } sub check_for_input { - print "[Input] " . $_[0]; - $input = ; - chomp $input; + print "[Input] " . $_[0]; + $input = ; + chomp $input; } sub check_for_world_bootup_database_update { - if($OS eq "Windows"){ - @db_version = split(': ', `world db_version`); - } - if($OS eq "Linux"){ - @db_version = split(': ', `./world db_version`); - } + if ($OS eq "Windows") { + @db_version = split(': ', `world db_version`); + } + if ($OS eq "Linux") { + @db_version = split(': ', `./world db_version`); + } - $binary_database_version = trim($db_version[1]); - $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + $binary_database_version = trim($db_version[1]); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); - #::: Bots - $bots_binary_version = trim($db_version[2]); - if($bots_binary_version > 0){ - $bots_local_db_version = get_bots_db_version(); - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + #::: Bots + $bots_binary_version = trim($db_version[2]); + if ($bots_binary_version > 0) { + $bots_local_db_version = get_bots_db_version(); + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup - if($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Bots Database not up to date with binaries... Automatically updating...\n"; - print "[Update] Issuing database backup first...\n"; - database_dump_compress(); - print "[Update] Updating bots database...\n"; - sleep(1); - bots_db_management(); - run_database_check(); - print "[Update] Continuing bootup\n"; - analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + if ($bots_local_db_version < $bots_binary_version && $ARGV[0] eq "ran_from_world") { + print "[Update] Bots Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating bots database...\n"; + sleep(1); + bots_db_management(); + run_database_check(); + print "[Update] Continuing bootup\n"; + analytics_insertion("auto database bots upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); - exit; - } - else { - print "[Update] Bots database up to Date: Continuing World Bootup...\n"; - } - } + exit; + } + else { + print "[Update] Bots database up to Date: Continuing World Bootup...\n"; + } + } - if($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database up to date...\n"; - exit; - } - else { - #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup - if($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world"){ - print "[Update] Database not up to date with binaries... Automatically updating...\n"; - print "[Update] Issuing database backup first...\n"; - database_dump_compress(); - print "[Update] Updating database...\n"; - sleep(1); - main_db_management(); - main_db_management(); - print "[Update] Continuing bootup\n"; - analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); + if ($binary_database_version == $local_database_version && $ARGV[0] eq "ran_from_world") { + print "[Update] Database up to date...\n"; + exit; + } + else { + #::: We ran world - Database needs to update, lets backup and run updates and continue world bootup + if ($local_database_version < $binary_database_version && $ARGV[0] eq "ran_from_world") { + print "[Update] Database not up to date with binaries... Automatically updating...\n"; + print "[Update] Issuing database backup first...\n"; + database_dump_compress(); + print "[Update] Updating database...\n"; + sleep(1); + main_db_management(); + main_db_management(); + print "[Update] Continuing bootup\n"; + analytics_insertion("auto database upgrade world", $db . " :: Binary DB Version / Local DB Version :: " . $binary_database_version . " / " . $local_database_version); - exit; - } + exit; + } - #::: Make sure that we didn't pass any arugments to the script - else { - if(!$db){ print "[eqemu_server.pl] No database connection found... Running without\n"; } - show_menu_prompt(); - } - } + #::: Make sure that we didn't pass any arugments to the script + else { + if (!$db) {print "[eqemu_server.pl] No database connection found... Running without\n";} + show_menu_prompt(); + } + } } sub check_internet_connection { - if($OS eq "Linux"){ - $count = "c"; - } - if($OS eq "Windows"){ - $count = "n"; - } + if ($OS eq "Linux") { + $count = "c"; + } + if ($OS eq "Windows") { + $count = "n"; + } - if (`ping 8.8.8.8 -$count 1 -w 500`=~/TTL|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - elsif (`ping 4.2.2.2 -$count 1 -w 500`=~/TTL|1 received/i) { - # print "[Update] We have a connection to the internet, continuing...\n"; - return 1; - } - else{ - print "[Update] No connection to the internet, can't check update\n"; - return; - } + if (`ping 8.8.8.8 -$count 1 -w 500` =~ /TTL|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + elsif (`ping 4.2.2.2 -$count 1 -w 500` =~ /TTL|1 received/i) { + # print "[Update] We have a connection to the internet, continuing...\n"; + return 1; + } + else { + print "[Update] No connection to the internet, can't check update\n"; + return; + } } sub get_perl_version { - #::: Check Perl version - $perl_version = $^V; - $perl_version =~s/v//g; - print "[Update] Perl Version is " . $perl_version . "\n" if $debug; - if($perl_version > 5.12){ - no warnings 'uninitialized'; - } - no warnings; + #::: Check Perl version + $perl_version = $^V; + $perl_version =~ s/v//g; + print "[Update] Perl Version is " . $perl_version . "\n" if $debug; + if ($perl_version > 5.12) { + no warnings 'uninitialized'; + } + no warnings; } sub get_windows_wget { - if(!-e "wget.exe" && $OS eq "Windows"){ - eval "use LWP::Simple qw(getstore);"; - getstore("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/wget.exe", "wget.exe"); - } + if (!-e "wget.exe" && $OS eq "Windows") { + eval "use LWP::Simple qw(getstore);"; + getstore("https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/wget.exe", "wget.exe"); + } } sub do_self_update_check_routine { - #::: Check for internet connection before updating - if(!$has_internet_connection){ - print "[Update] Cannot check update without internet connection...\n"; - return; - } + #::: Check for internet connection before updating + if (!$has_internet_connection) { + print "[Update] Cannot check update without internet connection...\n"; + return; + } - #::: Check for script changes :: eqemu_server.pl - get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); + #::: Check for script changes :: eqemu_server.pl + get_remote_file($eqemu_repository_request_url . "utils/scripts/eqemu_server.pl", "updates_staged/eqemu_server.pl", 0, 1, 1); - if(-e "updates_staged/eqemu_server.pl") { + if (-e "updates_staged/eqemu_server.pl") { - my $remote_script_size = -s "updates_staged/eqemu_server.pl"; - my $local_script_size = -s "eqemu_server.pl"; + my $remote_script_size = -s "updates_staged/eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; - if($remote_script_size != $local_script_size){ - print "[Update] Script has been updated, updating...\n"; + if ($remote_script_size != $local_script_size) { + print "[Update] Script has been updated, updating...\n"; - my @files; - my $start_dir = "updates_staged/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/eqemu_server/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 eqemu_server.pl"); - } - system("perl eqemu_server.pl start_from_world"); - } - } - print "[Install] Done\n"; - } - else { - print "[Update] No script update necessary...\n"; - } + my @files; + my $start_dir = "updates_staged/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + if ($file =~ /eqemu_server/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 eqemu_server.pl"); + } + system("perl eqemu_server.pl start_from_world"); + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } - unlink("updates_staged/eqemu_server.pl"); - unlink("updates_staged"); - } + unlink("updates_staged/eqemu_server.pl"); + unlink("updates_staged"); + } } -sub get_installation_variables{ - #::: Fetch installation variables before building the config - if($OS eq "Linux"){ - 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"); - } - while (){ - chomp; - $o = $_; - @data = split(":", $o); - $installation_variables{trim($data[0])} = trim($data[1]); - } - close (INSTALL_VARS); +sub get_installation_variables { + #::: Fetch installation variables before building the config + if ($OS eq "Linux") { + 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"); + } + while () { + chomp; + $o = $_; + @data = split(":", $o); + $installation_variables{trim($data[0])} = trim($data[1]); + } + close(INSTALL_VARS); } sub do_install_config_json { - get_installation_variables(); + get_installation_variables(); - #::: Fetch json template - get_remote_file($install_repository_request_url . "eqemu_config.json", "eqemu_config_template.json"); + #::: Fetch json template + get_remote_file($install_repository_request_url . "eqemu_config.json", "eqemu_config_template.json"); - use JSON; - my $json = new JSON(); + 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); + my $content; + open(my $fh, '<', "eqemu_config_template.json") or die "cannot open file $filename"; { + local $/; + $content = <$fh>; + } + close($fh); - $config = $json->decode($content); + $config = $json->decode($content); - $long_name = "Akkas " . $OS . " PEQ Installer (" . generate_random_password(5) . ')'; - $config->{"server"}{"world"}{"longname"} = $long_name; - $config->{"server"}{"world"}{"key"} = generate_random_password(30); + $long_name = "Akkas " . $OS . " PEQ Installer (" . generate_random_password(5) . ')'; + $config->{"server"}{"world"}{"longname"} = $long_name; + $config->{"server"}{"world"}{"key"} = generate_random_password(30); - if($installation_variables{"mysql_eqemu_db_name"}){ - $db_name = $installation_variables{"mysql_eqemu_db_name"}; - } - else { - $db_name = "peq"; - } + if ($installation_variables{"mysql_eqemu_db_name"}) { + $db_name = $installation_variables{"mysql_eqemu_db_name"}; + } + else { + $db_name = "peq"; + } - $config->{"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"}{"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; + $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); + $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; + open(my $fh, '>', 'eqemu_config.json'); + print $fh $json->pretty->indent_length(5)->utf8->encode($config); + close $fh; - unlink("eqemu_config_template.json"); + unlink("eqemu_config_template.json"); } sub fetch_utility_scripts { - if($OS eq "Windows"){ - get_remote_file($install_repository_request_url . "t_database_backup.bat", "t_database_backup.bat"); - get_remote_file($install_repository_request_url . "t_start_server.bat", "t_start_server.bat"); - get_remote_file($install_repository_request_url . "t_server_update_binaries_no_bots.bat", "t_server_update_binaries_no_bots.bat"); - get_remote_file($install_repository_request_url . "t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); - get_remote_file($install_repository_request_url . "t_stop_server.bat", "t_stop_server.bat"); - get_remote_file($install_repository_request_url . "t_server_crash_report.pl", "t_server_crash_report.pl"); - get_remote_file($install_repository_request_url . "win_server_launcher.pl", "win_server_launcher.pl"); - get_remote_file($install_repository_request_url . "t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); - } - else { - get_remote_file($install_repository_request_url . "linux/server_launcher.pl", "server_launcher.pl"); - get_remote_file($install_repository_request_url . "linux/server_start.sh", "server_start.sh"); - get_remote_file($install_repository_request_url . "linux/server_start_dev.sh", "server_start_dev.sh"); - get_remote_file($install_repository_request_url . "linux/server_status.sh", "server_status.sh"); - get_remote_file($install_repository_request_url . "linux/server_stop.sh", "server_stop.sh"); - } + if ($OS eq "Windows") { + get_remote_file($install_repository_request_url . "t_database_backup.bat", "t_database_backup.bat"); + get_remote_file($install_repository_request_url . "t_start_server.bat", "t_start_server.bat"); + get_remote_file($install_repository_request_url . "t_server_update_binaries_no_bots.bat", "t_server_update_binaries_no_bots.bat"); + get_remote_file($install_repository_request_url . "t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); + get_remote_file($install_repository_request_url . "t_stop_server.bat", "t_stop_server.bat"); + get_remote_file($install_repository_request_url . "t_server_crash_report.pl", "t_server_crash_report.pl"); + get_remote_file($install_repository_request_url . "win_server_launcher.pl", "win_server_launcher.pl"); + get_remote_file($install_repository_request_url . "t_start_server_with_login_server.bat", "t_start_server_with_login_server.bat"); + } + else { + get_remote_file($install_repository_request_url . "linux/server_launcher.pl", "server_launcher.pl"); + get_remote_file($install_repository_request_url . "linux/server_start.sh", "server_start.sh"); + get_remote_file($install_repository_request_url . "linux/server_start_dev.sh", "server_start_dev.sh"); + get_remote_file($install_repository_request_url . "linux/server_status.sh", "server_status.sh"); + get_remote_file($install_repository_request_url . "linux/server_stop.sh", "server_stop.sh"); + } } sub setup_bots { - if($OS eq "Windows"){ - fetch_latest_windows_binaries_bots(); - } - if($OS eq "Linux"){ - build_linux_source("bots"); - } - bots_db_management(); - run_database_check(); + if ($OS eq "Windows") { + fetch_latest_windows_binaries_bots(); + } + if ($OS eq "Linux") { + build_linux_source("bots"); + } + bots_db_management(); + run_database_check(); - print "Bots should be setup, run your server and the #bot command should be available in-game\n"; + print "Bots should be setup, run your server and the #bot command should be available in-game\n"; } sub show_menu_prompt { - $dc = 0; - while (1) { + $dc = 0; + while (1) { - if($ARGV[0] ne ""){ - $input = trim($ARGV[0]); - } - else { - $input = trim($input); - } + if ($ARGV[0] ne "") { + $input = trim($ARGV[0]); + } + else { + $input = trim($input); + } - $errored_command = 0; + $errored_command = 0; - if($input eq "database"){ - print "\n>>> Database Menu\n\n"; - print " [backup_database] Back up database to backups/ directory\n"; - print " [backup_player_tables] Back up player tables to backups/ directory\n"; - print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; - print " \n"; - print " [check_db_updates] Checks for database updates manually\n"; - print " [check_bot_db_updates] Checks for bot database updates\n"; - print " \n"; - print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; - print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; - print " [drop_bots_db_schema] Removes bot database schema\n"; + if ($input eq "database") { + print "\n>>> Database Menu\n\n"; + print " [backup_database] Back up database to backups/ directory\n"; + print " [backup_player_tables] Back up player tables to backups/ directory\n"; + print " [backup_database_compressed] Back up database compressed to backups/ directory\n"; + print " \n"; + print " [check_db_updates] Checks for database updates manually\n"; + print " [check_bot_db_updates] Checks for bot database updates\n"; + print " \n"; + print " [aa_tables] Downloads and installs clean slate AA data from PEQ\n"; + print " [remove_duplicate_rules] Removes duplicate rules from rule_values table\n"; + print " [drop_bots_db_schema] Removes bot database schema\n"; - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "conversions"){ - print "\n>>> Conversions Menu\n\n"; - print " [quest_heading_convert] Converts old heading format in quest scripts to new (live format)\n"; - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "assets"){ - print "\n>>> Server Assets Menu\n\n"; - print " [maps] Download latest maps\n"; - print " [opcodes] Download opcodes (Patches for eq clients)\n"; - print " [quests] Download latest quests\n"; - print " [plugins] Download latest plugins\n"; - print " [lua_modules] Download latest lua_modules\n"; - print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; - if($OS eq "Windows") { - print ">>> Windows\n"; - print " [windows_server_download] Updates server via latest 'stable' code\n"; - print " [windows_server_latest] Updates server via latest commit 'unstable'\n"; - print " [windows_server_download_bots] Updates server (bots) from latest 'stable'\n"; - print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; - print " [setup_loginserver] Sets up loginserver for Windows\n"; - } - print " \n> main - go back to main menu\n"; - print "Enter a command #> "; - $last_menu = trim($input); - } - elsif($input eq "backup_database"){ database_dump(); $dc = 1; } - elsif($input eq "backup_player_tables"){ database_dump_player_tables(); $dc = 1; } - elsif($input eq "backup_database_compressed"){ database_dump_compress(); $dc = 1; } - elsif($input eq "drop_bots_db_schema"){ do_bots_db_schema_drop(); $dc = 1; } - elsif($input eq "aa_tables"){ aa_fetch(); $dc = 1; } - elsif($input eq "remove_duplicate_rules"){ remove_duplicate_rule_values(); $dc = 1; } - elsif($input eq "maps"){ map_files_fetch_bulk(); $dc = 1; } - elsif($input eq "opcodes"){ opcodes_fetch(); $dc = 1; } - elsif($input eq "plugins"){ plugins_fetch(); $dc = 1; } - elsif($input eq "quests"){ quest_files_fetch(); $dc = 1; } - elsif($input eq "lua_modules"){ lua_modules_fetch(); $dc = 1; } - elsif($input eq "windows_server_download"){ fetch_latest_windows_binaries(); $dc = 1; } - elsif($input eq "windows_server_latest"){ fetch_latest_windows_appveyor(); $dc = 1; } - elsif($input eq "windows_server_download_bots"){ fetch_latest_windows_binaries_bots(); $dc = 1; } - elsif($input eq "fetch_dlls"){ fetch_server_dlls(); $dc = 1; } - elsif($input eq "utility_scripts"){ fetch_utility_scripts(); $dc = 1; } - elsif($input eq "check_db_updates"){ main_db_management(); main_db_management(); $dc = 1; } - elsif($input eq "check_bot_db_updates"){ bots_db_management(); run_database_check(); $dc = 1; } - 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 "quest_heading_convert"){ quest_heading_convert(); $dc = 1; } - elsif($input eq "source_peq_db"){ fetch_peq_db_full(); $dc = 1; } - elsif($input eq "exit"){ - exit; - } - elsif($input eq "main"){ - print "Returning to main menu...\n"; - print_main_menu(); - $last_menu = trim($input); - } - elsif($input eq "" && $last_menu ne ""){ - $errored_command = 1; - } - elsif($input ne ""){ - print "Invalid command '" . $input . "'\n"; - $errored_command = 1; - } - else { - print_main_menu(); - } + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif ($input eq "conversions") { + print "\n>>> Conversions Menu\n\n"; + print " [quest_heading_convert] Converts old heading format in quest scripts to new (live format)\n"; + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif ($input eq "assets") { + print "\n>>> Server Assets Menu\n\n"; + print " [maps] Download latest maps\n"; + print " [opcodes] Download opcodes (Patches for eq clients)\n"; + print " [quests] Download latest quests\n"; + print " [plugins] Download latest plugins\n"; + print " [lua_modules] Download latest lua_modules\n"; + print " [utility_scripts] Download utility scripts to run and operate the EQEmu Server\n"; + if ($OS eq "Windows") { + print ">>> Windows\n"; + print " [windows_server_download] Updates server via latest 'stable' code\n"; + print " [windows_server_latest] Updates server via latest commit 'unstable'\n"; + print " [windows_server_download_bots] Updates server (bots) from latest 'stable'\n"; + print " [fetch_dlls] Grabs dll's needed to run windows binaries\n"; + print " [setup_loginserver] Sets up loginserver for Windows\n"; + } + print " \n> main - go back to main menu\n"; + print "Enter a command #> "; + $last_menu = trim($input); + } + elsif ($input eq "backup_database") { + database_dump(); + $dc = 1; + } + elsif ($input eq "backup_player_tables") { + database_dump_player_tables(); + $dc = 1; + } + elsif ($input eq "backup_database_compressed") { + database_dump_compress(); + $dc = 1; + } + elsif ($input eq "drop_bots_db_schema") { + do_bots_db_schema_drop(); + $dc = 1; + } + elsif ($input eq "aa_tables") { + aa_fetch(); + $dc = 1; + } + elsif ($input eq "remove_duplicate_rules") { + remove_duplicate_rule_values(); + $dc = 1; + } + elsif ($input eq "maps") { + map_files_fetch_bulk(); + $dc = 1; + } + elsif ($input eq "opcodes") { + opcodes_fetch(); + $dc = 1; + } + elsif ($input eq "plugins") { + plugins_fetch(); + $dc = 1; + } + elsif ($input eq "quests") { + quest_files_fetch(); + $dc = 1; + } + elsif ($input eq "lua_modules") { + lua_modules_fetch(); + $dc = 1; + } + elsif ($input eq "windows_server_download") { + fetch_latest_windows_binaries(); + $dc = 1; + } + elsif ($input eq "windows_server_latest") { + fetch_latest_windows_appveyor(); + $dc = 1; + } + elsif ($input eq "windows_server_download_bots") { + fetch_latest_windows_binaries_bots(); + $dc = 1; + } + elsif ($input eq "fetch_dlls") { + fetch_server_dlls(); + $dc = 1; + } + elsif ($input eq "utility_scripts") { + fetch_utility_scripts(); + $dc = 1; + } + elsif ($input eq "check_db_updates") { + main_db_management(); + $dc = 1; + } + elsif ($input eq "check_bot_db_updates") { + bots_db_management(); + run_database_check(); + $dc = 1; + } + 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 "quest_heading_convert") { + quest_heading_convert(); + $dc = 1; + } + elsif ($input eq "source_peq_db") { + fetch_peq_db_full(); + $dc = 1; + } + elsif ($input eq "exit") { + exit; + } + elsif ($input eq "main") { + print "Returning to main menu...\n"; + print_main_menu(); + $last_menu = trim($input); + } + elsif ($input eq "" && $last_menu ne "") { + $errored_command = 1; + } + elsif ($input ne "") { + print "Invalid command '" . $input . "'\n"; + $errored_command = 1; + } + else { + print_main_menu(); + } - #::: Errored command checking - if($errored_command == 1){ - $input = $last_menu; - } - elsif($dc == 1){ - analytics_insertion("menu", trim($input)); - $dc = 0; - $input = ""; - } - else { - $input = <>; - } + #::: Errored command checking + if ($errored_command == 1) { + $input = $last_menu; + } + elsif ($dc == 1) { + analytics_insertion("menu", trim($input)); + $dc = 0; + $input = ""; + } + else { + $input = <>; + } - #::: If we're processing a CLI command, kill the loop - if($ARGV[0] ne ""){ - analytics_insertion("cli", trim($input)); - $input = ""; - $ARGV[0] = ""; - exit; - } - } + #::: If we're processing a CLI command, kill the loop + if ($ARGV[0] ne "") { + analytics_insertion("cli", trim($input)); + $input = ""; + $ARGV[0] = ""; + exit; + } + } } sub print_main_menu { - print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; - print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; - print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; - print " [database] Enter database management menu \n"; - print " [assets] Manage server assets \n"; - print " [new_server] New folder EQEmu/PEQ install - Assumes MySQL/Perl installed \n"; - print " [setup_bots] Enables bots on server - builds code and database requirements \n"; - print " [conversions] Routines used for conversion of scripts/data \n"; - print "\n"; - print " exit \n"; - print "\n"; - print "Enter a command #> "; + print "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"; + print ">>> EQEmu Server Main Menu >>>>>>>>>>>>\n"; + print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n\n"; + print " [database] Enter database management menu \n"; + print " [assets] Manage server assets \n"; + print " [new_server] New folder EQEmu/PEQ install - Assumes MySQL/Perl installed \n"; + print " [setup_bots] Enables bots on server - builds code and database requirements \n"; + print " [conversions] Routines used for conversion of scripts/data \n"; + print "\n"; + print " exit \n"; + print "\n"; + print "Enter a command #> "; } sub get_mysql_path { - if($OS eq "Windows"){ - $has_mysql_path = `echo %PATH%`; - if($has_mysql_path=~/MySQL|MariaDB/i){ - @mysql = split(';', $has_mysql_path); - foreach my $v (@mysql){ - if($v=~/MySQL|MariaDB/i){ - $v =~s/\n//g; - $path = trim($v) . "/mysql"; - last; - } - } - } - } - if($OS eq "Linux"){ - $path = `which mysql`; - if ($path eq "") { - $path = `which mariadb`; - } - $path =~s/\n//g; - } + if ($OS eq "Windows") { + $has_mysql_path = `echo %PATH%`; + if ($has_mysql_path =~ /MySQL|MariaDB/i) { + @mysql = split(';', $has_mysql_path); + foreach my $v (@mysql) { + if ($v =~ /MySQL|MariaDB/i) { + $v =~ s/\n//g; + $path = trim($v) . "/mysql"; + last; + } + } + } + } + if ($OS eq "Linux") { + $path = `which mysql`; + if ($path eq "") { + $path = `which mariadb`; + } + $path =~ s/\n//g; + } - #::: Path not found, error and exit - if($path eq ""){ - print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; - exit; - } + #::: Path not found, error and exit + if ($path eq "") { + print "[Error:eqemu_server.pl] MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; + exit; + } } -sub check_for_database_dump_script{ - #::: Check for internet connection before updating - if(!$has_internet_connection){ - print "[Update] Cannot check update without internet connection...\n"; - return; - } +sub check_for_database_dump_script { + #::: Check for internet connection before updating + if (!$has_internet_connection) { + print "[Update] Cannot check update without internet connection...\n"; + return; + } - #::: 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); + #::: 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/database_dumper.pl") { + if (-e "updates_staged/database_dumper.pl") { - my $remote_script_size = -s "updates_staged/database_dumper.pl"; - my $local_script_size = -s "database_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"; + if ($remote_script_size != $local_script_size) { + print "[Update] Script has been updated, updating...\n"; - my @files; - my $start_dir = "updates_staged/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - 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 database_dumper.pl"); - } - } - } - print "[Install] Done\n"; - } - else { - print "[Update] No script update necessary...\n"; - } + my @files; + my $start_dir = "updates_staged/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + 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 database_dumper.pl"); + } + } + } + print "[Install] Done\n"; + } + else { + print "[Update] No script update necessary...\n"; + } - unlink("updates_staged/database_dumper.pl"); - } + unlink("updates_staged/database_dumper.pl"); + } - return; + return; } sub database_dump { - check_for_database_dump_script(); - print "[Database] Performing database backup....\n"; - print `perl database_dumper.pl database="$db" loc="backups"`; + check_for_database_dump_script(); + print "[Database] Performing database backup....\n"; + print `perl database_dumper.pl database="$db" loc="backups"`; } sub database_dump_player_tables { - check_for_database_dump_script(); - print "[Database] Performing database backup of player tables....\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); + check_for_database_dump_script(); + print "[Database] Performing database backup of player tables....\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/character_table_list.txt", "backups/character_table_list.txt"); - $tables = ""; - open (FILE, "backups/character_table_list.txt"); - $i = 0; - while (){ - chomp; - $o = $_; - $tables .= $o . ","; - } - $tables = substr($tables, 0, -1); + $tables = ""; + open(FILE, "backups/character_table_list.txt"); + $i = 0; + while () { + chomp; + $o = $_; + $tables .= $o . ","; + } + $tables = substr($tables, 0, -1); - print `perl database_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"; + print "[Database] Press any key to continue...\n"; - <>; #Read from STDIN + <>; #Read from STDIN } sub database_dump_compress { - check_for_database_dump_script(); - print "[Database] Performing database backup....\n"; - print `perl database_dumper.pl database="$db" loc="backups" compress`; + check_for_database_dump_script(); + print "[Database] Performing database backup....\n"; + print `perl database_dumper.pl database="$db" loc="backups" compress`; } -sub script_exit{ - #::: Cleanup staged folder... - rmtree("updates_staged/"); - exit; +sub script_exit { + #::: Cleanup staged folder... + rmtree("updates_staged/"); + exit; } -sub check_db_version_table{ - if(get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db){ - print get_mysql_result(" +sub check_db_version_table { + if (get_mysql_result("SHOW TABLES LIKE 'db_version'") eq "" && $db) { + print get_mysql_result(" CREATE TABLE db_version ( version int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO db_version (version) VALUES ('1000');"); - print "[Database] Table 'db_version' does not exist.... Creating...\n\n"; - } + print "[Database] Table 'db_version' does not exist.... Creating...\n\n"; + } } #::: Returns Tab Delimited MySQL Result from Command Line -sub get_mysql_result{ - my $run_query = $_[0]; - if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } - if($OS eq "Linux"){ - $run_query =~s/`//g; - return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; - } +sub get_mysql_result { + my $run_query = $_[0]; + if (!$db) {return;} + if ($OS eq "Windows") {return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`;} + if ($OS eq "Linux") { + $run_query =~ s/`//g; + return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; + } } -sub get_mysql_result_from_file{ - my $update_file = $_[0]; - if(!$db){ return; } - if($OS eq "Windows"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } - if($OS eq "Linux"){ return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; } +sub get_mysql_result_from_file { + my $update_file = $_[0]; + if (!$db) {return;} + if ($OS eq "Windows") {return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`;} + if ($OS eq "Linux") {return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`;} } #::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) #::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); -sub get_remote_file{ - my $request_url = $_[0]; - my $destination_file = $_[1]; - my $content_type = $_[2]; - my $no_retry = $_[3]; - my $silent_download = $_[4]; +sub get_remote_file { + my $request_url = $_[0]; + my $destination_file = $_[1]; + my $content_type = $_[2]; + my $no_retry = $_[3]; + my $silent_download = $_[4]; - if(!$has_internet_connection){ - print "[Download] Cannot download without internet connection...\n"; - return; - } + if (!$has_internet_connection) { + print "[Download] Cannot download without internet connection...\n"; + return; + } - #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary + #::: Build file path of the destination file so that we may check for the folder's existence and make it if necessary - if($destination_file=~/\//i){ - my @directory_path = split('/', $destination_file); - $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index] && $directory_path[$directory_index + 1]){ - $build_path .= $directory_path[$directory_index] . "/"; - # print "checking '" . $build_path . "'\n"; - #::: If path does not exist, create the directory... - if (!-d $build_path) { - print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; - mkdir($build_path); - } - if(!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]){ - # print $actual_path . "\n"; - $actual_path = $build_path; - last; - } - $directory_index++; - } - } + if ($destination_file =~ /\//i) { + my @directory_path = split('/', $destination_file); + $build_path = ""; + $directory_index = 0; + while ($directory_path[$directory_index] && $directory_path[$directory_index + 1]) { + $build_path .= $directory_path[$directory_index] . "/"; + # print "checking '" . $build_path . "'\n"; + #::: If path does not exist, create the directory... + if (!-d $build_path) { + print "[Copy] folder doesn't exist, creating '" . $build_path . "'\n"; + mkdir($build_path); + } + if (!$directory_indexr_path[$directory_index + 2] && $directory_indexr_path[$directory_index + 1]) { + # print $actual_path . "\n"; + $actual_path = $build_path; + last; + } + $directory_index++; + } + } - #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt - $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"; - #die; - } + #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt + $wget = `wget -N --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"; + #die; + } } #::: Trim Whitespaces sub trim { - my $string = $_[0]; - $string =~ s/^\s+//; - $string =~ s/\s+$//; - return $string; + my $string = $_[0]; + $string =~ s/^\s+//; + $string =~ s/\s+$//; + return $string; } sub read_eqemu_config_xml { - open (CONFIG, "eqemu_config.xml"); - while (){ - chomp; - $o = $_; + open(CONFIG, "eqemu_config.xml"); + while () { + chomp; + $o = $_; - if($o=~/\<\!--/i){ - next; - } + if ($o =~ /\<\!--/i) { + next; + } - if($o=~/database/i && $o=~/\<\//i){ - $in_database_tag = 0; - } - if($o=~//i){ - print "IN DATABASE TAG\n" if $debug; - $in_database_tag = 1; - } - if($o=~//i){ - ($long_name) = $o =~ /(.*)<\/longname>/; - print "Long Name: '" . $long_name . "'\n" if $debug; - } - if($in_database_tag == 1){ - @left = split (">", $o); - @right = split("<", $left[1]); - $tag_data = trim($right[0]); + if ($o =~ /database/i && $o =~ /\<\//i) { + $in_database_tag = 0; + } + if ($o =~ //i) { + print "IN DATABASE TAG\n" if $debug; + $in_database_tag = 1; + } + if ($o =~ //i) { + ($long_name) = $o =~ /(.*)<\/longname>/; + print "Long Name: '" . $long_name . "'\n" if $debug; + } + if ($in_database_tag == 1) { + @left = split(">", $o); + @right = split("<", $left[1]); + $tag_data = trim($right[0]); - if($o=~//i && $in_database_tag){ - $user = $tag_data; - print "Database User: '" . $user . "'\n" if $debug; - } - if($o=~//i && $in_database_tag){ - $pass = $tag_data; - print "Database Pass: '" . $pass . "'\n" if $debug; - } - if($o=~//i){ - $db = $tag_data; - print "Database Name: '" . $db . "'\n" if $debug; - } - if($o=~//i){ - $host = $tag_data; - print "Database Host: '" . $host . "'\n" if $debug; - } - } - } - close(CONFIG); + if ($o =~ //i && $in_database_tag) { + $user = $tag_data; + print "Database User: '" . $user . "'\n" if $debug; + } + if ($o =~ //i && $in_database_tag) { + $pass = $tag_data; + print "Database Pass: '" . $pass . "'\n" if $debug; + } + if ($o =~ //i) { + $db = $tag_data; + print "Database Name: '" . $db . "'\n" if $debug; + } + if ($o =~ //i) { + $host = $tag_data; + print "Database Host: '" . $host . "'\n" if $debug; + } + } + } + close(CONFIG); } sub read_eqemu_config_json { - use JSON; - my $json = new 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); + my $content; + open(my $fh, '<', "eqemu_config.json") or die "cannot open file $filename"; { + local $/; + $content = <$fh>; + } + close($fh); - $config = $json->decode($content); + $config = $json->decode($content); - $db = $config->{"server"}{"database"}{"db"}; - $host = $config->{"server"}{"database"}{"host"}; - $user = $config->{"server"}{"database"}{"username"}; - $pass = $config->{"server"}{"database"}{"password"}; + $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){ - print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; - return; - } +sub aa_fetch { + if (!$db) { + print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; + return; + } - print "[Install] Pulling down PEQ AA Tables...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Installing AA Tables...\n"; - print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); - print "[Install] Done...\n\n"; + print "[Install] Pulling down PEQ AA Tables...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/peq_aa_tables_post_rework.sql", "db_update/peq_aa_tables_post_rework.sql"); + print "[Install] Installing AA Tables...\n"; + print get_mysql_result_from_file("db_update/peq_aa_tables_post_rework.sql"); + print "[Install] Done...\n\n"; } #::: Fetch Latest Opcodes -sub opcodes_fetch{ - print "[Update] Pulling down latest opcodes...\n"; - %opcodes = ( - 1 => ["opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf"], - 2 => ["mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf"], - 3 => ["Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf"], - 4 => ["Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf"], - 5 => ["Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf"], - 6 => ["Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf"], - 7 => ["Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf"], - 8 => ["Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf"], - ); - $loop = 1; - while($opcodes{$loop}[0]){ - #::: Split the request_url by the patches folder to get the file name from request_url - @real_file = split("patches/", $opcodes{$loop}[1]); - $find = 0; - while($real_file[$find]){ - $file_name = $real_file[$find]; - $find++; - } +sub opcodes_fetch { + print "[Update] Pulling down latest opcodes...\n"; + %opcodes = ( + 1 => [ "opcodes", $eqemu_repository_request_url . "utils/patches/opcodes.conf" ], + 2 => [ "mail_opcodes", $eqemu_repository_request_url . "utils/patches/mail_opcodes.conf" ], + 3 => [ "Titanium", $eqemu_repository_request_url . "utils/patches/patch_Titanium.conf" ], + 4 => [ "Secrets of Faydwer", $eqemu_repository_request_url . "utils/patches/patch_SoF.conf" ], + 5 => [ "Seeds of Destruction", $eqemu_repository_request_url . "utils/patches/patch_SoD.conf" ], + 6 => [ "Underfoot", $eqemu_repository_request_url . "utils/patches/patch_UF.conf" ], + 7 => [ "Rain of Fear", $eqemu_repository_request_url . "utils/patches/patch_RoF.conf" ], + 8 => [ "Rain of Fear 2", $eqemu_repository_request_url . "utils/patches/patch_RoF2.conf" ], + ); + $loop = 1; + while ($opcodes{$loop}[0]) { + #::: Split the request_url by the patches folder to get the file name from request_url + @real_file = split("patches/", $opcodes{$loop}[1]); + $find = 0; + while ($real_file[$find]) { + $file_name = $real_file[$find]; + $find++; + } - get_remote_file($opcodes{$loop}[1], $file_name); - $loop++; - } - print "[Update] Done...\n"; + get_remote_file($opcodes{$loop}[1], $file_name); + $loop++; + } + print "[Update] Done...\n"; } sub remove_duplicate_rule_values { - $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); - print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; + $ruleset_id = trim(get_mysql_result("SELECT `ruleset_id` FROM `rule_sets` WHERE `name` = 'default'")); + print "[Database] Default Ruleset ID: " . $ruleset_id . "\n"; - $total_removed = 0; + $total_removed = 0; - #::: Store Default values... - $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); - my @lines = split("\n", $mysql_result); - foreach my $val (@lines){ - my @values = split("\t", $val); - $rule_set_values{$values[1]}[0] = $values[2]; - } + #::: Store Default values... + $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); + my @lines = split("\n", $mysql_result); + foreach my $val (@lines) { + my @values = split("\t", $val); + $rule_set_values{$values[1]}[0] = $values[2]; + } - #::: Compare default values against other rulesets to check for duplicates... - $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); - my @lines = split("\n", $mysql_result); - foreach my $val (@lines){ - my @values = split("\t", $val); - if($values[2] == $rule_set_values{$values[1]}[0]){ - print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; - get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); - $total_removed++; - } - } + #::: Compare default values against other rulesets to check for duplicates... + $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); + my @lines = split("\n", $mysql_result); + foreach my $val (@lines) { + my @values = split("\t", $val); + if ($values[2] == $rule_set_values{$values[1]}[0]) { + print "[Database] Removing duplicate : " . $values[1] . " (Ruleset (" . $values[0] . ")) matches default value of : " . $values[2] . "\n"; + get_mysql_result("DELETE FROM `rule_values` WHERE `ruleset_id` = " . $values[0] . " AND `rule_name` = '" . $values[1] . "'"); + $total_removed++; + } + } - print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; + print "[Database] Total duplicate rules removed... " . $total_removed . "\n"; } sub copy_file { - $l_source_file = $_[0]; - $l_destination_file = $_[1]; - if($l_destination_file=~/\//i){ - my @directory_path = split('/', $l_destination_file); - $build_path = ""; - $directory_index = 0; - while($directory_path[$directory_index]){ - $build_path .= $directory_path[$directory_index] . "/"; - #::: If path does not exist, create the directory... - if (!-d $build_path) { - mkdir($build_path); - } - if(!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]){ - # print $actual_path . "\n"; - $actual_path = $build_path; - last; - } - $directory_index++; - } - } - copy $l_source_file, $l_destination_file; + $l_source_file = $_[0]; + $l_destination_file = $_[1]; + if ($l_destination_file =~ /\//i) { + my @directory_path = split('/', $l_destination_file); + $build_path = ""; + $directory_index = 0; + while ($directory_path[$directory_index]) { + $build_path .= $directory_path[$directory_index] . "/"; + #::: If path does not exist, create the directory... + if (!-d $build_path) { + mkdir($build_path); + } + if (!$directory_path[$directory_index + 2] && $directory_path[$directory_index + 1]) { + # print $actual_path . "\n"; + $actual_path = $build_path; + last; + } + $directory_index++; + } + } + copy $l_source_file, $l_destination_file; } sub fetch_latest_windows_appveyor { - print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; - get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/eqemu-x86-no-bots.zip", "updates_staged/eqemu-x86-no-bots.zip", 1); + print "[Update] Fetching Latest Windows Binaries (unstable) from Appveyor... \n"; + get_remote_file("https://ci.appveyor.com/api/projects/KimLS/server/artifacts/eqemu-x86-no-bots.zip", "updates_staged/eqemu-x86-no-bots.zip", 1); - print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; - print "[Update] Extracting... --- \n"; - unzip('updates_staged/eqemu-x86-no-bots.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Update] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Update] Done\n"; + print "[Update] Fetched Latest Windows Binaries (unstable) from Appveyor... \n"; + print "[Update] Extracting... --- \n"; + unzip('updates_staged/eqemu-x86-no-bots.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "[Update] Done\n"; - rmtree('updates_staged'); + rmtree('updates_staged'); } sub fetch_latest_windows_binaries { - print "[Update] Fetching Latest Windows Binaries... \n"; - get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); - print "[Update] Fetched Latest Windows Binaries... \n"; - print "[Update] Extracting... --- \n"; - unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Update] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Update] Done\n"; + print "[Update] Fetching Latest Windows Binaries... \n"; + get_remote_file($install_repository_request_url . "master_windows_build.zip", "updates_staged/master_windows_build.zip", 1); + print "[Update] Fetched Latest Windows Binaries... \n"; + print "[Update] Extracting... --- \n"; + unzip('updates_staged/master_windows_build.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/binaries\///g; + print "[Update] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "[Update] Done\n"; - - rmtree('updates_staged'); + rmtree('updates_staged'); } sub fetch_latest_windows_binaries_bots { - print "[Update] Fetching Latest Windows Binaries with Bots...\n"; - get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); - print "[Update] Fetched Latest Windows Binaries with Bots...\n"; - print "[Update] Extracting...\n"; - unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); - my @files; - my $start_dir = "updates_staged/binaries"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/binaries\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Update] Done...\n"; + print "[Update] Fetching Latest Windows Binaries with Bots...\n"; + get_remote_file($install_repository_request_url . "master_windows_build_bots.zip", "updates_staged/master_windows_build_bots.zip", 1); + print "[Update] Fetched Latest Windows Binaries with Bots...\n"; + print "[Update] Extracting...\n"; + unzip('updates_staged/master_windows_build_bots.zip', 'updates_staged/binaries/'); + my @files; + my $start_dir = "updates_staged/binaries"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/binaries\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "[Update] Done...\n"; - rmtree('updates_staged'); + rmtree('updates_staged'); } sub do_windows_login_server_setup { - print "[Install] Fetching Loginserver... \n"; - get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); - print "[Install] Extracting... \n"; - unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); - my @files; - my $start_dir = "updates_staged/login_server"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "[Install] Done... \n"; + print "[Install] Fetching Loginserver... \n"; + get_remote_file($install_repository_request_url . "login_server.zip", "updates_staged/login_server.zip", 1); + print "[Install] Extracting... \n"; + unzip('updates_staged/login_server.zip', 'updates_staged/login_server/'); + my @files; + my $start_dir = "updates_staged/login_server"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "[Install] Done... \n"; - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; - print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n"; + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "[Install] Done...\n"; - add_login_server_firewall_rules(); + add_login_server_firewall_rules(); - rmtree('updates_staged'); - rmtree('db_update'); + rmtree('updates_staged'); + rmtree('db_update'); - print "[Install] Press any key to continue...\n"; + print "[Install] Press any key to continue...\n"; - <>; #Read from STDIN + <>; #Read from STDIN } sub do_linux_login_server_setup { - build_linux_source(); + build_linux_source(); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/login_server\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, $destination_file); - } - print "\n Done... \n"; + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/login_server\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, $destination_file); + } + print "\n Done... \n"; - print "[Install] Pulling down Loginserver database tables...\n"; - get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); - print "[Install] Installing Loginserver tables...\n"; - print get_mysql_result_from_file("db_update/login_server_tables.sql"); - print "[Install] Done...\n\n"; + print "[Install] Pulling down Loginserver database tables...\n"; + get_remote_file($install_repository_request_url . "login_server_tables.sql", "db_update/login_server_tables.sql"); + print "[Install] Installing Loginserver tables...\n"; + print get_mysql_result_from_file("db_update/login_server_tables.sql"); + print "[Install] Done...\n\n"; - rmtree('updates_staged'); - rmtree('db_update'); + rmtree('updates_staged'); + rmtree('db_update'); - 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_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"}; - my $db_user = $installation_variables{"mysql_eqemu_user"}; - my $db_password = $installation_variables{"mysql_eqemu_password"}; + get_installation_variables(); + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_password = $installation_variables{"mysql_eqemu_password"}; - #::: Open new config file - open (NEW_CONFIG, '>', 'login.ini'); + #::: Open new config file + open(NEW_CONFIG, '>', 'login.ini'); - #::: Iterate through template and replace variables... - open (FILE_TEMPLATE, "login_template.ini"); - while (){ - chomp; - $o = $_; - #::: Find replace variables - if($o=~/db/i){ $o = "db = " . $db_name; } - if($o=~/user/i){ $o = "user = " . $db_user; } - if($o=~/password/i){ $o = "password = " . $db_password; } + #::: Iterate through template and replace variables... + open(FILE_TEMPLATE, "login_template.ini"); + while () { + chomp; + $o = $_; + #::: Find replace variables + if ($o =~ /db/i) {$o = "db = " . $db_name;} + if ($o =~ /user/i) {$o = "user = " . $db_user;} + if ($o =~ /password/i) {$o = "password = " . $db_password;} - print NEW_CONFIG $o . "\n"; - } + print NEW_CONFIG $o . "\n"; + } - close(FILE_TEMPLATE); - close(NEW_CONFIG); - unlink("login_template.ini"); + close(FILE_TEMPLATE); + close(NEW_CONFIG); + unlink("login_template.ini"); - print "[Install] Press any key to continue...\n"; + print "[Install] Press any key to continue...\n"; - <>; #Read from STDIN + <>; #Read from STDIN } sub add_login_server_firewall_rules { - #::: Check Loginserver Firewall install for Windows - if($OS eq "Windows"){ - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); - $has_loginserver_rules_titanium = 0; - $has_loginserver_rules_sod = 0; - foreach my $val (@output_buffer){ - if($val=~/Rule Name/i){ - $val=~s/Rule Name://g; - if($val=~/EQEmu Loginserver/i && $val=~/Titanium/i){ - $has_loginserver_rules_titanium = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - if($val=~/EQEmu Loginserver/i && $val=~/SOD/i){ - $has_loginserver_rules_sod = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - } - } + #::: Check Loginserver Firewall install for Windows + if ($OS eq "Windows") { + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); + $has_loginserver_rules_titanium = 0; + $has_loginserver_rules_sod = 0; + foreach my $val (@output_buffer) { + if ($val =~ /Rule Name/i) { + $val =~ s/Rule Name://g; + if ($val =~ /EQEmu Loginserver/i && $val =~ /Titanium/i) { + $has_loginserver_rules_titanium = 1; + print "[Install] Found existing rule :: " . trim($val) . "\n"; + } + if ($val =~ /EQEmu Loginserver/i && $val =~ /SOD/i) { + $has_loginserver_rules_sod = 1; + print "[Install] Found existing rule :: " . trim($val) . "\n"; + } + } + } - if($has_loginserver_rules_titanium == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; - } - if($has_loginserver_rules_sod == 0){ - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; - print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; - print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; - } + if ($has_loginserver_rules_titanium == 0) { + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (TCP) port 5998 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) TCP" dir=in action=allow protocol=TCP localport=5998`; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (Titanium) (UDP) port 5998 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (Titanium) (5998) UDP" dir=in action=allow protocol=UDP localport=5998`; + } + if ($has_loginserver_rules_sod == 0) { + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (TCP) port 5999 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) TCP" dir=in action=allow protocol=TCP localport=5999`; + print "[Install] Attempting to add EQEmu Loginserver Firewall Rules (SOD+) (UDP) port 5999 \n"; + print `netsh advfirewall firewall add rule name="EQEmu Loginserver (SOD+) (5999) UDP" dir=in action=allow protocol=UDP localport=5999`; + } - print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; - print "\n"; - print "[Install] Instructions \n"; - print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; - print " + print "If firewall rules don't add you must run this script (eqemu_server.pl) as administrator\n"; + print "\n"; + print "[Install] Instructions \n"; + print "[Install] In order to connect your server to the loginserver you must point your eqemu_config.xml to your local server similar to the following:\n"; + print " login.eqemulator.net 5998 @@ -1475,934 +1547,940 @@ sub add_login_server_firewall_rules { "; - print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; - } + print "[Install] When done, make sure your EverQuest client points to your loginserver's IP (In this case it would be 127.0.0.1) in the eqhosts.txt file\n"; + } } -sub check_windows_firewall_rules{ - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); - $has_world_rules = 0; - $has_zone_rules = 0; - foreach my $val (@output_buffer){ - if($val=~/Rule Name/i){ - $val=~s/Rule Name://g; - if($val=~/EQEmu World/i){ - $has_world_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - if($val=~/EQEmu Zone/i){ - $has_zone_rules = 1; - print "[Install] Found existing rule :: " . trim($val) . "\n"; - } - } - } +sub check_windows_firewall_rules { + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); + $has_world_rules = 0; + $has_zone_rules = 0; + foreach my $val (@output_buffer) { + if ($val =~ /Rule Name/i) { + $val =~ s/Rule Name://g; + if ($val =~ /EQEmu World/i) { + $has_world_rules = 1; + print "[Install] Found existing rule :: " . trim($val) . "\n"; + } + if ($val =~ /EQEmu Zone/i) { + $has_zone_rules = 1; + print "[Install] Found existing rule :: " . trim($val) . "\n"; + } + } + } - if($has_world_rules == 0){ - print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; - print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; - print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; - print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; - } - if($has_zone_rules == 0){ - print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; - print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; - print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; - print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; - } + if ($has_world_rules == 0) { + print "[Install] Attempting to add EQEmu World Firewall Rules (TCP) port 9000 \n"; + print `netsh advfirewall firewall add rule name="EQEmu World (9000) TCP" dir=in action=allow protocol=TCP localport=9000`; + print "[Install] Attempting to add EQEmu World Firewall Rules (UDP) port 9000 \n"; + print `netsh advfirewall firewall add rule name="EQEmu World (9000) UDP" dir=in action=allow protocol=UDP localport=9000`; + } + if ($has_zone_rules == 0) { + print "[Install] Attempting to add EQEmu Zones (7000-7500) TCP \n"; + print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) TCP" dir=in action=allow protocol=TCP localport=7000-7500`; + print "[Install] Attempting to add EQEmu Zones (7000-7500) UDP \n"; + print `netsh advfirewall firewall add rule name="EQEmu Zones (7000-7500) UDP" dir=in action=allow protocol=UDP localport=7000-7500`; + } } -sub fetch_server_dlls{ - print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; - get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); - get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); - get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); +sub fetch_server_dlls { + print "[Download] Fetching lua51.dll, zlib1.dll, libmysql.dll...\n"; + get_remote_file($install_repository_request_url . "lua51.dll", "lua51.dll", 1); + get_remote_file($install_repository_request_url . "zlib1.dll", "zlib1.dll", 1); + get_remote_file($install_repository_request_url . "libmysql.dll", "libmysql.dll", 1); } -sub fetch_peq_db_full{ - print "[Install] Downloading latest PEQ Database... Please wait...\n"; - get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); - print "[Install] Downloaded latest PEQ Database... Extracting...\n"; - unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); - my $start_dir = "updates_staged/peq_db"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/updates_staged\/peq_db\///g; - if($file=~/peqbeta|player_tables/i){ - print "[Install] DB :: Installing :: " . $destination_file . "\n"; - get_mysql_result_from_file($file); - } - } +sub fetch_peq_db_full { + print "[Install] Downloading latest PEQ Database... Please wait...\n"; + get_remote_file("http://edit.peqtgc.com/weekly/peq_beta.zip", "updates_staged/peq_beta.zip", 1); + print "[Install] Downloaded latest PEQ Database... Extracting...\n"; + unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); + my $start_dir = "updates_staged/peq_db"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/updates_staged\/peq_db\///g; + if ($file =~ /peqbeta|player_tables/i) { + print "[Install] DB :: Installing :: " . $destination_file . "\n"; + get_mysql_result_from_file($file); + } + } - #::: PEQ DB baseline version - print get_mysql_result("DELETE FROM db_version"); - print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);"); + #::: PEQ DB baseline version + print get_mysql_result("DELETE FROM db_version"); + print get_mysql_result("INSERT INTO `db_version` (`version`) VALUES (9130);"); } -sub map_files_fetch_bulk{ - print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; - get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); - unzip('maps/maps.zip', 'maps/'); - my @files; - my $start_dir = "maps/EQEmuMaps-master/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - $destination_file = $file; - $destination_file =~s/maps\/EQEmuMaps-master\///g; - print "[Install] Installing :: " . $destination_file . "\n"; - copy_file($file, "maps/" . $destination_file); - } - print "[Install] Fetched Latest Maps\n"; +sub map_files_fetch_bulk { + print "[Install] Fetching Latest Maps... (This could take a few minutes...)\n"; + get_remote_file("http://github.com/Akkadius/EQEmuMaps/archive/master.zip", "maps/maps.zip", 1); + unzip('maps/maps.zip', 'maps/'); + my @files; + my $start_dir = "maps/EQEmuMaps-master/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + $destination_file = $file; + $destination_file =~ s/maps\/EQEmuMaps-master\///g; + print "[Install] Installing :: " . $destination_file . "\n"; + copy_file($file, "maps/" . $destination_file); + } + print "[Install] Fetched Latest Maps\n"; - rmtree('maps/EQEmuMaps-master'); - unlink('maps/maps.zip'); + rmtree('maps/EQEmuMaps-master'); + unlink('maps/maps.zip'); } -sub map_files_fetch{ - print "[Install] Fetching Latest Maps --- \n"; +sub map_files_fetch { + print "[Install] Fetching Latest Maps --- \n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/!eqemu_maps_manifest.txt", "updates_staged/eqemu_maps_manifest.txt"); - #::: Get Data from manifest - open (FILE, "updates_staged/eqemu_maps_manifest.txt"); - $i = 0; - while (){ - chomp; - $o = $_; - @manifest_map_data = split(',', $o); - if($manifest_map_data[0] ne ""){ - $maps_manifest[$i] = [$manifest_map_data[0], $manifest_map_data[1]]; - $i++; - } - } + #::: Get Data from manifest + open(FILE, "updates_staged/eqemu_maps_manifest.txt"); + $i = 0; + while () { + chomp; + $o = $_; + @manifest_map_data = split(',', $o); + if ($manifest_map_data[0] ne "") { + $maps_manifest[$i] = [ $manifest_map_data[0], $manifest_map_data[1] ]; + $i++; + } + } - #::: Download - $fc = 0; - for($m = 0; $m <= $i; $m++){ - my $file_existing = $maps_manifest[$m][0]; - my $file_existing_size = (stat $file_existing)[7]; - if($file_existing_size != $maps_manifest[$m][1]){ - print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; - get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); - $fc++; - } - } + #::: Download + $fc = 0; + for ($m = 0; $m <= $i; $m++) { + my $file_existing = $maps_manifest[$m][0]; + my $file_existing_size = (stat $file_existing)[7]; + if ($file_existing_size != $maps_manifest[$m][1]) { + print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; + get_remote_file("https://raw.githubusercontent.com/Akkadius/EQEmuMaps/master/" . $maps_manifest[$m][0], $maps_manifest[$m][0], 1); + $fc++; + } + } - if($fc == 0){ - print "[Install] No Map Updates found... \n\n"; - } + if ($fc == 0) { + print "[Install] No Map Updates found... \n\n"; + } } -sub quest_files_fetch{ - if (!-e "updates_staged/projecteqquests-master/") { - print "[Update] Fetching Latest Quests --- \n"; - get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); - print "[Install] Fetched latest quests...\n"; - mkdir('updates_staged'); - unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); - } +sub quest_files_fetch { + if (!-e "updates_staged/projecteqquests-master/") { + print "[Update] Fetching Latest Quests --- \n"; + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); + print "[Install] Fetched latest quests...\n"; + mkdir('updates_staged'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); + } - $fc = 0; - use File::Find; - use File::Compare; + $fc = 0; + use File::Find; + use File::Compare; - my @files; - my $start_dir = "updates_staged/projecteqquests-master/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/projecteqquests-master\//quests\//g; + my @files; + my $start_dir = "updates_staged/projecteqquests-master/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + if ($file =~ /\.pl|\.lua|\.ext/i) { + $staged_file = $file; + $destination_file = $file; + $destination_file =~ s/updates_staged\/projecteqquests-master\//quests\//g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; + $fc++; + } + else { + $directory_indexff = do_file_diff($destination_file, $staged_file); + if ($directory_indexff ne "") { + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Quest? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if ($input =~ /N/i) {} + else { + #::: Make a backup + copy_file($destination_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; + } + $fc++; + } + } + } + } - if($fc == 0){ - print "[Update] No Quest Updates found... \n\n"; - } + if ($fc == 0) { + print "[Update] No Quest Updates found... \n\n"; + } } sub lua_modules_fetch { - if (!-e "updates_staged/projecteqquests-master/") { - print "[Update] Fetching Latest lua modules --- \n"; - get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); - print "[Install] Fetched latest lua modules...\n"; - mkdir('updates_staged'); - unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); - } + if (!-e "updates_staged/projecteqquests-master/") { + print "[Update] Fetching Latest lua modules --- \n"; + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); + print "[Install] Fetched latest lua modules...\n"; + mkdir('updates_staged'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); + } - $fc = 0; - use File::Find; - use File::Compare; + $fc = 0; + use File::Find; + use File::Compare; - mkdir('lua_modules'); + mkdir('lua_modules'); - my @files; - my $start_dir = "updates_staged/projecteqquests-master/lua_modules/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/projecteqquests-master\/lua_modules\//lua_modules\//g; + my @files; + my $start_dir = "updates_staged/projecteqquests-master/lua_modules/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + if ($file =~ /\.pl|\.lua|\.ext/i) { + $staged_file = $file; + $destination_file = $file; + $destination_file =~ s/updates_staged\/projecteqquests-master\/lua_modules\//lua_modules\//g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; + $fc++; + } + else { + $directory_indexff = do_file_diff($destination_file, $staged_file); + if ($directory_indexff ne "") { + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this LUA Module? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if ($input =~ /N/i) {} + else { + #::: Make a backup + copy_file($destination_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; + } + $fc++; + } + } + } + } - if($fc == 0){ - print "[Update] No LUA Modules Updates found... \n\n"; - } + if ($fc == 0) { + print "[Update] No LUA Modules Updates found... \n\n"; + } } -sub plugins_fetch{ - if (!-e "updates_staged/projecteqquests-master/") { - print "[Update] Fetching Latest plugins --- \n"; - get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); - print "[Install] Fetched latest plugins...\n"; - mkdir('updates_staged'); - unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); - } +sub plugins_fetch { + if (!-e "updates_staged/projecteqquests-master/") { + print "[Update] Fetching Latest plugins --- \n"; + get_remote_file("https://codeload.github.com/ProjectEQ/projecteqquests/zip/master", "updates_staged/projecteqquests-master.zip", 1); + print "[Install] Fetched latest plugins...\n"; + mkdir('updates_staged'); + unzip('updates_staged/projecteqquests-master.zip', 'updates_staged/'); + } - $fc = 0; - use File::Find; - use File::Compare; + $fc = 0; + use File::Find; + use File::Compare; - mkdir('plugins'); + mkdir('plugins'); - my @files; - my $start_dir = "updates_staged/projecteqquests-master/plugins/"; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { - if($file=~/\.pl|\.lua|\.ext/i){ - $staged_file = $file; - $destination_file = $file; - $destination_file =~s/updates_staged\/projecteqquests-master\///g; + my @files; + my $start_dir = "updates_staged/projecteqquests-master/plugins/"; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { + if ($file =~ /\.pl|\.lua|\.ext/i) { + $staged_file = $file; + $destination_file = $file; + $destination_file =~ s/updates_staged\/projecteqquests-master\///g; - if (!-e $destination_file) { - copy_file($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n"; - $fc++; - } - else{ - $directory_indexff = do_file_diff($destination_file, $staged_file); - if($directory_indexff ne ""){ - $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; - print $directory_indexff . "\n"; - print "[Update] File Different :: '" . $destination_file . "'\n"; - print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; - my $input = ; - if($input=~/N/i){} - else{ - #::: Make a backup - copy_file($destination_file, $backup_dest); - #::: Copy staged to running - copy($staged_file, $destination_file); - print "[Install] Installing :: '" . $destination_file . "'\n\n"; - } - $fc++; - } - } - } - } + if (!-e $destination_file) { + copy_file($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n"; + $fc++; + } + else { + $directory_indexff = do_file_diff($destination_file, $staged_file); + if ($directory_indexff ne "") { + $backup_dest = "updates_backups/" . $time_stamp . "/" . $destination_file; + print $directory_indexff . "\n"; + print "[Update] File Different :: '" . $destination_file . "'\n"; + print "[Update] Do you wish to update this Plugin? '" . $destination_file . "' [Yes (Enter) - No (N)] \nA backup will be found in '" . $backup_dest . "'\n"; + my $input = ; + if ($input =~ /N/i) {} + else { + #::: Make a backup + copy_file($destination_file, $backup_dest); + #::: Copy staged to running + copy($staged_file, $destination_file); + print "[Install] Installing :: '" . $destination_file . "'\n\n"; + } + $fc++; + } + } + } + } - if($fc == 0){ - print "[Update] No Plugin Updates found... \n\n"; - } + if ($fc == 0) { + print "[Update] No Plugin Updates found... \n\n"; + } } -sub do_file_diff{ - $file_1 = $_[0]; - $file_2 = $_[1]; - if($OS eq "Windows"){ - eval "use Text::Diff"; - $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); - return $directory_indexff; - } - if($OS eq "Linux"){ - # print 'diff -u "$file_1" "$file_2"' . "\n"; - return `diff -u "$file_1" "$file_2"`; - } +sub do_file_diff { + $file_1 = $_[0]; + $file_2 = $_[1]; + if ($OS eq "Windows") { + eval "use Text::Diff"; + $directory_indexff = diff($file_1, $file_2, { STYLE => "Unified" }); + return $directory_indexff; + } + if ($OS eq "Linux") { + # print 'diff -u "$file_1" "$file_2"' . "\n"; + return `diff -u "$file_1" "$file_2"`; + } } sub unzip { - $archive_to_unzip = $_[0]; - $dest_folder = $_[1]; + $archive_to_unzip = $_[0]; + $dest_folder = $_[1]; - if($OS eq "Windows"){ - eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )"; - my $zip = Archive::Zip->new(); - unless ( $zip->read($archive_to_unzip) == AZ_OK ) { - die 'read error'; - } - print "[Unzip] Extracting...\n"; - $zip->extractTree('', $dest_folder); - } - if($OS eq "Linux"){ - print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; - } + if ($OS eq "Windows") { + eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )"; + my $zip = Archive::Zip->new(); + unless ($zip->read($archive_to_unzip) == AZ_OK) { + die 'read error'; + } + print "[Unzip] Extracting...\n"; + $zip->extractTree('', $dest_folder); + } + if ($OS eq "Linux") { + print `unzip -o -q "$archive_to_unzip" -d "$dest_folder"`; + } } -sub are_file_sizes_different{ - $file_1 = $_[0]; - $file_2 = $_[1]; - my $file_1 = (stat $file_1)[7]; - my $file_2 = (stat $file_2)[7]; - # print $file_1 . " :: " . $file_2 . "\n"; - if($file_1 != $file_2){ - return 1; - } - return; +sub are_file_sizes_different { + $file_1 = $_[0]; + $file_2 = $_[1]; + my $file_1 = (stat $file_1)[7]; + my $file_2 = (stat $file_2)[7]; + # print $file_1 . " :: " . $file_2 . "\n"; + if ($file_1 != $file_2) { + return 1; + } + return; } -sub do_bots_db_schema_drop{ - #"drop_bots.sql" is run before reverting database back to 'normal' - print "[Database] Fetching drop_bots.sql...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); - print get_mysql_result_from_file("db_update/drop_bots.sql"); +sub do_bots_db_schema_drop { + #"drop_bots.sql" is run before reverting database back to 'normal' + print "[Database] Fetching drop_bots.sql...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/drop_bots.sql", "db_update/drop_bots.sql"); + print get_mysql_result_from_file("db_update/drop_bots.sql"); - print "[Database] Removing bot database tables...\n"; - print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); + print "[Database] Removing bot database tables...\n"; + print get_mysql_result("DELETE FROM `rule_values` WHERE `rule_name` LIKE 'Bots:%';"); - if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db){ - print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';"); - } + if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && $db) { + print get_mysql_result("DELETE FROM `commands` WHERE `command` LIKE 'bot';"); + } - if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db){ - print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';"); - } + if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && $db) { + print get_mysql_result("DELETE FROM `command_settings` WHERE `command` LIKE 'bot';"); + } - if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`);"); + if (get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) { + print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY (`groupid`, `charid`, `ismerc`);"); - if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`);"); + if (get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) { + print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `guild_members` ADD PRIMARY KEY (`char_id`);"); - print get_mysql_result("UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298);"); + print get_mysql_result("UPDATE `spawn2` SET `enabled` = 0 WHERE `id` IN (59297,59298);"); - if(get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db){ - print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); - } - print "[Database] Done...\n"; + if (get_mysql_result("SHOW COLUMNS FROM `db_version` LIKE 'bots_version'") ne "" && $db) { + print get_mysql_result("UPDATE `db_version` SET `bots_version` = 0;"); + } + print "[Database] Done...\n"; } -sub modify_db_for_bots{ - #Called after the db bots schema (2015_09_30_bots.sql) has been loaded - print "[Database] Modifying database for bots...\n"; - print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); +sub modify_db_for_bots { + #Called after the db bots schema (2015_09_30_bots.sql) has been loaded + print "[Database] Modifying database for bots...\n"; + print get_mysql_result("UPDATE `spawn2` SET `enabled` = 1 WHERE `id` IN (59297,59298);"); - if(get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); - } + if (get_mysql_result("SHOW KEYS FROM `guild_members` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) { + print get_mysql_result("ALTER TABLE `guild_members` DROP PRIMARY KEY;"); + } - if(get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db){ - print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); - } - print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);"); + if (get_mysql_result("SHOW KEYS FROM `group_id` WHERE `Key_name` LIKE 'PRIMARY'") ne "" && $db) { + print get_mysql_result("ALTER TABLE `group_id` DROP PRIMARY KEY;"); + } + print get_mysql_result("ALTER TABLE `group_id` ADD PRIMARY KEY USING BTREE(`groupid`, `charid`, `name`, `ismerc`);"); - if(get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db){ - print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');"); - } + if (get_mysql_result("SHOW TABLES LIKE 'command_settings'") ne "" && get_mysql_result("SELECT `command` FROM `command_settings` WHERE `command` LIKE 'bot'") eq "" && $db) { + print get_mysql_result("INSERT INTO `command_settings` VALUES ('bot', '0', '');"); + } - if(get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db){ - print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');"); - } + if (get_mysql_result("SHOW TABLES LIKE 'commands'") ne "" && get_mysql_result("SELECT `command` FROM `commands` WHERE `command` LIKE 'bot'") eq "" && $db) { + print get_mysql_result("INSERT INTO `commands` VALUES ('bot', '0');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotAAExpansion'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:AAExpansion' WHERE `rule_name` LIKE 'Bots:BotAAExpansion';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:AAExpansion'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:AAExpansion', '8', 'The expansion through which bots will obtain AAs');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreateBotCount'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:CreationLimit' WHERE `rule_name` LIKE 'Bots:CreateBotCount';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:CreationLimit'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:CreationLimit', '150', 'Number of bots that each account can create');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotFinishBuffing'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:FinishBuffing' WHERE `rule_name` LIKE 'Bots:BotFinishBuffing';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:FinishBuffing'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:FinishBuffing', 'false', 'Allow for buffs to complete even if the bot caster is out of mana. Only affects buffing out of combat.');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotGroupBuffing'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:GroupBuffing' WHERE `rule_name` LIKE 'Bots:BotGroupBuffing';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:GroupBuffing'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:GroupBuffing', 'false', 'Bots will cast single target buffs as group buffs, default is false for single. Does not make single target buffs work for MGB.');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotManaRegen'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:ManaRegen' WHERE `rule_name` LIKE 'Bots:BotManaRegen';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:ManaRegen'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:ManaRegen', '3.0', 'Adjust mana regen for bots, 1 is fast and higher numbers slow it down 3 is about the same as players.');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotQuest'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpawnLimit' WHERE `rule_name` LIKE 'Bots:BotQuest';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpawnLimit'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpawnLimit', 'false', 'Optional quest method to manage bot spawn limits using the quest_globals name bot_spawn_limit, see: /bazaar/Aediles_Thrall.pl');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:BotSpellQuest'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:QuestableSpells' WHERE `rule_name` LIKE 'Bots:BotSpellQuest';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:QuestableSpells'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:QuestableSpells', 'false', 'Anita Thrall\\\'s (Anita_Thrall.pl) Bot Spell Scriber quests.');"); + } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db){ - print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';"); - } - if(get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db){ - print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');"); - } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnBotCount'") ne "" && $db) { + print get_mysql_result("UPDATE `rule_values` SET `rule_name` = 'Bots:SpawnLimit' WHERE `rule_name` LIKE 'Bots:SpawnBotCount';"); + } + if (get_mysql_result("SELECT `rule_name` FROM `rule_values` WHERE `rule_name` LIKE 'Bots:SpawnLimit'") eq "" && $db) { + print get_mysql_result("INSERT INTO `rule_values` VALUES ('1', 'Bots:SpawnLimit', '71', 'Number of bots a character can have spawned at one time, You + 71 bots is a 12 group raid');"); + } - convert_existing_bot_data(); + convert_existing_bot_data(); } -sub convert_existing_bot_data{ - if(get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db){ - print "[Database] Converting existing bot data...\n"; - print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); +sub convert_existing_bot_data { + if (get_mysql_result("SHOW TABLES LIKE 'bots'") ne "" && $db) { + print "[Database] Converting existing bot data...\n"; + print get_mysql_result("INSERT INTO `bot_data` (`bot_id`, `owner_id`, `spells_id`, `name`, `last_name`, `zone_id`, `gender`, `race`, `class`, `level`, `creation_day`, `last_spawn`, `time_spawned`, `size`, `face`, `hair_color`, `hair_style`, `beard`, `beard_color`, `eye_color_1`, `eye_color_2`, `drakkin_heritage`, `drakkin_tattoo`, `drakkin_details`, `ac`, `atk`, `hp`, `mana`, `str`, `sta`, `cha`, `dex`, `int`, `agi`, `wis`, `fire`, `cold`, `magic`, `poison`, `disease`, `corruption`) SELECT `BotID`, `BotOwnerCharacterID`, `BotSpellsID`, `Name`, `LastName`, `LastZoneId`, `Gender`, `Race`, `Class`, `BotLevel`, UNIX_TIMESTAMP(`BotCreateDate`), UNIX_TIMESTAMP(`LastSpawnDate`), `TotalPlayTime`, `Size`, `Face`, `LuclinHairColor`, `LuclinHairStyle`, `LuclinBeard`, `LuclinBeardColor`, `LuclinEyeColor`, `LuclinEyeColor2`, `DrakkinHeritage`, `DrakkinTattoo`, `DrakkinDetails`, `AC`, `ATK`, `HP`, `Mana`, `STR`, `STA`, `CHA`, `DEX`, `_INT`, `AGI`, `WIS`, `FR`, `CR`, `MR`, `PR`, `DR`, `Corrup` FROM `bots`;"); - print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); + print get_mysql_result("INSERT INTO `bot_inspect_messages` (`bot_id`, `inspect_message`) SELECT `BotID`, `BotInspectMessage` FROM `bots`;"); - print get_mysql_result("RENAME TABLE `bots` TO `bots_old`;"); - } + print get_mysql_result("RENAME TABLE `bots` TO `bots_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botstances'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) SELECT bs.`BotID`, bs.`StanceID` FROM `botstances` bs INNER JOIN `bot_data` bd ON bs.`BotID` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botstances'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_stances` (`bot_id`, `stance_id`) SELECT bs.`BotID`, bs.`StanceID` FROM `botstances` bs INNER JOIN `bot_data` bd ON bs.`BotID` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `botstances` TO `botstances_old`;"); - } + print get_mysql_result("RENAME TABLE `botstances` TO `botstances_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'bottimers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) SELECT bt.`BotID`, bt.`TimerID`, bt.`Value` FROM `bottimers` bt INNER JOIN `bot_data` bd ON bt.`BotID` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'bottimers'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_timers` (`bot_id`, `timer_id`, `timer_value`) SELECT bt.`BotID`, bt.`TimerID`, bt.`Value` FROM `bottimers` bt INNER JOIN `bot_data` bd ON bt.`BotID` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `bottimers` TO `bottimers_old`;"); - } + print get_mysql_result("RENAME TABLE `bottimers` TO `bottimers_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botbuffs'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_buffs` (`buffs_index`, `bot_id`, `spell_id`, `caster_level`, `duration_formula`, `tics_remaining`, `poison_counters`, `disease_counters`, `curse_counters`, `corruption_counters`, `numhits`, `melee_rune`, `magic_rune`, `persistent`) SELECT bb.`BotBuffId`, bb.`BotId`, bb.`SpellId`, bb.`CasterLevel`, bb.`DurationFormula`, bb.`TicsRemaining`, bb.`PoisonCounters`, bb.`DiseaseCounters`, bb.`CurseCounters`, bb.`CorruptionCounters`, bb.`HitCount`, bb.`MeleeRune`, bb.`MagicRune`, bb.`Persistent` FROM `botbuffs` bb INNER JOIN `bot_data` bd ON bb.`BotId` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botbuffs'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_buffs` (`buffs_index`, `bot_id`, `spell_id`, `caster_level`, `duration_formula`, `tics_remaining`, `poison_counters`, `disease_counters`, `curse_counters`, `corruption_counters`, `numhits`, `melee_rune`, `magic_rune`, `persistent`) SELECT bb.`BotBuffId`, bb.`BotId`, bb.`SpellId`, bb.`CasterLevel`, bb.`DurationFormula`, bb.`TicsRemaining`, bb.`PoisonCounters`, bb.`DiseaseCounters`, bb.`CurseCounters`, bb.`CorruptionCounters`, bb.`HitCount`, bb.`MeleeRune`, bb.`MagicRune`, bb.`Persistent` FROM `botbuffs` bb INNER JOIN `bot_data` bd ON bb.`BotId` = bd.`bot_id`;"); - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`dot_rune` = bbo.`dot_rune` WHERE bb.`bot_id` = bbo.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'dot_rune'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`dot_rune` = bbo.`dot_rune` WHERE bb.`bot_id` = bbo.`BotID`;"); + } - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_x` = bbo.`caston_x` WHERE bb.`bot_id` = bbo.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_x'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_x` = bbo.`caston_x` WHERE bb.`bot_id` = bbo.`BotID`;"); + } - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_y` = bbo.`caston_y` WHERE bb.`bot_id` = bbo.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_y'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_y` = bbo.`caston_y` WHERE bb.`bot_id` = bbo.`BotID`;"); + } - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_z` = bbo.`caston_z` WHERE bb.`bot_id` = bbo.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'caston_z'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`caston_z` = bbo.`caston_z` WHERE bb.`bot_id` = bbo.`BotID`;"); + } - if(get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`extra_di_chance` = bbo.`ExtraDIChance` WHERE bb.`bot_id` = bbo.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botbuffs` LIKE 'ExtraDIChance'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_buffs` bb INNER JOIN `botbuffs` bbo ON bb.`buffs_index` = bbo.`BotBuffId` SET bb.`extra_di_chance` = bbo.`ExtraDIChance` WHERE bb.`bot_id` = bbo.`BotID`;"); + } - print get_mysql_result("RENAME TABLE `botbuffs` TO `botbuffs_old`;"); - } + print get_mysql_result("RENAME TABLE `botbuffs` TO `botbuffs_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botinventory'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_inventories` (`inventories_index`, `bot_id`, `slot_id`, `item_id`, `inst_charges`, `inst_color`, `inst_no_drop`, `augment_1`, `augment_2`, `augment_3`, `augment_4`, `augment_5`) SELECT bi.`BotInventoryID`, bi.`BotID`, bi.`SlotID`, bi.`ItemID`, bi.`charges`, bi.`color`, bi.`instnodrop`, bi.`augslot1`, bi.`augslot2`, bi.`augslot3`, bi.`augslot4`, bi.`augslot5` FROM `botinventory` bi INNER JOIN `bot_data` bd ON bi.`BotID` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botinventory'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_inventories` (`inventories_index`, `bot_id`, `slot_id`, `item_id`, `inst_charges`, `inst_color`, `inst_no_drop`, `augment_1`, `augment_2`, `augment_3`, `augment_4`, `augment_5`) SELECT bi.`BotInventoryID`, bi.`BotID`, bi.`SlotID`, bi.`ItemID`, bi.`charges`, bi.`color`, bi.`instnodrop`, bi.`augslot1`, bi.`augslot2`, bi.`augslot3`, bi.`augslot4`, bi.`augslot5` FROM `botinventory` bi INNER JOIN `bot_data` bd ON bi.`BotID` = bd.`bot_id`;"); - if(get_mysql_result("SHOW COLUMNS FROM `botinventory` LIKE 'augslot6'") ne "" && $db){ - print get_mysql_result("UPDATE `bot_inventories` bi INNER JOIN `botinventory` bio ON bi.`inventories_index` = bio.`BotInventoryID` SET bi.`augment_6` = bio.`augslot6` WHERE bi.`bot_id` = bio.`BotID`;"); - } + if (get_mysql_result("SHOW COLUMNS FROM `botinventory` LIKE 'augslot6'") ne "" && $db) { + print get_mysql_result("UPDATE `bot_inventories` bi INNER JOIN `botinventory` bio ON bi.`inventories_index` = bio.`BotInventoryID` SET bi.`augment_6` = bio.`augslot6` WHERE bi.`bot_id` = bio.`BotID`;"); + } - print get_mysql_result("RENAME TABLE `botinventory` TO `botinventory_old`;"); - } + print get_mysql_result("RENAME TABLE `botinventory` TO `botinventory_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botpets'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pets` (`pets_index`, `pet_id`, `bot_id`, `name`, `mana`, `hp`) SELECT bp.`BotPetsId`, bp.`PetId`, bp.`BotId`, bp.`Name`, bp.`Mana`, bp.`HitPoints` FROM `botpets` bp INNER JOIN `bot_data` bd ON bp.`BotId` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botpets'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_pets` (`pets_index`, `pet_id`, `bot_id`, `name`, `mana`, `hp`) SELECT bp.`BotPetsId`, bp.`PetId`, bp.`BotId`, bp.`Name`, bp.`Mana`, bp.`HitPoints` FROM `botpets` bp INNER JOIN `bot_data` bd ON bp.`BotId` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `botpets` TO `botpets_old`;"); - } + print get_mysql_result("RENAME TABLE `botpets` TO `botpets_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botpetbuffs'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pet_buffs` (`pet_buffs_index`, `pets_index`, `spell_id`, `caster_level`, `duration`) SELECT bpb.`BotPetBuffId`, bpb.`BotPetsId`, bpb.`SpellId`, bpb.`CasterLevel`, bpb.`Duration` FROM `botpetbuffs` bpb INNER JOIN `bot_pets` bp ON bpb.`BotPetsId` = bp.`pets_index`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botpetbuffs'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_pet_buffs` (`pet_buffs_index`, `pets_index`, `spell_id`, `caster_level`, `duration`) SELECT bpb.`BotPetBuffId`, bpb.`BotPetsId`, bpb.`SpellId`, bpb.`CasterLevel`, bpb.`Duration` FROM `botpetbuffs` bpb INNER JOIN `bot_pets` bp ON bpb.`BotPetsId` = bp.`pets_index`;"); - print get_mysql_result("RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`;"); - } + print get_mysql_result("RENAME TABLE `botpetbuffs` TO `botpetbuffs_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botpetinventory'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_pet_inventories` (`pet_inventories_index`, `pets_index`, `item_id`) SELECT bpi.`BotPetInventoryId`, bpi.`BotPetsId`, bpi.`ItemId` FROM `botpetinventory` bpi INNER JOIN `bot_pets` bp ON bpi.`BotPetsId` = bp.`pets_index`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botpetinventory'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_pet_inventories` (`pet_inventories_index`, `pets_index`, `item_id`) SELECT bpi.`BotPetInventoryId`, bpi.`BotPetsId`, bpi.`ItemId` FROM `botpetinventory` bpi INNER JOIN `bot_pets` bp ON bpi.`BotPetsId` = bp.`pets_index`;"); - print get_mysql_result("RENAME TABLE `botpetinventory` TO `botpetinventory_old`;"); - } + print get_mysql_result("RENAME TABLE `botpetinventory` TO `botpetinventory_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botgroup'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_groups` (`groups_index`, `group_leader_id`, `group_name`) SELECT bg.`BotGroupId`, bg.`BotGroupLeaderBotId`, bg.`BotGroupName` FROM `botgroup` bg INNER JOIN `bot_data` bd ON bg.`BotGroupLeaderBotId` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botgroup'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_groups` (`groups_index`, `group_leader_id`, `group_name`) SELECT bg.`BotGroupId`, bg.`BotGroupLeaderBotId`, bg.`BotGroupName` FROM `botgroup` bg INNER JOIN `bot_data` bd ON bg.`BotGroupLeaderBotId` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `botgroup` TO `botgroup_old`;"); - } + print get_mysql_result("RENAME TABLE `botgroup` TO `botgroup_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botgroupmembers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_group_members` (`group_members_index`, `groups_index`, `bot_id`) SELECT bgm.`BotGroupMemberId`, bgm.`BotGroupId`, bgm.`BotId` FROM `botgroupmembers` bgm INNER JOIN `bot_groups` bg ON bgm.`BotGroupId` = bg.`groups_index` INNER JOIN `bot_data` bd ON bgm.`BotId` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botgroupmembers'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_group_members` (`group_members_index`, `groups_index`, `bot_id`) SELECT bgm.`BotGroupMemberId`, bgm.`BotGroupId`, bgm.`BotId` FROM `botgroupmembers` bgm INNER JOIN `bot_groups` bg ON bgm.`BotGroupId` = bg.`groups_index` INNER JOIN `bot_data` bd ON bgm.`BotId` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`;"); - } + print get_mysql_result("RENAME TABLE `botgroupmembers` TO `botgroupmembers_old`;"); + } - if(get_mysql_result("SHOW TABLES LIKE 'botguildmembers'") ne "" && $db){ - print get_mysql_result("INSERT INTO `bot_guild_members` (`bot_id`, `guild_id`, `rank`, `tribute_enable`, `total_tribute`, `last_tribute`, `banker`, `public_note`, `alt`) SELECT bgm.`char_id`, bgm.`guild_id`, bgm.`rank`, bgm.`tribute_enable`, bgm.`total_tribute`, bgm.`last_tribute`, bgm.`banker`, bgm.`public_note`, bgm.`alt` FROM `botguildmembers` bgm INNER JOIN `guilds` g ON bgm.`guild_id` = g.`id` INNER JOIN `bot_data` bd ON bgm.`char_id` = bd.`bot_id`;"); + if (get_mysql_result("SHOW TABLES LIKE 'botguildmembers'") ne "" && $db) { + print get_mysql_result("INSERT INTO `bot_guild_members` (`bot_id`, `guild_id`, `rank`, `tribute_enable`, `total_tribute`, `last_tribute`, `banker`, `public_note`, `alt`) SELECT bgm.`char_id`, bgm.`guild_id`, bgm.`rank`, bgm.`tribute_enable`, bgm.`total_tribute`, bgm.`last_tribute`, bgm.`banker`, bgm.`public_note`, bgm.`alt` FROM `botguildmembers` bgm INNER JOIN `guilds` g ON bgm.`guild_id` = g.`id` INNER JOIN `bot_data` bd ON bgm.`char_id` = bd.`bot_id`;"); - print get_mysql_result("RENAME TABLE `botguildmembers` TO `botguildmembers_old`;"); - } + print get_mysql_result("RENAME TABLE `botguildmembers` TO `botguildmembers_old`;"); + } } -sub get_bots_db_version{ - #::: Check if bots_version column exists... - if(get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db){ - print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); - print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; - } - $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); - return $bots_local_db_version; +sub get_bots_db_version { + #::: Check if bots_version column exists... + if (get_mysql_result("SHOW COLUMNS FROM db_version LIKE 'bots_version'") eq "" && $db) { + print get_mysql_result("ALTER TABLE db_version ADD bots_version int(11) DEFAULT '0' AFTER version;"); + print "[Database] Column 'bots_version' does not exists.... Adding to 'db_version' table...\n\n"; + } + $bots_local_db_version = trim(get_mysql_result("SELECT bots_version FROM db_version LIMIT 1")); + return $bots_local_db_version; } -sub bots_db_management{ - if($OS eq "Windows"){ - @db_version = split(': ', `world db_version`); - } - if($OS eq "Linux"){ - @db_version = split(': ', `./world db_version`); - } +sub bots_db_management { + if ($OS eq "Windows") { + @db_version = split(': ', `world db_version`); + } + if ($OS eq "Linux") { + @db_version = split(': ', `./world db_version`); + } - #::: Main Binary Database version - $binary_database_version = trim($db_version[2]); + #::: Main Binary Database version + $binary_database_version = trim($db_version[2]); - #::: If we have stale data from main db run - if($db_run_stage > 0 && $bots_db_management == 0){ - clear_database_runs(); - } + #::: If we have stale data from main db run + if ($db_run_stage > 0 && $bots_db_management == 0) { + clear_database_runs(); + } - if($binary_database_version == 0){ - print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; - return; - } + if ($binary_database_version == 0) { + print "[Database] Your server binaries (world/zone) are not compiled for bots...\n\n"; + return; + } - #::: Set on flag for running bot updates... - $bots_db_management = 1; + #::: Set on flag for running bot updates... + $bots_db_management = 1; - $bots_local_db_version = get_bots_db_version(); + $bots_local_db_version = get_bots_db_version(); - $local_database_version = $bots_local_db_version; + $local_database_version = $bots_local_db_version; - run_database_check(); + run_database_check(); } -sub main_db_management{ - #::: If we have stale data from bots db run - if($db_run_stage > 0 && $bots_db_management == 1){ - clear_database_runs(); - } +sub main_db_management { + #::: If we have stale data from bots db run + if ($db_run_stage > 0 && $bots_db_management == 1) { + clear_database_runs(); + } - #::: Main Binary Database version - $binary_database_version = trim($db_version[1]); + #::: Main Binary Database version + $binary_database_version = trim($db_version[1]); - $bots_db_management = 0; - run_database_check(); + $bots_db_management = 0; + run_database_check(); } -sub clear_database_runs{ - # print "DEBUG :: clear_database_runs\n\n"; - #::: Clear manifest data... - %m_d = (); - #::: Clear updates... - @total_updates = (); - #::: Clear stage - $db_run_stage = 0; +sub clear_database_runs { + # print "DEBUG :: clear_database_runs\n\n"; + #::: Clear manifest data... + %m_d = (); + #::: Clear updates... + @total_updates = (); + #::: Clear stage + $db_run_stage = 0; } #::: Responsible for Database Upgrade Routines -sub run_database_check{ +sub run_database_check { - if(!$db){ - print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; - return; - } + if (!$db) { + print "No database present, check your eqemu_config.xml for proper MySQL/MariaDB configuration...\n"; + return; + } - if(!@total_updates){ - #::: Pull down bots database manifest - if($bots_db_management == 1){ - print "[Database] Retrieving latest bots database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); - } - #::: Pull down mainstream database manifest - else{ - print "[Database] Retrieving latest database manifest...\n"; - get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); - } - } + if (!@total_updates) { + #::: Pull down bots database manifest + if ($bots_db_management == 1) { + print "[Database] Retrieving latest bots database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/bots_db_update_manifest.txt", "db_update/db_update_manifest.txt"); + } + #::: Pull down mainstream database manifest + else { + print "[Database] Retrieving latest database manifest...\n"; + get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); + } + } - #::: Run 2 - Running pending updates... - if(@total_updates || $db_run_stage == 1){ - @total_updates = sort @total_updates; - foreach my $val (@total_updates){ - $file_name = trim($m_d{$val}[1]); - print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; - print get_mysql_result_from_file("db_update/$file_name"); - print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); + #::: Run 2 - Running pending updates... + if (@total_updates || $db_run_stage == 1) { + @total_updates = sort @total_updates; + foreach my $val (@total_updates) { + $file_name = trim($m_d{$val}[1]); + print "[Database] Running Update: " . $val . " - " . $file_name . "\n"; + print get_mysql_result_from_file("db_update/$file_name"); + print get_mysql_result("UPDATE db_version SET version = $val WHERE version < $val"); - if($bots_db_management == 1 && $val == 9000){ - modify_db_for_bots(); - } - } - $db_run_stage = 2; - } - #::: Run 1 - Initial checking of needed updates... - else{ - print "[Database] Reading manifest...\n"; - use Data::Dumper; - open (FILE, "db_update/db_update_manifest.txt"); - while () { - chomp; - $o = $_; - if($o=~/#/i){ next; } - @manifest = split('\|', $o); - $m_d{$manifest[0]} = [@manifest]; - } - #::: Setting Manifest stage... - $db_run_stage = 1; - } + if ($bots_db_management == 1 && $val == 9000) { + modify_db_for_bots(); + } + } + $db_run_stage = 2; + } + #::: Run 1 - Initial checking of needed updates... + else { + print "[Database] Reading manifest...\n"; - @total_updates = (); + use Data::Dumper; + open(FILE, "db_update/db_update_manifest.txt"); + while () { + chomp; + $o = $_; + if ($o =~ /#/i) { + next; + } - #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... - if($local_database_version >= 9000){ - $revision_check = $local_database_version; - } - else { - $revision_check = 1000; - if(get_mysql_result("SHOW TABLES LIKE 'character_data'") ne ""){ - $revision_check = 8999; - } - } + @manifest = split('\|', $o); + $m_d{$manifest[0]} = [ @manifest ]; + } + #::: Setting Manifest stage... + $db_run_stage = 1; + } - #::: Iterate through Manifest backwards from binary version down to local version... - for($i = $revision_check; $i <= $binary_database_version; $i++){ - if(!defined($m_d{$i}[0])){ next; } + @total_updates = (); - $file_name = trim($m_d{$i}[1]); - $query_check = trim($m_d{$i}[2]); - $match_type = trim($m_d{$i}[3]); - $match_text = trim($m_d{$i}[4]); + #::: This is where we set checkpoints for where a database might be so we don't check so far back in the manifest... + if ($local_database_version >= 9000) { + $revision_check = $local_database_version; + } + else { + $revision_check = 1000; + if (get_mysql_result("SHOW TABLES LIKE 'character_data'") ne "") { + $revision_check = 8999; + } + } - #::: Match type update - if($match_type eq "contains"){ - if(trim(get_mysql_result($query_check))=~/$match_text/i){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - if($match_type eq "missing"){ - if(get_mysql_result($query_check)=~/$match_text/i){ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - next; - } - else{ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - print_match_debug(); - print_break(); - } - if($match_type eq "empty"){ - if(get_mysql_result($query_check) eq ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - if($match_type eq "not_empty"){ - if(get_mysql_result($query_check) ne ""){ - print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; - fetch_missing_db_update($i, $file_name); - push(@total_updates, $i); - } - else{ - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; - } - print_match_debug(); - print_break(); - } - } - print "\n"; + #::: Iterate through Manifest backwards from binary version down to local version... + for ($i = $revision_check; $i <= $binary_database_version; $i++) { + if (!defined($m_d{$i}[0])) { + next; + } - if(scalar (@total_updates) == 0 && $db_run_stage == 2){ - print "[Database] No updates need to be run...\n"; - if($bots_db_management == 1){ - print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET bots_version = $binary_database_version "); - } - else{ - print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n"; - get_mysql_result("UPDATE db_version SET version = $binary_database_version "); - } + $file_name = trim($m_d{$i}[1]); + $query_check = trim($m_d{$i}[2]); + $match_type = trim($m_d{$i}[3]); + $match_text = trim($m_d{$i}[4]); - clear_database_runs(); - } + #::: Match type update + if ($match_type eq "contains") { + if (trim(get_mysql_result($query_check)) =~ /$match_text/i) { + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else { + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + if ($match_type eq "missing") { + if (get_mysql_result($query_check) =~ /$match_text/i) { + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + next; + } + else { + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + print_match_debug(); + print_break(); + } + if ($match_type eq "empty") { + if (get_mysql_result($query_check) eq "") { + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else { + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + if ($match_type eq "not_empty") { + if (get_mysql_result($query_check) ne "") { + print "[Database] missing update: " . $i . " '" . $file_name . "' \n"; + fetch_missing_db_update($i, $file_name); + push(@total_updates, $i); + } + else { + print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + } + print_match_debug(); + print_break(); + } + } + print "\n"; + + if (scalar(@total_updates) == 0 && $db_run_stage == 2) { + print "[Database] No updates need to be run...\n"; + if ($bots_db_management == 1) { + print "[Database] Setting Database to Bots Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET bots_version = $binary_database_version "); + } + else { + print "[Database] Setting Database to Binary Version (" . $binary_database_version . ") if not already...\n\n"; + get_mysql_result("UPDATE db_version SET version = $binary_database_version "); + } + + clear_database_runs(); + } } -sub fetch_missing_db_update{ - $db_update = $_[0]; - $update_file = $_[1]; - if($db_update >= 9000){ - if($bots_db_management == 1){ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); - } - else{ - get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); - } - } - elsif($db_update >= 5000 && $db_update <= 9000){ - get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); - } +sub fetch_missing_db_update { + $db_update = $_[0]; + $update_file = $_[1]; + if ($db_update >= 9000) { + if ($bots_db_management == 1) { + get_remote_file($eqemu_repository_request_url . "utils/sql/git/bots/required/" . $update_file, "db_update/" . $update_file . ""); + } + else { + get_remote_file($eqemu_repository_request_url . "utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); + } + } + elsif ($db_update >= 5000 && $db_update <= 9000) { + get_remote_file($eqemu_repository_request_url . "utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); + } } -sub print_match_debug{ - if(!$debug){ return; } - print " Match Type: '" . $match_type . "'\n"; - print " Match Text: '" . $match_text . "'\n"; - print " Query Check: '" . $query_check . "'\n"; - print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; +sub print_match_debug { + if (!$debug) {return;} + print " Match Type: '" . $match_type . "'\n"; + print " Match Text: '" . $match_text . "'\n"; + print " Query Check: '" . $query_check . "'\n"; + print " Result: '" . trim(get_mysql_result($query_check)) . "'\n"; } -sub print_break{ - if(!$debug){ return; } - print "\n==============================================\n"; +sub print_break { + if (!$debug) {return;} + print "\n==============================================\n"; } sub generate_random_password { - my $passwordsize = shift; - my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9); - my $randpassword = join '', - map $alphanumeric[rand @alphanumeric], 0..$passwordsize; + my $passwordsize = shift; + my @alphanumeric = ('a' .. 'z', 'A' .. 'Z', 0 .. 9); + my $randpassword = join '', + map $alphanumeric[rand @alphanumeric], 0 .. $passwordsize; - return $randpassword; + return $randpassword; } sub quest_heading_convert { - if(trim(get_mysql_result("SELECT value FROM variables WHERE varname = 'new_heading_conversion'")) eq "true") { - print "Conversion script has already ran... doing this again would skew proper heading values in function calls...\n"; - exit; - } + if (trim(get_mysql_result("SELECT value FROM variables WHERE varname = 'new_heading_conversion'")) eq "true") { + print "Conversion script has already ran... doing this again would skew proper heading values in function calls...\n"; + exit; + } - %matches = ( - 0 => ["quest::spawn2", 6], - 1 => ["eq.spawn2", 6], - 2 => ["eq.unique_spawn", 6], - 3 => ["quest::unique_spawn", 6], - 4 => ["GMMove", 3], - 5 => ["MovePCInstance", 5], - 6 => ["MovePC", 4], - 7 => ["moveto", 3], - ); + %matches = ( + 0 => [ "quest::spawn2", 6 ], + 1 => [ "eq.spawn2", 6 ], + 2 => [ "eq.unique_spawn", 6 ], + 3 => [ "quest::unique_spawn", 6 ], + 4 => [ "GMMove", 3 ], + 5 => [ "MovePCInstance", 5 ], + 6 => [ "MovePC", 4 ], + 7 => [ "moveto", 3 ], + ); - $total_matches = 0; + $total_matches = 0; - use Scalar::Util qw(looks_like_number); + use Scalar::Util qw(looks_like_number); - my @files; - my $start_dir = "quests/."; - find( - sub { push @files, $File::Find::name unless -d; }, - $start_dir - ); - for my $file (@files) { + my @files; + my $start_dir = "quests/."; + find( + sub {push @files, $File::Find::name unless -d;}, + $start_dir + ); + for my $file (@files) { - #::: Skip non script files - if($file!~/lua|pl/i){ next; } + #::: Skip non script files + if ($file !~ /lua|pl/i) {next;} - if($file=~/lua|pl/i){ - $print_buffer = ""; + if ($file =~ /lua|pl/i) { + $print_buffer = ""; - $changes_made = 0; + $changes_made = 0; - #::: Open and read line by line - open (FILE, $file); - while () { - chomp; - $line = $_; + #::: Open and read line by line + open(FILE, $file); + while () { + chomp; + $line = $_; - #::: Loop through matches - foreach my $key (sort(keys %matches)) { - $argument_position = $matches{$key}[1]; - $match = $matches{$key}[0]; + #::: Loop through matches + foreach my $key (sort (keys %matches)) { + $argument_position = $matches{$key}[1]; + $match = $matches{$key}[0]; - if($line=~/$match/i) { - $line_temp = $line; - $line_temp =~s/$match\(//g; - $line_temp =~s/\(.*?\)//gs; - $line_temp =~s/\);.*//; - $line_temp =~s/\).*//; - $line_temp =~s/\):.*//; - $line_temp =~s/\);//g; + if ($line =~ /$match/i) { + $line_temp = $line; + $line_temp =~ s/$match\(//g; + $line_temp =~ s/\(.*?\)//gs; + $line_temp =~ s/\);.*//; + $line_temp =~ s/\).*//; + $line_temp =~ s/\):.*//; + $line_temp =~ s/\);//g; - @line_data = split(",", $line_temp); + @line_data = split(",", $line_temp); - # use Data::Dumper; - # print Dumper(\@line_data); + # use Data::Dumper; + # print Dumper(\@line_data); - $heading_value = $line_data[$argument_position]; - $heading_value_clean = trim($heading_value); - $heading_value_raw = $line_data[$argument_position]; - $heading_value_before = $line_data[$argument_position - 1]; + $heading_value = $line_data[$argument_position]; + $heading_value_clean = trim($heading_value); + $heading_value_raw = $line_data[$argument_position]; + $heading_value_before = $line_data[$argument_position - 1]; - if (looks_like_number($heading_value) && $heading_value != 0 && ($heading_value * 2) <= 512) { - $heading_value_new = $heading_value * 2; + if (looks_like_number($heading_value) && $heading_value != 0 && ($heading_value * 2) <= 512) { + $heading_value_new = $heading_value * 2; - $heading_value=~s/$heading_value_clean/$heading_value_new/g; + $heading_value =~ s/$heading_value_clean/$heading_value_new/g; - $heading_value_search = quotemeta($heading_value_before . "," . $heading_value_raw); - $heading_value_replace = $heading_value_before . "," . $heading_value; + $heading_value_search = quotemeta($heading_value_before . "," . $heading_value_raw); + $heading_value_replace = $heading_value_before . "," . $heading_value; - print $file . "\n"; - print $line . "\n"; - $line=~s/$heading_value_search/$heading_value_replace/g; - print $line . "\n"; - print "\n"; + print $file . "\n"; + print $line . "\n"; + $line =~ s/$heading_value_search/$heading_value_replace/g; + print $line . "\n"; + print "\n"; - $changes_made = 1; - } - elsif ($heading_value == 0){} #::: Do nothing - elsif ($heading_value=~/GetHeading|heading|\$h/i){} #::: Do nothing - else { - if ($file=~/\.pl/i) { - if($line_temp=~/#/i) { - $line .= " - needs_heading_validation"; - } - else { - $line .= " # needs_heading_validation"; - } - } - elsif ($file=~/\.lua/i) { - if($line_temp=~/--/i) { - $line .= " - needs_heading_validation"; - } - else { - $line .= " -- needs_heading_validation"; - } - } + $changes_made = 1; + } + elsif ($heading_value == 0) {} #::: Do nothing + elsif ($heading_value =~ /GetHeading|heading|\$h/i) {} #::: Do nothing + else { + if ($file =~ /\.pl/i) { + if ($line_temp =~ /#/i) { + $line .= " - needs_heading_validation"; + } + else { + $line .= " # needs_heading_validation"; + } + } + elsif ($file =~ /\.lua/i) { + if ($line_temp =~ /--/i) { + $line .= " - needs_heading_validation"; + } + else { + $line .= " -- needs_heading_validation"; + } + } - $changes_made = 1; + $changes_made = 1; - print $line . "\n"; - } + print $line . "\n"; + } - $total_matches++; - } - } + $total_matches++; + } + } - $print_buffer .= $line . "\n"; - } - close (FILE); + $print_buffer .= $line . "\n"; + } + close(FILE); - if($changes_made == 1) { - #::: Write changes - open (NEW_FILE, '>', $file); - print NEW_FILE $print_buffer; - close NEW_FILE; - } - } - } + if ($changes_made == 1) { + #::: Write changes + open(NEW_FILE, '>', $file); + print NEW_FILE $print_buffer; + close NEW_FILE; + } + } + } - #::: Mark conversion as ran - print get_mysql_result("INSERT INTO `variables` (varname, value, information, ts) VALUES ('new_heading_conversion', 'true', 'Script ran against quests folder to convert new heading values', NOW())"); + #::: Mark conversion as ran + print get_mysql_result("INSERT INTO `variables` (varname, value, information, ts) VALUES ('new_heading_conversion', 'true', 'Script ran against quests folder to convert new heading values', NOW())"); - print "Total matches: " . $total_matches . "\n"; + print "Total matches: " . $total_matches . "\n"; } From f6ea89f1006df94f5eb1ef6f5dbaa385cfab2c76 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 02:49:51 -0600 Subject: [PATCH 24/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 204 ++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 98 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 90a75b724..6189bef8b 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -19,13 +19,13 @@ use Time::HiRes qw(usleep); #::: Variables $install_repository_request_url = "https://raw.githubusercontent.com/Akkadius/EQEmuInstall/master/"; -$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; +$eqemu_repository_request_url = "https://raw.githubusercontent.com/EQEmu/Server/master/"; #::: Globals -$time_stamp = strftime('%m-%d-%Y', gmtime()); +$time_stamp = strftime('%m-%d-%Y', gmtime()); $db_run_stage = 0; #::: Sets database run stage check if ($Config{osname} =~ /freebsd|linux/i) { - $OS = "Linux"; + $OS = "Linux"; $os_flavor = ""; if (-e "/etc/debian_version") { $os_flavor = "debian"; @@ -134,7 +134,7 @@ sub analytics_insertion { $extended_os = trim($extended_os); } if ($OS eq "Windows") { - my $output = `ver`; + my $output = `ver`; my @os_version = split("\n", $output); foreach my $val (@os_version) { if ($val =~ /Windows/i) { @@ -179,7 +179,7 @@ sub show_install_summary_info { open(INSTALL_VARS, $file_to_open); while () { chomp; - $o = $_; + $o = $_; @data = split(":", $o); print " - " . $data[0] . "\t" . $data[1] . "\n"; } @@ -227,8 +227,8 @@ sub new_server { while (1) { - $database_name = $installation_variables{"mysql_eqemu_db_name"}; - $database_user = $installation_variables{"mysql_eqemu_user"}; + $database_name = $installation_variables{"mysql_eqemu_db_name"}; + $database_user = $installation_variables{"mysql_eqemu_user"}; $database_password = $installation_variables{"mysql_eqemu_password"}; if ($database_name ne "") { @@ -248,13 +248,13 @@ sub new_server { $database_password = trim($input); $check_connection = `mysql -u $database_user -p$database_password -N -B -e "SHOW PROCESSLIST" > mysqlcheck.txt`; - $mysql_pass = 0; + $mysql_pass = 0; open(MYSQL_CHECK, "mysqlcheck.txt"); while () { chomp; - $o = $_; - if ($o =~ /Error/i) {$mysql_pass = 0;} - if ($o =~ /SHOW PROCESSLIST/i) {$mysql_pass = 1;} + $o = $_; + if ($o =~ /Error/i) { $mysql_pass = 0; } + if ($o =~ /SHOW PROCESSLIST/i) { $mysql_pass = 1; } } close(MYSQL_CHECK); unlink("mysqlcheck.txt"); @@ -368,23 +368,23 @@ sub build_linux_source { $build_options = $_[0]; - $cmake_options = ""; + $cmake_options = ""; $source_folder_post_fix = ""; if ($build_options =~ /bots/i) { - $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; + $cmake_options .= " -DEQEMU_ENABLE_BOTS=ON"; $source_folder_post_fix = "_bots"; } $current_directory = `pwd`; - @directories = split('/', $current_directory); + @directories = split('/', $current_directory); foreach my $val (@directories) { if (trim($val) ne "") { $last_directory = trim($val); } } my $eqemu_server_directory = "/home/eqemu"; - my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix; + my $source_dir = $eqemu_server_directory . '/' . $last_directory . '_source' . $source_folder_post_fix; $current_directory = trim($current_directory); @@ -467,9 +467,9 @@ sub do_installer_routines { print `"$path" --host $host --user $user --password="$pass" -N -B -e "CREATE DATABASE $db_name"`; #::: Get Binary DB version - if ($OS eq "Windows") {@db_version = split(': ', `world db_version`);} - if ($OS eq "Linux") {@db_version = split(': ', `./world db_version`);} - $binary_database_version = trim($db_version[1]); + if ($OS eq "Windows") { @db_version = split(': ', `world db_version`); } + if ($OS eq "Linux") { @db_version = split(': ', `./world db_version`); } + $binary_database_version = trim($db_version[1]); #::: Local DB Version check_db_version_table(); @@ -508,7 +508,7 @@ sub check_for_world_bootup_database_update { } $binary_database_version = trim($db_version[1]); - $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); + $local_database_version = trim(get_mysql_result("SELECT version FROM db_version LIMIT 1")); #::: Bots $bots_binary_version = trim($db_version[2]); @@ -556,7 +556,7 @@ sub check_for_world_bootup_database_update { #::: Make sure that we didn't pass any arugments to the script else { - if (!$db) {print "[eqemu_server.pl] No database connection found... Running without\n";} + if (!$db) { print "[eqemu_server.pl] No database connection found... Running without\n"; } show_menu_prompt(); } } @@ -616,7 +616,7 @@ sub do_self_update_check_routine { if (-e "updates_staged/eqemu_server.pl") { my $remote_script_size = -s "updates_staged/eqemu_server.pl"; - my $local_script_size = -s "eqemu_server.pl"; + my $local_script_size = -s "eqemu_server.pl"; if ($remote_script_size != $local_script_size) { print "[Update] Script has been updated, updating...\n"; @@ -624,7 +624,7 @@ sub do_self_update_check_routine { my @files; my $start_dir = "updates_staged/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -666,8 +666,8 @@ sub get_installation_variables { } while () { chomp; - $o = $_; - @data = split(":", $o); + $o = $_; + @data = split(":", $o); $installation_variables{trim($data[0])} = trim($data[1]); } close(INSTALL_VARS); @@ -691,9 +691,9 @@ sub do_install_config_json { $config = $json->decode($content); - $long_name = "Akkas " . $OS . " PEQ Installer (" . generate_random_password(5) . ')'; + $long_name = "Akkas " . $OS . " PEQ Installer (" . generate_random_password(5) . ')'; $config->{"server"}{"world"}{"longname"} = $long_name; - $config->{"server"}{"world"}{"key"} = generate_random_password(30); + $config->{"server"}{"world"}{"key"} = generate_random_password(30); if ($installation_variables{"mysql_eqemu_db_name"}) { $db_name = $installation_variables{"mysql_eqemu_db_name"}; @@ -704,11 +704,11 @@ sub do_install_config_json { $config->{"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"}{"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; + $config->{"server"}{"qsdatabase"}{"db"} = $db_name; $json->canonical(1); $json->indent_length(5); @@ -933,7 +933,7 @@ sub show_menu_prompt { } elsif ($dc == 1) { analytics_insertion("menu", trim($input)); - $dc = 0; + $dc = 0; $input = ""; } else { @@ -943,7 +943,7 @@ sub show_menu_prompt { #::: If we're processing a CLI command, kill the loop if ($ARGV[0] ne "") { analytics_insertion("cli", trim($input)); - $input = ""; + $input = ""; $ARGV[0] = ""; exit; } @@ -1007,7 +1007,7 @@ sub check_for_database_dump_script { if (-e "updates_staged/database_dumper.pl") { my $remote_script_size = -s "updates_staged/database_dumper.pl"; - my $local_script_size = -s "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"; @@ -1015,7 +1015,7 @@ sub check_for_database_dump_script { my @files; my $start_dir = "updates_staged/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1059,7 +1059,7 @@ sub database_dump_player_tables { $i = 0; while () { chomp; - $o = $_; + $o = $_; $tables .= $o . ","; } $tables = substr($tables, 0, -1); @@ -1098,8 +1098,8 @@ sub check_db_version_table { #::: Returns Tab Delimited MySQL Result from Command Line sub get_mysql_result { my $run_query = $_[0]; - if (!$db) {return;} - if ($OS eq "Windows") {return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`;} + if (!$db) { return; } + if ($OS eq "Windows") { return `"$path" --host $host --user $user --password="$pass" $db -N -B -e "$run_query"`; } if ($OS eq "Linux") { $run_query =~ s/`//g; return `$path --user="$user" --host $host --password="$pass" $db -N -B -e "$run_query"`; @@ -1108,19 +1108,27 @@ sub get_mysql_result { sub get_mysql_result_from_file { my $update_file = $_[0]; - if (!$db) {return;} - if ($OS eq "Windows") {return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`;} - if ($OS eq "Linux") {return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`;} + if (!$db) { + return; + } + + if ($OS eq "Windows") { + return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; + } + + if ($OS eq "Linux") { + return `"$path" --host $host --user $user --password="$pass" --force $db < $update_file`; + } } #::: Gets Remote File based on request_url (1st Arg), and saves to destination file (2nd Arg) #::: Example: get_remote_file($eqemu_repository_request_url . "utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); sub get_remote_file { - my $request_url = $_[0]; + my $request_url = $_[0]; my $destination_file = $_[1]; - my $content_type = $_[2]; - my $no_retry = $_[3]; - my $silent_download = $_[4]; + my $content_type = $_[2]; + my $no_retry = $_[3]; + my $silent_download = $_[4]; if (!$has_internet_connection) { print "[Download] Cannot download without internet connection...\n"; @@ -1131,8 +1139,8 @@ sub get_remote_file { if ($destination_file =~ /\//i) { my @directory_path = split('/', $destination_file); - $build_path = ""; - $directory_index = 0; + $build_path = ""; + $directory_index = 0; while ($directory_path[$directory_index] && $directory_path[$directory_index + 1]) { $build_path .= $directory_path[$directory_index] . "/"; # print "checking '" . $build_path . "'\n"; @@ -1190,8 +1198,8 @@ sub read_eqemu_config_xml { print "Long Name: '" . $long_name . "'\n" if $debug; } if ($in_database_tag == 1) { - @left = split(">", $o); - @right = split("<", $left[1]); + @left = split(">", $o); + @right = split("<", $left[1]); $tag_data = trim($right[0]); if ($o =~ //i && $in_database_tag) { @@ -1228,7 +1236,7 @@ sub read_eqemu_config_json { $config = $json->decode($content); - $db = $config->{"server"}{"database"}{"db"}; + $db = $config->{"server"}{"database"}{"db"}; $host = $config->{"server"}{"database"}{"host"}; $user = $config->{"server"}{"database"}{"username"}; $pass = $config->{"server"}{"database"}{"password"}; @@ -1266,7 +1274,7 @@ sub opcodes_fetch { while ($opcodes{$loop}[0]) { #::: Split the request_url by the patches folder to get the file name from request_url @real_file = split("patches/", $opcodes{$loop}[1]); - $find = 0; + $find = 0; while ($real_file[$find]) { $file_name = $real_file[$find]; $find++; @@ -1286,15 +1294,15 @@ sub remove_duplicate_rule_values { #::: Store Default values... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` = " . $ruleset_id); - my @lines = split("\n", $mysql_result); + my @lines = split("\n", $mysql_result); foreach my $val (@lines) { - my @values = split("\t", $val); + my @values = split("\t", $val); $rule_set_values{$values[1]}[0] = $values[2]; } #::: Compare default values against other rulesets to check for duplicates... $mysql_result = get_mysql_result("SELECT * FROM `rule_values` WHERE `ruleset_id` != " . $ruleset_id); - my @lines = split("\n", $mysql_result); + my @lines = split("\n", $mysql_result); foreach my $val (@lines) { my @values = split("\t", $val); if ($values[2] == $rule_set_values{$values[1]}[0]) { @@ -1308,12 +1316,12 @@ sub remove_duplicate_rule_values { } sub copy_file { - $l_source_file = $_[0]; + $l_source_file = $_[0]; $l_destination_file = $_[1]; if ($l_destination_file =~ /\//i) { my @directory_path = split('/', $l_destination_file); - $build_path = ""; - $directory_index = 0; + $build_path = ""; + $directory_index = 0; while ($directory_path[$directory_index]) { $build_path .= $directory_path[$directory_index] . "/"; #::: If path does not exist, create the directory... @@ -1341,7 +1349,7 @@ sub fetch_latest_windows_appveyor { my @files; my $start_dir = "updates_staged/binaries"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1364,7 +1372,7 @@ sub fetch_latest_windows_binaries { my @files; my $start_dir = "updates_staged/binaries"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1387,7 +1395,7 @@ sub fetch_latest_windows_binaries_bots { my @files; my $start_dir = "updates_staged/binaries"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1409,7 +1417,7 @@ sub do_windows_login_server_setup { my @files; my $start_dir = "updates_staged/login_server"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1465,8 +1473,8 @@ sub do_linux_login_server_setup { system("chmod 755 *.sh"); get_installation_variables(); - my $db_name = $installation_variables{"mysql_eqemu_db_name"}; - my $db_user = $installation_variables{"mysql_eqemu_user"}; + my $db_name = $installation_variables{"mysql_eqemu_db_name"}; + my $db_user = $installation_variables{"mysql_eqemu_user"}; my $db_password = $installation_variables{"mysql_eqemu_password"}; #::: Open new config file @@ -1478,9 +1486,9 @@ sub do_linux_login_server_setup { chomp; $o = $_; #::: Find replace variables - if ($o =~ /db/i) {$o = "db = " . $db_name;} - if ($o =~ /user/i) {$o = "user = " . $db_user;} - if ($o =~ /password/i) {$o = "password = " . $db_password;} + if ($o =~ /db/i) { $o = "db = " . $db_name; } + if ($o =~ /user/i) { $o = "user = " . $db_user; } + if ($o =~ /password/i) { $o = "password = " . $db_password; } print NEW_CONFIG $o . "\n"; } @@ -1498,10 +1506,10 @@ sub do_linux_login_server_setup { sub add_login_server_firewall_rules { #::: Check Loginserver Firewall install for Windows if ($OS eq "Windows") { - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); $has_loginserver_rules_titanium = 0; - $has_loginserver_rules_sod = 0; + $has_loginserver_rules_sod = 0; foreach my $val (@output_buffer) { if ($val =~ /Rule Name/i) { $val =~ s/Rule Name://g; @@ -1552,10 +1560,10 @@ sub add_login_server_firewall_rules { } sub check_windows_firewall_rules { - $output = `netsh advfirewall firewall show rule name=all`; - @output_buffer = split("\n", $output); + $output = `netsh advfirewall firewall show rule name=all`; + @output_buffer = split("\n", $output); $has_world_rules = 0; - $has_zone_rules = 0; + $has_zone_rules = 0; foreach my $val (@output_buffer) { if ($val =~ /Rule Name/i) { $val =~ s/Rule Name://g; @@ -1598,7 +1606,7 @@ sub fetch_peq_db_full { unzip('updates_staged/peq_beta.zip', 'updates_staged/peq_db/'); my $start_dir = "updates_staged/peq_db"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1622,7 +1630,7 @@ sub map_files_fetch_bulk { my @files; my $start_dir = "maps/EQEmuMaps-master/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { @@ -1647,7 +1655,7 @@ sub map_files_fetch { $i = 0; while () { chomp; - $o = $_; + $o = $_; @manifest_map_data = split(',', $o); if ($manifest_map_data[0] ne "") { $maps_manifest[$i] = [ $manifest_map_data[0], $manifest_map_data[1] ]; @@ -1656,9 +1664,9 @@ sub map_files_fetch { } #::: Download - $fc = 0; - for ($m = 0; $m <= $i; $m++) { - my $file_existing = $maps_manifest[$m][0]; + $fc = 0; + for ($m = 0; $m <= $i; $m++) { + my $file_existing = $maps_manifest[$m][0]; my $file_existing_size = (stat $file_existing)[7]; if ($file_existing_size != $maps_manifest[$m][1]) { print "[Install] Updating: '" . $maps_manifest[$m][0] . "'\n"; @@ -1688,12 +1696,12 @@ sub quest_files_fetch { my @files; my $start_dir = "updates_staged/projecteqquests-master/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { if ($file =~ /\.pl|\.lua|\.ext/i) { - $staged_file = $file; + $staged_file = $file; $destination_file = $file; $destination_file =~ s/updates_staged\/projecteqquests-master\//quests\//g; @@ -1748,12 +1756,12 @@ sub lua_modules_fetch { my @files; my $start_dir = "updates_staged/projecteqquests-master/lua_modules/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { if ($file =~ /\.pl|\.lua|\.ext/i) { - $staged_file = $file; + $staged_file = $file; $destination_file = $file; $destination_file =~ s/updates_staged\/projecteqquests-master\/lua_modules\//lua_modules\//g; @@ -1807,12 +1815,12 @@ sub plugins_fetch { my @files; my $start_dir = "updates_staged/projecteqquests-master/plugins/"; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { if ($file =~ /\.pl|\.lua|\.ext/i) { - $staged_file = $file; + $staged_file = $file; $destination_file = $file; $destination_file =~ s/updates_staged\/projecteqquests-master\///g; @@ -1864,7 +1872,7 @@ sub do_file_diff { sub unzip { $archive_to_unzip = $_[0]; - $dest_folder = $_[1]; + $dest_folder = $_[1]; if ($OS eq "Windows") { eval "use Archive::Zip qw( :ERROR_CODES :CONSTANTS )"; @@ -1881,8 +1889,8 @@ sub unzip { } sub are_file_sizes_different { - $file_1 = $_[0]; - $file_2 = $_[1]; + $file_1 = $_[0]; + $file_2 = $_[1]; my $file_1 = (stat $file_1)[7]; my $file_2 = (stat $file_2)[7]; # print $file_1 . " :: " . $file_2 . "\n"; @@ -2216,7 +2224,7 @@ sub run_database_check { next; } - @manifest = split('\|', $o); + @manifest = split('\|', $o); $m_d{$manifest[0]} = [ @manifest ]; } #::: Setting Manifest stage... @@ -2242,10 +2250,10 @@ sub run_database_check { next; } - $file_name = trim($m_d{$i}[1]); + $file_name = trim($m_d{$i}[1]); $query_check = trim($m_d{$i}[2]); - $match_type = trim($m_d{$i}[3]); - $match_text = trim($m_d{$i}[4]); + $match_type = trim($m_d{$i}[3]); + $match_text = trim($m_d{$i}[4]); #::: Match type update if ($match_type eq "contains") { @@ -2316,7 +2324,7 @@ sub run_database_check { } sub fetch_missing_db_update { - $db_update = $_[0]; + $db_update = $_[0]; $update_file = $_[1]; if ($db_update >= 9000) { if ($bots_db_management == 1) { @@ -2332,7 +2340,7 @@ sub fetch_missing_db_update { } sub print_match_debug { - if (!$debug) {return;} + if (!$debug) { return; } print " Match Type: '" . $match_type . "'\n"; print " Match Text: '" . $match_text . "'\n"; print " Query Check: '" . $query_check . "'\n"; @@ -2340,7 +2348,7 @@ sub print_match_debug { } sub print_break { - if (!$debug) {return;} + if (!$debug) { return; } print "\n==============================================\n"; } @@ -2378,13 +2386,13 @@ sub quest_heading_convert { my @files; my $start_dir = "quests/."; find( - sub {push @files, $File::Find::name unless -d;}, + sub { push @files, $File::Find::name unless -d; }, $start_dir ); for my $file (@files) { #::: Skip non script files - if ($file !~ /lua|pl/i) {next;} + if ($file !~ /lua|pl/i) { next; } if ($file =~ /lua|pl/i) { $print_buffer = ""; @@ -2400,7 +2408,7 @@ sub quest_heading_convert { #::: Loop through matches foreach my $key (sort (keys %matches)) { $argument_position = $matches{$key}[1]; - $match = $matches{$key}[0]; + $match = $matches{$key}[0]; if ($line =~ /$match/i) { $line_temp = $line; @@ -2416,9 +2424,9 @@ sub quest_heading_convert { # use Data::Dumper; # print Dumper(\@line_data); - $heading_value = $line_data[$argument_position]; - $heading_value_clean = trim($heading_value); - $heading_value_raw = $line_data[$argument_position]; + $heading_value = $line_data[$argument_position]; + $heading_value_clean = trim($heading_value); + $heading_value_raw = $line_data[$argument_position]; $heading_value_before = $line_data[$argument_position - 1]; if (looks_like_number($heading_value) && $heading_value != 0 && ($heading_value * 2) <= 512) { @@ -2426,7 +2434,7 @@ sub quest_heading_convert { $heading_value =~ s/$heading_value_clean/$heading_value_new/g; - $heading_value_search = quotemeta($heading_value_before . "," . $heading_value_raw); + $heading_value_search = quotemeta($heading_value_before . "," . $heading_value_raw); $heading_value_replace = $heading_value_before . "," . $heading_value; print $file . "\n"; From b82e870e2246673d7e89b0e858e36fb6f7caf859 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 02:50:30 -0600 Subject: [PATCH 25/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 6189bef8b..dbc82c247 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -920,7 +920,7 @@ sub show_menu_prompt { $errored_command = 1; } elsif ($input ne "") { - print "Invalid command '" . $input . "'\n"; + # print "Invalid command '" . $input . "'\n"; $errored_command = 1; } else { From 6d5c99d89293175893d478d2d70399aef5375580 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 02:57:40 -0600 Subject: [PATCH 26/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index dbc82c247..cfb54353f 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -876,6 +876,7 @@ sub show_menu_prompt { $dc = 1; } elsif ($input eq "check_db_updates") { + main_db_management(); main_db_management(); $dc = 1; } From 16270d7f93277b113a8e17ffac9f9f69d6e4f3ee Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 03:02:20 -0600 Subject: [PATCH 27/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index cfb54353f..e79322658 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -2246,7 +2246,7 @@ sub run_database_check { } #::: Iterate through Manifest backwards from binary version down to local version... - for ($i = $revision_check; $i <= $binary_database_version; $i++) { + for ($i = $revision_check; $i < $binary_database_version; $i++) { if (!defined($m_d{$i}[0])) { next; } From 5aa64f362d014a4bb7157db0fb54783d60ea7d8e Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 03:11:00 -0600 Subject: [PATCH 28/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index e79322658..22d59a4b1 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -2246,7 +2246,7 @@ sub run_database_check { } #::: Iterate through Manifest backwards from binary version down to local version... - for ($i = $revision_check; $i < $binary_database_version; $i++) { + for ($i = $revision_check; $i <= $binary_database_version; $i++) { if (!defined($m_d{$i}[0])) { next; } @@ -2264,14 +2264,14 @@ sub run_database_check { push(@total_updates, $i); } else { - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update (" . $i . ") '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if ($match_type eq "missing") { if (get_mysql_result($query_check) =~ /$match_text/i) { - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update (" . $i . ") '" . $file_name . "' \n"; next; } else { @@ -2289,7 +2289,7 @@ sub run_database_check { push(@total_updates, $i); } else { - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update (" . $i . ") '" . $file_name . "' \n"; } print_match_debug(); print_break(); @@ -2301,7 +2301,7 @@ sub run_database_check { push(@total_updates, $i); } else { - print "[Database] has update: " . $i . " - '" . $file_name . "' \n"; + print "[Database] has update (" . $i . ") '" . $file_name . "' \n"; } print_match_debug(); print_break(); From b0c4d626f296bc4a3d1255fd9c53c992bac032f7 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 03:16:02 -0600 Subject: [PATCH 29/38] Update db_update_manifest.txt [skip ci] --- utils/sql/db_update_manifest.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/sql/db_update_manifest.txt b/utils/sql/db_update_manifest.txt index 9e3a7190f..2a6f35e89 100644 --- a/utils/sql/db_update_manifest.txt +++ b/utils/sql/db_update_manifest.txt @@ -388,7 +388,7 @@ 9132|2018_12_16_global_base_scaling.sql|SHOW TABLES LIKE 'npc_scale_global_base'|empty| 9133|2018_11_25_StuckBehavior.sql|SHOW COLUMNS FROM `npc_types` LIKE 'stuck_behavior'|empty| 9134|2019_01_04_update_global_base_scaling.sql|SELECT * FROM db_version WHERE version >= 9134|empty| -9135|2019_01_10_multi_version_spawns.sql|SELECT * FROM db_version WHERE version >= 9135|empty| +9135|2019_01_10_multi_version_spawns.sql|SHOW COLUMNS FROM `spawn2` LIKE 'version'|contains|unsigned| # Upgrade conditions: # This won't be needed after this system is implemented, but it is used database that are not From 2d5f0dce42b062d9d54d8ef469c6c29928cd3014 Mon Sep 17 00:00:00 2001 From: Akkadius Date: Tue, 22 Jan 2019 03:18:47 -0600 Subject: [PATCH 30/38] Update eqemu_server.pl [skip ci] --- utils/scripts/eqemu_server.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/scripts/eqemu_server.pl b/utils/scripts/eqemu_server.pl index 22d59a4b1..29552c82b 100644 --- a/utils/scripts/eqemu_server.pl +++ b/utils/scripts/eqemu_server.pl @@ -1160,7 +1160,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 --cache=no --no-check-certificate --quiet -O $destination_file $request_url`; + $wget = `wget -N --no-cache --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"; From 4658ad676fafbf1c58901f170b5041446c10aa08 Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Jan 2019 03:53:41 -0500 Subject: [PATCH 31/38] Extended server spellbook entries to RoF2 standard and added per-client restriction of spell id max --- changelog.txt | 11 +++++++++++ common/emu_constants.h | 2 +- common/eq_packet_structs.h | 12 ++++++++++++ common/patches/rof.cpp | 25 ++++++++++++++++++------- common/patches/rof2.cpp | 25 ++++++++++++++++++------- common/patches/sod.cpp | 21 ++++++++++++++++++++- common/patches/sof.cpp | 21 ++++++++++++++++++++- common/patches/titanium.cpp | 21 ++++++++++++++++++++- common/patches/uf.cpp | 22 ++++++++++++++++++++-- world/client.cpp | 10 ++++------ world/worlddb.cpp | 1 + zone/client.cpp | 7 ++++++- zone/client_packet.cpp | 22 +++++++++++++++------- zone/command.cpp | 10 +++++++++- zone/questmgr.cpp | 11 +++++++++-- zone/spells.cpp | 6 ++---- zone/zonedb.cpp | 27 +++++++++++++++++++-------- 17 files changed, 205 insertions(+), 49 deletions(-) diff --git a/changelog.txt b/changelog.txt index d6bae58d2..dc0223d52 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,17 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 1/24/2019 == +Uleat: Extended server spellbook entries to RoF2 standard and added per-client restriction of spell id max + - Bumped server spellbook entry capacity to 720 spells + - Server keeps all 'learned' spells as found + -- Access is limited by the clients' limitations of spellbook capacities and max spell ids + -- This is done to avoid losing spells by switching from newer clients to older ones + -- Existing behavior is kept in place for illegal access conditions + - Each client is still restricted to its spellbook capacity (400, 480, 480, 720, 720, 720 - respectively) + - Each client is restricted to its max supported spell id (9999, 15999, 23000, 28000, 45000, 45000 - respectively) + - Please report any abnormal behavior so it may be addressed + == 1/20/2019 == Uleat: Added 'spells' entry to EQDictionary Akkadius: diff --git a/common/emu_constants.h b/common/emu_constants.h index 6fe6f8ec6..e3869570e 100644 --- a/common/emu_constants.h +++ b/common/emu_constants.h @@ -243,7 +243,7 @@ namespace EQEmu }; using RoF2::spells::SPELL_ID_MAX; - using SoD::spells::SPELLBOOK_SIZE; + using RoF2::spells::SPELLBOOK_SIZE; using UF::spells::SPELL_GEM_COUNT; // RoF+ clients define more than UF client..but, they are not valid beyond UF using RoF2::spells::LONG_BUFFS; diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index 8e0d4d0d1..a5d86d140 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1091,6 +1091,18 @@ struct PlayerProfile_Struct /*19559*/ uint8 unknown19595[5]; // ***Placeholder (6/29/2005) /*19564*/ uint32 RestTimer; /*19568*/ + + // All player profile packets are translated and this overhead is ignored in out-bound packets + PlayerProfile_Struct() : m_player_profile_version(EQEmu::versions::MobVersion::Unknown) { } + + EQEmu::versions::MobVersion PlayerProfileVersion() { return m_player_profile_version; } + void SetPlayerProfileVersion(EQEmu::versions::MobVersion mob_version) { m_player_profile_version = EQEmu::versions::ValidateMobVersion(mob_version); } + void SetPlayerProfileVersion(EQEmu::versions::ClientVersion client_version) { SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version)); } + +// private: + // No need for gm flag since pp already has one + // No need for lookup pointer since this struct is not tied to any one system + EQEmu::versions::MobVersion m_player_profile_version; // kept public for now so checksum can calc sizeof (client_packet.cpp:1586) }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 5a87748a4..be077d750 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -2126,14 +2126,25 @@ namespace RoF outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots - for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) - { - outapp->WriteUInt32(emu->spell_book[r]); + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + outapp->WriteUInt32(emu->spell_book[r]); + else + outapp->WriteUInt32(0xFFFFFFFFU); + } } - // zeroes for the rest of the spellbook slots - for (uint32 r = 0; r < spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE; r++) - { - outapp->WriteUInt32(0xFFFFFFFFU); + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + outapp->WriteUInt32(emu->spell_book[r]); + else + outapp->WriteUInt32(0xFFFFFFFFU); + } + // invalidate the rest of the spellbook slots + for (uint32 r = EQEmu::spells::SPELLBOOK_SIZE; r < spells::SPELLBOOK_SIZE; r++) { + outapp->WriteUInt32(0xFFFFFFFFU); + } } outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 74453f1ff..33af8506f 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -2202,14 +2202,25 @@ namespace RoF2 outapp->WriteUInt32(spells::SPELLBOOK_SIZE); // Spellbook slots - for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) - { - outapp->WriteUInt32(emu->spell_book[r]); + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + outapp->WriteUInt32(emu->spell_book[r]); + else + outapp->WriteUInt32(0xFFFFFFFFU); + } } - // zeroes for the rest of the spellbook slots - for (uint32 r = 0; r < spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE; r++) - { - outapp->WriteUInt32(0xFFFFFFFFU); + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + outapp->WriteUInt32(emu->spell_book[r]); + else + outapp->WriteUInt32(0xFFFFFFFFU); + } + // invalidate the rest of the spellbook slots + for (uint32 r = EQEmu::spells::SPELLBOOK_SIZE; r < spells::SPELLBOOK_SIZE; r++) { + outapp->WriteUInt32(0xFFFFFFFFU); + } } outapp->WriteUInt32(spells::SPELL_GEM_COUNT); // Memorised spell slots diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index e64510d06..1241e142a 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1492,7 +1492,26 @@ namespace SoD OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, spells::SPELLBOOK_SIZE); + + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + } + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + // invalidate the rest of the spellbook slots + memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE))); + } + // OUT(unknown4184[128]); OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index a1141f99c..247912dfd 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1156,7 +1156,26 @@ namespace SoF OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, spells::SPELLBOOK_SIZE); + + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + } + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + // invalidate the rest of the spellbook slots + memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE))); + } + // OUT(unknown4184[128]); OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 9220875a8..e15913669 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1012,7 +1012,26 @@ namespace Titanium OUT(WIS); OUT(face); // OUT(unknown02264[47]); - OUT_array(spell_book, spells::SPELLBOOK_SIZE); + + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + } + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + // invalidate the rest of the spellbook slots + memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE))); + } + // OUT(unknown4184[448]); OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 9e87a7579..549fa7698 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1724,8 +1724,26 @@ namespace UF OUT(WIS); OUT(face); // OUT(unknown02264[47]); - memset(eq->spell_book, 0xFF, sizeof(uint32)* spells::SPELLBOOK_SIZE); - OUT_array(spell_book, 480U); + + if (spells::SPELLBOOK_SIZE <= EQEmu::spells::SPELLBOOK_SIZE) { + for (uint32 r = 0; r < spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + } + else { + for (uint32 r = 0; r < EQEmu::spells::SPELLBOOK_SIZE; r++) { + if (emu->spell_book[r] <= spells::SPELL_ID_MAX) + eq->spell_book[r] = emu->spell_book[r]; + else + eq->spell_book[r] = 0xFFFFFFFFU; + } + // invalidate the rest of the spellbook slots + memset(&eq->spell_book[EQEmu::spells::SPELLBOOK_SIZE], 0xFF, (sizeof(uint32) * (spells::SPELLBOOK_SIZE - EQEmu::spells::SPELLBOOK_SIZE))); + } + // OUT(unknown4184[128]); OUT_array(mem_spells, spells::SPELL_GEM_COUNT); // OUT(unknown04396[32]); diff --git a/world/client.cpp b/world/client.cpp index 822b648b6..06bceb52d 100644 --- a/world/client.cpp +++ b/world/client.cpp @@ -1446,6 +1446,7 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) ExtendedProfile_Struct ext; EQEmu::InventoryProfile inv; + pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit))); inv.SetInventoryVersion(EQEmu::versions::ConvertClientVersionBitToClientVersion(m_ClientVersionBit)); inv.SetGMInventory(false); // character cannot have gm flag at this point @@ -1528,12 +1529,9 @@ bool Client::OPCharCreate(char *name, CharCreate_Struct *cc) // strcpy(pp.servername, WorldConfig::get()->ShortName.c_str()); - - for (i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) - pp.spell_book[i] = 0xFFFFFFFF; - - for(i = 0; i < EQEmu::spells::SPELL_GEM_COUNT; i++) - pp.mem_spells[i] = 0xFFFFFFFF; + memset(pp.spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE)); + + memset(pp.mem_spells, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELL_GEM_COUNT)); for(i = 0; i < BUFF_COUNT; i++) pp.buffs[i].spellid = 0xFFFF; diff --git a/world/worlddb.cpp b/world/worlddb.cpp index 4daa7fa77..47354cc60 100644 --- a/world/worlddb.cpp +++ b/world/worlddb.cpp @@ -98,6 +98,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 accountID, EQApplicationPacket **ou PlayerProfile_Struct pp; EQEmu::InventoryProfile inv; + pp.SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version)); inv.SetInventoryVersion(client_version); inv.SetGMInventory(true); // charsel can not interact with items..but, no harm in setting to full expansion support diff --git a/zone/client.cpp b/zone/client.cpp index b0eca3c43..5077e5d53 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2640,6 +2640,11 @@ bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) { } void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){ + if (slot < 0 || slot >= EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) + return; + if (spellid < 3 || spellid > EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) + return; + auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct)); MemorizeSpell_Struct* mss=(MemorizeSpell_Struct*)outapp->pBuffer; mss->scribing=scribing; @@ -9126,4 +9131,4 @@ bool Client::GotoPlayer(std::string player_name) } return false; -} \ No newline at end of file +} diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7485d7451..7ea18206a 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -530,10 +530,14 @@ void Client::CompleteConnect() SendAppearancePacket(AT_GuildID, GuildID(), false); SendAppearancePacket(AT_GuildRank, rank, false); } - for (uint32 spellInt = 0; spellInt < EQEmu::spells::SPELLBOOK_SIZE; spellInt++) { - if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > 50000) + + // moved to dbload and translators since we iterate there also .. keep m_pp values whatever they are when they get here + /*const auto sbs = EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize; + for (uint32 spellInt = 0; spellInt < sbs; ++spellInt) { + if (m_pp.spell_book[spellInt] < 3 || m_pp.spell_book[spellInt] > EQEmu::spells::SPELL_ID_MAX) m_pp.spell_book[spellInt] = 0xFFFFFFFF; - } + }*/ + //SendAATable(); if (GetHideMe()) Message(13, "[GM] You are currently hidden to all clients"); @@ -1154,6 +1158,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) SetClientVersion(Connection()->ClientVersion()); m_ClientVersionBit = EQEmu::versions::ConvertClientVersionToClientVersionBit(Connection()->ClientVersion()); + m_pp.SetPlayerProfileVersion(m_ClientVersion); m_inv.SetInventoryVersion(m_ClientVersion); /* Antighost code @@ -1587,8 +1592,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) if ((m_pp.RestTimer > RuleI(Character, RestRegenTimeToActivate)) && (m_pp.RestTimer > RuleI(Character, RestRegenRaidTimeToActivate))) m_pp.RestTimer = 0; - /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ - CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - 4); + /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ // looks to be in place now + CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - sizeof(m_pp.m_player_profile_version) - 4); outapp = new EQApplicationPacket(OP_PlayerProfile, sizeof(PlayerProfile_Struct)); @@ -5263,7 +5268,7 @@ void Client::Handle_OP_DeleteSpell(const EQApplicationPacket *app) EQApplicationPacket* outapp = app->Copy(); DeleteSpell_Struct* dss = (DeleteSpell_Struct*)outapp->pBuffer; - if (dss->spell_slot < 0 || dss->spell_slot > int(EQEmu::spells::SPELLBOOK_SIZE)) + if (dss->spell_slot < 0 || dss->spell_slot >= EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) return; if (m_pp.spell_book[dss->spell_slot] != SPELLBOOK_UNKNOWN) { @@ -13337,7 +13342,10 @@ void Client::Handle_OP_SwapSpell(const EQApplicationPacket *app) const SwapSpell_Struct* swapspell = (const SwapSpell_Struct*)app->pBuffer; int swapspelltemp; - if (swapspell->from_slot < 0 || swapspell->from_slot > EQEmu::spells::SPELLBOOK_SIZE || swapspell->to_slot < 0 || swapspell->to_slot > EQEmu::spells::SPELLBOOK_SIZE) + const auto sbs = EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize; + if (swapspell->from_slot < 0 || swapspell->from_slot >= sbs) + return; + if (swapspell->to_slot < 0 || swapspell->to_slot >= sbs) return; swapspelltemp = m_pp.spell_book[swapspell->from_slot]; diff --git a/zone/command.cpp b/zone/command.cpp index 8c64c44a4..0590b16ea 100755 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -6441,7 +6441,15 @@ void command_scribespells(Client *c, const Seperator *sep) c->Message(0, "Scribing spells for %s.", t->GetName()); Log(Logs::General, Logs::Normal, "Scribe spells request for %s from %s, levels: %u -> %u", t->GetName(), c->GetName(), min_level, max_level); - for(curspell = 0, book_slot = t->GetNextAvailableSpellBookSlot(), count = 0; curspell < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; curspell++, book_slot = t->GetNextAvailableSpellBookSlot(book_slot)) + for ( + curspell = 0, + book_slot = t->GetNextAvailableSpellBookSlot(), + count = 0; // ; + curspell < SPDAT_RECORDS && + book_slot < EQEmu::spells::SPELLBOOK_SIZE; // ; + curspell++, + book_slot = t->GetNextAvailableSpellBookSlot(book_slot) + ) { if ( diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 660ac3273..1c93eb3ed 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -984,8 +984,15 @@ uint16 QuestManager::scribespells(uint8 max_level, uint8 min_level) { bool SpellGlobalCheckResult = 0; bool SpellBucketCheckResult = 0; - - for(spell_id = 0, book_slot = initiator->GetNextAvailableSpellBookSlot(), count = 0; spell_id < SPDAT_RECORDS && book_slot < EQEmu::spells::SPELLBOOK_SIZE; spell_id++, book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot)) + for ( + spell_id = 0, + book_slot = initiator->GetNextAvailableSpellBookSlot(), + count = 0; // ; + spell_id < SPDAT_RECORDS && + book_slot < EQEmu::spells::SPELLBOOK_SIZE; // ; + spell_id++, + book_slot = initiator->GetNextAvailableSpellBookSlot(book_slot) + ) { if ( diff --git a/zone/spells.cpp b/zone/spells.cpp index c88522a57..296097376 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -5053,7 +5053,7 @@ void Client::UnscribeSpell(int slot, bool update_client) m_pp.spell_book[slot] = 0xFFFFFFFF; database.DeleteCharacterSpell(this->CharacterID(), m_pp.spell_book[slot], slot); - if(update_client) + if(update_client && slot < EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) { auto outapp = new EQApplicationPacket(OP_DeleteSpell, sizeof(DeleteSpell_Struct)); DeleteSpell_Struct* del = (DeleteSpell_Struct*)outapp->pBuffer; @@ -5066,9 +5066,7 @@ void Client::UnscribeSpell(int slot, bool update_client) void Client::UnscribeSpellAll(bool update_client) { - int i; - - for(i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) + for(int i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++) { if(m_pp.spell_book[i] != 0xFFFFFFFF) UnscribeSpell(i, update_client); diff --git a/zone/zonedb.cpp b/zone/zonedb.cpp index 078fc7a4c..45786adbe 100644 --- a/zone/zonedb.cpp +++ b/zone/zonedb.cpp @@ -1225,17 +1225,28 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str "`character_spells` " "WHERE `id` = %u ORDER BY `slot_id`", character_id); auto results = database.QueryDatabase(query); - int i = 0; + /* Initialize Spells */ - for (i = 0; i < EQEmu::spells::SPELLBOOK_SIZE; i++){ - pp->spell_book[i] = 0xFFFFFFFF; - } + + memset(pp->spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE)); + + // We have the ability to block loaded spells by max id on a per-client basis.. + // but, we do not have to ability to keep players from using older clients after + // they have scribed spells on a newer one that exceeds the older one's limit. + // Load them all so that server actions are valid..but, nix them in translators. + for (auto row = results.begin(); row != results.end(); ++row) { - i = atoi(row[0]); - if (i < EQEmu::spells::SPELLBOOK_SIZE && atoi(row[1]) <= SPDAT_RECORDS){ - pp->spell_book[i] = atoi(row[1]); - } + int idx = atoi(row[0]); + int id = atoi(row[1]); + + if (idx < 0 || idx >= EQEmu::spells::SPELLBOOK_SIZE) + continue; + if (id < 3 || id > SPDAT_RECORDS) // 3 ("Summon Corpse") is the first scribable spell in spells_us.txt + continue; + + pp->spell_book[idx] = id; } + return true; } From 2f3cd45c4ae6988da94a70e30d8c1b990e55654f Mon Sep 17 00:00:00 2001 From: Uleat Date: Thu, 24 Jan 2019 04:26:14 -0500 Subject: [PATCH 32/38] Removed server-side checksum of player profile --- changelog.txt | 1 + common/eq_packet_structs.h | 6 +++--- zone/client_packet.cpp | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/changelog.txt b/changelog.txt index dc0223d52..47c4e1e86 100644 --- a/changelog.txt +++ b/changelog.txt @@ -11,6 +11,7 @@ Uleat: Extended server spellbook entries to RoF2 standard and added per-client r - Each client is still restricted to its spellbook capacity (400, 480, 480, 720, 720, 720 - respectively) - Each client is restricted to its max supported spell id (9999, 15999, 23000, 28000, 45000, 45000 - respectively) - Please report any abnormal behavior so it may be addressed +Uleat: Removed server-side checksum of player profile..wasted calculation since it's performed again in all translators == 1/20/2019 == Uleat: Added 'spells' entry to EQDictionary diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index a5d86d140..c80fdcc02 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -909,7 +909,7 @@ sed -e 's/_t//g' -e 's/MAX_AA/MAX_PP_AA_ARRAY/g' \ struct PlayerProfile_Struct { -/*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum +// /*0000*/ uint32 checksum; // Checksum from CRC32::SetEQChecksum /*0004*/ char name[64]; // Name of player sizes not right /*0068*/ char last_name[32]; // Last name of player sizes not right /*0100*/ uint32 gender; // Player Gender - 0 Male, 1 Female @@ -1099,10 +1099,10 @@ struct PlayerProfile_Struct void SetPlayerProfileVersion(EQEmu::versions::MobVersion mob_version) { m_player_profile_version = EQEmu::versions::ValidateMobVersion(mob_version); } void SetPlayerProfileVersion(EQEmu::versions::ClientVersion client_version) { SetPlayerProfileVersion(EQEmu::versions::ConvertClientVersionToMobVersion(client_version)); } -// private: +private: // No need for gm flag since pp already has one // No need for lookup pointer since this struct is not tied to any one system - EQEmu::versions::MobVersion m_player_profile_version; // kept public for now so checksum can calc sizeof (client_packet.cpp:1586) + EQEmu::versions::MobVersion m_player_profile_version; }; diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 7ea18206a..41b38b0c9 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -1593,7 +1593,8 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app) m_pp.RestTimer = 0; /* This checksum should disappear once dynamic structs are in... each struct strategy will do it */ // looks to be in place now - CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - sizeof(m_pp.m_player_profile_version) - 4); + //CRC32::SetEQChecksum((unsigned char*)&m_pp, sizeof(PlayerProfile_Struct) - sizeof(m_pp.m_player_profile_version) - 4); + // m_pp.checksum = 0; // All server out-bound player profile packets are now translated - no need to waste cycles calculating this... outapp = new EQApplicationPacket(OP_PlayerProfile, sizeof(PlayerProfile_Struct)); From 16036ab492f2ee8340ebd159b3f4c9737754de8c Mon Sep 17 00:00:00 2001 From: Uleat Date: Sat, 26 Jan 2019 22:30:49 -0500 Subject: [PATCH 33/38] Fix for class Bot not honoring NPCType data reference --- changelog.txt | 5 + zone/bot.cpp | 426 ++++++++++++++++++++++++++++-------------- zone/bot.h | 8 +- zone/bot_command.cpp | 11 +- zone/bot_database.cpp | 34 ++-- zone/questmgr.cpp | 3 +- 6 files changed, 311 insertions(+), 176 deletions(-) diff --git a/changelog.txt b/changelog.txt index 47c4e1e86..236fe430f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,11 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 1/26/2019 == +Uleat: Fix for class Bot not honoring NPCType data reference + - Fixes bots not moving on spawn/grouping issue + - Report any issues with non movement-related behavior + == 1/24/2019 == Uleat: Extended server spellbook entries to RoF2 standard and added per-client restriction of spell id max - Bumped server spellbook entry capacity to 720 spells diff --git a/zone/bot.cpp b/zone/bot.cpp index 4076eafef..5c37e47fa 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded; // This constructor is used during the bot create command -Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) { +Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) { if(botOwner) { this->SetBotOwner(botOwner); this->_botOwnerCharacterID = botOwner->CharacterID(); @@ -46,23 +46,23 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm _lastTotalPlayTime = 0; _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = 0; - _baseMR = npcTypeData.MR; - _baseCR = npcTypeData.CR; - _baseDR = npcTypeData.DR; - _baseFR = npcTypeData.FR; - _basePR = npcTypeData.PR; - _baseCorrup = npcTypeData.Corrup; - _baseAC = npcTypeData.AC; - _baseSTR = npcTypeData.STR; - _baseSTA = npcTypeData.STA; - _baseDEX = npcTypeData.DEX; - _baseAGI = npcTypeData.AGI; - _baseINT = npcTypeData.INT; - _baseWIS = npcTypeData.WIS; - _baseCHA = npcTypeData.CHA; - _baseATK = npcTypeData.ATK; - _baseRace = npcTypeData.race; - _baseGender = npcTypeData.gender; + _baseMR = npcTypeData->MR; + _baseCR = npcTypeData->CR; + _baseDR = npcTypeData->DR; + _baseFR = npcTypeData->FR; + _basePR = npcTypeData->PR; + _baseCorrup = npcTypeData->Corrup; + _baseAC = npcTypeData->AC; + _baseSTR = npcTypeData->STR; + _baseSTA = npcTypeData->STA; + _baseDEX = npcTypeData->DEX; + _baseAGI = npcTypeData->AGI; + _baseINT = npcTypeData->INT; + _baseWIS = npcTypeData->WIS; + _baseCHA = npcTypeData->CHA; + _baseATK = npcTypeData->ATK; + _baseRace = npcTypeData->race; + _baseGender = npcTypeData->gender; RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; @@ -104,8 +104,8 @@ Bot::Bot(NPCType npcTypeData, Client* botOwner) : NPC(&npcTypeData, nullptr, glm } // This constructor is used when the bot is loaded out of the database -Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData) - : NPC(&npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) +Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData) + : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) { this->_botOwnerCharacterID = botOwnerCharacterID; if(this->_botOwnerCharacterID > 0) @@ -122,25 +122,25 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to _startTotalPlayTime = time(&_startTotalPlayTime); _lastZoneId = lastZoneId; berserk = false; - _baseMR = npcTypeData.MR; - _baseCR = npcTypeData.CR; - _baseDR = npcTypeData.DR; - _baseFR = npcTypeData.FR; - _basePR = npcTypeData.PR; - _baseCorrup = npcTypeData.Corrup; - _baseAC = npcTypeData.AC; - _baseSTR = npcTypeData.STR; - _baseSTA = npcTypeData.STA; - _baseDEX = npcTypeData.DEX; - _baseAGI = npcTypeData.AGI; - _baseINT = npcTypeData.INT; - _baseWIS = npcTypeData.WIS; - _baseCHA = npcTypeData.CHA; - _baseATK = npcTypeData.ATK; - _baseRace = npcTypeData.race; - _baseGender = npcTypeData.gender; - current_hp = npcTypeData.current_hp; - current_mana = npcTypeData.Mana; + _baseMR = npcTypeData->MR; + _baseCR = npcTypeData->CR; + _baseDR = npcTypeData->DR; + _baseFR = npcTypeData->FR; + _basePR = npcTypeData->PR; + _baseCorrup = npcTypeData->Corrup; + _baseAC = npcTypeData->AC; + _baseSTR = npcTypeData->STR; + _baseSTA = npcTypeData->STA; + _baseDEX = npcTypeData->DEX; + _baseAGI = npcTypeData->AGI; + _baseINT = npcTypeData->INT; + _baseWIS = npcTypeData->WIS; + _baseCHA = npcTypeData->CHA; + _baseATK = npcTypeData->ATK; + _baseRace = npcTypeData->race; + _baseGender = npcTypeData->gender; + current_hp = npcTypeData->current_hp; + current_mana = npcTypeData->Mana; RestRegenHP = 0; RestRegenMana = 0; RestRegenEndurance = 0; @@ -313,112 +313,252 @@ bool Bot::IsStanding() { return result; } -NPCType Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) { - NPCType BotNPCType; - int CopyLength = 0; - CopyLength = botName.copy(BotNPCType.name, 63); - BotNPCType.name[CopyLength] = '\0'; - CopyLength = 0; - CopyLength = botLastName.copy(BotNPCType.lastname, 69); - BotNPCType.lastname[CopyLength] = '\0'; - CopyLength = 0; - BotNPCType.npc_spells_id = botSpellsID; - BotNPCType.level = botLevel; - BotNPCType.race = botRace; - BotNPCType.class_ = botClass; - BotNPCType.gender = gender; - BotNPCType.size = size; - BotNPCType.luclinface = face; - BotNPCType.hairstyle = hairStyle; - BotNPCType.haircolor = hairColor; - BotNPCType.eyecolor1 = eyeColor; - BotNPCType.eyecolor2 = eyeColor2; - BotNPCType.beardcolor = beardColor; - BotNPCType.beard = beard; - BotNPCType.drakkin_heritage = drakkinHeritage; - BotNPCType.drakkin_tattoo = drakkinTattoo; - BotNPCType.drakkin_details = drakkinDetails; - BotNPCType.current_hp = hp; - BotNPCType.Mana = mana; - BotNPCType.MR = mr; - BotNPCType.CR = cr; - BotNPCType.DR = dr; - BotNPCType.FR = fr; - BotNPCType.PR = pr; - BotNPCType.Corrup = corrup; - BotNPCType.AC = ac; - BotNPCType.STR = str; - BotNPCType.STA = sta; - BotNPCType.DEX = dex; - BotNPCType.AGI = agi; - BotNPCType.INT = _int; - BotNPCType.WIS = wis; - BotNPCType.CHA = cha; - BotNPCType.ATK = attack; - BotNPCType.npc_id = 0; - BotNPCType.texture = 0; - BotNPCType.d_melee_texture1 = 0; - BotNPCType.d_melee_texture2 = 0; - BotNPCType.qglobal = false; - BotNPCType.attack_speed = 0; - BotNPCType.runspeed = 0.7f; - BotNPCType.bodytype = 1; - BotNPCType.findable = 0; - BotNPCType.hp_regen = 1; - BotNPCType.mana_regen = 1; - BotNPCType.maxlevel = botLevel; - BotNPCType.light = 0; // due to the way that bots are coded..this is sent post-spawn - return BotNPCType; +NPCType *Bot::FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack) { + auto bot_npc_type = new NPCType{ 0 }; + int copy_length = 0; + + copy_length = botName.copy(bot_npc_type->name, 63); + bot_npc_type->name[copy_length] = '\0'; + copy_length = 0; + + copy_length = botLastName.copy(bot_npc_type->lastname, 69); + bot_npc_type->lastname[copy_length] = '\0'; + copy_length = 0; + + bot_npc_type->current_hp = hp; + bot_npc_type->max_hp = hp; + bot_npc_type->size = size; + bot_npc_type->runspeed = 0.7f; + bot_npc_type->gender = gender; + bot_npc_type->race = botRace; + bot_npc_type->class_ = botClass; + bot_npc_type->bodytype = 1; + bot_npc_type->deity = EQEmu::deity::DeityAgnostic; + bot_npc_type->level = botLevel; + //bot_npc_type->npc_id = 0; + //bot_npc_type->texture = 0; + //bot_npc_type->helmtexture = 0; + //bot_npc_type->herosforgemodel = 0; + //bot_npc_type->loottable_id = 0; + bot_npc_type->npc_spells_id = botSpellsID; + //bot_npc_type->npc_spells_effects_id = 0; + //bot_npc_type->npc_faction_id = 0; + //bot_npc_type->merchanttype = 0; + //bot_npc_type->alt_currency_type = 0; + //bot_npc_type->adventure_template = 0; + //bot_npc_type->trap_template = 0; + //bot_npc_type->light = 0; + bot_npc_type->AC = ac; + bot_npc_type->Mana = mana; + bot_npc_type->ATK = attack; + bot_npc_type->STR = str; + bot_npc_type->STA = sta; + bot_npc_type->DEX = dex; + bot_npc_type->AGI = agi; + bot_npc_type->INT = _int; + bot_npc_type->WIS = wis; + bot_npc_type->CHA = cha; + bot_npc_type->MR = mr; + bot_npc_type->FR = fr; + bot_npc_type->CR = cr; + bot_npc_type->PR = pr; + bot_npc_type->DR = dr; + bot_npc_type->Corrup = corrup; + //bot_npc_type->PhR = 0; + bot_npc_type->haircolor = hairColor; + bot_npc_type->beardcolor = beardColor; + bot_npc_type->eyecolor1 = eyeColor; + bot_npc_type->eyecolor2 = eyeColor2; + bot_npc_type->hairstyle = hairStyle; + bot_npc_type->luclinface = face; + bot_npc_type->beard = beard; + bot_npc_type->drakkin_heritage = drakkinHeritage; + bot_npc_type->drakkin_tattoo = drakkinTattoo; + bot_npc_type->drakkin_details = drakkinDetails; + //bot_npc_type->armor_tint = { 0 }; + //bot_npc_type->min_dmg = 0; + //bot_npc_type->max_dmg = 0; + //bot_npc_type->charm_ac = 0; + //bot_npc_type->charm_min_dmg = 0; + //bot_npc_type->charm_max_dmg = 0; + //bot_npc_type->charm_attack_delay = 0; + //bot_npc_type->charm_accuracy_rating = 0; + //bot_npc_type->charm_avoidance_rating = 0; + //bot_npc_type->charm_atk = 0; + //bot_npc_type->attack_count = 0; + //*bot_npc_type->special_abilities = { 0 }; + //bot_npc_type->d_melee_texture1 = 0; + //bot_npc_type->d_melee_texture2 = 0; + //*bot_npc_type->ammo_idfile = { 0 }; + //bot_npc_type->prim_melee_type = 0; + //bot_npc_type->sec_melee_type = 0; + //bot_npc_type->ranged_type = 0; + bot_npc_type->hp_regen = 1; + bot_npc_type->mana_regen = 1; + //bot_npc_type->aggroradius = 0; + //bot_npc_type->assistradius = 0; + //bot_npc_type->see_invis = 0; + //bot_npc_type->see_invis_undead = false; + //bot_npc_type->see_hide = false; + //bot_npc_type->see_improved_hide = false; + //bot_npc_type->qglobal = false; + //bot_npc_type->npc_aggro = false; + //bot_npc_type->spawn_limit = 0; + //bot_npc_type->mount_color = 0; + //bot_npc_type->attack_speed = 0.0f; + //bot_npc_type->attack_delay = 0; + //bot_npc_type->accuracy_rating = 0; + //bot_npc_type->avoidance_rating = 0; + //bot_npc_type->findable = false; + bot_npc_type->trackable = true; + //bot_npc_type->slow_mitigation = 0; + bot_npc_type->maxlevel = botLevel; + //bot_npc_type->scalerate = 0; + //bot_npc_type->private_corpse = false; + //bot_npc_type->unique_spawn_by_name = false; + //bot_npc_type->underwater = false; + //bot_npc_type->emoteid = 0; + //bot_npc_type->spellscale = 0.0f; + //bot_npc_type->healscale = 0.0f; + //bot_npc_type->no_target_hotkey = false; + //bot_npc_type->raid_target = false; + //bot_npc_type->armtexture = 0; + //bot_npc_type->bracertexture = 0; + //bot_npc_type->handtexture = 0; + //bot_npc_type->legtexture = 0; + //bot_npc_type->feettexture = 0; + //bot_npc_type->ignore_despawn = false; + bot_npc_type->show_name = true; + //bot_npc_type->untargetable = false; + bot_npc_type->skip_global_loot = true; + //bot_npc_type->rare_spawn = false; + bot_npc_type->stuck_behavior = Ground; + + return bot_npc_type; } -NPCType Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) { - NPCType Result; - int CopyLength = 0; - CopyLength = botName.copy(Result.name, 63); - Result.name[CopyLength] = '\0'; - CopyLength = 0; - CopyLength = botLastName.copy(Result.lastname, 69); - Result.lastname[CopyLength] = '\0'; - CopyLength = 0; - Result.level = botLevel; - Result.race = botRace; - Result.class_ = botClass; - Result.gender = gender; - // default values - Result.maxlevel = botLevel; - Result.size = 6.0; - Result.npc_id = 0; - Result.current_hp = 0; - Result.drakkin_details = 0; - Result.drakkin_heritage = 0; - Result.drakkin_tattoo = 0; - Result.runspeed = 0.7f; - Result.bodytype = 1; - Result.findable = 0; - Result.hp_regen = 1; - Result.mana_regen = 1; - Result.texture = 0; - Result.d_melee_texture1 = 0; - Result.d_melee_texture2 = 0; - Result.qglobal = false; - Result.npc_spells_id = 0; - Result.attack_speed = 0; - Result.STR = 75; - Result.STA = 75; - Result.DEX = 75; - Result.AGI = 75; - Result.WIS = 75; - Result.INT = 75; - Result.CHA = 75; - Result.ATK = 75; - Result.MR = 25; - Result.FR = 25; - Result.DR = 15; - Result.PR = 15; - Result.CR = 25; - Result.Corrup = 15; - Result.AC = 12; - return Result; +NPCType *Bot::CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender) { + auto bot_npc_type = new NPCType{ 0 }; + int copy_length = 0; + + copy_length = botName.copy(bot_npc_type->name, 63); + bot_npc_type->name[copy_length] = '\0'; + copy_length = 0; + + copy_length = botLastName.copy(bot_npc_type->lastname, 69); + bot_npc_type->lastname[copy_length] = '\0'; + copy_length = 0; + + //bot_npc_type->current_hp = 0; + //bot_npc_type->max_hp = 0; + bot_npc_type->size = 6.0f; + bot_npc_type->runspeed = 0.7f; + bot_npc_type->gender = gender; + bot_npc_type->race = botRace; + bot_npc_type->class_ = botClass; + bot_npc_type->bodytype = 1; + bot_npc_type->deity = EQEmu::deity::DeityAgnostic; + bot_npc_type->level = botLevel; + //bot_npc_type->npc_id = 0; + //bot_npc_type->texture = 0; + //bot_npc_type->helmtexture = 0; + //bot_npc_type->herosforgemodel = 0; + //bot_npc_type->loottable_id = 0; + //bot_npc_type->npc_spells_id = 0; + //bot_npc_type->npc_spells_effects_id = 0; + //bot_npc_type->npc_faction_id = 0; + //bot_npc_type->merchanttype = 0; + //bot_npc_type->alt_currency_type = 0; + //bot_npc_type->adventure_template = 0; + //bot_npc_type->trap_template = 0; + //bot_npc_type->light = 0; + bot_npc_type->AC = 12; + //bot_npc_type->Mana = 0; + bot_npc_type->ATK = 75; + bot_npc_type->STR = 75; + bot_npc_type->STA = 75; + bot_npc_type->DEX = 75; + bot_npc_type->AGI = 75; + bot_npc_type->INT = 75; + bot_npc_type->WIS = 75; + bot_npc_type->CHA = 75; + bot_npc_type->MR = 25; + bot_npc_type->FR = 25; + bot_npc_type->CR = 25; + bot_npc_type->PR = 15; + bot_npc_type->DR = 15; + bot_npc_type->Corrup = 15; + //bot_npc_type->PhR = 0; + //bot_npc_type->haircolor = 0; + //bot_npc_type->beardcolor = 0; + //bot_npc_type->eyecolor1 = 0; + //bot_npc_type->eyecolor2 = 0; + //bot_npc_type->hairstyle = 0; + //bot_npc_type->luclinface = 0; + //bot_npc_type->beard = 0; + //bot_npc_type->drakkin_heritage = 0; + //bot_npc_type->drakkin_tattoo = 0; + //bot_npc_type->drakkin_details = 0; + //bot_npc_type->armor_tint = { 0 }; + //bot_npc_type->min_dmg = 0; + //bot_npc_type->max_dmg = 0; + //bot_npc_type->charm_ac = 0; + //bot_npc_type->charm_min_dmg = 0; + //bot_npc_type->charm_max_dmg = 0; + //bot_npc_type->charm_attack_delay = 0; + //bot_npc_type->charm_accuracy_rating = 0; + //bot_npc_type->charm_avoidance_rating = 0; + //bot_npc_type->charm_atk = 0; + //bot_npc_type->attack_count = 0; + //*bot_npc_type->special_abilities = { 0 }; + //bot_npc_type->d_melee_texture1 = 0; + //bot_npc_type->d_melee_texture2 = 0; + //*bot_npc_type->ammo_idfile = { 0 }; + //bot_npc_type->prim_melee_type = 0; + //bot_npc_type->sec_melee_type = 0; + //bot_npc_type->ranged_type = 0; + bot_npc_type->hp_regen = 1; + bot_npc_type->mana_regen = 1; + //bot_npc_type->aggroradius = 0; + //bot_npc_type->assistradius = 0; + //bot_npc_type->see_invis = 0; + //bot_npc_type->see_invis_undead = false; + //bot_npc_type->see_hide = false; + //bot_npc_type->see_improved_hide = false; + //bot_npc_type->qglobal = false; + //bot_npc_type->npc_aggro = false; + //bot_npc_type->spawn_limit = 0; + //bot_npc_type->mount_color = 0; + //bot_npc_type->attack_speed = 0.0f; + //bot_npc_type->attack_delay = 0; + //bot_npc_type->accuracy_rating = 0; + //bot_npc_type->avoidance_rating = 0; + //bot_npc_type->findable = false; + bot_npc_type->trackable = true; + //bot_npc_type->slow_mitigation = 0; + bot_npc_type->maxlevel = botLevel; + //bot_npc_type->scalerate = 0; + //bot_npc_type->private_corpse = false; + //bot_npc_type->unique_spawn_by_name = false; + //bot_npc_type->underwater = false; + //bot_npc_type->emoteid = 0; + //bot_npc_type->spellscale = 0.0f; + //bot_npc_type->healscale = 0.0f; + //bot_npc_type->no_target_hotkey = false; + //bot_npc_type->raid_target = false; + //bot_npc_type->armtexture = 0; + //bot_npc_type->bracertexture = 0; + //bot_npc_type->handtexture = 0; + //bot_npc_type->legtexture = 0; + //bot_npc_type->feettexture = 0; + //bot_npc_type->ignore_despawn = false; + bot_npc_type->show_name = true; + //bot_npc_type->untargetable = false; + bot_npc_type->skip_global_loot = true; + //bot_npc_type->rare_spawn = false; + bot_npc_type->stuck_behavior = Ground; + + return bot_npc_type; } void Bot::GenerateBaseStats() diff --git a/zone/bot.h b/zone/bot.h index 6a528a4e7..76a8a564f 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -250,8 +250,8 @@ public: }; // Class Constructors - Bot(NPCType npcTypeData, Client* botOwner); - Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType npcTypeData); + Bot(NPCType *npcTypeData, Client* botOwner); + Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData); //abstract virtual function implementations requird by base abstract class virtual bool Death(Mob* killerMob, int32 damage, uint16 spell_id, EQEmu::skills::SkillType attack_skill); @@ -494,7 +494,7 @@ public: static BotSpell GetBestBotSpellForCure(Bot* botCaster, Mob* target); static BotSpell GetBestBotSpellForResistDebuff(Bot* botCaster, Mob* target); - static NPCType CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender); + static NPCType *CreateDefaultNPCTypeStructForBot(std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender); // Static Bot Group Methods static bool AddBotToGroup(Bot* bot, Group* group); @@ -656,7 +656,7 @@ public: virtual void BotRangedAttack(Mob* other); // Publicized private functions - static NPCType FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); + static NPCType *FillNPCTypeStruct(uint32 botSpellsID, std::string botName, std::string botLastName, uint8 botLevel, uint16 botRace, uint8 botClass, uint8 gender, float size, uint32 face, uint32 hairStyle, uint32 hairColor, uint32 eyeColor, uint32 eyeColor2, uint32 beardColor, uint32 beard, uint32 drakkinHeritage, uint32 drakkinTattoo, uint32 drakkinDetails, int32 hp, int32 mana, int32 mr, int32 cr, int32 dr, int32 fr, int32 pr, int32 corrup, int32 ac, uint32 str, uint32 sta, uint32 dex, uint32 agi, uint32 _int, uint32 wis, uint32 cha, uint32 attack); void BotRemoveEquipItem(int16 slot); void RemoveBotItemBySlot(uint32 slotID, std::string* errorMessage); uint32 GetTotalPlayTime(); diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index b44681341..94b25b3ad 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -7707,16 +7707,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas return bot_id; } - auto DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot( - bot_name.c_str(), - "", - bot_owner->GetLevel(), - bot_race, - bot_class, - bot_gender - ); - - auto my_bot = new Bot(DefaultNPCTypeStruct, bot_owner); + auto my_bot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(bot_name.c_str(), "", bot_owner->GetLevel(), bot_race, bot_class, bot_gender), bot_owner); if (!my_bot->Save()) { bot_owner->Message(m_unknown, "Failed to create '%s' due to unknown cause", my_bot->GetCleanName()); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 17bc51487..f32ecafc4 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -357,8 +357,8 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) // TODO: Consider removing resists and basic attributes from the load query above since we're using defaultNPCType values instead auto row = results.begin(); - NPCType defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7])); - NPCType tempNPCStruct = Bot::FillNPCTypeStruct( + auto defaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(std::string(row[2]), std::string(row[3]), atoi(row[10]), atoi(row[8]), atoi(row[9]), atoi(row[7])); + auto tempNPCStruct = Bot::FillNPCTypeStruct( atoi(row[1]), std::string(row[2]), std::string(row[3]), @@ -379,21 +379,21 @@ bool BotDatabase::LoadBot(const uint32 bot_id, Bot*& loaded_bot) atoi(row[25]), atoi(row[28]), atoi(row[29]), - defaultNPCTypeStruct.MR, - defaultNPCTypeStruct.CR, - defaultNPCTypeStruct.DR, - defaultNPCTypeStruct.FR, - defaultNPCTypeStruct.PR, - defaultNPCTypeStruct.Corrup, - defaultNPCTypeStruct.AC, - defaultNPCTypeStruct.STR, - defaultNPCTypeStruct.STA, - defaultNPCTypeStruct.DEX, - defaultNPCTypeStruct.AGI, - defaultNPCTypeStruct.INT, - defaultNPCTypeStruct.WIS, - defaultNPCTypeStruct.CHA, - defaultNPCTypeStruct.ATK + defaultNPCTypeStruct->MR, + defaultNPCTypeStruct->CR, + defaultNPCTypeStruct->DR, + defaultNPCTypeStruct->FR, + defaultNPCTypeStruct->PR, + defaultNPCTypeStruct->Corrup, + defaultNPCTypeStruct->AC, + defaultNPCTypeStruct->STR, + defaultNPCTypeStruct->STA, + defaultNPCTypeStruct->DEX, + defaultNPCTypeStruct->AGI, + defaultNPCTypeStruct->INT, + defaultNPCTypeStruct->WIS, + defaultNPCTypeStruct->CHA, + defaultNPCTypeStruct->ATK ); loaded_bot = new Bot(bot_id, atoi(row[0]), atoi(row[1]), atof(row[14]), atoi(row[6]), tempNPCStruct); diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 1c93eb3ed..cd6c048cd 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2142,8 +2142,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level return false; } - NPCType DefaultNPCTypeStruct = Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender); - Bot* NewBot = new Bot(DefaultNPCTypeStruct, initiator); + Bot* NewBot = new Bot(Bot::CreateDefaultNPCTypeStructForBot(name, lastname, level, race, botclass, gender), initiator); if(NewBot) { From 3c0bd2bf5df8480f9e103649a150a7d040217633 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Jan 2019 08:08:01 -0500 Subject: [PATCH 34/38] Synchronized bot code to new movement system --- zone/bot.h | 5 ++--- zone/mob.h | 4 ++-- zone/mob_movement_manager.cpp | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/zone/bot.h b/zone/bot.h index 76a8a564f..c4f47cd66 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -337,9 +337,8 @@ public: void Stand(); bool IsSitting(); bool IsStanding(); - int GetBotWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.786f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 - int GetBotRunspeed() const { return (int)((float)_GetRunSpeed() * 1.786f); } - int GetBotFearSpeed() const { return (int)((float)_GetFearSpeed() * 1.786f); } + virtual int GetWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.785714f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 + virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714f); } bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); diff --git a/zone/mob.h b/zone/mob.h index ad65bab39..807007a68 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -576,8 +576,8 @@ public: virtual void SetMoving(bool move) { moving = move; m_Delta = glm::vec4(); } virtual void GoToBind(uint8 bindnum = 0) { } virtual void Gate(uint8 bindnum = 0); - int GetWalkspeed() const { return(_GetWalkSpeed()); } - int GetRunspeed() const { return(_GetRunSpeed()); } + virtual int GetWalkspeed() const { return(_GetWalkSpeed()); } + virtual int GetRunspeed() const { return(_GetRunSpeed()); } int GetBaseRunspeed() const { return base_runspeed; } int GetBaseWalkspeed() const { return base_walkspeed; } int GetBaseFearSpeed() const { return base_fearspeed; } diff --git a/zone/mob_movement_manager.cpp b/zone/mob_movement_manager.cpp index 437468285..23cccc8f4 100644 --- a/zone/mob_movement_manager.cpp +++ b/zone/mob_movement_manager.cpp @@ -759,7 +759,7 @@ void MobMovementManager::FillCommandStruct(PlayerPositionUpdateServer_Struct *sp spu->delta_y = FloatToEQ13(dy); spu->delta_z = FloatToEQ13(dz); spu->delta_heading = FloatToEQ10(dh); - spu->animation = anim; + spu->animation = (m->IsBot() ? (int)((float)anim / 1.785714f) : anim); } void MobMovementManager::UpdatePath(Mob *who, float x, float y, float z, MobMovementMode mode) From 5b371ad054ec4b053e7361bbdbe7ca6c59acac79 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Jan 2019 08:09:54 -0500 Subject: [PATCH 35/38] Fix for bot out-of-combat movement animation glitches --- zone/bot.h | 2 ++ zone/mob.h | 4 ++-- zone/waypoints.cpp | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/zone/bot.h b/zone/bot.h index c4f47cd66..7b8bb59c5 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -339,6 +339,8 @@ public: bool IsStanding(); virtual int GetWalkspeed() const { return (int)((float)_GetWalkSpeed() * 1.785714f); } // 1.25 / 0.7 = 1.7857142857142857142857142857143 virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714f); } + virtual void WalkTo(float x, float y, float z); + virtual void RunTo(float x, float y, float z); bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); diff --git a/zone/mob.h b/zone/mob.h index 807007a68..423dbb63e 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -998,8 +998,8 @@ public: inline bool CheckAggro(Mob* other) {return hate_list.IsEntOnHateList(other);} float CalculateHeadingToTarget(float in_x, float in_y) { return HeadingAngleToMob(in_x, in_y); } - void WalkTo(float x, float y, float z); - void RunTo(float x, float y, float z); + virtual void WalkTo(float x, float y, float z); + virtual void RunTo(float x, float y, float z); void NavigateTo(float x, float y, float z); void RotateTo(float new_heading); void RotateToWalking(float new_heading); diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index 60a85449e..cf79aae08 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1063,3 +1063,26 @@ void NPC::RestoreGuardSpotCharm() { m_GuardPoint = m_GuardPointSaved; } + +/****************** +* Bot-specific overloads to make them play nice with the new movement system +*/ +#ifdef BOTS +#include "bot.h" + +void Bot::WalkTo(float x, float y, float z) +{ + if (IsSitting()) + Stand(); + + Mob::WalkTo(x, y, z); +} + +void Bot::RunTo(float x, float y, float z) +{ + if (IsSitting()) + Stand(); + + Mob::RunTo(x, y, z); +} +#endif From 036e4739ae44aa644d4c8a587f6889f0d6946dd9 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Jan 2019 09:14:47 -0500 Subject: [PATCH 36/38] Fix for bots disappearing while idle --- zone/bot.cpp | 24 ++++++++++++++++++++++-- zone/bot.h | 3 +++ zone/mob.h | 4 ++-- zone/waypoints.cpp | 6 ++++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/zone/bot.cpp b/zone/bot.cpp index 5c37e47fa..b6496fd80 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -29,7 +29,7 @@ extern volatile bool is_zone_loaded; // This constructor is used during the bot create command -Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) { +Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) { if(botOwner) { this->SetBotOwner(botOwner); this->_botOwnerCharacterID = botOwner->CharacterID(); @@ -80,6 +80,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm SetShowHelm(true); SetPauseAI(false); rest_timer.Disable(); + ping_timer.Disable(); SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT); if (IsCasterClass(GetClass())) SetStopMeleeLevel((uint8)RuleI(Bots, CasterStopMeleeLevel)); @@ -105,7 +106,7 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm // This constructor is used when the bot is loaded out of the database Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData) - : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1) + : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) { this->_botOwnerCharacterID = botOwnerCharacterID; if(this->_botOwnerCharacterID > 0) @@ -162,6 +163,7 @@ Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double to SetPauseAI(false); rest_timer.Disable(); + ping_timer.Disable(); SetFollowDistance(BOT_FOLLOW_DISTANCE_DEFAULT); if (IsCasterClass(GetClass())) SetStopMeleeLevel((uint8)RuleI(Bots, CasterStopMeleeLevel)); @@ -2010,6 +2012,9 @@ bool Bot::Process() { if (IsStunned() || IsMezzed()) return true; + if (!IsMoving() && ping_timer.Check()) + SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); + // Bot AI AI_Process(); return true; @@ -3251,6 +3256,7 @@ bool Bot::Spawn(Client* botCharacterOwner) { // Load pet LoadPet(); SentPositionPacket(0.0f, 0.0f, 0.0f, 0.0f, 0); + ping_timer.Start(8000); // there is something askew with spawn struct appearance fields... // I re-enabled this until I can sort it out uint32 itemID = 0; @@ -9072,4 +9078,18 @@ std::string Bot::CreateSayLink(Client* c, const char* message, const char* name) return saylink; } +void Bot::StopMoving() { + if (!ping_timer.Enabled()) + ping_timer.Start(8000); + + Mob::StopMoving(); +} + +void Bot::StopMoving(float new_heading) { + if (!ping_timer.Enabled()) + ping_timer.Start(8000); + + Mob::StopMoving(new_heading); +} + #endif diff --git a/zone/bot.h b/zone/bot.h index 7b8bb59c5..ed3cf8d92 100644 --- a/zone/bot.h +++ b/zone/bot.h @@ -341,6 +341,8 @@ public: virtual int GetRunspeed() const { return (int)((float)_GetRunSpeed() * 1.785714f); } virtual void WalkTo(float x, float y, float z); virtual void RunTo(float x, float y, float z); + virtual void StopMoving(); + virtual void StopMoving(float new_heading); bool UseDiscipline(uint32 spell_id, uint32 target); uint8 GetNumberNeedingHealedInGroup(uint8 hpr, bool includePets); bool GetNeedsCured(Mob *tar); @@ -731,6 +733,7 @@ private: unsigned int RestRegenMana; unsigned int RestRegenEndurance; Timer rest_timer; + Timer ping_timer; int32 base_end; int32 cur_end; int32 max_end; diff --git a/zone/mob.h b/zone/mob.h index 423dbb63e..809e7841c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -589,8 +589,8 @@ public: void MakeSpawnUpdateNoDelta(PlayerPositionUpdateServer_Struct* spu); void MakeSpawnUpdate(PlayerPositionUpdateServer_Struct* spu); void SentPositionPacket(float dx, float dy, float dz, float dh, int anim, bool send_to_self = false); - void StopMoving(); - void StopMoving(float new_heading); + virtual void StopMoving(); + virtual void StopMoving(float new_heading); void SetSpawned() { spawned = true; }; bool Spawned() { return spawned; }; virtual bool ShouldISpawnFor(Client *c) { return true; } diff --git a/zone/waypoints.cpp b/zone/waypoints.cpp index cf79aae08..968300e56 100644 --- a/zone/waypoints.cpp +++ b/zone/waypoints.cpp @@ -1075,6 +1075,9 @@ void Bot::WalkTo(float x, float y, float z) if (IsSitting()) Stand(); + if (ping_timer.Enabled()) + ping_timer.Disable(); + Mob::WalkTo(x, y, z); } @@ -1083,6 +1086,9 @@ void Bot::RunTo(float x, float y, float z) if (IsSitting()) Stand(); + if (ping_timer.Enabled()) + ping_timer.Disable(); + Mob::RunTo(x, y, z); } #endif From c8645475b9770cb17400fa841b0416c484d87f37 Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Jan 2019 20:19:51 -0500 Subject: [PATCH 37/38] Fix for client not scribing spells (thanks Secrets!) --- zone/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zone/client.cpp b/zone/client.cpp index 5077e5d53..beb21ae3d 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -2642,7 +2642,7 @@ bool Client::CheckAccess(int16 iDBLevel, int16 iDefaultLevel) { void Client::MemorizeSpell(uint32 slot,uint32 spellid,uint32 scribing){ if (slot < 0 || slot >= EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellbookSize) return; - if (spellid < 3 || spellid > EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) + if ((spellid < 3 || spellid > EQEmu::spells::DynamicLookup(ClientVersion(), GetGM())->SpellIdMax) && spellid != 0xFFFFFFFF) return; auto outapp = new EQApplicationPacket(OP_MemorizeSpell, sizeof(MemorizeSpell_Struct)); From 444acb7c709cfbfd38c1489b268128b5a951ea8b Mon Sep 17 00:00:00 2001 From: Uleat Date: Sun, 27 Jan 2019 21:49:21 -0500 Subject: [PATCH 38/38] Fix for bot npctype memory leak (thanks mackal!) --- zone/bot.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zone/bot.cpp b/zone/bot.cpp index b6496fd80..f7575c030 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -30,6 +30,8 @@ extern volatile bool is_zone_loaded; // This constructor is used during the bot create command Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) { + GiveNPCTypeData(npcTypeData); + if(botOwner) { this->SetBotOwner(botOwner); this->_botOwnerCharacterID = botOwner->CharacterID(); @@ -108,6 +110,8 @@ Bot::Bot(NPCType *npcTypeData, Client* botOwner) : NPC(npcTypeData, nullptr, glm Bot::Bot(uint32 botID, uint32 botOwnerCharacterID, uint32 botSpellsID, double totalPlayTime, uint32 lastZoneId, NPCType *npcTypeData) : NPC(npcTypeData, nullptr, glm::vec4(), Ground, false), rest_timer(1), ping_timer(1) { + GiveNPCTypeData(npcTypeData); + this->_botOwnerCharacterID = botOwnerCharacterID; if(this->_botOwnerCharacterID > 0) this->SetBotOwner(entity_list.GetClientByCharID(this->_botOwnerCharacterID));