[Base Data] Remove from shared memory and simplify (#4045)

* [Base Data] Remove from shared memory and simplify

- Removes Base Data loading from shared memory and puts it into zone.
- Changes type of `level` and `class` to `uint8_t` from `uint32_t` for consistency since we're renaming fields here anyway.
- Renames `unk1` to `hp_regen` in `base_data` table.
- Renames `unk2` to `end_regen` in `base_data` table.
- These changed fields were already mapped, we just hadn't renamed them for whatever reason.
- Regenerates Base Data repository.
- Adds `#reload base_data` to reload base data in real time.

* Cleanup

* Update shareddb.h

* Cleanup.

* Update shareddb.cpp

* Update main.cpp
This commit is contained in:
Alex King 2024-02-05 18:11:20 -05:00 committed by GitHub
parent b6b779723e
commit 8edf7a07e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 213 additions and 381 deletions

View File

@ -27,6 +27,8 @@
#include "../../common/content/world_content_service.h"
#include "../../common/zone_store.h"
#include "../../common/path_manager.h"
#include "../../common/repositories/base_data_repository.h"
#include "../../common/file.h"
EQEmuLogSys LogSys;
WorldContentService content_service;
@ -255,50 +257,45 @@ void ImportSkillCaps(SharedDatabase *db) {
fclose(f);
}
void ImportBaseData(SharedDatabase *db) {
void ImportBaseData(SharedDatabase *db)
{
LogInfo("Importing Base Data");
std::string file = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
FILE *f = fopen(file.c_str(), "r");
if(!f) {
LogError("Unable to open {} to read, skipping.", file);
return;
const std::string& file_name = fmt::format("{}/import/BaseData.txt", path.GetServerPath());
const auto& file_contents = File::GetContents(file_name);
if (!file_contents.error.empty()) {
LogError("{}", file_contents.error);
}
std::string delete_sql = "DELETE FROM base_data";
db->QueryDatabase(delete_sql);
db->QueryDatabase("DELETE FROM base_data");
char buffer[2048];
while(fgets(buffer, 2048, f)) {
auto split = Strings::Split(buffer, '^');
std::vector<BaseDataRepository::BaseData> v;
if(split.size() < 10) {
auto e = BaseDataRepository::NewEntity();
for (const auto& line: Strings::Split(file_contents.contents, "\n")) {
const auto& line_data = Strings::Split(line, '^');
if (line_data.size() < 10) {
continue;
}
std::string sql;
int level, class_id;
double hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac;
e.level = static_cast<uint8_t>(Strings::ToUnsignedInt(line_data[0]));
e.class_ = static_cast<uint8_t>(Strings::ToUnsignedInt(line_data[1]));
e.hp = Strings::ToFloat(line_data[2]);
e.mana = Strings::ToFloat(line_data[3]);
e.end = Strings::ToFloat(line_data[4]);
e.hp_regen = Strings::ToFloat(line_data[5]);
e.end_regen = Strings::ToFloat(line_data[6]);
e.hp_fac = Strings::ToFloat(line_data[7]);
e.mana_fac = Strings::ToFloat(line_data[8]);
e.end_fac = Strings::ToFloat(line_data[9]);
level = Strings::ToInt(split[0].c_str());
class_id = Strings::ToInt(split[1].c_str());
hp = Strings::ToFloat(split[2].c_str());
mana = Strings::ToFloat(split[3].c_str());
end = Strings::ToFloat(split[4].c_str());
unk1 = Strings::ToFloat(split[5].c_str());
unk2 = Strings::ToFloat(split[6].c_str());
hp_fac = Strings::ToFloat(split[7].c_str());
mana_fac = Strings::ToFloat(split[8].c_str());
end_fac = Strings::ToFloat(split[9].c_str());
sql = StringFormat("INSERT INTO base_data(level, class, hp, mana, end, unk1, unk2, hp_fac, "
"mana_fac, end_fac) VALUES(%d, %d, %f, %f, %f, %f, %f, %f, %f, %f)",
level, class_id, hp, mana, end, unk1, unk2, hp_fac, mana_fac, end_fac);
db->QueryDatabase(sql);
v.emplace_back(e);
}
fclose(f);
BaseDataRepository::InsertMany(*db, v);
}
void ImportDBStrings(SharedDatabase *db) {

View File

@ -491,7 +491,6 @@ SET(repositories
SET(common_headers
additive_lagged_fibonacci_engine.h
base_packet.h
base_data.h
bodytypes.h
classes.h
compression.h

View File

@ -1,34 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __EQEMU_COMMON_BASE_DATA_H
#define __EQEMU_COMMON_BASE_DATA_H
struct BaseDataStruct
{
double base_hp;
double base_mana;
double base_end;
double hp_regen;
double end_regen;
double hp_factor;
double mana_factor;
double endurance_factor;
};
#endif

View File

@ -5253,6 +5253,21 @@ MODIFY COLUMN `name` varchar(200) CHARACTER SET latin1 COLLATE latin1_swedish_ci
ALTER TABLE `ground_spawns`
ADD COLUMN `fix_z` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 AFTER `respawn_timer`;
)"
},
ManifestEntry{
.version = 9258,
.description = "2024_02_04_base_data.sql",
.check = "SHOW COLUMNS FROM `base_data` LIKE `hp_regen`",
.condition = "empty",
.match = "",
.sql = R"(
ALTER TABLE `base_data`
CHANGE COLUMN `unk1` `hp_regen` double NOT NULL AFTER `end`,
CHANGE COLUMN `unk2` `end_regen` double NOT NULL AFTER `hp_regen`,
MODIFY COLUMN `level` tinyint(3) UNSIGNED NOT NULL FIRST,
MODIFY COLUMN `class` tinyint(2) UNSIGNED NOT NULL AFTER `level`;
)",
.content_schema_update = true
}
// -- template; copy/paste this when you need to create a new entry
// ManifestEntry{

View File

@ -19,16 +19,16 @@
class BaseBaseDataRepository {
public:
struct BaseData {
uint32_t level;
uint32_t class_;
double hp;
double mana;
double end;
double unk1;
double unk2;
double hp_fac;
double mana_fac;
double end_fac;
uint8_t level;
uint8_t class_;
double hp;
double mana;
double end;
double hp_regen;
double end_regen;
double hp_fac;
double mana_fac;
double end_fac;
};
static std::string PrimaryKey()
@ -44,8 +44,8 @@ public:
"hp",
"mana",
"end",
"unk1",
"unk2",
"hp_regen",
"end_regen",
"hp_fac",
"mana_fac",
"end_fac",
@ -60,8 +60,8 @@ public:
"hp",
"mana",
"end",
"unk1",
"unk2",
"hp_regen",
"end_regen",
"hp_fac",
"mana_fac",
"end_fac",
@ -105,16 +105,16 @@ public:
{
BaseData e{};
e.level = 0;
e.class_ = 0;
e.hp = 0;
e.mana = 0;
e.end = 0;
e.unk1 = 0;
e.unk2 = 0;
e.hp_fac = 0;
e.mana_fac = 0;
e.end_fac = 0;
e.level = 0;
e.class_ = 0;
e.hp = 0;
e.mana = 0;
e.end = 0;
e.hp_regen = 0;
e.end_regen = 0;
e.hp_fac = 0;
e.mana_fac = 0;
e.end_fac = 0;
return e;
}
@ -151,16 +151,16 @@ public:
if (results.RowCount() == 1) {
BaseData e{};
e.level = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.unk1 = row[5] ? strtod(row[5], nullptr) : 0;
e.unk2 = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
e.level = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.hp_regen = row[5] ? strtod(row[5], nullptr) : 0;
e.end_regen = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
return e;
}
@ -199,8 +199,8 @@ public:
v.push_back(columns[2] + " = " + std::to_string(e.hp));
v.push_back(columns[3] + " = " + std::to_string(e.mana));
v.push_back(columns[4] + " = " + std::to_string(e.end));
v.push_back(columns[5] + " = " + std::to_string(e.unk1));
v.push_back(columns[6] + " = " + std::to_string(e.unk2));
v.push_back(columns[5] + " = " + std::to_string(e.hp_regen));
v.push_back(columns[6] + " = " + std::to_string(e.end_regen));
v.push_back(columns[7] + " = " + std::to_string(e.hp_fac));
v.push_back(columns[8] + " = " + std::to_string(e.mana_fac));
v.push_back(columns[9] + " = " + std::to_string(e.end_fac));
@ -230,8 +230,8 @@ public:
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.end));
v.push_back(std::to_string(e.unk1));
v.push_back(std::to_string(e.unk2));
v.push_back(std::to_string(e.hp_regen));
v.push_back(std::to_string(e.end_regen));
v.push_back(std::to_string(e.hp_fac));
v.push_back(std::to_string(e.mana_fac));
v.push_back(std::to_string(e.end_fac));
@ -269,8 +269,8 @@ public:
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.end));
v.push_back(std::to_string(e.unk1));
v.push_back(std::to_string(e.unk2));
v.push_back(std::to_string(e.hp_regen));
v.push_back(std::to_string(e.end_regen));
v.push_back(std::to_string(e.hp_fac));
v.push_back(std::to_string(e.mana_fac));
v.push_back(std::to_string(e.end_fac));
@ -307,16 +307,16 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
BaseData e{};
e.level = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.unk1 = row[5] ? strtod(row[5], nullptr) : 0;
e.unk2 = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
e.level = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.hp_regen = row[5] ? strtod(row[5], nullptr) : 0;
e.end_regen = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
all_entries.push_back(e);
}
@ -341,16 +341,16 @@ public:
for (auto row = results.begin(); row != results.end(); ++row) {
BaseData e{};
e.level = row[0] ? static_cast<uint32_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint32_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.unk1 = row[5] ? strtod(row[5], nullptr) : 0;
e.unk2 = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
e.level = row[0] ? static_cast<uint8_t>(strtoul(row[0], nullptr, 10)) : 0;
e.class_ = row[1] ? static_cast<uint8_t>(strtoul(row[1], nullptr, 10)) : 0;
e.hp = row[2] ? strtod(row[2], nullptr) : 0;
e.mana = row[3] ? strtod(row[3], nullptr) : 0;
e.end = row[4] ? strtod(row[4], nullptr) : 0;
e.hp_regen = row[5] ? strtod(row[5], nullptr) : 0;
e.end_regen = row[6] ? strtod(row[6], nullptr) : 0;
e.hp_fac = row[7] ? strtod(row[7], nullptr) : 0;
e.mana_fac = row[8] ? strtod(row[8], nullptr) : 0;
e.end_fac = row[9] ? strtod(row[9], nullptr) : 0;
all_entries.push_back(e);
}
@ -430,8 +430,8 @@ public:
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.end));
v.push_back(std::to_string(e.unk1));
v.push_back(std::to_string(e.unk2));
v.push_back(std::to_string(e.hp_regen));
v.push_back(std::to_string(e.end_regen));
v.push_back(std::to_string(e.hp_fac));
v.push_back(std::to_string(e.mana_fac));
v.push_back(std::to_string(e.end_fac));
@ -462,8 +462,8 @@ public:
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.end));
v.push_back(std::to_string(e.unk1));
v.push_back(std::to_string(e.unk2));
v.push_back(std::to_string(e.hp_regen));
v.push_back(std::to_string(e.end_regen));
v.push_back(std::to_string(e.hp_fac));
v.push_back(std::to_string(e.mana_fac));
v.push_back(std::to_string(e.end_fac));

