mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-17 18:41:29 +00:00
Merge branch 'feature/peq-expansions' of https://github.com/EQEmu/Server into feature/generated-repositories
This commit is contained in:
commit
a19bb7b544
@ -26,8 +26,10 @@
|
|||||||
#include "../../common/crash.h"
|
#include "../../common/crash.h"
|
||||||
#include "../../common/rulesys.h"
|
#include "../../common/rulesys.h"
|
||||||
#include "../../common/string_util.h"
|
#include "../../common/string_util.h"
|
||||||
|
#include "../../common/content/world_content_service.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
|
WorldContentService content_service;
|
||||||
|
|
||||||
void ExportSpells(SharedDatabase *db);
|
void ExportSpells(SharedDatabase *db);
|
||||||
void ExportSkillCaps(SharedDatabase *db);
|
void ExportSkillCaps(SharedDatabase *db);
|
||||||
|
|||||||
@ -24,8 +24,10 @@
|
|||||||
#include "../../common/crash.h"
|
#include "../../common/crash.h"
|
||||||
#include "../../common/rulesys.h"
|
#include "../../common/rulesys.h"
|
||||||
#include "../../common/string_util.h"
|
#include "../../common/string_util.h"
|
||||||
|
#include "../../common/content/world_content_service.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
|
WorldContentService content_service;
|
||||||
|
|
||||||
void ImportSpells(SharedDatabase *db);
|
void ImportSpells(SharedDatabase *db);
|
||||||
void ImportSkillCaps(SharedDatabase *db);
|
void ImportSkillCaps(SharedDatabase *db);
|
||||||
@ -87,7 +89,7 @@ int main(int argc, char **argv) {
|
|||||||
ImportDBStrings(&database);
|
ImportDBStrings(&database);
|
||||||
|
|
||||||
LogSys.CloseFileLogs();
|
LogSys.CloseFileLogs();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,10 +326,10 @@ void ImportDBStrings(SharedDatabase *db) {
|
|||||||
std::string sql;
|
std::string sql;
|
||||||
int id, type;
|
int id, type;
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
id = atoi(split[0].c_str());
|
id = atoi(split[0].c_str());
|
||||||
type = atoi(split[1].c_str());
|
type = atoi(split[1].c_str());
|
||||||
|
|
||||||
if(split.size() >= 3) {
|
if(split.size() >= 3) {
|
||||||
value = ::EscapeString(split[2]);
|
value = ::EscapeString(split[2]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,7 +28,7 @@ namespace Expansion {
|
|||||||
enum ExpansionNumber {
|
enum ExpansionNumber {
|
||||||
Classic = 0,
|
Classic = 0,
|
||||||
TheRuinsOfKunark,
|
TheRuinsOfKunark,
|
||||||
TheShardsOfVelious,
|
TheScarsOfVelious,
|
||||||
TheShadowsOfLuclin,
|
TheShadowsOfLuclin,
|
||||||
ThePlanesOfPower,
|
ThePlanesOfPower,
|
||||||
TheLegacyOfYkesha,
|
TheLegacyOfYkesha,
|
||||||
@ -62,8 +62,10 @@ namespace Expansion {
|
|||||||
static const char *ExpansionName[ExpansionNumber::MaxId] = {
|
static const char *ExpansionName[ExpansionNumber::MaxId] = {
|
||||||
"Classic",
|
"Classic",
|
||||||
"The Ruins of Kunark",
|
"The Ruins of Kunark",
|
||||||
|
"The Scars of Velious",
|
||||||
"The Shadows of Luclin",
|
"The Shadows of Luclin",
|
||||||
"The Planes of Power",
|
"The Planes of Power",
|
||||||
|
"The Legacy of Ykesha",
|
||||||
"Lost Dungeons of Norrath",
|
"Lost Dungeons of Norrath",
|
||||||
"Gates of Discord",
|
"Gates of Discord",
|
||||||
"Omens of War",
|
"Omens of War",
|
||||||
@ -96,7 +98,7 @@ public:
|
|||||||
|
|
||||||
bool IsClassicEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::Classic; }
|
bool IsClassicEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::Classic; }
|
||||||
bool IsTheRuinsOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheRuinsOfKunark; }
|
bool IsTheRuinsOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheRuinsOfKunark; }
|
||||||
bool IsTheShardsOfVeliousEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheShardsOfVelious; }
|
bool IsTheScarsOfVeliousEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheScarsOfVelious; }
|
||||||
bool IsTheShadowsOfLuclinEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheShadowsOfLuclin; }
|
bool IsTheShadowsOfLuclinEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheShadowsOfLuclin; }
|
||||||
bool IsThePlanesOfPowerEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::ThePlanesOfPower; }
|
bool IsThePlanesOfPowerEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::ThePlanesOfPower; }
|
||||||
bool IsTheLegacyOfYkeshaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheLegacyOfYkesha; }
|
bool IsTheLegacyOfYkeshaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheLegacyOfYkesha; }
|
||||||
@ -124,7 +126,7 @@ public:
|
|||||||
|
|
||||||
bool IsCurrentExpansionClassic() { return current_expansion == Expansion::ExpansionNumber::Classic; }
|
bool IsCurrentExpansionClassic() { return current_expansion == Expansion::ExpansionNumber::Classic; }
|
||||||
bool IsCurrentExpansionTheRuinsOfKunark() { return current_expansion == Expansion::ExpansionNumber::TheRuinsOfKunark; }
|
bool IsCurrentExpansionTheRuinsOfKunark() { return current_expansion == Expansion::ExpansionNumber::TheRuinsOfKunark; }
|
||||||
bool IsCurrentExpansionTheShardsOfVelious() { return current_expansion == Expansion::ExpansionNumber::TheShardsOfVelious; }
|
bool IsCurrentExpansionTheScarsOfVelious() { return current_expansion == Expansion::ExpansionNumber::TheScarsOfVelious; }
|
||||||
bool IsCurrentExpansionTheShadowsOfLuclin() { return current_expansion == Expansion::ExpansionNumber::TheShadowsOfLuclin; }
|
bool IsCurrentExpansionTheShadowsOfLuclin() { return current_expansion == Expansion::ExpansionNumber::TheShadowsOfLuclin; }
|
||||||
bool IsCurrentExpansionThePlanesOfPower() { return current_expansion == Expansion::ExpansionNumber::ThePlanesOfPower; }
|
bool IsCurrentExpansionThePlanesOfPower() { return current_expansion == Expansion::ExpansionNumber::ThePlanesOfPower; }
|
||||||
bool IsCurrentExpansionTheLegacyOfYkesha() { return current_expansion == Expansion::ExpansionNumber::TheLegacyOfYkesha; }
|
bool IsCurrentExpansionTheLegacyOfYkesha() { return current_expansion == Expansion::ExpansionNumber::TheLegacyOfYkesha; }
|
||||||
|
|||||||
@ -26,28 +26,47 @@
|
|||||||
#include "../../string_util.h"
|
#include "../../string_util.h"
|
||||||
|
|
||||||
namespace ContentFilterCriteria {
|
namespace ContentFilterCriteria {
|
||||||
static std::string apply()
|
static std::string apply(std::string table_prefix = "")
|
||||||
{
|
{
|
||||||
std::string criteria;
|
std::string criteria;
|
||||||
|
|
||||||
|
if (!table_prefix.empty()) {
|
||||||
|
table_prefix = table_prefix + ".";
|
||||||
|
}
|
||||||
|
|
||||||
criteria += fmt::format(
|
criteria += fmt::format(
|
||||||
" AND (min_expansion >= {} OR min_expansion = 0)",
|
" AND ({}min_expansion <= {} OR {}min_expansion = 0)",
|
||||||
content_service.GetCurrentExpansion()
|
table_prefix,
|
||||||
|
content_service.GetCurrentExpansion(),
|
||||||
|
table_prefix
|
||||||
);
|
);
|
||||||
|
|
||||||
criteria += fmt::format(
|
criteria += fmt::format(
|
||||||
" AND (max_expansion <= {} OR max_expansion = 0)",
|
" AND ({}max_expansion >= {} OR {}max_expansion = 0)",
|
||||||
content_service.GetCurrentExpansion()
|
table_prefix,
|
||||||
|
content_service.GetCurrentExpansion(),
|
||||||
|
table_prefix
|
||||||
);
|
);
|
||||||
|
|
||||||
std::vector<std::string> flags = content_service.GetContentFlags();
|
std::vector<std::string> flags = content_service.GetContentFlags();
|
||||||
|
|
||||||
for (auto &flag: flags) {
|
for (auto &flag: flags) {
|
||||||
flag = "'" + flag + "'";
|
flag = "'" + flag + "'";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string flags_in_filter;
|
||||||
|
if (!flags.empty()) {
|
||||||
|
flags_in_filter = fmt::format(
|
||||||
|
" OR {}content_flags IN ({})",
|
||||||
|
table_prefix,
|
||||||
|
implode(", ", flags)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
criteria += fmt::format(
|
criteria += fmt::format(
|
||||||
" AND (content_flags IS NULL OR content_flags IN ({}))",
|
" AND ({}content_flags IS NULL{})",
|
||||||
implode(", ", flags)
|
table_prefix,
|
||||||
|
flags_in_filter
|
||||||
);
|
);
|
||||||
|
|
||||||
return std::string(criteria);
|
return std::string(criteria);
|
||||||
|
|||||||
@ -38,6 +38,7 @@
|
|||||||
#include "shareddb.h"
|
#include "shareddb.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include "eqemu_config.h"
|
#include "eqemu_config.h"
|
||||||
|
#include "repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
namespace ItemField
|
namespace ItemField
|
||||||
{
|
{
|
||||||
@ -431,16 +432,25 @@ bool SharedDatabase::SetSharedPlatinum(uint32 account_id, int32 amount_to_add) {
|
|||||||
|
|
||||||
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
bool SharedDatabase::SetStartingItems(PlayerProfile_Struct* pp, EQEmu::InventoryProfile* inv, uint32 si_race, uint32 si_class, uint32 si_deity, uint32 si_current_zone, char* si_name, int admin_level) {
|
||||||
|
|
||||||
const EQEmu::ItemData* myitem;
|
const EQEmu::ItemData *myitem;
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT itemid, item_charges, slot FROM starting_items "
|
std::string query = StringFormat(
|
||||||
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
"SELECT itemid, item_charges, slot FROM starting_items "
|
||||||
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
|
"WHERE (race = %i or race = 0) AND (class = %i or class = 0) AND "
|
||||||
"gm <= %i ORDER BY id",
|
"(deityid = %i or deityid = 0) AND (zoneid = %i or zoneid = 0) AND "
|
||||||
si_race, si_class, si_deity, si_current_zone, admin_level);
|
"gm <= %i %s ORDER BY id",
|
||||||
auto results = QueryDatabase(query);
|
si_race,
|
||||||
if (!results.Success())
|
si_class,
|
||||||
return false;
|
si_deity,
|
||||||
|
si_current_zone,
|
||||||
|
admin_level,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
@ -567,7 +577,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
{
|
{
|
||||||
if (!char_id || !inv)
|
if (!char_id || !inv)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Retrieve character inventory
|
// Retrieve character inventory
|
||||||
std::string query =
|
std::string query =
|
||||||
StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
|
StringFormat("SELECT slotid, itemid, charges, color, augslot1, augslot2, augslot3, augslot4, augslot5, "
|
||||||
@ -728,7 +738,7 @@ bool SharedDatabase::GetInventory(uint32 char_id, EQEmu::InventoryProfile *inv)
|
|||||||
char_id, item_id, slot_id);
|
char_id, item_id, slot_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cv_conflict) {
|
if (cv_conflict) {
|
||||||
char char_name[64] = "";
|
char char_name[64] = "";
|
||||||
GetCharName(char_id, char_name);
|
GetCharName(char_id, char_name);
|
||||||
@ -1462,7 +1472,7 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
command_settings[row[0]].first = atoi(row[1]);
|
command_settings[row[0]].first = atoi(row[1]);
|
||||||
if (row[2][0] == 0)
|
if (row[2][0] == 0)
|
||||||
@ -1696,7 +1706,7 @@ bool SharedDatabase::LoadSpells(const std::string &prefix, int32 *records, const
|
|||||||
auto Config = EQEmuConfig::get();
|
auto Config = EQEmuConfig::get();
|
||||||
EQEmu::IPCMutex mutex("spells");
|
EQEmu::IPCMutex mutex("spells");
|
||||||
mutex.Lock();
|
mutex.Lock();
|
||||||
|
|
||||||
std::string file_name = Config->SharedMemDir + prefix + std::string("spells");
|
std::string file_name = Config->SharedMemDir + prefix + std::string("spells");
|
||||||
spells_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
spells_mmf = std::unique_ptr<EQEmu::MemoryMappedFile>(new EQEmu::MemoryMappedFile(file_name));
|
||||||
*records = *reinterpret_cast<uint32*>(spells_mmf->Get());
|
*records = *reinterpret_cast<uint32*>(spells_mmf->Get());
|
||||||
@ -1996,7 +2006,11 @@ void SharedDatabase::GetLootTableInfo(uint32 &loot_table_count, uint32 &max_loot
|
|||||||
loot_table_count = 0;
|
loot_table_count = 0;
|
||||||
max_loot_table = 0;
|
max_loot_table = 0;
|
||||||
loot_table_entries = 0;
|
loot_table_entries = 0;
|
||||||
const std::string query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable";
|
const std::string query =
|
||||||
|
fmt::format(
|
||||||
|
"SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM loottable_entries) FROM loottable WHERE TRUE {}",
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
@ -2017,7 +2031,11 @@ void SharedDatabase::GetLootDropInfo(uint32 &loot_drop_count, uint32 &max_loot_d
|
|||||||
max_loot_drop = 0;
|
max_loot_drop = 0;
|
||||||
loot_drop_entries = 0;
|
loot_drop_entries = 0;
|
||||||
|
|
||||||
const std::string query = "SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop";
|
const std::string query = fmt::format(
|
||||||
|
"SELECT COUNT(*), MAX(id), (SELECT COUNT(*) FROM lootdrop_entries) FROM lootdrop WHERE TRUE {}",
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
@ -2039,50 +2057,79 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) {
|
|||||||
uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)];
|
uint8 loot_table[sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128)];
|
||||||
LootTable_Struct *lt = reinterpret_cast<LootTable_Struct*>(loot_table);
|
LootTable_Struct *lt = reinterpret_cast<LootTable_Struct*>(loot_table);
|
||||||
|
|
||||||
const std::string query = "SELECT loottable.id, loottable.mincash, loottable.maxcash, loottable.avgcoin, "
|
const std::string query = fmt::format(
|
||||||
"loottable_entries.lootdrop_id, loottable_entries.multiplier, loottable_entries.droplimit, "
|
SQL(
|
||||||
"loottable_entries.mindrop, loottable_entries.probability FROM loottable LEFT JOIN loottable_entries "
|
SELECT
|
||||||
"ON loottable.id = loottable_entries.loottable_id ORDER BY id";
|
loottable.id,
|
||||||
|
loottable.mincash,
|
||||||
|
loottable.maxcash,
|
||||||
|
loottable.avgcoin,
|
||||||
|
loottable_entries.lootdrop_id,
|
||||||
|
loottable_entries.multiplier,
|
||||||
|
loottable_entries.droplimit,
|
||||||
|
loottable_entries.mindrop,
|
||||||
|
loottable_entries.probability
|
||||||
|
FROM
|
||||||
|
loottable
|
||||||
|
LEFT JOIN loottable_entries ON loottable.id = loottable_entries.loottable_id
|
||||||
|
WHERE TRUE {}
|
||||||
|
ORDER BY
|
||||||
|
id
|
||||||
|
),
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 current_id = 0;
|
uint32 current_id = 0;
|
||||||
uint32 current_entry = 0;
|
uint32 current_entry = 0;
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
uint32 id = static_cast<uint32>(atoul(row[0]));
|
uint32 id = static_cast<uint32>(atoul(row[0]));
|
||||||
if(id != current_id) {
|
if (id != current_id) {
|
||||||
if(current_id != 0)
|
if (current_id != 0) {
|
||||||
hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * lt->NumEntries)));
|
hash.insert(
|
||||||
|
current_id,
|
||||||
|
loot_table,
|
||||||
|
(sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * lt->NumEntries)));
|
||||||
|
}
|
||||||
|
|
||||||
memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128));
|
memset(loot_table, 0, sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * 128));
|
||||||
current_entry = 0;
|
current_entry = 0;
|
||||||
current_id = id;
|
current_id = id;
|
||||||
lt->mincash = static_cast<uint32>(atoul(row[1]));
|
lt->mincash = static_cast<uint32>(atoul(row[1]));
|
||||||
lt->maxcash = static_cast<uint32>(atoul(row[2]));
|
lt->maxcash = static_cast<uint32>(atoul(row[2]));
|
||||||
lt->avgcoin = static_cast<uint32>(atoul(row[3]));
|
lt->avgcoin = static_cast<uint32>(atoul(row[3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current_entry > 128)
|
if (current_entry > 128) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!row[4])
|
if (!row[4]) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
lt->Entries[current_entry].lootdrop_id = static_cast<uint32>(atoul(row[4]));
|
lt->Entries[current_entry].lootdrop_id = static_cast<uint32>(atoul(row[4]));
|
||||||
lt->Entries[current_entry].multiplier = static_cast<uint8>(atoi(row[5]));
|
lt->Entries[current_entry].multiplier = static_cast<uint8>(atoi(row[5]));
|
||||||
lt->Entries[current_entry].droplimit = static_cast<uint8>(atoi(row[6]));
|
lt->Entries[current_entry].droplimit = static_cast<uint8>(atoi(row[6]));
|
||||||
lt->Entries[current_entry].mindrop = static_cast<uint8>(atoi(row[7]));
|
lt->Entries[current_entry].mindrop = static_cast<uint8>(atoi(row[7]));
|
||||||
lt->Entries[current_entry].probability = static_cast<float>(atof(row[8]));
|
lt->Entries[current_entry].probability = static_cast<float>(atof(row[8]));
|
||||||
|
|
||||||
++(lt->NumEntries);
|
++(lt->NumEntries);
|
||||||
++current_entry;
|
++current_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(current_id != 0)
|
if (current_id != 0) {
|
||||||
hash.insert(current_id, loot_table, (sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * lt->NumEntries)));
|
hash.insert(
|
||||||
|
current_id,
|
||||||
|
loot_table,
|
||||||
|
(sizeof(LootTable_Struct) + (sizeof(LootTableEntries_Struct) * lt->NumEntries))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2092,10 +2139,28 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) {
|
|||||||
uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)];
|
uint8 loot_drop[sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)];
|
||||||
LootDrop_Struct *ld = reinterpret_cast<LootDrop_Struct*>(loot_drop);
|
LootDrop_Struct *ld = reinterpret_cast<LootDrop_Struct*>(loot_drop);
|
||||||
|
|
||||||
const std::string query = "SELECT lootdrop.id, lootdrop_entries.item_id, lootdrop_entries.item_charges, "
|
const std::string query = fmt::format(
|
||||||
"lootdrop_entries.equip_item, lootdrop_entries.chance, lootdrop_entries.minlevel, "
|
SQL(
|
||||||
"lootdrop_entries.maxlevel, lootdrop_entries.multiplier FROM lootdrop JOIN lootdrop_entries "
|
SELECT
|
||||||
"ON lootdrop.id = lootdrop_entries.lootdrop_id ORDER BY lootdrop_id";
|
lootdrop.id,
|
||||||
|
lootdrop_entries.item_id,
|
||||||
|
lootdrop_entries.item_charges,
|
||||||
|
lootdrop_entries.equip_item,
|
||||||
|
lootdrop_entries.chance,
|
||||||
|
lootdrop_entries.minlevel,
|
||||||
|
lootdrop_entries.maxlevel,
|
||||||
|
lootdrop_entries.multiplier
|
||||||
|
FROM
|
||||||
|
lootdrop
|
||||||
|
JOIN lootdrop_entries ON lootdrop.id = lootdrop_entries.lootdrop_id
|
||||||
|
WHERE
|
||||||
|
TRUE {}
|
||||||
|
ORDER BY
|
||||||
|
lootdrop_id
|
||||||
|
),
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -33,8 +33,10 @@
|
|||||||
#include "skill_caps.h"
|
#include "skill_caps.h"
|
||||||
#include "spells.h"
|
#include "spells.h"
|
||||||
#include "base_data.h"
|
#include "base_data.h"
|
||||||
|
#include "../common/content/world_content_service.h"
|
||||||
|
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
|
WorldContentService content_service;
|
||||||
|
|
||||||
#ifdef _WINDOWS
|
#ifdef _WINDOWS
|
||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
@ -139,6 +141,39 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rules: TODO: Remove later
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
std::string tmp;
|
||||||
|
if (database.GetVariable("RuleSet", tmp)) {
|
||||||
|
LogInfo("Loading rule set [{}]", tmp.c_str());
|
||||||
|
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||||
|
LogError("Failed to load ruleset [{}], falling back to defaults", tmp.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||||
|
LogInfo("No rule set configured, using default rules");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LogInfo("Loaded default rule set 'default'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EQEmu::InitializeDynamicLookups();
|
||||||
|
LogInfo("Initialized dynamic dictionary entries");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Current expansion is [{}] ({})",
|
||||||
|
content_service.GetCurrentExpansion(),
|
||||||
|
Expansion::ExpansionName[content_service.GetCurrentExpansion()]
|
||||||
|
);
|
||||||
|
|
||||||
std::string hotfix_name = "";
|
std::string hotfix_name = "";
|
||||||
|
|
||||||
bool load_all = true;
|
bool load_all = true;
|
||||||
|
|||||||
@ -59,6 +59,7 @@ namespace WorldserverCommandHandler {
|
|||||||
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
|
function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema;
|
||||||
function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump;
|
function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump;
|
||||||
function_map["test:test"] = &WorldserverCommandHandler::TestCommand;
|
function_map["test:test"] = &WorldserverCommandHandler::TestCommand;
|
||||||
|
function_map["test:expansion"] = &WorldserverCommandHandler::ExpansionTestCommand;
|
||||||
function_map["test:repository"] = &WorldserverCommandHandler::TestRepository;
|
function_map["test:repository"] = &WorldserverCommandHandler::TestRepository;
|
||||||
function_map["test:repository2"] = &WorldserverCommandHandler::TestRepository2;
|
function_map["test:repository2"] = &WorldserverCommandHandler::TestRepository2;
|
||||||
|
|
||||||
@ -293,6 +294,22 @@ namespace WorldserverCommandHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param argc
|
||||||
|
* @param argv
|
||||||
|
* @param cmd
|
||||||
|
* @param description
|
||||||
|
*/
|
||||||
|
void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description)
|
||||||
|
{
|
||||||
|
description = "Expansion test command";
|
||||||
|
|
||||||
|
if (cmd[{"-h", "--help"}]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||||
LogInfo("No rule set configured, using default rules");
|
LogInfo("No rule set configured, using default rules");
|
||||||
}
|
}
|
||||||
@ -310,7 +327,7 @@ namespace WorldserverCommandHandler {
|
|||||||
"Current expansion is [{}] ({}) is Velious Enabled [{}] Criteria [{}]",
|
"Current expansion is [{}] ({}) is Velious Enabled [{}] Criteria [{}]",
|
||||||
content_service.GetCurrentExpansion(),
|
content_service.GetCurrentExpansion(),
|
||||||
Expansion::ExpansionName[content_service.GetCurrentExpansion()],
|
Expansion::ExpansionName[content_service.GetCurrentExpansion()],
|
||||||
content_service.IsTheShardsOfVeliousEnabled() ? "true" : "false",
|
content_service.IsTheScarsOfVeliousEnabled() ? "true" : "false",
|
||||||
ContentFilterCriteria::apply()
|
ContentFilterCriteria::apply()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,7 @@ namespace WorldserverCommandHandler {
|
|||||||
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
|
void ExpansionTestCommand(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void TestRepository(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description);
|
void TestRepository2(int argc, char **argv, argh::parser &cmd, std::string &description);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "sof_char_create_data.h"
|
#include "sof_char_create_data.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
WorldDatabase database;
|
WorldDatabase database;
|
||||||
WorldDatabase content_db;
|
WorldDatabase content_db;
|
||||||
@ -197,10 +198,11 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o
|
|||||||
|
|
||||||
if (has_home == 0 || has_bind == 0) {
|
if (has_home == 0 || has_bind == 0) {
|
||||||
character_list_query = StringFormat(
|
character_list_query = StringFormat(
|
||||||
"SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i",
|
"SELECT `zone_id`, `bind_id`, `x`, `y`, `z` FROM `start_zones` WHERE `player_class` = %i AND `player_deity` = %i AND `player_race` = %i %s",
|
||||||
p_character_select_entry_struct->Class,
|
p_character_select_entry_struct->Class,
|
||||||
p_character_select_entry_struct->Deity,
|
p_character_select_entry_struct->Deity,
|
||||||
p_character_select_entry_struct->Race
|
p_character_select_entry_struct->Race,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
);
|
);
|
||||||
auto results_bind = content_db.QueryDatabase(character_list_query);
|
auto results_bind = content_db.QueryDatabase(character_list_query);
|
||||||
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
for (auto row_d = results_bind.begin(); row_d != results_bind.end(); ++row_d) {
|
||||||
@ -313,7 +315,7 @@ void WorldDatabase::GetCharSelectInfo(uint32 account_id, EQApplicationPacket **o
|
|||||||
|
|
||||||
if (matslot > 6) {
|
if (matslot > 6) {
|
||||||
uint32 item_id_file = 0;
|
uint32 item_id_file = 0;
|
||||||
// Weapon Models
|
// Weapon Models
|
||||||
if (inst->GetOrnamentationIDFile() != 0) {
|
if (inst->GetOrnamentationIDFile() != 0) {
|
||||||
item_id_file = inst->GetOrnamentationIDFile();
|
item_id_file = inst->GetOrnamentationIDFile();
|
||||||
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
|
p_character_select_entry_struct->Equip[matslot].Material = item_id_file;
|
||||||
@ -381,7 +383,7 @@ int WorldDatabase::MoveCharacterToBind(int CharID, uint8 bindnum)
|
|||||||
heading = atof(row[5]);
|
heading = atof(row[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
query = StringFormat("UPDATE character_data SET zone_id = '%d', zone_instance = '%d', x = '%f', y = '%f', z = '%f', heading = '%f' WHERE id = %u",
|
query = StringFormat("UPDATE character_data SET zone_id = '%d', zone_instance = '%d', x = '%f', y = '%f', z = '%f', heading = '%f' WHERE id = %u",
|
||||||
zone_id, instance_id, x, y, z, heading, CharID);
|
zone_id, instance_id, x, y, z, heading, CharID);
|
||||||
|
|
||||||
results = database.QueryDatabase(query);
|
results = database.QueryDatabase(query);
|
||||||
@ -423,11 +425,12 @@ bool WorldDatabase::GetStartZone(
|
|||||||
// see if we have an entry for start_zone. We can support both titanium & SOF+ by having two entries per class/race/deity combo with different zone_ids
|
// see if we have an entry for start_zone. We can support both titanium & SOF+ by having two entries per class/race/deity combo with different zone_ids
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"SELECT x, y, z, heading, start_zone, bind_id, bind_x, bind_y, bind_z FROM start_zones WHERE zone_id = %i "
|
"SELECT x, y, z, heading, start_zone, bind_id, bind_x, bind_y, bind_z FROM start_zones WHERE zone_id = %i "
|
||||||
"AND player_class = %i AND player_deity = %i AND player_race = %i",
|
"AND player_class = %i AND player_deity = %i AND player_race = %i %s",
|
||||||
p_char_create_struct->start_zone,
|
p_char_create_struct->start_zone,
|
||||||
p_char_create_struct->class_,
|
p_char_create_struct->class_,
|
||||||
p_char_create_struct->deity,
|
p_char_create_struct->deity,
|
||||||
p_char_create_struct->race
|
p_char_create_struct->race,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
@ -469,7 +472,7 @@ bool WorldDatabase::GetStartZone(
|
|||||||
void WorldDatabase::SetSoFDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc){
|
void WorldDatabase::SetSoFDefaultStartZone(PlayerProfile_Struct* in_pp, CharCreate_Struct* in_cc){
|
||||||
if (in_cc->start_zone == RuleI(World, TutorialZoneID)) {
|
if (in_cc->start_zone == RuleI(World, TutorialZoneID)) {
|
||||||
in_pp->zone_id = in_cc->start_zone;
|
in_pp->zone_id = in_cc->start_zone;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
in_pp->x = in_pp->binds[0].x = -51;
|
in_pp->x = in_pp->binds[0].x = -51;
|
||||||
in_pp->y = in_pp->binds[0].y = -20;
|
in_pp->y = in_pp->binds[0].y = -20;
|
||||||
@ -805,4 +808,4 @@ bool WorldDatabase::GetCharSelInventory(uint32 account_id, char *name, EQEmu::In
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
#include "mob_movement_manager.h"
|
#include "mob_movement_manager.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
#include "bot.h"
|
#include "bot.h"
|
||||||
@ -599,7 +600,7 @@ void Client::CompleteConnect()
|
|||||||
if (group)
|
if (group)
|
||||||
group->SendHPManaEndPacketsTo(this);
|
group->SendHPManaEndPacketsTo(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//bulk raid send in here eventually
|
//bulk raid send in here eventually
|
||||||
|
|
||||||
@ -1237,7 +1238,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
database.ClearOldRecastTimestamps(cid); /* Clear out our old recast timestamps to keep the DB clean */
|
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...
|
// 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
|
// item loss will occur when they use the 'empty' slots, if this is not done
|
||||||
m_inv.SetGMInventory(true);
|
m_inv.SetGMInventory(true);
|
||||||
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
|
loaditems = database.GetInventory(cid, &m_inv); /* Load Character Inventory */
|
||||||
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
database.LoadCharacterBandolier(cid, &m_pp); /* Load Character Bandolier */
|
||||||
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
database.LoadCharacterBindPoint(cid, &m_pp); /* Load Character Bind */
|
||||||
@ -1341,7 +1342,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
|||||||
client_max_level = GetCharMaxLevelFromBucket();
|
client_max_level = GetCharMaxLevelFromBucket();
|
||||||
}
|
}
|
||||||
SetClientMaxLevel(client_max_level);
|
SetClientMaxLevel(client_max_level);
|
||||||
|
|
||||||
// we know our class now, so we might have to fix our consume timer!
|
// we know our class now, so we might have to fix our consume timer!
|
||||||
if (class_ == MONK)
|
if (class_ == MONK)
|
||||||
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
|
consume_food_timer.SetTimer(CONSUMPTION_MNK_TIMER);
|
||||||
@ -2840,7 +2841,7 @@ void Client::Handle_OP_ApplyPoison(const EQApplicationPacket *app)
|
|||||||
// rogue simply won't apply at all, no skill check done.
|
// rogue simply won't apply at all, no skill check done.
|
||||||
|
|
||||||
uint16 poison_skill = GetSkill(EQEmu::skills::SkillApplyPoison);
|
uint16 poison_skill = GetSkill(EQEmu::skills::SkillApplyPoison);
|
||||||
|
|
||||||
if (ChanceRoll < (.75 + poison_skill / 1000)) {
|
if (ChanceRoll < (.75 + poison_skill / 1000)) {
|
||||||
ApplyPoisonSuccessResult = 1;
|
ApplyPoisonSuccessResult = 1;
|
||||||
AddProcToWeapon(poison->Proc.Effect, false, (GetDEX() / 100) + 103, POISON_PROC);
|
AddProcToWeapon(poison->Proc.Effect, false, (GetDEX() / 100) + 103, POISON_PROC);
|
||||||
@ -3917,7 +3918,7 @@ void Client::Handle_OP_Bug(const EQApplicationPacket *app)
|
|||||||
Message(0, "Bug reporting is disabled on this server.");
|
Message(0, "Bug reporting is disabled on this server.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app->size != sizeof(BugReport_Struct)) {
|
if (app->size != sizeof(BugReport_Struct)) {
|
||||||
printf("Wrong size of BugReport_Struct got %d expected %zu!\n", app->size, sizeof(BugReport_Struct));
|
printf("Wrong size of BugReport_Struct got %d expected %zu!\n", app->size, sizeof(BugReport_Struct));
|
||||||
}
|
}
|
||||||
@ -4362,9 +4363,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
sizeof(PlayerPositionUpdateClient_Struct), app->size);
|
sizeof(PlayerPositionUpdateClient_Struct), app->size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer;
|
PlayerPositionUpdateClient_Struct *ppu = (PlayerPositionUpdateClient_Struct *) app->pBuffer;
|
||||||
|
|
||||||
/* Boat handling */
|
/* Boat handling */
|
||||||
if (ppu->spawn_id != GetID()) {
|
if (ppu->spawn_id != GetID()) {
|
||||||
/* If player is controlling boat */
|
/* If player is controlling boat */
|
||||||
@ -4374,16 +4375,16 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
controlling_boat_id = 0;
|
controlling_boat_id = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
auto boat_delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||||
boat->SetDelta(boat_delta);
|
boat->SetDelta(boat_delta);
|
||||||
|
|
||||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
PlayerPositionUpdateServer_Struct *ppus = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
||||||
boat->MakeSpawnUpdate(ppus);
|
boat->MakeSpawnUpdate(ppus);
|
||||||
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
|
entity_list.QueueCloseClients(boat, outapp, true, 300, this, false);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
/* Update the boat's position on the server, without sending an update */
|
/* Update the boat's position on the server, without sending an update */
|
||||||
boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading), false);
|
boat->GMMove(ppu->x_pos, ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading), false);
|
||||||
return;
|
return;
|
||||||
@ -4398,9 +4399,9 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
if (cmob != nullptr) {
|
if (cmob != nullptr) {
|
||||||
cmob->SetPosition(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
cmob->SetPosition(ppu->x_pos, ppu->y_pos, ppu->z_pos);
|
||||||
cmob->SetHeading(EQ12toFloat(ppu->heading));
|
cmob->SetHeading(EQ12toFloat(ppu->heading));
|
||||||
mMovementManager->SendCommandToClients(cmob, 0.0, 0.0, 0.0,
|
mMovementManager->SendCommandToClients(cmob, 0.0, 0.0, 0.0,
|
||||||
0.0, 0, ClientRangeAny, nullptr, this);
|
0.0, 0, ClientRangeAny, nullptr, this);
|
||||||
cmob->CastToNPC()->SaveGuardSpot(glm::vec4(ppu->x_pos,
|
cmob->CastToNPC()->SaveGuardSpot(glm::vec4(ppu->x_pos,
|
||||||
ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading)));
|
ppu->y_pos, ppu->z_pos, EQ12toFloat(ppu->heading)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4418,7 +4419,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
// From this point forward, we need to use a new set of variables for client
|
// From this point forward, we need to use a new set of variables for client
|
||||||
// position. If the client is in a boat, we need to add the boat pos and
|
// position. If the client is in a boat, we need to add the boat pos and
|
||||||
// the client offset together.
|
// the client offset together.
|
||||||
|
|
||||||
float cx = ppu->x_pos;
|
float cx = ppu->x_pos;
|
||||||
float cy = ppu->y_pos;
|
float cy = ppu->y_pos;
|
||||||
float cz = ppu->z_pos;
|
float cz = ppu->z_pos;
|
||||||
@ -4443,45 +4444,45 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
/* Check to see if PPU should trigger an update to the rewind position. */
|
/* Check to see if PPU should trigger an update to the rewind position. */
|
||||||
float rewind_x_diff = 0;
|
float rewind_x_diff = 0;
|
||||||
float rewind_y_diff = 0;
|
float rewind_y_diff = 0;
|
||||||
|
|
||||||
rewind_x_diff = cx - m_RewindLocation.x;
|
rewind_x_diff = cx - m_RewindLocation.x;
|
||||||
rewind_x_diff *= rewind_x_diff;
|
rewind_x_diff *= rewind_x_diff;
|
||||||
rewind_y_diff = cy - m_RewindLocation.y;
|
rewind_y_diff = cy - m_RewindLocation.y;
|
||||||
rewind_y_diff *= rewind_y_diff;
|
rewind_y_diff *= rewind_y_diff;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We only need to store updated values if the player has moved.
|
We only need to store updated values if the player has moved.
|
||||||
If the player has moved more than units for x or y, then we'll store
|
If the player has moved more than units for x or y, then we'll store
|
||||||
his pre-PPU x and y for /rewind, in case he gets stuck.
|
his pre-PPU x and y for /rewind, in case he gets stuck.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((rewind_x_diff > 750) || (rewind_y_diff > 750))
|
if ((rewind_x_diff > 750) || (rewind_y_diff > 750))
|
||||||
m_RewindLocation = glm::vec3(m_Position);
|
m_RewindLocation = glm::vec3(m_Position);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
If the PPU was a large jump, such as a cross zone gate or Call of Hero,
|
If the PPU was a large jump, such as a cross zone gate or Call of Hero,
|
||||||
just update rewind coordinates to the new ppu coordinates. This will prevent exploitation.
|
just update rewind coordinates to the new ppu coordinates. This will prevent exploitation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
if ((rewind_x_diff > 5000) || (rewind_y_diff > 5000))
|
||||||
m_RewindLocation = glm::vec3(cx, cy, cz);
|
m_RewindLocation = glm::vec3(cx, cy, cz);
|
||||||
|
|
||||||
if (proximity_timer.Check()) {
|
if (proximity_timer.Check()) {
|
||||||
entity_list.ProcessMove(this, glm::vec3(cx, cy, cz));
|
entity_list.ProcessMove(this, glm::vec3(cx, cy, cz));
|
||||||
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
if (RuleB(TaskSystem, EnableTaskSystem) && RuleB(TaskSystem, EnableTaskProximity))
|
||||||
ProcessTaskProximities(cx, cy, cz);
|
ProcessTaskProximities(cx, cy, cz);
|
||||||
|
|
||||||
m_Proximity = glm::vec3(cx, cy, cz);
|
m_Proximity = glm::vec3(cx, cy, cz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update internal state */
|
/* Update internal state */
|
||||||
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
m_Delta = glm::vec4(ppu->delta_x, ppu->delta_y, ppu->delta_z, EQ10toFloat(ppu->delta_heading));
|
||||||
|
|
||||||
if (IsTracking() && ((m_Position.x != cx) || (m_Position.y != cy))) {
|
if (IsTracking() && ((m_Position.x != cx) || (m_Position.y != cy))) {
|
||||||
if (zone->random.Real(0, 100) < 70)//should be good
|
if (zone->random.Real(0, 100) < 70)//should be good
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
CheckIncreaseSkill(EQEmu::skills::SkillTracking, nullptr, -20);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
/* Break Hide if moving without sneaking and set rewind timer if moved */
|
||||||
if (cy != m_Position.y || cx != m_Position.x) {
|
if (cy != m_Position.y || cx != m_Position.x) {
|
||||||
if ((hidden || improved_hidden) && !sneaking) {
|
if ((hidden || improved_hidden) && !sneaking) {
|
||||||
@ -4500,7 +4501,7 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
rewind_timer.Start(30000, true);
|
rewind_timer.Start(30000, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle client aggro scanning timers NPCs */
|
/* Handle client aggro scanning timers NPCs */
|
||||||
is_client_moving = (cy == m_Position.y && cx == m_Position.x) ? false : true;
|
is_client_moving = (cy == m_Position.y && cx == m_Position.x) ? false : true;
|
||||||
|
|
||||||
@ -4564,55 +4565,55 @@ void Client::Handle_OP_ClientUpdate(const EQApplicationPacket *app) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int32 new_animation = ppu->animation;
|
int32 new_animation = ppu->animation;
|
||||||
|
|
||||||
/* Update internal server position from what the client has sent */
|
/* Update internal server position from what the client has sent */
|
||||||
m_Position.x = cx;
|
m_Position.x = cx;
|
||||||
m_Position.y = cy;
|
m_Position.y = cy;
|
||||||
m_Position.z = cz;
|
m_Position.z = cz;
|
||||||
|
|
||||||
/* Visual Debugging */
|
/* Visual Debugging */
|
||||||
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
if (RuleB(Character, OPClientUpdateVisualDebug)) {
|
||||||
LogDebug("ClientUpdate: ppu x: [{}] y: [{}] z: [{}] h: [{}]", cx, cy, cz, new_heading);
|
LogDebug("ClientUpdate: ppu x: [{}] y: [{}] z: [{}] h: [{}]", cx, cy, cz, new_heading);
|
||||||
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
this->SendAppearanceEffect(78, 0, 0, 0, 0);
|
||||||
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
this->SendAppearanceEffect(41, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Only feed real time updates when client is moving */
|
/* Only feed real time updates when client is moving */
|
||||||
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
if (is_client_moving || new_heading != m_Position.w || new_animation != animation) {
|
||||||
|
|
||||||
animation = ppu->animation;
|
animation = ppu->animation;
|
||||||
m_Position.w = new_heading;
|
m_Position.w = new_heading;
|
||||||
|
|
||||||
/* Broadcast update to other clients */
|
/* Broadcast update to other clients */
|
||||||
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
auto outapp = new EQApplicationPacket(OP_ClientUpdate, sizeof(PlayerPositionUpdateServer_Struct));
|
||||||
PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
PlayerPositionUpdateServer_Struct *position_update = (PlayerPositionUpdateServer_Struct *) outapp->pBuffer;
|
||||||
|
|
||||||
MakeSpawnUpdate(position_update);
|
MakeSpawnUpdate(position_update);
|
||||||
|
|
||||||
if (gm_hide_me) {
|
if (gm_hide_me) {
|
||||||
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 255);
|
entity_list.QueueClientsStatus(this, outapp, true, Admin(), 255);
|
||||||
} else {
|
} else {
|
||||||
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
|
entity_list.QueueCloseClients(this, outapp, true, RuleI(Range, ClientPositionUpdates), nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
|
/* Always send position updates to group - send when beyond normal ClientPositionUpdate range */
|
||||||
Group *group = this->GetGroup();
|
Group *group = this->GetGroup();
|
||||||
Raid *raid = this->GetRaid();
|
Raid *raid = this->GetRaid();
|
||||||
|
|
||||||
if (raid) {
|
if (raid) {
|
||||||
raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
raid->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||||
} else if (group) {
|
} else if (group) {
|
||||||
group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
group->QueueClients(this, outapp, true, true, (RuleI(Range, ClientPositionUpdates) * -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zone->watermap) {
|
if (zone->watermap) {
|
||||||
if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
|
if (zone->watermap->InLiquid(glm::vec3(m_Position))) {
|
||||||
CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17);
|
CheckIncreaseSkill(EQEmu::skills::SkillSwimming, nullptr, -17);
|
||||||
|
|
||||||
// Dismount horses when entering water
|
// Dismount horses when entering water
|
||||||
if (GetHorseId() && RuleB(Character, DismountWater)) {
|
if (GetHorseId() && RuleB(Character, DismountWater)) {
|
||||||
SetHorseId(0);
|
SetHorseId(0);
|
||||||
@ -5749,23 +5750,23 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
|||||||
printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size);
|
printf("Error in FindPersonRequest_Struct. Expected size of: %zu, but got: %i\n", sizeof(FindPersonRequest_Struct), app->size);
|
||||||
else {
|
else {
|
||||||
FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer;
|
FindPersonRequest_Struct* t = (FindPersonRequest_Struct*)app->pBuffer;
|
||||||
|
|
||||||
std::vector<FindPerson_Point> points;
|
std::vector<FindPerson_Point> points;
|
||||||
Mob* target = entity_list.GetMob(t->npc_id);
|
Mob* target = entity_list.GetMob(t->npc_id);
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
//empty length packet == not found.
|
//empty length packet == not found.
|
||||||
EQApplicationPacket outapp(OP_FindPersonReply, 0);
|
EQApplicationPacket outapp(OP_FindPersonReply, 0);
|
||||||
QueuePacket(&outapp);
|
QueuePacket(&outapp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader ||
|
if (!RuleB(Pathing, Find) && RuleB(Bazaar, EnableWarpToTrader) && target->IsClient() && (target->CastToClient()->Trader ||
|
||||||
target->CastToClient()->Buyer)) {
|
target->CastToClient()->Buyer)) {
|
||||||
Message(Chat::Yellow, "Moving you to Trader %s", target->GetName());
|
Message(Chat::Yellow, "Moving you to Trader %s", target->GetName());
|
||||||
MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f);
|
MovePC(zone->GetZoneID(), zone->GetInstanceID(), target->GetX(), target->GetY(), target->GetZ(), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!RuleB(Pathing, Find) || !zone->pathing)
|
if (!RuleB(Pathing, Find) || !zone->pathing)
|
||||||
{
|
{
|
||||||
//fill in the path array...
|
//fill in the path array...
|
||||||
@ -5788,40 +5789,40 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
|
glm::vec3 Start(GetX(), GetY(), GetZ() + (GetSize() < 6.0 ? 6 : GetSize()) * HEAD_POSITION);
|
||||||
glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION);
|
glm::vec3 End(target->GetX(), target->GetY(), target->GetZ() + (target->GetSize() < 6.0 ? 6 : target->GetSize()) * HEAD_POSITION);
|
||||||
|
|
||||||
bool partial = false;
|
bool partial = false;
|
||||||
bool stuck = false;
|
bool stuck = false;
|
||||||
auto pathlist = zone->pathing->FindRoute(Start, End, partial, stuck);
|
auto pathlist = zone->pathing->FindRoute(Start, End, partial, stuck);
|
||||||
|
|
||||||
if (pathlist.empty() || partial)
|
if (pathlist.empty() || partial)
|
||||||
{
|
{
|
||||||
EQApplicationPacket outapp(OP_FindPersonReply, 0);
|
EQApplicationPacket outapp(OP_FindPersonReply, 0);
|
||||||
QueuePacket(&outapp);
|
QueuePacket(&outapp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Live appears to send the points in this order:
|
// Live appears to send the points in this order:
|
||||||
// Final destination.
|
// Final destination.
|
||||||
// Current Position.
|
// Current Position.
|
||||||
// rest of the points.
|
// rest of the points.
|
||||||
FindPerson_Point p;
|
FindPerson_Point p;
|
||||||
|
|
||||||
int PointNumber = 0;
|
int PointNumber = 0;
|
||||||
|
|
||||||
bool LeadsToTeleporter = false;
|
bool LeadsToTeleporter = false;
|
||||||
|
|
||||||
auto v = pathlist.back();
|
auto v = pathlist.back();
|
||||||
|
|
||||||
p.x = v.pos.x;
|
p.x = v.pos.x;
|
||||||
p.y = v.pos.y;
|
p.y = v.pos.y;
|
||||||
p.z = v.pos.z;
|
p.z = v.pos.z;
|
||||||
points.push_back(p);
|
points.push_back(p);
|
||||||
|
|
||||||
p.x = GetX();
|
p.x = GetX();
|
||||||
p.y = GetY();
|
p.y = GetY();
|
||||||
p.z = GetZ();
|
p.z = GetZ();
|
||||||
points.push_back(p);
|
points.push_back(p);
|
||||||
|
|
||||||
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
for (auto Iterator = pathlist.begin(); Iterator != pathlist.end(); ++Iterator)
|
||||||
{
|
{
|
||||||
if ((*Iterator).teleport) // Teleporter
|
if ((*Iterator).teleport) // Teleporter
|
||||||
@ -5829,7 +5830,7 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
|||||||
LeadsToTeleporter = true;
|
LeadsToTeleporter = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 v = (*Iterator).pos;
|
glm::vec3 v = (*Iterator).pos;
|
||||||
p.x = v.x;
|
p.x = v.x;
|
||||||
p.y = v.y;
|
p.y = v.y;
|
||||||
@ -5837,17 +5838,17 @@ void Client::Handle_OP_FindPersonRequest(const EQApplicationPacket *app)
|
|||||||
points.push_back(p);
|
points.push_back(p);
|
||||||
++PointNumber;
|
++PointNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!LeadsToTeleporter)
|
if (!LeadsToTeleporter)
|
||||||
{
|
{
|
||||||
p.x = target->GetX();
|
p.x = target->GetX();
|
||||||
p.y = target->GetY();
|
p.y = target->GetY();
|
||||||
p.z = target->GetZ();
|
p.z = target->GetZ();
|
||||||
|
|
||||||
points.push_back(p);
|
points.push_back(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SendPathPacket(points);
|
SendPathPacket(points);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11090,14 +11091,14 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
case RaidCommandInviteIntoExisting:
|
case RaidCommandInviteIntoExisting:
|
||||||
case RaidCommandInvite: {
|
case RaidCommandInvite: {
|
||||||
|
|
||||||
Client *player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name);
|
Client *player_to_invite = entity_list.GetClientByName(raid_command_packet->player_name);
|
||||||
|
|
||||||
if (!player_to_invite)
|
if (!player_to_invite)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Group *player_to_invite_group = player_to_invite->GetGroup();
|
Group *player_to_invite_group = player_to_invite->GetGroup();
|
||||||
|
|
||||||
if (player_to_invite->HasRaid()) {
|
if (player_to_invite->HasRaid()) {
|
||||||
Message(Chat::Red, "%s is already in a raid.", player_to_invite->GetName());
|
Message(Chat::Red, "%s is already in a raid.", player_to_invite->GetName());
|
||||||
break;
|
break;
|
||||||
@ -11112,7 +11113,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid.");
|
Message(Chat::Red, "You can only invite an ungrouped player or group leader to join your raid.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send out invite to the client */
|
/* Send out invite to the client */
|
||||||
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
|
auto outapp = new EQApplicationPacket(OP_RaidUpdate, sizeof(RaidGeneral_Struct));
|
||||||
RaidGeneral_Struct *raid_command = (RaidGeneral_Struct*)outapp->pBuffer;
|
RaidGeneral_Struct *raid_command = (RaidGeneral_Struct*)outapp->pBuffer;
|
||||||
@ -11124,7 +11125,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
raid_command->action = 20;
|
raid_command->action = 20;
|
||||||
|
|
||||||
player_to_invite->QueuePacket(outapp);
|
player_to_invite->QueuePacket(outapp);
|
||||||
|
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -11220,7 +11221,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
if (player_invited_group->IsLeader(player_invited_group->members[x])) {
|
if (player_invited_group->IsLeader(player_invited_group->members[x])) {
|
||||||
Client *c = nullptr;
|
Client *c = nullptr;
|
||||||
|
|
||||||
if (player_invited_group->members[x]->IsClient())
|
if (player_invited_group->members[x]->IsClient())
|
||||||
c = player_invited_group->members[x]->CastToClient();
|
c = player_invited_group->members[x]->CastToClient();
|
||||||
else
|
else
|
||||||
@ -11230,24 +11231,24 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
||||||
raid->AddMember(c, raid_free_group_id, true, true, true);
|
raid->AddMember(c, raid_free_group_id, true, true, true);
|
||||||
raid->SendBulkRaid(c);
|
raid->SendBulkRaid(c);
|
||||||
|
|
||||||
if (raid->IsLocked()) {
|
if (raid->IsLocked()) {
|
||||||
raid->SendRaidLockTo(c);
|
raid->SendRaidLockTo(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Client *c = nullptr;
|
Client *c = nullptr;
|
||||||
|
|
||||||
if (player_invited_group->members[x]->IsClient())
|
if (player_invited_group->members[x]->IsClient())
|
||||||
c = player_invited_group->members[x]->CastToClient();
|
c = player_invited_group->members[x]->CastToClient();
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
raid->SendRaidCreate(c);
|
raid->SendRaidCreate(c);
|
||||||
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
||||||
raid->AddMember(c, raid_free_group_id);
|
raid->AddMember(c, raid_free_group_id);
|
||||||
raid->SendBulkRaid(c);
|
raid->SendBulkRaid(c);
|
||||||
|
|
||||||
if (raid->IsLocked()) {
|
if (raid->IsLocked()) {
|
||||||
raid->SendRaidLockTo(c);
|
raid->SendRaidLockTo(c);
|
||||||
}
|
}
|
||||||
@ -11281,12 +11282,12 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
c = group->members[x]->CastToClient();
|
c = group->members[x]->CastToClient();
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
raid->SendRaidCreate(c);
|
raid->SendRaidCreate(c);
|
||||||
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
||||||
raid->AddMember(c, raid_free_group_id, false, true);
|
raid->AddMember(c, raid_free_group_id, false, true);
|
||||||
raid->SendBulkRaid(c);
|
raid->SendBulkRaid(c);
|
||||||
|
|
||||||
if (raid->IsLocked()) {
|
if (raid->IsLocked()) {
|
||||||
raid->SendRaidLockTo(c);
|
raid->SendRaidLockTo(c);
|
||||||
}
|
}
|
||||||
@ -11294,17 +11295,17 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
Client *c = nullptr;
|
Client *c = nullptr;
|
||||||
|
|
||||||
if (group->members[x]->IsClient())
|
if (group->members[x]->IsClient())
|
||||||
c = group->members[x]->CastToClient();
|
c = group->members[x]->CastToClient();
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
raid->SendRaidCreate(c);
|
raid->SendRaidCreate(c);
|
||||||
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
||||||
raid->AddMember(c, raid_free_group_id);
|
raid->AddMember(c, raid_free_group_id);
|
||||||
raid->SendBulkRaid(c);
|
raid->SendBulkRaid(c);
|
||||||
|
|
||||||
if (raid->IsLocked()) {
|
if (raid->IsLocked()) {
|
||||||
raid->SendRaidLockTo(c);
|
raid->SendRaidLockTo(c);
|
||||||
}
|
}
|
||||||
@ -11321,7 +11322,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
if (player_invited_group) {
|
if (player_invited_group) {
|
||||||
|
|
||||||
raid = new Raid(player_accepting_invite);
|
raid = new Raid(player_accepting_invite);
|
||||||
|
|
||||||
entity_list.AddRaid(raid);
|
entity_list.AddRaid(raid);
|
||||||
raid->SetRaidDetails();
|
raid->SetRaidDetails();
|
||||||
Client *addClientig = nullptr;
|
Client *addClientig = nullptr;
|
||||||
@ -11345,7 +11346,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
raid->SendMakeLeaderPacketTo(raid->leadername, c);
|
||||||
raid->AddMember(c, 0, true, true, true);
|
raid->AddMember(c, 0, true, true, true);
|
||||||
raid->SendBulkRaid(c);
|
raid->SendBulkRaid(c);
|
||||||
|
|
||||||
if (raid->IsLocked()) {
|
if (raid->IsLocked()) {
|
||||||
raid->SendRaidLockTo(c);
|
raid->SendRaidLockTo(c);
|
||||||
}
|
}
|
||||||
@ -11470,7 +11471,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
raid->SetGroupLeader(raid_command_packet->leader_name, false);
|
raid->SetGroupLeader(raid_command_packet->leader_name, false);
|
||||||
|
|
||||||
/* We were the leader of our old group */
|
/* We were the leader of our old group */
|
||||||
if (old_group < 12) {
|
if (old_group < 12) {
|
||||||
/* Assign new group leader if we can */
|
/* Assign new group leader if we can */
|
||||||
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||||
if (raid->members[x].GroupNumber == old_group) {
|
if (raid->members[x].GroupNumber == old_group) {
|
||||||
@ -11499,7 +11500,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64);
|
strn0cpy(raid_command_packet->playername, raid->members[x].membername, 64);
|
||||||
|
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
|
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -11545,7 +11546,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
raid->SetGroupLeader(raid_command_packet->leader_name, false);
|
raid->SetGroupLeader(raid_command_packet->leader_name, false);
|
||||||
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
for (int x = 0; x < MAX_RAID_MEMBERS; x++) {
|
||||||
if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0){
|
if (raid->members[x].GroupNumber == oldgrp && strlen(raid->members[x].membername) > 0 && strcmp(raid->members[x].membername, raid_command_packet->leader_name) != 0){
|
||||||
|
|
||||||
raid->SetGroupLeader(raid->members[x].membername);
|
raid->SetGroupLeader(raid->members[x].membername);
|
||||||
raid->UpdateGroupAAs(oldgrp);
|
raid->UpdateGroupAAs(oldgrp);
|
||||||
|
|
||||||
@ -11568,7 +11569,7 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
strn0cpy(raid_command->playername, raid->members[x].membername, 64);
|
strn0cpy(raid_command->playername, raid->members[x].membername, 64);
|
||||||
raid_command->zoneid = zone->GetZoneID();
|
raid_command->zoneid = zone->GetZoneID();
|
||||||
raid_command->instance_id = zone->GetInstanceID();
|
raid_command->instance_id = zone->GetInstanceID();
|
||||||
|
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
@ -11583,14 +11584,14 @@ void Client::Handle_OP_RaidCommand(const EQApplicationPacket *app)
|
|||||||
else {
|
else {
|
||||||
auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct));
|
auto pack = new ServerPacket(ServerOP_RaidGroupDisband, sizeof(ServerRaidGeneralAction_Struct));
|
||||||
ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
|
ServerRaidGeneralAction_Struct* raid_command = (ServerRaidGeneralAction_Struct*)pack->pBuffer;
|
||||||
|
|
||||||
raid_command->rid = raid->GetID();
|
raid_command->rid = raid->GetID();
|
||||||
raid_command->zoneid = zone->GetZoneID();
|
raid_command->zoneid = zone->GetZoneID();
|
||||||
raid_command->instance_id = zone->GetInstanceID();
|
raid_command->instance_id = zone->GetInstanceID();
|
||||||
strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64);
|
strn0cpy(raid_command->playername, raid_command_packet->leader_name, 64);
|
||||||
|
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
|
|
||||||
safe_delete(pack);
|
safe_delete(pack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11778,7 +11779,7 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
|||||||
{
|
{
|
||||||
if (app->size != sizeof(TradeskillFavorites_Struct)) {
|
if (app->size != sizeof(TradeskillFavorites_Struct)) {
|
||||||
LogError("Invalid size for TradeskillFavorites_Struct: Expected: [{}], Got: [{}]",
|
LogError("Invalid size for TradeskillFavorites_Struct: Expected: [{}], Got: [{}]",
|
||||||
sizeof(TradeskillFavorites_Struct), app->size);
|
sizeof(TradeskillFavorites_Struct), app->size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11828,6 +11829,7 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
|||||||
if (first) //no favorites....
|
if (first) //no favorites....
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO: Clean this up
|
||||||
const std::string query = StringFormat(
|
const std::string query = StringFormat(
|
||||||
SQL (
|
SQL (
|
||||||
SELECT
|
SELECT
|
||||||
@ -11844,11 +11846,12 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
|||||||
AND tr.id IN (%s)
|
AND tr.id IN (%s)
|
||||||
AND tr.must_learn & 0x20 <> 0x20
|
AND tr.must_learn & 0x20 <> 0x20
|
||||||
AND (
|
AND (
|
||||||
(
|
(
|
||||||
tr.must_learn & 0x3 <> 0
|
tr.must_learn & 0x3 <> 0
|
||||||
)
|
)
|
||||||
OR (tr.must_learn & 0x3 = 0)
|
OR (tr.must_learn & 0x3 = 0)
|
||||||
)
|
)
|
||||||
|
%s
|
||||||
GROUP BY
|
GROUP BY
|
||||||
tr.id
|
tr.id
|
||||||
HAVING
|
HAVING
|
||||||
@ -11861,10 +11864,12 @@ void Client::Handle_OP_RecipesFavorite(const EQApplicationPacket *app)
|
|||||||
)
|
)
|
||||||
) > 0
|
) > 0
|
||||||
AND SUM(tre.componentcount) <= %u
|
AND SUM(tre.componentcount) <= %u
|
||||||
|
|
||||||
LIMIT
|
LIMIT
|
||||||
100
|
100
|
||||||
),
|
),
|
||||||
favoriteIDs.c_str(),
|
favoriteIDs.c_str(),
|
||||||
|
ContentFilterCriteria::apply().c_str(),
|
||||||
containers.c_str(),
|
containers.c_str(),
|
||||||
combineObjectSlots
|
combineObjectSlots
|
||||||
);
|
);
|
||||||
@ -11924,6 +11929,7 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//arbitrary limit of 200 recipes, makes sense to me.
|
//arbitrary limit of 200 recipes, makes sense to me.
|
||||||
|
// TODO: Clean this up
|
||||||
std::string query = fmt::format(
|
std::string query = fmt::format(
|
||||||
SQL(
|
SQL(
|
||||||
SELECT
|
SELECT
|
||||||
@ -11931,39 +11937,22 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
|
|||||||
tr.name,
|
tr.name,
|
||||||
tr.trivial,
|
tr.trivial,
|
||||||
SUM(tre.componentcount),
|
SUM(tre.componentcount),
|
||||||
crl.madecount,
|
|
||||||
tr.tradeskill
|
tr.tradeskill
|
||||||
FROM
|
FROM
|
||||||
tradeskill_recipe
|
tradeskill_recipe AS tr
|
||||||
AS tr
|
LEFT JOIN tradeskill_recipe_entries AS tre ON tr.id = tre.recipe_id
|
||||||
LEFT
|
|
||||||
JOIN
|
|
||||||
tradeskill_recipe_entries
|
|
||||||
AS
|
|
||||||
tre
|
|
||||||
ON
|
|
||||||
tr.id = tre.recipe_id
|
|
||||||
LEFT JOIN(
|
|
||||||
SELECT
|
|
||||||
recipe_id,
|
|
||||||
madecount
|
|
||||||
FROM
|
|
||||||
char_recipe_list
|
|
||||||
WHERE
|
|
||||||
char_id = {}
|
|
||||||
) AS crl ON tr.id = crl.recipe_id
|
|
||||||
WHERE
|
WHERE
|
||||||
{} tr.trivial >= {}
|
{} tr.trivial >= {}
|
||||||
AND tr.trivial <= {}
|
AND tr.trivial <= {}
|
||||||
AND tr.enabled <> 0
|
AND tr.enabled <> 0
|
||||||
AND tr.must_learn & 0x20 <> 0x20
|
AND tr.must_learn & 0x20 <> 0x20
|
||||||
AND (
|
AND (
|
||||||
(
|
(
|
||||||
tr.must_learn & 0x3 <> 0
|
tr.must_learn & 0x3 <> 0
|
||||||
AND crl.madecount IS NOT NULL
|
)
|
||||||
)
|
|
||||||
OR (tr.must_learn & 0x3 = 0)
|
OR (tr.must_learn & 0x3 = 0)
|
||||||
)
|
)
|
||||||
|
{}
|
||||||
GROUP BY
|
GROUP BY
|
||||||
tr.id
|
tr.id
|
||||||
HAVING
|
HAVING
|
||||||
@ -11976,13 +11965,14 @@ void Client::Handle_OP_RecipesSearch(const EQApplicationPacket *app)
|
|||||||
)
|
)
|
||||||
) > 0
|
) > 0
|
||||||
AND SUM(tre.componentcount) <= {}
|
AND SUM(tre.componentcount) <= {}
|
||||||
|
|
||||||
LIMIT
|
LIMIT
|
||||||
200
|
200
|
||||||
),
|
),
|
||||||
CharacterID(),
|
|
||||||
search_clause,
|
search_clause,
|
||||||
p_recipes_search_struct->mintrivial,
|
p_recipes_search_struct->mintrivial,
|
||||||
p_recipes_search_struct->maxtrivial,
|
p_recipes_search_struct->maxtrivial,
|
||||||
|
ContentFilterCriteria::apply(),
|
||||||
containers_where_clause,
|
containers_where_clause,
|
||||||
combine_object_slots
|
combine_object_slots
|
||||||
);
|
);
|
||||||
@ -12447,9 +12437,14 @@ void Client::Handle_OP_SetStartCity(const EQApplicationPacket *app)
|
|||||||
uint32 zoneid = 0;
|
uint32 zoneid = 0;
|
||||||
uint32 startCity = (uint32)strtol((const char*)app->pBuffer, nullptr, 10);
|
uint32 startCity = (uint32)strtol((const char*)app->pBuffer, nullptr, 10);
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT zone_id, bind_id, x, y, z FROM start_zones "
|
std::string query = StringFormat(
|
||||||
"WHERE player_class=%i AND player_deity=%i AND player_race=%i",
|
"SELECT zone_id, bind_id, x, y, z FROM start_zones "
|
||||||
m_pp.class_, m_pp.deity, m_pp.race);
|
"WHERE player_class=%i AND player_deity=%i AND player_race=%i %s",
|
||||||
|
m_pp.class_,
|
||||||
|
m_pp.deity,
|
||||||
|
m_pp.race,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
auto results = content_db.QueryDatabase(query);
|
auto results = content_db.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
LogError("No valid start zones found for /setstartcity");
|
LogError("No valid start zones found for /setstartcity");
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include "string_ids.h"
|
#include "string_ids.h"
|
||||||
#include "worldserver.h"
|
#include "worldserver.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -716,10 +717,12 @@ bool ZoneDatabase::LoadDoors(int32 door_count, Door *into, const char *zone_name
|
|||||||
" WHERE "
|
" WHERE "
|
||||||
" zone = '%s' "
|
" zone = '%s' "
|
||||||
" AND ( version = % u OR version = - 1 ) "
|
" AND ( version = % u OR version = - 1 ) "
|
||||||
|
" %s "
|
||||||
" ORDER BY "
|
" ORDER BY "
|
||||||
" doorid ASC ",
|
" doorid ASC ",
|
||||||
zone_name,
|
zone_name,
|
||||||
version
|
version,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
);
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include "titles.h"
|
#include "titles.h"
|
||||||
#include "water_map.h"
|
#include "water_map.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -54,9 +55,25 @@ uint32 ZoneDatabase::GetZoneForage(uint32 ZoneID, uint8 skill) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32 chancepool = 0;
|
uint32 chancepool = 0;
|
||||||
std::string query = StringFormat("SELECT itemid, chance FROM "
|
std::string query = fmt::format(
|
||||||
"forage WHERE zoneid = '%i' and level <= '%i' "
|
SQL(
|
||||||
"LIMIT %i", ZoneID, skill, FORAGE_ITEM_LIMIT);
|
SELECT
|
||||||
|
itemid,
|
||||||
|
chance
|
||||||
|
FROM
|
||||||
|
forage
|
||||||
|
WHERE
|
||||||
|
zoneid = '{}'
|
||||||
|
and level <= '{}'
|
||||||
|
{}
|
||||||
|
LIMIT
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
ZoneID,
|
||||||
|
skill,
|
||||||
|
ContentFilterCriteria::apply(),
|
||||||
|
FORAGE_ITEM_LIMIT
|
||||||
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -109,9 +126,24 @@ uint32 ZoneDatabase::GetZoneFishing(uint32 ZoneID, uint8 skill, uint32 &npc_id,
|
|||||||
chance[c]=0;
|
chance[c]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT itemid, chance, npc_id, npc_chance "
|
std::string query = fmt::format(
|
||||||
"FROM fishing WHERE (zoneid = '%i' || zoneid = 0) AND skill_level <= '%i'",
|
SQL(
|
||||||
ZoneID, skill);
|
SELECT
|
||||||
|
itemid,
|
||||||
|
chance,
|
||||||
|
npc_id,
|
||||||
|
npc_chance
|
||||||
|
FROM
|
||||||
|
fishing
|
||||||
|
WHERE
|
||||||
|
(zoneid = '{}' || zoneid = 0)
|
||||||
|
AND skill_level <= '{}'
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
ZoneID,
|
||||||
|
skill,
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -27,6 +27,7 @@
|
|||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
#include "global_loot_manager.h"
|
#include "global_loot_manager.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -463,42 +464,70 @@ void NPC::CheckGlobalLootTables()
|
|||||||
|
|
||||||
void ZoneDatabase::LoadGlobalLoot()
|
void ZoneDatabase::LoadGlobalLoot()
|
||||||
{
|
{
|
||||||
auto query = StringFormat("SELECT id, loottable_id, description, min_level, max_level, rare, raid, race, "
|
auto query = fmt::format(
|
||||||
"class, bodytype, zone, hot_zone FROM global_loot WHERE enabled = 1");
|
SQL
|
||||||
|
(
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
loottable_id,
|
||||||
|
description,
|
||||||
|
min_level,
|
||||||
|
max_level,
|
||||||
|
rare,
|
||||||
|
raid,
|
||||||
|
race,
|
||||||
|
class,
|
||||||
|
bodytype,
|
||||||
|
zone,
|
||||||
|
hot_zone
|
||||||
|
FROM
|
||||||
|
global_loot
|
||||||
|
WHERE
|
||||||
|
enabled = 1
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success() || results.RowCount() == 0)
|
if (!results.Success() || results.RowCount() == 0) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// we might need this, lets not keep doing it in a loop
|
// we might need this, lets not keep doing it in a loop
|
||||||
auto zoneid = std::to_string(zone->GetZoneID());
|
auto zoneid = std::to_string(zone->GetZoneID());
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
// checking zone limits
|
// checking zone limits
|
||||||
if (row[10]) {
|
if (row[10]) {
|
||||||
auto zones = SplitString(row[10], '|');
|
auto zones = SplitString(row[10], '|');
|
||||||
|
|
||||||
auto it = std::find(zones.begin(), zones.end(), zoneid);
|
auto it = std::find(zones.begin(), zones.end(), zoneid);
|
||||||
if (it == zones.end()) // not in here, skip
|
if (it == zones.end()) { // not in here, skip
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : "");
|
GlobalLootEntry e(atoi(row[0]), atoi(row[1]), row[2] ? row[2] : "");
|
||||||
|
|
||||||
auto min_level = atoi(row[3]);
|
auto min_level = atoi(row[3]);
|
||||||
if (min_level)
|
if (min_level) {
|
||||||
e.AddRule(GlobalLoot::RuleTypes::LevelMin, min_level);
|
e.AddRule(GlobalLoot::RuleTypes::LevelMin, min_level);
|
||||||
|
}
|
||||||
|
|
||||||
auto max_level = atoi(row[4]);
|
auto max_level = atoi(row[4]);
|
||||||
if (max_level)
|
if (max_level) {
|
||||||
e.AddRule(GlobalLoot::RuleTypes::LevelMax, max_level);
|
e.AddRule(GlobalLoot::RuleTypes::LevelMax, max_level);
|
||||||
|
}
|
||||||
|
|
||||||
// null is not used
|
// null is not used
|
||||||
if (row[5])
|
if (row[5]) {
|
||||||
e.AddRule(GlobalLoot::RuleTypes::Rare, atoi(row[5]));
|
e.AddRule(GlobalLoot::RuleTypes::Rare, atoi(row[5]));
|
||||||
|
}
|
||||||
|
|
||||||
// null is not used
|
// null is not used
|
||||||
if (row[6])
|
if (row[6]) {
|
||||||
e.AddRule(GlobalLoot::RuleTypes::Raid, atoi(row[6]));
|
e.AddRule(GlobalLoot::RuleTypes::Raid, atoi(row[6]));
|
||||||
|
}
|
||||||
|
|
||||||
if (row[7]) {
|
if (row[7]) {
|
||||||
auto races = SplitString(row[7], '|');
|
auto races = SplitString(row[7], '|');
|
||||||
@ -522,8 +551,9 @@ void ZoneDatabase::LoadGlobalLoot()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// null is not used
|
// null is not used
|
||||||
if (row[11])
|
if (row[11]) {
|
||||||
e.AddRule(GlobalLoot::RuleTypes::HotZone, atoi(row[11]));
|
e.AddRule(GlobalLoot::RuleTypes::HotZone, atoi(row[11]));
|
||||||
|
}
|
||||||
|
|
||||||
zone->AddGlobalLootEntry(e);
|
zone->AddGlobalLootEntry(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -90,6 +90,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
#else
|
#else
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "../common/unix.h"
|
#include "../common/unix.h"
|
||||||
|
|
||||||
|
#include "../common/content/world_content_service.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
volatile bool RunLoops = true;
|
volatile bool RunLoops = true;
|
||||||
@ -107,6 +110,7 @@ TaskManager *taskmanager = 0;
|
|||||||
NpcScaleManager *npc_scale_manager;
|
NpcScaleManager *npc_scale_manager;
|
||||||
QuestParserCollection *parse = 0;
|
QuestParserCollection *parse = 0;
|
||||||
EQEmuLogSys LogSys;
|
EQEmuLogSys LogSys;
|
||||||
|
WorldContentService content_service;
|
||||||
const SPDat_Spell_Struct* spells;
|
const SPDat_Spell_Struct* spells;
|
||||||
int32 SPDAT_RECORDS = -1;
|
int32 SPDAT_RECORDS = -1;
|
||||||
const ZoneConfig *Config;
|
const ZoneConfig *Config;
|
||||||
@ -392,6 +396,14 @@ int main(int argc, char** argv) {
|
|||||||
LogInfo("Initialized dynamic dictionary entries");
|
LogInfo("Initialized dynamic dictionary entries");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion));
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Current expansion is [{}] ({})",
|
||||||
|
content_service.GetCurrentExpansion(),
|
||||||
|
Expansion::ExpansionName[content_service.GetCurrentExpansion()]
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
LogInfo("Loading bot commands");
|
LogInfo("Loading bot commands");
|
||||||
int botretval = bot_command_init();
|
int botretval = bot_command_init();
|
||||||
|
|||||||
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "quest_parser_collection.h"
|
#include "quest_parser_collection.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -460,7 +461,7 @@ void Object::RandomSpawn(bool send_packet) {
|
|||||||
|
|
||||||
m_data.x = zone->random.Real(m_min_x, m_max_x);
|
m_data.x = zone->random.Real(m_min_x, m_max_x);
|
||||||
m_data.y = zone->random.Real(m_min_y, m_max_y);
|
m_data.y = zone->random.Real(m_min_y, m_max_y);
|
||||||
|
|
||||||
if(m_data.z == BEST_Z_INVALID) {
|
if(m_data.z == BEST_Z_INVALID) {
|
||||||
glm::vec3 me;
|
glm::vec3 me;
|
||||||
me.x = m_data.x;
|
me.x = m_data.x;
|
||||||
@ -470,11 +471,11 @@ void Object::RandomSpawn(bool send_packet) {
|
|||||||
float best_z = zone->zonemap->FindClosestZ(me, &hit);
|
float best_z = zone->zonemap->FindClosestZ(me, &hit);
|
||||||
if (best_z != BEST_Z_INVALID) {
|
if (best_z != BEST_Z_INVALID) {
|
||||||
m_data.z = best_z + 0.1f;
|
m_data.z = best_z + 0.1f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogInfo("Object::RandomSpawn([{}]): [{}] ([{}], [{}], [{}])", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z);
|
LogInfo("Object::RandomSpawn([{}]): [{}] ([{}], [{}], [{}])", m_data.object_name, m_inst->GetID(), m_data.x, m_data.y, m_data.z);
|
||||||
|
|
||||||
respawn_timer.Disable();
|
respawn_timer.Disable();
|
||||||
|
|
||||||
if(send_packet) {
|
if(send_packet) {
|
||||||
@ -520,7 +521,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
|||||||
co->drop_id = 0;
|
co->drop_id = 0;
|
||||||
entity_list.QueueClients(nullptr, outapp, false);
|
entity_list.QueueClients(nullptr, outapp, false);
|
||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
|
|
||||||
// No longer using a tradeskill object
|
// No longer using a tradeskill object
|
||||||
sender->SetTradeskillObject(nullptr);
|
sender->SetTradeskillObject(nullptr);
|
||||||
user = nullptr;
|
user = nullptr;
|
||||||
@ -681,7 +682,7 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec
|
|||||||
"size = %f, tilt_x = %f, tilt_y = %f "
|
"size = %f, tilt_x = %f, tilt_y = %f "
|
||||||
"WHERE id = %i",
|
"WHERE id = %i",
|
||||||
object.zone_id, object.x, object.y, object.z, object.heading,
|
object.zone_id, object.x, object.y, object.z, object.heading,
|
||||||
item_id, charges, object_name, type, icon,
|
item_id, charges, object_name, type, icon,
|
||||||
object.size, object.tilt_x, object.tilt_y, id);
|
object.size, object.tilt_x, object.tilt_y, id);
|
||||||
safe_delete_array(object_name);
|
safe_delete_array(object_name);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
@ -698,14 +699,20 @@ void ZoneDatabase::UpdateObject(uint32 id, uint32 type, uint32 icon, const Objec
|
|||||||
//
|
//
|
||||||
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs) {
|
Ground_Spawns* ZoneDatabase::LoadGroundSpawns(uint32 zone_id, int16 version, Ground_Spawns* gs) {
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT max_x, max_y, max_z, "
|
std::string query = StringFormat(
|
||||||
"min_x, min_y, heading, name, "
|
"SELECT max_x, max_y, max_z, "
|
||||||
"item, max_allowed, respawn_timer "
|
"min_x, min_y, heading, name, "
|
||||||
"FROM ground_spawns "
|
"item, max_allowed, respawn_timer "
|
||||||
"WHERE zoneid = %i AND (version = %u OR version = -1) "
|
"FROM ground_spawns "
|
||||||
"LIMIT 50", zone_id, version);
|
"WHERE zoneid = %i AND (version = %u OR version = -1) %s "
|
||||||
auto results = QueryDatabase(query);
|
"LIMIT 50",
|
||||||
if (!results.Success()) {
|
zone_id,
|
||||||
|
version,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
return gs;
|
return gs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "spawngroup.h"
|
#include "spawngroup.h"
|
||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
extern EntityList entity_list;
|
extern EntityList entity_list;
|
||||||
extern Zone *zone;
|
extern Zone *zone;
|
||||||
@ -209,9 +210,11 @@ bool ZoneDatabase::LoadSpawnGroups(const char *zone_name, uint16 version, SpawnG
|
|||||||
spawn2.spawngroupID = spawngroup.ID
|
spawn2.spawngroupID = spawngroup.ID
|
||||||
AND
|
AND
|
||||||
spawn2.version = {} and zone = '{}'
|
spawn2.version = {} and zone = '{}'
|
||||||
|
{}
|
||||||
),
|
),
|
||||||
version,
|
version,
|
||||||
zone_name
|
zone_name,
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
);
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
|
|||||||
@ -310,6 +310,7 @@
|
|||||||
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
|
#define WHOALL_NO_RESULTS 5029 //There are no players in EverQuest that match those who filters.
|
||||||
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
|
#define TELL_QUEUED_MESSAGE 5045 //You told %1 '%T2. %3'
|
||||||
#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time.
|
#define TOLD_NOT_ONLINE 5046 //%1 is not online at this time.
|
||||||
|
#define ZONING_NO_EXPANSION 5052 //The zone that you are attempting to enter is part of an expansion that you do not yet own. You may need to return to the Login screen and enter an account key for that expansion. If you have received this message in error, please /petition or send an email to EQAccounts@soe.sony.com
|
||||||
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
|
#define PETITION_NO_DELETE 5053 //You do not have a petition in the queue.
|
||||||
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
|
#define PETITION_DELETED 5054 //Your petition was successfully deleted.
|
||||||
#define ALREADY_IN_RAID 5060 //%1 is already in a raid.
|
#define ALREADY_IN_RAID 5060 //%1 is already in a raid.
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#include "entity.h"
|
#include "entity.h"
|
||||||
#include "mob.h"
|
#include "mob.h"
|
||||||
#include "trap.h"
|
#include "trap.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -104,7 +105,7 @@ bool Trap::Process()
|
|||||||
reset_timer.Disable();
|
reset_timer.Disable();
|
||||||
charid = 0;
|
charid = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (respawn_timer.Enabled() && respawn_timer.Check())
|
if (respawn_timer.Enabled() && respawn_timer.Check())
|
||||||
{
|
{
|
||||||
detected = false;
|
detected = false;
|
||||||
@ -225,13 +226,13 @@ void Trap::Trigger(Mob* trigger)
|
|||||||
safe_delete(outapp);
|
safe_delete(outapp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigger && trigger->IsClient())
|
if (trigger && trigger->IsClient())
|
||||||
{
|
{
|
||||||
trigger->CastToClient()->trapid = trap_id;
|
trigger->CastToClient()->trapid = trap_id;
|
||||||
charid = trigger->CastToClient()->CharacterID();
|
charid = trigger->CastToClient()->CharacterID();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update = false;
|
bool update = false;
|
||||||
if (despawn_when_triggered)
|
if (despawn_when_triggered)
|
||||||
{
|
{
|
||||||
@ -242,16 +243,16 @@ void Trap::Trigger(Mob* trigger)
|
|||||||
{
|
{
|
||||||
reset_timer.Start(5000);
|
reset_timer.Start(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (triggered_number > 0)
|
if (triggered_number > 0)
|
||||||
++times_triggered;
|
++times_triggered;
|
||||||
|
|
||||||
if (triggered_number > 0 && triggered_number <= times_triggered)
|
if (triggered_number > 0 && triggered_number <= times_triggered)
|
||||||
{
|
{
|
||||||
Log(Logs::General, Logs::Traps, "Triggered number for trap %d reached. %d/%d", trap_id, times_triggered, triggered_number);
|
Log(Logs::General, Logs::Traps, "Triggered number for trap %d reached. %d/%d", trap_id, times_triggered, triggered_number);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
UpdateTrap();
|
UpdateTrap();
|
||||||
@ -290,7 +291,7 @@ Trap* EntityList::FindNearbyTrap(Mob* searcher, float max_dist, float &trap_curd
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
trap_curdist = INVALID_INDEX;
|
trap_curdist = INVALID_INDEX;
|
||||||
|
|
||||||
return current_trap;
|
return current_trap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -399,9 +400,14 @@ void EntityList::ClearTrapPointers()
|
|||||||
|
|
||||||
bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
|
bool ZoneDatabase::LoadTraps(const char* zonename, int16 version) {
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
|
std::string query = StringFormat(
|
||||||
|
"SELECT id, x, y, z, effect, effectvalue, effectvalue2, skill, "
|
||||||
"maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
|
"maxzdiff, radius, chance, message, respawn_time, respawn_var, level, "
|
||||||
"`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u", zonename, version);
|
"`group`, triggered_number, despawn_when_triggered, undetectable FROM traps WHERE zone='%s' AND version=%u %s",
|
||||||
|
zonename,
|
||||||
|
version,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
|
|||||||
187
zone/zone.cpp
187
zone/zone.cpp
@ -56,6 +56,7 @@
|
|||||||
#include "npc_scale_manager.h"
|
#include "npc_scale_manager.h"
|
||||||
#include "../common/data_verification.h"
|
#include "../common/data_verification.h"
|
||||||
#include "zone_reload.h"
|
#include "zone_reload.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
@ -140,7 +141,7 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
|||||||
if(iInstanceID != 0)
|
if(iInstanceID != 0)
|
||||||
{
|
{
|
||||||
auto pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16));
|
auto pack = new ServerPacket(ServerOP_AdventureZoneData, sizeof(uint16));
|
||||||
*((uint16*)pack->pBuffer) = iInstanceID;
|
*((uint16*)pack->pBuffer) = iInstanceID;
|
||||||
worldserver.SendPacket(pack);
|
worldserver.SendPacket(pack);
|
||||||
delete pack;
|
delete pack;
|
||||||
}
|
}
|
||||||
@ -170,11 +171,14 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool iStaticZone) {
|
|||||||
//this really loads the objects into entity_list
|
//this really loads the objects into entity_list
|
||||||
bool Zone::LoadZoneObjects()
|
bool Zone::LoadZoneObjects()
|
||||||
{
|
{
|
||||||
std::string query =
|
std::string query = StringFormat(
|
||||||
StringFormat("SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
|
"SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
|
||||||
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
|
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
|
||||||
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1)",
|
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1) %s",
|
||||||
zoneid, instanceversion);
|
zoneid,
|
||||||
|
instanceversion,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
auto results = content_db.QueryDatabase(query);
|
auto results = content_db.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
LogError("Error Loading Objects from DB: [{}]",
|
LogError("Error Loading Objects from DB: [{}]",
|
||||||
@ -498,73 +502,111 @@ void Zone::LoadTempMerchantData()
|
|||||||
void Zone::LoadNewMerchantData(uint32 merchantid) {
|
void Zone::LoadNewMerchantData(uint32 merchantid) {
|
||||||
|
|
||||||
std::list<MerchantList> merlist;
|
std::list<MerchantList> merlist;
|
||||||
std::string query = StringFormat("SELECT item, slot, faction_required, level_required, alt_currency_cost, "
|
|
||||||
"classes_required, probability FROM merchantlist WHERE merchantid=%d ORDER BY slot", merchantid);
|
std::string query = fmt::format(
|
||||||
|
SQL(
|
||||||
|
SELECT
|
||||||
|
item,
|
||||||
|
slot,
|
||||||
|
faction_required,
|
||||||
|
level_required,
|
||||||
|
alt_currency_cost,
|
||||||
|
classes_required,
|
||||||
|
probability
|
||||||
|
FROM
|
||||||
|
merchantlist
|
||||||
|
WHERE
|
||||||
|
merchantid = {}
|
||||||
|
{}
|
||||||
|
ORDER BY
|
||||||
|
slot
|
||||||
|
),
|
||||||
|
merchantid,
|
||||||
|
ContentFilterCriteria::apply()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = content_db.QueryDatabase(query);
|
auto results = content_db.QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
MerchantList ml;
|
MerchantList ml;
|
||||||
ml.id = merchantid;
|
ml.id = merchantid;
|
||||||
ml.item = atoul(row[0]);
|
ml.item = atoul(row[0]);
|
||||||
ml.slot = atoul(row[1]);
|
ml.slot = atoul(row[1]);
|
||||||
ml.faction_required = atoul(row[2]);
|
ml.faction_required = atoul(row[2]);
|
||||||
ml.level_required = atoul(row[3]);
|
ml.level_required = atoul(row[3]);
|
||||||
ml.alt_currency_cost = atoul(row[4]);
|
ml.alt_currency_cost = atoul(row[4]);
|
||||||
ml.classes_required = atoul(row[5]);
|
ml.classes_required = atoul(row[5]);
|
||||||
ml.probability = atoul(row[6]);
|
ml.probability = atoul(row[6]);
|
||||||
merlist.push_back(ml);
|
merlist.push_back(ml);
|
||||||
}
|
}
|
||||||
|
|
||||||
merchanttable[merchantid] = merlist;
|
merchanttable[merchantid] = merlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Zone::GetMerchantDataForZoneLoad() {
|
void Zone::GetMerchantDataForZoneLoad() {
|
||||||
LogInfo("Loading Merchant Lists");
|
LogInfo("Loading Merchant Lists");
|
||||||
std::string query = StringFormat(
|
std::string query = fmt::format(
|
||||||
"SELECT "
|
SQL (
|
||||||
"DISTINCT ml.merchantid, "
|
SELECT
|
||||||
"ml.slot, "
|
DISTINCT merchantlist.merchantid,
|
||||||
"ml.item, "
|
merchantlist.slot,
|
||||||
"ml.faction_required, "
|
merchantlist.item,
|
||||||
"ml.level_required, "
|
merchantlist.faction_required,
|
||||||
"ml.alt_currency_cost, "
|
merchantlist.level_required,
|
||||||
"ml.classes_required, "
|
merchantlist.alt_currency_cost,
|
||||||
"ml.probability "
|
merchantlist.classes_required,
|
||||||
"FROM "
|
merchantlist.probability
|
||||||
"merchantlist AS ml, "
|
FROM
|
||||||
"npc_types AS nt, "
|
merchantlist,
|
||||||
"spawnentry AS se, "
|
npc_types,
|
||||||
"spawn2 AS s2 "
|
spawnentry,
|
||||||
"WHERE nt.merchant_id = ml.merchantid AND nt.id = se.npcid "
|
spawn2
|
||||||
"AND se.spawngroupid = s2.spawngroupid AND s2.zone = '%s' AND s2.version = %i "
|
WHERE
|
||||||
"ORDER BY ml.slot ", GetShortName(), GetInstanceVersion());
|
npc_types.merchant_id = merchantlist.merchantid
|
||||||
|
AND npc_types.id = spawnentry.npcid
|
||||||
|
AND spawnentry.spawngroupid = spawn2.spawngroupid
|
||||||
|
AND spawn2.zone = '{}'
|
||||||
|
AND spawn2.version = {}
|
||||||
|
{}
|
||||||
|
ORDER BY
|
||||||
|
merchantlist.slot
|
||||||
|
),
|
||||||
|
GetShortName(),
|
||||||
|
GetInstanceVersion(),
|
||||||
|
ContentFilterCriteria::apply("merchantlist")
|
||||||
|
);
|
||||||
|
|
||||||
auto results = content_db.QueryDatabase(query);
|
auto results = content_db.QueryDatabase(query);
|
||||||
std::map<uint32, std::list<MerchantList> >::iterator cur;
|
|
||||||
uint32 npcid = 0;
|
std::map<uint32, std::list<MerchantList> >::iterator merchant_list;
|
||||||
|
|
||||||
|
uint32 npc_id = 0;
|
||||||
|
|
||||||
if (results.RowCount() == 0) {
|
if (results.RowCount() == 0) {
|
||||||
LogDebug("No Merchant Data found for [{}]", GetShortName());
|
LogDebug("No Merchant Data found for [{}]", GetShortName());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
MerchantList ml;
|
MerchantList merchant_list_entry{};
|
||||||
ml.id = atoul(row[0]);
|
merchant_list_entry.id = atoul(row[0]);
|
||||||
if (npcid != ml.id) {
|
if (npc_id != merchant_list_entry.id) {
|
||||||
cur = merchanttable.find(ml.id);
|
merchant_list = merchanttable.find(merchant_list_entry.id);
|
||||||
if (cur == merchanttable.end()) {
|
if (merchant_list == merchanttable.end()) {
|
||||||
std::list<MerchantList> empty;
|
std::list<MerchantList> empty;
|
||||||
merchanttable[ml.id] = empty;
|
merchanttable[merchant_list_entry.id] = empty;
|
||||||
cur = merchanttable.find(ml.id);
|
merchant_list = merchanttable.find(merchant_list_entry.id);
|
||||||
}
|
}
|
||||||
npcid = ml.id;
|
|
||||||
|
npc_id = merchant_list_entry.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto iter = cur->second.begin();
|
auto iter = merchant_list->second.begin();
|
||||||
bool found = false;
|
bool found = false;
|
||||||
while (iter != cur->second.end()) {
|
while (iter != merchant_list->second.end()) {
|
||||||
if ((*iter).item == ml.id) {
|
if ((*iter).item == merchant_list_entry.id) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -575,14 +617,15 @@ void Zone::GetMerchantDataForZoneLoad() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ml.slot = atoul(row[1]);
|
merchant_list_entry.slot = atoul(row[1]);
|
||||||
ml.item = atoul(row[2]);
|
merchant_list_entry.item = atoul(row[2]);
|
||||||
ml.faction_required = atoul(row[3]);
|
merchant_list_entry.faction_required = atoul(row[3]);
|
||||||
ml.level_required = atoul(row[4]);
|
merchant_list_entry.level_required = atoul(row[4]);
|
||||||
ml.alt_currency_cost = atoul(row[5]);
|
merchant_list_entry.alt_currency_cost = atoul(row[5]);
|
||||||
ml.classes_required = atoul(row[6]);
|
merchant_list_entry.classes_required = atoul(row[6]);
|
||||||
ml.probability = atoul(row[7]);
|
merchant_list_entry.probability = atoul(row[7]);
|
||||||
cur->second.push_back(ml);
|
|
||||||
|
merchant_list->second.push_back(merchant_list_entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -847,7 +890,7 @@ Zone::Zone(uint32 in_zoneid, uint32 in_instanceid, const char* in_short_name)
|
|||||||
{
|
{
|
||||||
LogDebug("Graveyard ID is [{}]", graveyard_id());
|
LogDebug("Graveyard ID is [{}]", graveyard_id());
|
||||||
bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_Graveyard.x, &m_Graveyard.y, &m_Graveyard.z, &m_Graveyard.w);
|
bool GraveYardLoaded = content_db.GetZoneGraveyard(graveyard_id(), &pgraveyard_zoneid, &m_Graveyard.x, &m_Graveyard.y, &m_Graveyard.z, &m_Graveyard.w);
|
||||||
|
|
||||||
if (GraveYardLoaded) {
|
if (GraveYardLoaded) {
|
||||||
LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_Graveyard).c_str());
|
LogDebug("Loaded a graveyard for zone [{}]: graveyard zoneid is [{}] at [{}]", short_name, graveyard_zoneid(), to_string(m_Graveyard).c_str());
|
||||||
}
|
}
|
||||||
@ -1798,16 +1841,22 @@ ZonePoint* Zone::GetClosestZonePointWithoutZone(float x, float y, float z, Clien
|
|||||||
return closest_zp;
|
return closest_zp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneDatabase::LoadStaticZonePoints(LinkedList<ZonePoint*>* zone_point_list, const char* zonename, uint32 version)
|
bool ZoneDatabase::LoadStaticZonePoints(LinkedList<ZonePoint *> *zone_point_list, const char *zonename, uint32 version)
|
||||||
{
|
{
|
||||||
zone_point_list->Clear();
|
zone_point_list->Clear();
|
||||||
zone->numzonepoints = 0;
|
zone->numzonepoints = 0;
|
||||||
std::string query = StringFormat("SELECT x, y, z, target_x, target_y, "
|
|
||||||
"target_z, target_zone_id, heading, target_heading, "
|
std::string query = StringFormat(
|
||||||
"number, target_instance, client_version_mask "
|
"SELECT x, y, z, target_x, target_y, "
|
||||||
"FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) "
|
"target_z, target_zone_id, heading, target_heading, "
|
||||||
"ORDER BY number",
|
"number, target_instance, client_version_mask "
|
||||||
zonename, version);
|
"FROM zone_points WHERE zone='%s' AND (version=%i OR version=-1) %s"
|
||||||
|
"ORDER BY number",
|
||||||
|
zonename,
|
||||||
|
version,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
|
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -12,6 +12,7 @@
|
|||||||
#include "zone.h"
|
#include "zone.h"
|
||||||
#include "zonedb.h"
|
#include "zonedb.h"
|
||||||
#include "aura.h"
|
#include "aura.h"
|
||||||
|
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||||
|
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@ -83,19 +84,19 @@ bool ZoneDatabase::SaveZoneCFG(uint32 zoneid, uint16 instance_id, NewZone_Struct
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneDatabase::GetZoneCFG(
|
bool ZoneDatabase::GetZoneCFG(
|
||||||
uint32 zoneid,
|
uint32 zoneid,
|
||||||
uint16 instance_id,
|
uint16 instance_id,
|
||||||
NewZone_Struct *zone_data,
|
NewZone_Struct *zone_data,
|
||||||
bool &can_bind,
|
bool &can_bind,
|
||||||
bool &can_combat,
|
bool &can_combat,
|
||||||
bool &can_levitate,
|
bool &can_levitate,
|
||||||
bool &can_castoutdoor,
|
bool &can_castoutdoor,
|
||||||
bool &is_city,
|
bool &is_city,
|
||||||
bool &is_hotzone,
|
bool &is_hotzone,
|
||||||
bool &allow_mercs,
|
bool &allow_mercs,
|
||||||
double &max_movement_update_range,
|
double &max_movement_update_range,
|
||||||
uint8 &zone_type,
|
uint8 &zone_type,
|
||||||
int &ruleset,
|
int &ruleset,
|
||||||
char **map_filename) {
|
char **map_filename) {
|
||||||
|
|
||||||
*map_filename = new char[100];
|
*map_filename = new char[100];
|
||||||
@ -165,8 +166,11 @@ bool ZoneDatabase::GetZoneCFG(
|
|||||||
"fast_regen_endurance, " // 59
|
"fast_regen_endurance, " // 59
|
||||||
"npc_max_aggro_dist, " // 60
|
"npc_max_aggro_dist, " // 60
|
||||||
"max_movement_update_range " // 61
|
"max_movement_update_range " // 61
|
||||||
"FROM zone WHERE zoneidnumber = %i AND version = %i",
|
"FROM zone WHERE zoneidnumber = %i AND version = %i %s",
|
||||||
zoneid, instance_id);
|
zoneid,
|
||||||
|
instance_id,
|
||||||
|
ContentFilterCriteria::apply().c_str()
|
||||||
|
);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success()) {
|
if (!results.Success()) {
|
||||||
strcpy(*map_filename, "default");
|
strcpy(*map_filename, "default");
|
||||||
@ -361,7 +365,7 @@ void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
|
|||||||
char* type_ = nullptr;
|
char* type_ = nullptr;
|
||||||
char* target_ = nullptr;
|
char* target_ = nullptr;
|
||||||
char* bug_ = nullptr;
|
char* bug_ = nullptr;
|
||||||
|
|
||||||
len = strlen(bug_report->reporter_name);
|
len = strlen(bug_report->reporter_name);
|
||||||
if (len) {
|
if (len) {
|
||||||
if (len > 63) // check against db column size
|
if (len > 63) // check against db column size
|
||||||
@ -427,7 +431,7 @@ void ZoneDatabase::RegisterBug(BugReport_Struct* bug_report) {
|
|||||||
safe_delete_array(type_);
|
safe_delete_array(type_);
|
||||||
safe_delete_array(target_);
|
safe_delete_array(target_);
|
||||||
safe_delete_array(bug_);
|
safe_delete_array(bug_);
|
||||||
|
|
||||||
QueryDatabase(query);
|
QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -585,7 +589,7 @@ void ZoneDatabase::RegisterBug(Client* client, BugReport_Struct* bug_report) {
|
|||||||
safe_delete_array(target_name_);
|
safe_delete_array(target_name_);
|
||||||
safe_delete_array(bug_report_);
|
safe_delete_array(bug_report_);
|
||||||
safe_delete_array(system_info_);
|
safe_delete_array(system_info_);
|
||||||
|
|
||||||
auto result = QueryDatabase(query);
|
auto result = QueryDatabase(query);
|
||||||
|
|
||||||
// TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)]
|
// TODO: Entity dumping [RuleB(Bugs, DumpTargetEntity)]
|
||||||
@ -1244,9 +1248,9 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
|
|||||||
"`character_spells` "
|
"`character_spells` "
|
||||||
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
|
"WHERE `id` = %u ORDER BY `slot_id`", character_id);
|
||||||
auto results = database.QueryDatabase(query);
|
auto results = database.QueryDatabase(query);
|
||||||
|
|
||||||
/* Initialize Spells */
|
/* Initialize Spells */
|
||||||
|
|
||||||
memset(pp->spell_book, 0xFF, (sizeof(uint32) * EQEmu::spells::SPELLBOOK_SIZE));
|
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..
|
// We have the ability to block loaded spells by max id on a per-client basis..
|
||||||
@ -1262,7 +1266,7 @@ bool ZoneDatabase::LoadCharacterSpellBook(uint32 character_id, PlayerProfile_Str
|
|||||||
continue;
|
continue;
|
||||||
if (id < 3 || id > SPDAT_RECORDS) // 3 ("Summon Corpse") is the first scribable spell in spells_us.txt
|
if (id < 3 || id > SPDAT_RECORDS) // 3 ("Summon Corpse") is the first scribable spell in spells_us.txt
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
pp->spell_book[idx] = id;
|
pp->spell_book[idx] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1606,11 +1610,11 @@ bool ZoneDatabase::SaveCharacterLeadershipAA(uint32 character_id, PlayerProfile_
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){
|
bool ZoneDatabase::SaveCharacterData(uint32 character_id, uint32 account_id, PlayerProfile_Struct* pp, ExtendedProfile_Struct* m_epp){
|
||||||
|
|
||||||
/* If this is ever zero - the client hasn't fully loaded and potentially crashed during zone */
|
/* If this is ever zero - the client hasn't fully loaded and potentially crashed during zone */
|
||||||
if (account_id <= 0)
|
if (account_id <= 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::string mail_key = database.GetMailKey(character_id);
|
std::string mail_key = database.GetMailKey(character_id);
|
||||||
|
|
||||||
clock_t t = std::clock(); /* Function timer start */
|
clock_t t = std::clock(); /* Function timer start */
|
||||||
@ -4090,9 +4094,9 @@ bool ZoneDatabase::LoadFactionData()
|
|||||||
faction_array = new Faction *[max_faction + 1];
|
faction_array = new Faction *[max_faction + 1];
|
||||||
|
|
||||||
memset(faction_array, 0, (sizeof(Faction*) * (max_faction + 1)));
|
memset(faction_array, 0, (sizeof(Faction*) * (max_faction + 1)));
|
||||||
|
|
||||||
std::vector<size_t> faction_ids;
|
std::vector<size_t> faction_ids;
|
||||||
|
|
||||||
// load factions
|
// load factions
|
||||||
query = "SELECT `id`, `name`, `base` FROM `faction_list`";
|
query = "SELECT `id`, `name`, `base` FROM `faction_list`";
|
||||||
|
|
||||||
@ -4120,7 +4124,7 @@ bool ZoneDatabase::LoadFactionData()
|
|||||||
faction_array[index]->base = atoi(fr_row[2]);
|
faction_array[index]->base = atoi(fr_row[2]);
|
||||||
faction_array[index]->min = MIN_PERSONAL_FACTION;
|
faction_array[index]->min = MIN_PERSONAL_FACTION;
|
||||||
faction_array[index]->max = MAX_PERSONAL_FACTION;
|
faction_array[index]->max = MAX_PERSONAL_FACTION;
|
||||||
|
|
||||||
faction_ids.push_back(index);
|
faction_ids.push_back(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4156,7 +4160,7 @@ bool ZoneDatabase::LoadFactionData()
|
|||||||
else {
|
else {
|
||||||
LogInfo("Unable to load Faction Base data...");
|
LogInfo("Unable to load Faction Base data...");
|
||||||
}
|
}
|
||||||
|
|
||||||
// load race, class and diety modifiers
|
// load race, class and diety modifiers
|
||||||
query = fmt::format("SELECT `faction_id`, `mod`, `mod_name` FROM `faction_list_mod` WHERE `faction_id` IN ({})", faction_id_criteria);
|
query = fmt::format("SELECT `faction_id`, `mod`, `mod_name` FROM `faction_list_mod` WHERE `faction_id` IN ({})", faction_id_criteria);
|
||||||
|
|
||||||
@ -4879,7 +4883,7 @@ uint32 ZoneDatabase::LoadSaylinkID(const char* saylink_text, bool auto_insert)
|
|||||||
{
|
{
|
||||||
if (!saylink_text || saylink_text[0] == '\0')
|
if (!saylink_text || saylink_text[0] == '\0')
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1", saylink_text);
|
std::string query = StringFormat("SELECT `id` FROM `saylink` WHERE `phrase` = '%s' LIMIT 1", saylink_text);
|
||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
@ -4904,6 +4908,6 @@ uint32 ZoneDatabase::SaveSaylinkID(const char* saylink_text)
|
|||||||
auto results = QueryDatabase(query);
|
auto results = QueryDatabase(query);
|
||||||
if (!results.Success())
|
if (!results.Success())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return results.LastInsertedID();
|
return results.LastInsertedID();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,6 +35,9 @@ extern QueryServ* QServ;
|
|||||||
extern WorldServer worldserver;
|
extern WorldServer worldserver;
|
||||||
extern Zone* zone;
|
extern Zone* zone;
|
||||||
|
|
||||||
|
#include "../common/repositories/zone_repository.h"
|
||||||
|
#include "../common/content/world_content_service.h"
|
||||||
|
|
||||||
|
|
||||||
void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
@ -284,6 +287,29 @@ void Client::Handle_OP_ZoneChange(const EQApplicationPacket *app) {
|
|||||||
|
|
||||||
//TODO: ADVENTURE ENTRANCE CHECK
|
//TODO: ADVENTURE ENTRANCE CHECK
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expansion check
|
||||||
|
*/
|
||||||
|
auto zones = ZoneRepository::GetWhere(
|
||||||
|
fmt::format(
|
||||||
|
"expansion <= {} AND short_name = '{}'",
|
||||||
|
(content_service.GetCurrentExpansion() + 1),
|
||||||
|
target_zone_name
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
LogInfo(
|
||||||
|
"Checking zone request [{}] for expansion [{}] ({}) success [{}]",
|
||||||
|
target_zone_name,
|
||||||
|
(content_service.GetCurrentExpansion() + 1),
|
||||||
|
Expansion::ExpansionName[content_service.GetCurrentExpansion()],
|
||||||
|
!zones.empty() ? "true" : "false"
|
||||||
|
);
|
||||||
|
|
||||||
|
if (zones.empty()) {
|
||||||
|
myerror = ZONE_ERROR_NOEXPANSION;
|
||||||
|
}
|
||||||
|
|
||||||
if(myerror == 1) {
|
if(myerror == 1) {
|
||||||
//we have successfully zoned
|
//we have successfully zoned
|
||||||
DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);
|
DoZoneSuccess(zc, target_zone_id, target_instance_id, dest_x, dest_y, dest_z, dest_h, ignorerestrictions);
|
||||||
@ -530,7 +556,7 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
|||||||
heading = m_pp.binds[0].heading;
|
heading = m_pp.binds[0].heading;
|
||||||
|
|
||||||
zonesummon_ignorerestrictions = 1;
|
zonesummon_ignorerestrictions = 1;
|
||||||
LogDebug("Player [{}] has died and will be zoned to bind point in zone: [{}] at LOC x=[{}], y=[{}], z=[{}], heading=[{}]",
|
LogDebug("Player [{}] has died and will be zoned to bind point in zone: [{}] at LOC x=[{}], y=[{}], z=[{}], heading=[{}]",
|
||||||
GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
|
GetName(), pZoneName, m_pp.binds[0].x, m_pp.binds[0].y, m_pp.binds[0].z, m_pp.binds[0].heading);
|
||||||
break;
|
break;
|
||||||
case SummonPC:
|
case SummonPC:
|
||||||
@ -539,8 +565,8 @@ void Client::ZonePC(uint32 zoneID, uint32 instance_id, float x, float y, float z
|
|||||||
SetHeading(heading);
|
SetHeading(heading);
|
||||||
break;
|
break;
|
||||||
case Rewind:
|
case Rewind:
|
||||||
LogDebug("[{}] has requested a /rewind from [{}], [{}], [{}], to [{}], [{}], [{}] in [{}]", GetName(),
|
LogDebug("[{}] has requested a /rewind from [{}], [{}], [{}], to [{}], [{}], [{}] in [{}]", GetName(),
|
||||||
m_Position.x, m_Position.y, m_Position.z,
|
m_Position.x, m_Position.y, m_Position.z,
|
||||||
m_RewindLocation.x, m_RewindLocation.y, m_RewindLocation.z, zone->GetShortName());
|
m_RewindLocation.x, m_RewindLocation.y, m_RewindLocation.z, zone->GetShortName());
|
||||||
m_ZoneSummonLocation = glm::vec3(x, y, z);
|
m_ZoneSummonLocation = glm::vec3(x, y, z);
|
||||||
m_Position = glm::vec4(m_ZoneSummonLocation, 0.0f);
|
m_Position = glm::vec4(m_ZoneSummonLocation, 0.0f);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user