mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 16:51:29 +00:00
[Spells] Add content filtering to NPC spells (#4309)
* [Spells] Add content filtering to NPC spells * Update mob_ai.cpp * Add NPC spell reloading * Oops * Naming --------- Co-authored-by: Kinglykrab <kinglykrab@gmail.com>
This commit is contained in:
parent
c0a8fd097e
commit
099c6d657b
@ -5620,7 +5620,21 @@ ALTER TABLE `npc_types`
|
||||
ADD COLUMN `greed` tinyint(8) UNSIGNED NOT NULL DEFAULT 0 AFTER `merchant_id`;
|
||||
)",
|
||||
.content_schema_update = true
|
||||
}
|
||||
},
|
||||
ManifestEntry{
|
||||
.version = 9279,
|
||||
.description = "2024_05_13_content_flagging_npc_spells_entries.sql",
|
||||
.check = "SHOW COLUMNS FROM `npc_spells_entries` LIKE 'content_flags'",
|
||||
.condition = "empty",
|
||||
.match = "",
|
||||
.sql = R"(
|
||||
ALTER TABLE `npc_spells_entries` ADD `min_expansion` tinyint(4) NOT NULL DEFAULT -1;
|
||||
ALTER TABLE `npc_spells_entries` ADD `max_expansion` tinyint(4) NOT NULL DEFAULT -1;
|
||||
ALTER TABLE `npc_spells_entries` ADD `content_flags` varchar(100) NULL;
|
||||
ALTER TABLE `npc_spells_entries` ADD `content_flags_disabled` varchar(100) NULL;
|
||||
)",
|
||||
.content_schema_update = true
|
||||
},
|
||||
// -- template; copy/paste this when you need to create a new entry
|
||||
// ManifestEntry{
|
||||
// .version = 9228,
|
||||
|
||||
@ -19,18 +19,22 @@
|
||||
class BaseNpcSpellsEntriesRepository {
|
||||
public:
|
||||
struct NpcSpellsEntries {
|
||||
uint32_t id;
|
||||
int32_t npc_spells_id;
|
||||
uint16_t spellid;
|
||||
uint32_t type;
|
||||
uint8_t minlevel;
|
||||
uint8_t maxlevel;
|
||||
int16_t manacost;
|
||||
int32_t recast_delay;
|
||||
int16_t priority;
|
||||
int32_t resist_adjust;
|
||||
int16_t min_hp;
|
||||
int16_t max_hp;
|
||||
uint32_t id;
|
||||
int32_t npc_spells_id;
|
||||
uint16_t spellid;
|
||||
uint32_t type;
|
||||
uint8_t minlevel;
|
||||
uint8_t maxlevel;
|
||||
int16_t manacost;
|
||||
int32_t recast_delay;
|
||||
int16_t priority;
|
||||
int32_t resist_adjust;
|
||||
int16_t min_hp;
|
||||
int16_t max_hp;
|
||||
int8_t min_expansion;
|
||||
int8_t max_expansion;
|
||||
std::string content_flags;
|
||||
std::string content_flags_disabled;
|
||||
};
|
||||
|
||||
static std::string PrimaryKey()
|
||||
@ -53,6 +57,10 @@ public:
|
||||
"resist_adjust",
|
||||
"min_hp",
|
||||
"max_hp",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@ -71,6 +79,10 @@ public:
|
||||
"resist_adjust",
|
||||
"min_hp",
|
||||
"max_hp",
|
||||
"min_expansion",
|
||||
"max_expansion",
|
||||
"content_flags",
|
||||
"content_flags_disabled",
|
||||
};
|
||||
}
|
||||
|
||||
@ -111,18 +123,22 @@ public:
|
||||
{
|
||||
NpcSpellsEntries e{};
|
||||
|
||||
e.id = 0;
|
||||
e.npc_spells_id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.minlevel = 0;
|
||||
e.maxlevel = 255;
|
||||
e.manacost = -1;
|
||||
e.recast_delay = -1;
|
||||
e.priority = 0;
|
||||
e.resist_adjust = 0;
|
||||
e.min_hp = 0;
|
||||
e.max_hp = 0;
|
||||
e.id = 0;
|
||||
e.npc_spells_id = 0;
|
||||
e.spellid = 0;
|
||||
e.type = 0;
|
||||
e.minlevel = 0;
|
||||
e.maxlevel = 255;
|
||||
e.manacost = -1;
|
||||
e.recast_delay = -1;
|
||||
e.priority = 0;
|
||||
e.resist_adjust = 0;
|
||||
e.min_hp = 0;
|
||||
e.max_hp = 0;
|
||||
e.min_expansion = -1;
|
||||
e.max_expansion = -1;
|
||||
e.content_flags = "";
|
||||
e.content_flags_disabled = "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@ -159,18 +175,22 @@ public:
|
||||
if (results.RowCount() == 1) {
|
||||
NpcSpellsEntries e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
|
||||
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
return e;
|
||||
}
|
||||
@ -215,6 +235,10 @@ public:
|
||||
v.push_back(columns[9] + " = " + std::to_string(e.resist_adjust));
|
||||
v.push_back(columns[10] + " = " + std::to_string(e.min_hp));
|
||||
v.push_back(columns[11] + " = " + std::to_string(e.max_hp));
|
||||
v.push_back(columns[12] + " = " + std::to_string(e.min_expansion));
|
||||
v.push_back(columns[13] + " = " + std::to_string(e.max_expansion));
|
||||
v.push_back(columns[14] + " = '" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back(columns[15] + " = '" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -248,6 +272,10 @@ public:
|
||||
v.push_back(std::to_string(e.resist_adjust));
|
||||
v.push_back(std::to_string(e.min_hp));
|
||||
v.push_back(std::to_string(e.max_hp));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -289,6 +317,10 @@ public:
|
||||
v.push_back(std::to_string(e.resist_adjust));
|
||||
v.push_back(std::to_string(e.min_hp));
|
||||
v.push_back(std::to_string(e.max_hp));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
@ -322,18 +354,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
NpcSpellsEntries e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
|
||||
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@ -358,18 +394,22 @@ public:
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
NpcSpellsEntries e{};
|
||||
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.id = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
|
||||
e.npc_spells_id = row[1] ? static_cast<int32_t>(atoi(row[1])) : 0;
|
||||
e.spellid = row[2] ? static_cast<uint16_t>(strtoul(row[2], nullptr, 10)) : 0;
|
||||
e.type = row[3] ? static_cast<uint32_t>(strtoul(row[3], nullptr, 10)) : 0;
|
||||
e.minlevel = row[4] ? static_cast<uint8_t>(strtoul(row[4], nullptr, 10)) : 0;
|
||||
e.maxlevel = row[5] ? static_cast<uint8_t>(strtoul(row[5], nullptr, 10)) : 255;
|
||||
e.manacost = row[6] ? static_cast<int16_t>(atoi(row[6])) : -1;
|
||||
e.recast_delay = row[7] ? static_cast<int32_t>(atoi(row[7])) : -1;
|
||||
e.priority = row[8] ? static_cast<int16_t>(atoi(row[8])) : 0;
|
||||
e.resist_adjust = row[9] ? static_cast<int32_t>(atoi(row[9])) : 0;
|
||||
e.min_hp = row[10] ? static_cast<int16_t>(atoi(row[10])) : 0;
|
||||
e.max_hp = row[11] ? static_cast<int16_t>(atoi(row[11])) : 0;
|
||||
e.min_expansion = row[12] ? static_cast<int8_t>(atoi(row[12])) : -1;
|
||||
e.max_expansion = row[13] ? static_cast<int8_t>(atoi(row[13])) : -1;
|
||||
e.content_flags = row[14] ? row[14] : "";
|
||||
e.content_flags_disabled = row[15] ? row[15] : "";
|
||||
|
||||
all_entries.push_back(e);
|
||||
}
|
||||
@ -456,6 +496,10 @@ public:
|
||||
v.push_back(std::to_string(e.resist_adjust));
|
||||
v.push_back(std::to_string(e.min_hp));
|
||||
v.push_back(std::to_string(e.max_hp));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
@ -490,6 +534,10 @@ public:
|
||||
v.push_back(std::to_string(e.resist_adjust));
|
||||
v.push_back(std::to_string(e.min_hp));
|
||||
v.push_back(std::to_string(e.max_hp));
|
||||
v.push_back(std::to_string(e.min_expansion));
|
||||
v.push_back(std::to_string(e.max_expansion));
|
||||
v.push_back("'" + Strings::Escape(e.content_flags) + "'");
|
||||
v.push_back("'" + Strings::Escape(e.content_flags_disabled) + "'");
|
||||
|
||||
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
|
||||
}
|
||||
|
||||
@ -277,6 +277,7 @@
|
||||
#define ServerOP_ReloadLoot 0x4127
|
||||
#define ServerOP_ReloadBaseData 0x4128
|
||||
#define ServerOP_ReloadSkillCaps 0x4129
|
||||
#define ServerOP_ReloadNPCSpells 0x4130
|
||||
|
||||
#define ServerOP_CZDialogueWindow 0x4500
|
||||
#define ServerOP_CZLDoNUpdate 0x4501
|
||||
|
||||
@ -42,7 +42,7 @@
|
||||
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
|
||||
*/
|
||||
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9278
|
||||
#define CURRENT_BINARY_DATABASE_VERSION 9279
|
||||
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9044
|
||||
|
||||
#endif
|
||||
|
||||
@ -152,6 +152,7 @@ std::vector<Reload> reload_types = {
|
||||
Reload{.command = "loot", .opcode = ServerOP_ReloadLoot, .desc = "Loot"},
|
||||
Reload{.command = "merchants", .opcode = ServerOP_ReloadMerchants, .desc = "Merchants"},
|
||||
Reload{.command = "npc_emotes", .opcode = ServerOP_ReloadNPCEmotes, .desc = "NPC Emotes"},
|
||||
Reload{.command = "npc_spells", .opcode = ServerOP_ReloadNPCSpells, .desc = "NPC Spells"},
|
||||
Reload{.command = "objects", .opcode = ServerOP_ReloadObjects, .desc = "Objects"},
|
||||
Reload{.command = "opcodes", .opcode = ServerOP_ReloadOpcodes, .desc = "Opcodes"},
|
||||
Reload{.command = "perl_export", .opcode = ServerOP_ReloadPerlExportSettings, .desc = "Perl Event Export Settings"},
|
||||
|
||||
@ -1410,6 +1410,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
|
||||
case ServerOP_ReloadLevelEXPMods:
|
||||
case ServerOP_ReloadMerchants:
|
||||
case ServerOP_ReloadNPCEmotes:
|
||||
case ServerOP_ReloadNPCSpells:
|
||||
case ServerOP_ReloadObjects:
|
||||
case ServerOP_ReloadPerlExportSettings:
|
||||
case ServerOP_ReloadStaticZoneData:
|
||||
|
||||
@ -9367,6 +9367,7 @@ void Client::ShowDevToolsMenu()
|
||||
|
||||
menu_reload_five += Saylink::Silent("#reload merchants", "Merchants");
|
||||
menu_reload_five += " | " + Saylink::Silent("#reload npc_emotes", "NPC Emotes");
|
||||
menu_reload_five += " | " + Saylink::Silent("#reload npc_spells", "NPC Spells");
|
||||
menu_reload_five += " | " + Saylink::Silent("#reload objects", "Objects");
|
||||
menu_reload_five += " | " + Saylink::Silent("#reload opcodes", "Opcodes");
|
||||
|
||||
@ -11448,6 +11449,15 @@ void Client::SendReloadCommandMessages() {
|
||||
).c_str()
|
||||
);
|
||||
|
||||
auto npc_spells_link = Saylink::Silent("#reload npc_spells");
|
||||
Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Usage: {} - Reloads NPC Spells globally",
|
||||
npc_spells_link
|
||||
).c_str()
|
||||
);
|
||||
|
||||
auto objects_link = Saylink::Silent("#reload objects");
|
||||
|
||||
Message(
|
||||
|
||||
@ -29,6 +29,7 @@ void command_reload(Client *c, const Seperator *sep)
|
||||
bool is_loot = !strcasecmp(sep->arg[1], "loot");
|
||||
bool is_merchants = !strcasecmp(sep->arg[1], "merchants");
|
||||
bool is_npc_emotes = !strcasecmp(sep->arg[1], "npc_emotes");
|
||||
bool is_npc_spells = !strcasecmp(sep->arg[1], "npc_spells");
|
||||
bool is_objects = !strcasecmp(sep->arg[1], "objects");
|
||||
bool is_opcodes = !strcasecmp(sep->arg[1], "opcodes") || is_opcodes_reload_alias;
|
||||
bool is_perl_export = !strcasecmp(sep->arg[1], "perl_export");
|
||||
@ -62,6 +63,7 @@ void command_reload(Client *c, const Seperator *sep)
|
||||
!is_loot &&
|
||||
!is_merchants &&
|
||||
!is_npc_emotes &&
|
||||
!is_npc_spells &&
|
||||
!is_objects &&
|
||||
!is_opcodes &&
|
||||
!is_perl_export &&
|
||||
@ -137,6 +139,9 @@ void command_reload(Client *c, const Seperator *sep)
|
||||
} else if (is_npc_emotes) {
|
||||
c->Message(Chat::White, "Attempting to reload NPC Emotes globally.");
|
||||
pack = new ServerPacket(ServerOP_ReloadNPCEmotes, 0);
|
||||
} else if (is_npc_spells) {
|
||||
c->Message(Chat::White, "Attempting to reload NPC Spells globally.");
|
||||
pack = new ServerPacket(ServerOP_ReloadNPCSpells, 0);
|
||||
} else if (is_objects) {
|
||||
c->Message(Chat::White, "Attempting to reload Objects globally.");
|
||||
pack = new ServerPacket(ServerOP_ReloadObjects, 0);
|
||||
|
||||
137
zone/mob_ai.cpp
137
zone/mob_ai.cpp
@ -33,6 +33,9 @@
|
||||
#include "../common/data_verification.h"
|
||||
|
||||
#include "bot.h"
|
||||
#include "../common/repositories/npc_spells_repository.h"
|
||||
#include "../common/repositories/npc_spells_entries_repository.h"
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
|
||||
#include <glm/gtx/projection.hpp>
|
||||
#include <algorithm>
|
||||
@ -2841,102 +2844,92 @@ void NPC::AISpellsList(Client *c)
|
||||
return;
|
||||
}
|
||||
|
||||
DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 iDBSpellsID)
|
||||
DBnpcspells_Struct *ZoneDatabase::GetNPCSpells(uint32 npc_spells_id)
|
||||
{
|
||||
if (iDBSpellsID == 0)
|
||||
if (npc_spells_id == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto it = npc_spells_cache.find(iDBSpellsID);
|
||||
|
||||
auto it = npc_spells_cache.find(npc_spells_id);
|
||||
if (it != npc_spells_cache.end()) { // it's in the cache, easy =)
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
if (!npc_spells_loadtried.count(iDBSpellsID)) { // no reason to ask the DB again if we have failed once already
|
||||
npc_spells_loadtried.insert(iDBSpellsID);
|
||||
if (!npc_spells_loadtried.count(npc_spells_id)) { // no reason to ask the DB again if we have failed once already
|
||||
npc_spells_loadtried.insert(npc_spells_id);
|
||||
|
||||
std::string query = StringFormat("SELECT id, parent_list, attack_proc, proc_chance, "
|
||||
"range_proc, rproc_chance, defensive_proc, dproc_chance, "
|
||||
"fail_recast, engaged_no_sp_recast_min, engaged_no_sp_recast_max, "
|
||||
"engaged_b_self_chance, engaged_b_other_chance, engaged_d_chance, "
|
||||
"pursue_no_sp_recast_min, pursue_no_sp_recast_max, "
|
||||
"pursue_d_chance, idle_no_sp_recast_min, idle_no_sp_recast_max, "
|
||||
"idle_b_chance FROM npc_spells WHERE id=%d",
|
||||
iDBSpellsID);
|
||||
auto results = QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
auto ns = NpcSpellsRepository::FindOne(*this, npc_spells_id);
|
||||
if (!ns.id) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (results.RowCount() != 1)
|
||||
return nullptr;
|
||||
DBnpcspells_Struct ss;
|
||||
|
||||
auto row = results.begin();
|
||||
DBnpcspells_Struct spell_set;
|
||||
ss.parent_list = ns.parent_list;
|
||||
ss.attack_proc = ns.attack_proc;
|
||||
ss.proc_chance = ns.proc_chance;
|
||||
ss.range_proc = ns.range_proc;
|
||||
ss.rproc_chance = ns.rproc_chance;
|
||||
ss.defensive_proc = ns.defensive_proc;
|
||||
ss.dproc_chance = ns.dproc_chance;
|
||||
ss.fail_recast = ns.fail_recast;
|
||||
ss.engaged_no_sp_recast_min = ns.engaged_no_sp_recast_min;
|
||||
ss.engaged_no_sp_recast_max = ns.engaged_no_sp_recast_max;
|
||||
ss.engaged_beneficial_self_chance = ns.engaged_b_self_chance;
|
||||
ss.engaged_beneficial_other_chance = ns.engaged_b_other_chance;
|
||||
ss.engaged_detrimental_chance = ns.engaged_d_chance;
|
||||
ss.pursue_no_sp_recast_min = ns.pursue_no_sp_recast_min;
|
||||
ss.pursue_no_sp_recast_max = ns.pursue_no_sp_recast_max;
|
||||
ss.pursue_detrimental_chance = ns.pursue_d_chance;
|
||||
ss.idle_no_sp_recast_min = ns.idle_no_sp_recast_min;
|
||||
ss.idle_no_sp_recast_max = ns.idle_no_sp_recast_max;
|
||||
ss.idle_beneficial_chance = ns.idle_b_chance;
|
||||
|
||||
spell_set.parent_list = Strings::ToInt(row[1]);
|
||||
spell_set.attack_proc = Strings::ToInt(row[2]);
|
||||
spell_set.proc_chance = Strings::ToInt(row[3]);
|
||||
spell_set.range_proc = Strings::ToInt(row[4]);
|
||||
spell_set.rproc_chance = Strings::ToInt(row[5]);
|
||||
spell_set.defensive_proc = Strings::ToInt(row[6]);
|
||||
spell_set.dproc_chance = Strings::ToInt(row[7]);
|
||||
spell_set.fail_recast = Strings::ToInt(row[8]);
|
||||
spell_set.engaged_no_sp_recast_min = Strings::ToInt(row[9]);
|
||||
spell_set.engaged_no_sp_recast_max = Strings::ToInt(row[10]);
|
||||
spell_set.engaged_beneficial_self_chance = Strings::ToInt(row[11]);
|
||||
spell_set.engaged_beneficial_other_chance = Strings::ToInt(row[12]);
|
||||
spell_set.engaged_detrimental_chance = Strings::ToInt(row[13]);
|
||||
spell_set.pursue_no_sp_recast_min = Strings::ToInt(row[14]);
|
||||
spell_set.pursue_no_sp_recast_max = Strings::ToInt(row[15]);
|
||||
spell_set.pursue_detrimental_chance = Strings::ToInt(row[16]);
|
||||
spell_set.idle_no_sp_recast_min = Strings::ToInt(row[17]);
|
||||
spell_set.idle_no_sp_recast_max = Strings::ToInt(row[18]);
|
||||
spell_set.idle_beneficial_chance = Strings::ToInt(row[19]);
|
||||
auto entries = NpcSpellsEntriesRepository::GetWhere(
|
||||
*this,
|
||||
fmt::format(
|
||||
"npc_spells_id = {} {} ORDER BY minlevel",
|
||||
npc_spells_id,
|
||||
ContentFilterCriteria::apply()
|
||||
)
|
||||
);
|
||||
|
||||
// pulling fixed values from an auto-increment field is dangerous...
|
||||
query = StringFormat(
|
||||
"SELECT spellid, type, minlevel, maxlevel, "
|
||||
"manacost, recast_delay, priority, min_hp, max_hp, resist_adjust "
|
||||
"FROM npc_spells_entries "
|
||||
"WHERE npc_spells_id=%d ORDER BY minlevel",
|
||||
iDBSpellsID);
|
||||
results = QueryDatabase(query);
|
||||
|
||||
if (!results.Success()) {
|
||||
if (entries.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int entryIndex = 0;
|
||||
for (row = results.begin(); row != results.end(); ++row, ++entryIndex) {
|
||||
DBnpcspells_entries_Struct entry;
|
||||
int spell_id = Strings::ToInt(row[0]);
|
||||
entry.spellid = spell_id;
|
||||
entry.type = Strings::ToUnsignedInt(row[1]);
|
||||
entry.minlevel = Strings::ToInt(row[2]);
|
||||
entry.maxlevel = Strings::ToInt(row[3]);
|
||||
entry.manacost = Strings::ToInt(row[4]);
|
||||
entry.recast_delay = Strings::ToInt(row[5]);
|
||||
entry.priority = Strings::ToInt(row[6]);
|
||||
entry.min_hp = Strings::ToInt(row[7]);
|
||||
entry.max_hp = Strings::ToInt(row[8]);
|
||||
for (auto &e: entries) {
|
||||
DBnpcspells_entries_Struct se{};
|
||||
|
||||
se.spellid = e.spellid;
|
||||
se.type = e.type;
|
||||
se.minlevel = e.minlevel;
|
||||
se.maxlevel = e.maxlevel;
|
||||
se.manacost = e.manacost;
|
||||
se.recast_delay = e.recast_delay;
|
||||
se.priority = e.priority;
|
||||
se.min_hp = e.min_hp;
|
||||
se.max_hp = e.max_hp;
|
||||
|
||||
// some spell types don't make much since to be priority 0, so fix that
|
||||
if (!(entry.type & SPELL_TYPES_INNATE) && entry.priority == 0)
|
||||
entry.priority = 1;
|
||||
if (!(se.type & SPELL_TYPES_INNATE) && se.priority == 0) {
|
||||
se.priority = 1;
|
||||
}
|
||||
|
||||
if (row[9])
|
||||
entry.resist_adjust = Strings::ToInt(row[9]);
|
||||
else if (IsValidSpell(spell_id))
|
||||
entry.resist_adjust = spells[spell_id].resist_difficulty;
|
||||
if (e.resist_adjust) {
|
||||
se.resist_adjust = e.resist_adjust;
|
||||
}
|
||||
else if (IsValidSpell(e.id)) {
|
||||
se.resist_adjust = spells[e.id].resist_difficulty;
|
||||
}
|
||||
|
||||
spell_set.entries.push_back(entry);
|
||||
ss.entries.push_back(se);
|
||||
}
|
||||
|
||||
npc_spells_cache.emplace(std::make_pair(iDBSpellsID, spell_set));
|
||||
npc_spells_cache.emplace(std::make_pair(npc_spells_id, ss));
|
||||
|
||||
return &npc_spells_cache[iDBSpellsID];
|
||||
}
|
||||
return &npc_spells_cache[npc_spells_id];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -2086,6 +2086,17 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadNPCSpells:
|
||||
{
|
||||
if (zone && zone->IsLoaded()) {
|
||||
zone->SendReloadMessage("NPC Spells");
|
||||
content_db.ClearNPCSpells();
|
||||
for (auto& e : entity_list.GetNPCList()) {
|
||||
e.second->ReloadSpells();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ServerOP_ReloadPerlExportSettings:
|
||||
{
|
||||
zone->SendReloadMessage("Perl Event Export Settings");
|
||||
|
||||
@ -2899,6 +2899,8 @@ std::string Zone::GetZoneDescription()
|
||||
|
||||
void Zone::SendReloadMessage(std::string reload_type)
|
||||
{
|
||||
LogInfo("Reloaded [{}]", reload_type);
|
||||
|
||||
worldserver.SendEmoteMessage(
|
||||
0,
|
||||
0,
|
||||
|
||||
@ -569,7 +569,7 @@ public:
|
||||
bool GetAuraEntry(uint16 spell_id, AuraRecord &record);
|
||||
void LoadGlobalLoot();
|
||||
|
||||
DBnpcspells_Struct* GetNPCSpells(uint32 iDBSpellsID);
|
||||
DBnpcspells_Struct* GetNPCSpells(uint32 npc_spells_id);
|
||||
DBnpcspellseffects_Struct* GetNPCSpellsEffects(uint32 iDBSpellsEffectsID);
|
||||
void ClearNPCSpells() { npc_spells_cache.clear(); npc_spells_loadtried.clear(); }
|
||||
const NPCType* LoadNPCTypesData(uint32 id, bool bulk_load = false);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user