View File

@ -253,6 +253,7 @@
#define ServerOP_ReloadDataBucketsCache 0x4125
#define ServerOP_ReloadFactions 0x4126
#define ServerOP_ReloadLoot 0x4127
#define ServerOP_ReloadBaseData 0x4128
#define ServerOP_CZDialogueWindow 0x4500
#define ServerOP_CZLDoNUpdate 0x4501

View File

@ -1974,117 +1974,6 @@ void SharedDatabase::LoadSpells(void *data, int max_spells) {
LoadDamageShieldTypes(sp, max_spells);
}
int SharedDatabase::GetMaxBaseDataLevel() {
const std::string query = "SELECT MAX(level) FROM base_data";
auto results = QueryDatabase(query);
if (!results.Success()) {
return -1;
}
if (results.RowCount() == 0)
return -1;
auto& row = results.begin();
return Strings::ToInt(row[0]);
}
bool SharedDatabase::LoadBaseData(const std::string &prefix) {
base_data_mmf.reset(nullptr);
try {
const auto Config = EQEmuConfig::get();
EQ::IPCMutex mutex("base_data");
mutex.Lock();
std::string file_name = fmt::format("{}/{}{}", path.GetSharedMemoryPath(), prefix, std::string("base_data"));
base_data_mmf = std::make_unique<EQ::MemoryMappedFile>(file_name);
mutex.Unlock();
LogInfo("Loaded base data via shared memory");
} catch(std::exception& ex) {
LogError("Error Loading Base Data: {}", ex.what());
return false;
}
return true;
}
void SharedDatabase::LoadBaseData(void *data, int max_level) {
char *base_ptr = static_cast<char*>(data);
const std::string query = "SELECT * FROM base_data ORDER BY level, class ASC";
auto results = QueryDatabase(query);
if (!results.Success()) {
return;
}
for (auto& row = results.begin(); row != results.end(); ++row) {
const int lvl = Strings::ToInt(row[0]);
const int cl = Strings::ToInt(row[1]);
if(lvl <= 0) {
LogError("Non fatal error: base_data.level <= 0, ignoring.");
continue;
}
if(lvl >= max_level) {
LogError("Non fatal error: base_data.level >= max_level, ignoring.");
continue;
}
if(cl <= 0) {
LogError("Non fatal error: base_data.cl <= 0, ignoring.");
continue;
}
if(cl > 16) {
LogError("Non fatal error: base_data.class > 16, ignoring.");
continue;
}
BaseDataStruct *bd = reinterpret_cast<BaseDataStruct*>(base_ptr + (((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct)));
bd->base_hp = Strings::ToFloat(row[2]);
bd->base_mana = Strings::ToFloat(row[3]);
bd->base_end = Strings::ToFloat(row[4]);
bd->hp_regen = Strings::ToFloat(row[5]);
bd->end_regen = Strings::ToFloat(row[6]);
bd->hp_factor = Strings::ToFloat(row[7]);
bd->mana_factor = Strings::ToFloat(row[8]);
bd->endurance_factor = Strings::ToFloat(row[9]);
}
}
const BaseDataStruct* SharedDatabase::GetBaseData(int lvl, int cl) const
{
if(!base_data_mmf) {
return nullptr;
}
if(lvl <= 0) {
return nullptr;
}
if(cl <= 0) {
return nullptr;
}
if(cl > 16) {
return nullptr;
}
char *base_ptr = static_cast<char*>(base_data_mmf->Get());
const uint32 offset = ((16 * (lvl - 1)) + (cl - 1)) * sizeof(BaseDataStruct);
if(offset >= base_data_mmf->Size()) {
return nullptr;
}
const BaseDataStruct *bd = reinterpret_cast<BaseDataStruct*>(base_ptr + offset);
return bd;
}
void SharedDatabase::LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message) {
const std::string query = StringFormat("SELECT `inspect_message` FROM `character_inspect_messages` WHERE `id` = %u LIMIT 1", character_id);
auto results = QueryDatabase(query);

View File

@ -24,7 +24,6 @@
#include "database.h"
#include "skills.h"
#include "spdat.h"
#include "base_data.h"
#include "fixed_memory_hash_set.h"
#include "fixed_memory_variable_hash_set.h"
#include "say_link.h"
@ -35,7 +34,6 @@
#include <memory>
class EvolveInfo;
struct BaseDataStruct;
struct InspectMessage_Struct;
struct PlayerProfile_Struct;
struct SPDat_Spell_Struct;
@ -180,14 +178,6 @@ public:
uint32 GetSharedSpellsCount() { return m_shared_spells_count; }
uint32 GetSpellsCount();
/**
* basedata
*/
int GetMaxBaseDataLevel();
bool LoadBaseData(const std::string &prefix);
void LoadBaseData(void *data, int max_level);
const BaseDataStruct *GetBaseData(int lvl, int cl) const;
std::string CreateItemLink(uint32 item_id) const
{
EQ::SayLinkEngine linker;
@ -206,7 +196,6 @@ protected:
std::unique_ptr<EQ::FixedMemoryHashSet<NPCFactionList>> faction_hash;
std::unique_ptr<EQ::MemoryMappedFile> faction_associations_mmf;
std::unique_ptr<EQ::FixedMemoryHashSet<FactionAssociations>> faction_associations_hash;
std::unique_ptr<EQ::MemoryMappedFile> base_data_mmf;
std::unique_ptr<EQ::MemoryMappedFile> spells_mmf;
public:

View File

@ -42,7 +42,7 @@
* Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt
*/
#define CURRENT_BINARY_DATABASE_VERSION 9257
#define CURRENT_BINARY_DATABASE_VERSION 9258
#define CURRENT_BINARY_BOTS_DATABASE_VERSION 9042

View File

@ -1,7 +1,6 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
SET(shared_memory_sources
base_data.cpp
items.cpp
main.cpp
spells.cpp
@ -9,7 +8,6 @@ SET(shared_memory_sources
)
SET(shared_memory_headers
base_data.h
items.h
spells.h
skill_caps.h

View File

@ -1,44 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "base_data.h"
#include "../common/global_define.h"
#include "../common/shareddb.h"
#include "../common/ipc_mutex.h"
#include "../common/memory_mapped_file.h"
#include "../common/eqemu_exception.h"
void LoadBaseData(SharedDatabase *database, const std::string &prefix) {
EQ::IPCMutex mutex("base_data");
mutex.Lock();
int records = (database->GetMaxBaseDataLevel() + 1);
if(records == 0) {
EQ_EXCEPT("Shared Memory", "Unable to get base data from the database.");
}
uint32 size = records * 16 * sizeof(BaseDataStruct);
auto Config = EQEmuConfig::get();
std::string file_name = Config->SharedMemDir + prefix + std::string("base_data");
EQ::MemoryMappedFile mmf(file_name, size);
mmf.ZeroFile();
void *ptr = mmf.Get();
database->LoadBaseData(ptr, records);
mutex.Unlock();
}

View File

@ -1,28 +0,0 @@
/* EQEMu: Everquest Server Emulator
Copyright (C) 2001-2013 EQEMu Development Team (http://eqemulator.net)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __EQEMU_SHARED_MEMORY_BASE_DATA_H
#define __EQEMU_SHARED_MEMORY_BASE_DATA_H
#include <string>
#include "../common/eqemu_config.h"
class SharedDatabase;
void LoadBaseData(SharedDatabase *database, const std::string &prefix);
#endif

View File

@ -30,7 +30,6 @@
#include "items.h"
#include "skill_caps.h"
#include "spells.h"
#include "base_data.h"
#include "../common/content/world_content_service.h"
#include "../common/zone_store.h"
#include "../common/path_manager.h"
@ -180,22 +179,15 @@ int main(int argc, char **argv)
std::string hotfix_name = "";
bool load_all = true;
bool load_items = false;
bool load_skill_caps = false;
bool load_spells = false;
bool load_bd = false;
bool load_all = true;
bool load_items = false;
bool load_loot = false;
bool load_skill_caps = false;
bool load_spells = false;
if (argc > 1) {
for (int i = 1; i < argc; ++i) {
switch (argv[i][0]) {
case 'b':
if (strcasecmp("base_data", argv[i]) == 0) {
load_bd = true;
load_all = false;
}
break;
case 'i':
if (strcasecmp("items", argv[i]) == 0) {
load_items = true;
@ -263,16 +255,6 @@ int main(int argc, char **argv)
}
}
if (load_all || load_bd) {
LogInfo("Loading base data");
try {
LoadBaseData(&content_db, hotfix_name);
} catch (std::exception &ex) {
LogError("{}", ex.what());
return 1;
}
}
LogSys.CloseFileLogs();
return 0;
}

View File

@ -137,6 +137,7 @@ struct Reload {
std::vector<Reload> reload_types = {
Reload{.command = "aa", .opcode = ServerOP_ReloadAAData, .desc = "Alternate Advancement"},
Reload{.command = "alternate_currencies", .opcode = ServerOP_ReloadAlternateCurrencies, .desc = "Alternate Currencies"},
Reload{.command = "base_data", .opcode = ServerOP_ReloadBaseData, .desc = "Base Data"},
Reload{.command = "blocked_spells", .opcode = ServerOP_ReloadBlockedSpells, .desc = "Blocked Spells"},
Reload{.command = "commands", .opcode = ServerOP_ReloadCommands, .desc = "Commands"},
Reload{.command = "data_buckets_cache", .opcode = ServerOP_ReloadDataBucketsCache, .desc = "Data Buckets Cache"},

View File

@ -1385,6 +1385,7 @@ void ZoneServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) {
case ServerOP_RefreshCensorship:
case ServerOP_ReloadAAData:
case ServerOP_ReloadAlternateCurrencies:
case ServerOP_ReloadBaseData:
case ServerOP_ReloadBlockedSpells:
case ServerOP_ReloadCommands:
case ServerOP_ReloadDoors:

View File

@ -160,6 +160,7 @@ SET(zone_sources
zone.cpp
zone_config.cpp
zonedb.cpp
zone_base_data.cpp
zone_event_scheduler.cpp
zone_npc_factions.cpp
zone_reload.cpp

View File

@ -9087,6 +9087,7 @@ void Client::ShowDevToolsMenu()
*/
menu_reload_one += Saylink::Silent("#reload aa", "AAs");
menu_reload_one += " | " + Saylink::Silent("#reload alternate_currencies", "Alternate Currencies");
menu_reload_one += " | " + Saylink::Silent("#reload base_data", "Base Data");
menu_reload_one += " | " + Saylink::Silent("#reload blocked_spells", "Blocked Spells");
menu_reload_two += Saylink::Silent("#reload commands", "Commands");
@ -11019,6 +11020,16 @@ void Client::SendReloadCommandMessages() {
).c_str()
);
auto base_data_link = Saylink::Silent("#reload base_data");
Message(
Chat::White,
fmt::format(
"Usage: {} - Reloads Base Data globally",
base_data_link
).c_str()
);
auto blocked_spells_link = Saylink::Silent("#reload blocked_spells");
Message(

View File

@ -237,9 +237,10 @@ int64 Client::CalcHPRegen(bool bCombat)
item_regen += aabonuses.HPRegen;
int64 base = 0;
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data)
base = static_cast<int>(base_data->hp_regen);
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
base = static_cast<int>(base_data.hp_regen);
}
auto level = GetLevel();
bool skip_innate = false;
@ -486,9 +487,9 @@ int64 Client::CalcBaseHP()
stats += 255;
}
base_hp = 5;
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base_hp += base_data->base_hp + (base_data->hp_factor * stats);
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
base_hp += base_data.hp + (base_data.hp_fac * stats);
base_hp += itembonuses.heroic_max_hp;
}
}
@ -575,10 +576,9 @@ int64 Client::CalcBaseMana()
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana +
(ConvertedWisInt * base_data->mana_factor) + itembonuses.heroic_max_mana;
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
}
}
else {
@ -608,10 +608,9 @@ int64 Client::CalcBaseMana()
}
ConvertedWisInt = (3 * over200 - 300) / 2 + over200;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
max_m = base_data->base_mana +
(ConvertedWisInt * base_data->mana_factor) + itembonuses.heroic_max_mana;
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
max_m = base_data.mana + (ConvertedWisInt * base_data.mana_fac) + itembonuses.heroic_max_mana;
}
}
else {
@ -1639,9 +1638,9 @@ int64 Client::CalcBaseEndurance()
else if (stats > 100.0f) {
stats = 2.5f * (stats - 100.0f) + 100.0f;
}
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base_end = base_data->base_end + itembonuses.heroic_max_end + (base_data->endurance_factor * static_cast<int>(stats));
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
base_end = base_data.end + itembonuses.heroic_max_end + (base_data.end_fac * static_cast<int>(stats));
}
}
else {
@ -1676,9 +1675,9 @@ int64 Client::CalcEnduranceRegen(bool bCombat)
{
int64 base = 0;
if (!IsStarved()) {
auto base_data = database.GetBaseData(GetLevel(), GetClass());
if (base_data) {
base = static_cast<int>(base_data->end_regen);
auto base_data = zone->GetBaseData(GetLevel(), GetClass());
if (base_data.level == GetLevel()) {
base = static_cast<int>(base_data.end_regen);
if (!auto_attack && base > 0)
base += base / 2;
}

View File

@ -15,6 +15,7 @@ void command_reload(Client *c, const Seperator *sep)
bool is_rq_alias = sep->arg[0] && Strings::Contains(command, "#rq");
bool is_aa = !strcasecmp(sep->arg[1], "aa");
bool is_alternate_currencies = !strcasecmp(sep->arg[1], "alternate_currencies");
bool is_base_data = !strcasecmp(sep->arg[1], "base_data");
bool is_blocked_spells = !strcasecmp(sep->arg[1], "blocked_spells");
bool is_commands = !strcasecmp(sep->arg[1], "commands");
bool is_content_flags = !strcasecmp(sep->arg[1], "content_flags");
@ -46,6 +47,7 @@ void command_reload(Client *c, const Seperator *sep)
if (
!is_aa &&
!is_alternate_currencies &&
!is_base_data &&
!is_blocked_spells &&
!is_commands &&
!is_content_flags &&
@ -86,6 +88,9 @@ void command_reload(Client *c, const Seperator *sep)
} else if (is_alternate_currencies) {
c->Message(Chat::White, "Attempting to reload Alternate Currencies globally.");
pack = new ServerPacket(ServerOP_ReloadAlternateCurrencies, 0);
} else if (is_base_data) {
c->Message(Chat::White, "Attempting to reload Base Data globally.");
pack = new ServerPacket(ServerOP_ReloadBaseData, 0);
} else if (is_blocked_spells) {
c->Message(Chat::White, "Attempting to reload Blocked Spells globally.");
pack = new ServerPacket(ServerOP_ReloadBlockedSpells, 0);

View File

@ -381,11 +381,6 @@ int main(int argc, char **argv)
return 1;
}
if (!database.LoadBaseData(hotfix_name)) {
LogError("Loading base data failed!");
return 1;
}
guild_mgr.LoadGuilds();
content_db.LoadFactionData();
title_manager.LoadTitles();

View File

@ -1957,6 +1957,15 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
}
break;
}
case ServerOP_ReloadBaseData:
{
if (zone && zone->IsLoaded()) {
zone->SendReloadMessage("Base Data");
zone->ReloadBaseData();
}
break;
}
case ServerOP_ReloadBlockedSpells:
{
if (zone && zone->IsLoaded()) {
@ -3525,11 +3534,6 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p)
if (!content_db.LoadSpells(hotfix_name, &SPDAT_RECORDS, &spells)) {
LogError("Loading spells failed!");
}
LogInfo("Loading base data");
if (!content_db.LoadBaseData(hotfix_name)) {
LogError("Loading base data failed!");
}
break;
}
case ServerOP_CZClientMessageString:

View File

@ -1177,6 +1177,8 @@ bool Zone::Init(bool is_static) {
content_db.LoadGlobalLoot();
LoadBaseData();
//Load merchant data
LoadMerchants();

View File

@ -45,6 +45,7 @@
#include "../common/repositories/loottable_entries_repository.h"
#include "../common/repositories/lootdrop_repository.h"
#include "../common/repositories/lootdrop_entries_repository.h"
#include "../common/repositories/base_data_repository.h"
struct EXPModifier
{
@ -439,6 +440,12 @@ public:
LootdropRepository::Lootdrop GetLootdrop(const uint32 lootdrop_id) const;
std::vector<LootdropEntriesRepository::LootdropEntries> GetLootdropEntries(const uint32 lootdrop_id) const;
// Base Data
inline void ClearBaseData() { m_base_data.clear(); };
BaseDataRepository::BaseData GetBaseData(uint8 level, uint8 class_id);
void LoadBaseData();
void ReloadBaseData();
private:
bool allow_mercs;
bool can_bind;
@ -499,6 +506,9 @@ private:
std::vector<LoottableEntriesRepository::LoottableEntries> m_loottable_entries = {};
std::vector<LootdropRepository::Lootdrop> m_lootdrops = {};
std::vector<LootdropEntriesRepository::LootdropEntries> m_lootdrop_entries = {};
// Base Data
std::vector<BaseDataRepository::BaseData> m_base_data = { };
};
#endif

39
zone/zone_base_data.cpp Normal file
View File

@ -0,0 +1,39 @@
#include "zone.h"
BaseDataRepository::BaseData Zone::GetBaseData(uint8 level, uint8 class_id)
{
for (const auto& e : m_base_data) {
if (e.level == level && e.class_ == class_id) {
return e;
}
}
return BaseDataRepository::NewEntity();
}
void Zone::LoadBaseData()
{
const auto& l = BaseDataRepository::All(content_db);
m_base_data.reserve(l.size());
for (const auto& e : l) {
if (e.level < 1 || !IsPlayerClass(e.class_)) {
continue;
}
m_base_data.emplace_back(e);
}
LogInfo(
"Loaded [{}] Base Data Entr{}",
l.size(),
l.size() != 1 ? "ies" : "y"
);
}
void Zone::ReloadBaseData()
{
ClearBaseData();
LoadBaseData();
}