[Pets] Convert Load/Save of Pet Info to Repositories (#3853)

* [Pets] Convert Save/Load of Pet Info to Repositories

- Convert `LoadPetInfo` to repositories.
- `SavePetInfo` already used repositories, cleanup logic.

* Update repositories.

* Update zonedb.cpp
This commit is contained in:
Alex King 2024-01-07 00:59:02 -05:00 committed by GitHub
parent 1227f35382
commit f3de3e8c31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 393 additions and 158 deletions

View File

@ -716,6 +716,16 @@ namespace Language {
constexpr uint8 MaxValue = 100; constexpr uint8 MaxValue = 100;
} }
namespace PetInfoType {
constexpr int Current = 0;
constexpr int Suspended = 1;
}
namespace BuffEffectType {
constexpr uint8 None = 0;
constexpr uint8 Buff = 2;
constexpr uint8 InverseBuff = 4;
}
typedef enum { typedef enum {
FilterNone = 0, FilterNone = 0,

View File

@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only * Any modifications to base repositories are to be made by the generator only
* *
* @generator ./utils/scripts/generators/repository-generator.pl * @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories * @docs https://docs.eqemu.io/developer/repositories
*/ */
#ifndef EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H #ifndef EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H
@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseCharacterPetBuffsRepository { class BaseCharacterPetBuffsRepository {
public: public:
struct CharacterPetBuffs { struct CharacterPetBuffs {
@ -144,8 +145,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
character_pet_buffs_id character_pet_buffs_id
) )
); );
@ -418,6 +420,82 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
} }
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const CharacterPetBuffs &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back("'" + Strings::Escape(e.castername) + "'");
v.push_back(std::to_string(e.ticsremaining));
v.push_back(std::to_string(e.counters));
v.push_back(std::to_string(e.numhits));
v.push_back(std::to_string(e.rune));
v.push_back(std::to_string(e.instrument_mod));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<CharacterPetBuffs> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.caster_level));
v.push_back("'" + Strings::Escape(e.castername) + "'");
v.push_back(std::to_string(e.ticsremaining));
v.push_back(std::to_string(e.counters));
v.push_back(std::to_string(e.numhits));
v.push_back(std::to_string(e.rune));
v.push_back(std::to_string(e.instrument_mod));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
}; };
#endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H #endif //EQEMU_BASE_CHARACTER_PET_BUFFS_REPOSITORY_H

View File

@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only * Any modifications to base repositories are to be made by the generator only
* *
* @generator ./utils/scripts/generators/repository-generator.pl * @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories * @docs https://docs.eqemu.io/developer/repositories
*/ */
#ifndef EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H #ifndef EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H
@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseCharacterPetInfoRepository { class BaseCharacterPetInfoRepository {
public: public:
struct CharacterPetInfo { struct CharacterPetInfo {
@ -136,8 +137,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
character_pet_info_id character_pet_info_id
) )
); );
@ -398,6 +400,78 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
} }
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const CharacterPetInfo &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back("'" + Strings::Escape(e.petname) + "'");
v.push_back(std::to_string(e.petpower));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.size));
v.push_back(std::to_string(e.taunting));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<CharacterPetInfo> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back("'" + Strings::Escape(e.petname) + "'");
v.push_back(std::to_string(e.petpower));
v.push_back(std::to_string(e.spell_id));
v.push_back(std::to_string(e.hp));
v.push_back(std::to_string(e.mana));
v.push_back(std::to_string(e.size));
v.push_back(std::to_string(e.taunting));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
}; };
#endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H #endif //EQEMU_BASE_CHARACTER_PET_INFO_REPOSITORY_H

View File

@ -6,7 +6,7 @@
* Any modifications to base repositories are to be made by the generator only * Any modifications to base repositories are to be made by the generator only
* *
* @generator ./utils/scripts/generators/repository-generator.pl * @generator ./utils/scripts/generators/repository-generator.pl
* @docs https://eqemu.gitbook.io/server/in-development/developer-area/repositories * @docs https://docs.eqemu.io/developer/repositories
*/ */
#ifndef EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H #ifndef EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H
@ -16,6 +16,7 @@
#include "../../strings.h" #include "../../strings.h"
#include <ctime> #include <ctime>
class BaseCharacterPetInventoryRepository { class BaseCharacterPetInventoryRepository {
public: public:
struct CharacterPetInventory { struct CharacterPetInventory {
@ -116,8 +117,9 @@ public:
{ {
auto results = db.QueryDatabase( auto results = db.QueryDatabase(
fmt::format( fmt::format(
"{} WHERE id = {} LIMIT 1", "{} WHERE {} = {} LIMIT 1",
BaseSelect(), BaseSelect(),
PrimaryKey(),
character_pet_inventory_id character_pet_inventory_id
) )
); );
@ -348,6 +350,68 @@ public:
return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0); return (results.Success() && results.begin()[0] ? strtoll(results.begin()[0], nullptr, 10) : 0);
} }
static std::string BaseReplace()
{
return fmt::format(
"REPLACE INTO {} ({}) ",
TableName(),
ColumnsRaw()
);
}
static int ReplaceOne(
Database& db,
const CharacterPetInventory &e
)
{
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.item_id));
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES ({})",
BaseReplace(),
Strings::Implode(",", v)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
static int ReplaceMany(
Database& db,
const std::vector<CharacterPetInventory> &entries
)
{
std::vector<std::string> insert_chunks;
for (auto &e: entries) {
std::vector<std::string> v;
v.push_back(std::to_string(e.char_id));
v.push_back(std::to_string(e.pet));
v.push_back(std::to_string(e.slot));
v.push_back(std::to_string(e.item_id));
insert_chunks.push_back("(" + Strings::Implode(",", v) + ")");
}
std::vector<std::string> v;
auto results = db.QueryDatabase(
fmt::format(
"{} VALUES {}",
BaseReplace(),
Strings::Implode(",", insert_chunks)
)
);
return (results.Success() ? results.RowsAffected() : 0);
}
}; };
#endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H #endif //EQEMU_BASE_CHARACTER_PET_INVENTORY_REPOSITORY_H

View File

@ -382,7 +382,7 @@ public:
inline ExtendedProfile_Struct& GetEPP() { return m_epp; } inline ExtendedProfile_Struct& GetEPP() { return m_epp; }
inline EQ::InventoryProfile& GetInv() { return m_inv; } inline EQ::InventoryProfile& GetInv() { return m_inv; }
inline const EQ::InventoryProfile& GetInv() const { return m_inv; } inline const EQ::InventoryProfile& GetInv() const { return m_inv; }
inline PetInfo* GetPetInfo(uint16 pet) { return (pet==1)?&m_suspendedminion:&m_petinfo; } inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; }
inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; }
inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; }
void ReloadExpansionProfileSetting(); void ReloadExpansionProfileSetting();

View File

@ -3121,124 +3121,136 @@ void ZoneDatabase::LoadAuras(Client *c)
void ZoneDatabase::SavePetInfo(Client *client) void ZoneDatabase::SavePetInfo(Client *client)
{ {
PetInfo *petinfo = nullptr; PetInfo* p = nullptr;
// Pet Info std::vector<CharacterPetInfoRepository::CharacterPetInfo> pet_infos;
std::vector<CharacterPetInfoRepository::CharacterPetInfo> pet_infos = {}; auto pet_info = CharacterPetInfoRepository::NewEntity();
CharacterPetInfoRepository::CharacterPetInfo pet_info = {};
// Pet buffs std::vector<CharacterPetBuffsRepository::CharacterPetBuffs> pet_buffs;
std::vector<CharacterPetBuffsRepository::CharacterPetBuffs> pet_buffs = {}; auto pet_buff = CharacterPetBuffsRepository::NewEntity();
CharacterPetBuffsRepository::CharacterPetBuffs pet_buff = {};
// Pet inventory std::vector<CharacterPetInventoryRepository::CharacterPetInventory> inventory;
std::vector<CharacterPetInventoryRepository::CharacterPetInventory> inventory = {}; auto item = CharacterPetInventoryRepository::NewEntity();
CharacterPetInventoryRepository::CharacterPetInventory item = {};
// Loop through pet types for (int pet_info_type = PetInfoType::Current; pet_info_type <= PetInfoType::Suspended; pet_info_type++) {
for (int pet = 0; pet < 2; pet++) { p = client->GetPetInfo(pet_info_type);
petinfo = client->GetPetInfo(pet); if (!p) {
if (!petinfo) {
continue; continue;
} }
// build pet info into struct
pet_info.char_id = client->CharacterID(); pet_info.char_id = client->CharacterID();
pet_info.pet = pet; pet_info.pet = pet_info_type;
pet_info.petname = petinfo->Name; pet_info.petname = p->Name;
pet_info.petpower = petinfo->petpower; pet_info.petpower = p->petpower;
pet_info.spell_id = petinfo->SpellID; pet_info.spell_id = p->SpellID;
pet_info.hp = petinfo->HP; pet_info.hp = p->HP;
pet_info.mana = petinfo->Mana; pet_info.mana = p->Mana;
pet_info.size = petinfo->size; pet_info.size = p->size;
pet_info.taunting = (petinfo->taunting) ? 1 : 0; pet_info.taunting = p->taunting ? 1 : 0;
// add pet info to vector
pet_infos.push_back(pet_info); pet_infos.push_back(pet_info);
// build pet buffs into struct uint32 pet_buff_count = 0;
int pet_buff_count = 0;
// Guard against setting the maximum pet slots above the client allowed maximum.
int max_slots = RuleI(Spells, MaxTotalSlotsPET) > PET_BUFF_COUNT ? PET_BUFF_COUNT : RuleI(Spells, MaxTotalSlotsPET);
// count pet buffs const uint32 max_slots = (
for (int index = 0; index < max_slots; index++) { RuleI(Spells, MaxTotalSlotsPET) > PET_BUFF_COUNT ?
if (!IsValidSpell(petinfo->Buffs[index].spellid)) { PET_BUFF_COUNT :
RuleI(Spells, MaxTotalSlotsPET)
);
for (int slot_id = 0; slot_id < max_slots; slot_id++) {
if (!IsValidSpell(p->Buffs[slot_id].spellid)) {
continue; continue;
} }
pet_buff_count++; pet_buff_count++;
} }
// reserve space for pet buffs
pet_buffs.reserve(pet_buff_count); pet_buffs.reserve(pet_buff_count);
// loop through pet buffs for (int slot_id = 0; slot_id < max_slots; slot_id++) {
for (int index = 0; index < max_slots; index++) { if (!IsValidSpell(p->Buffs[slot_id].spellid)) {
if (!IsValidSpell(petinfo->Buffs[index].spellid)) {
continue; continue;
} }
pet_buff.char_id = client->CharacterID(); pet_buff.char_id = client->CharacterID();
pet_buff.pet = pet; pet_buff.pet = pet_info_type;
pet_buff.slot = index; pet_buff.slot = slot_id;
pet_buff.spell_id = petinfo->Buffs[index].spellid; pet_buff.spell_id = p->Buffs[slot_id].spellid;
pet_buff.caster_level = petinfo->Buffs[index].level; pet_buff.caster_level = p->Buffs[slot_id].level;
pet_buff.ticsremaining = petinfo->Buffs[index].duration; pet_buff.ticsremaining = p->Buffs[slot_id].duration;
pet_buff.counters = petinfo->Buffs[index].counters; pet_buff.counters = p->Buffs[slot_id].counters;
pet_buff.instrument_mod = petinfo->Buffs[index].bard_modifier; pet_buff.instrument_mod = p->Buffs[slot_id].bard_modifier;
// add pet buffs to vector
pet_buffs.push_back(pet_buff); pet_buffs.push_back(pet_buff);
} }
// build pet inventory into struct uint32 pet_inventory_count = 0;
int pet_inventory_count = 0;
for (int index = EQ::invslot::EQUIPMENT_BEGIN; index <= EQ::invslot::EQUIPMENT_END; index++) { for (
if (!petinfo->Items[index]) { int slot_id = EQ::invslot::EQUIPMENT_BEGIN;
slot_id <= EQ::invslot::EQUIPMENT_END;
slot_id++
) {
if (!p->Items[slot_id]) {
continue; continue;
} }
pet_inventory_count++; pet_inventory_count++;
} }
// reserve space for pet inventory
inventory.reserve(pet_inventory_count); inventory.reserve(pet_inventory_count);
// loop through pet inventory for (
for (int index = EQ::invslot::EQUIPMENT_BEGIN; index <= EQ::invslot::EQUIPMENT_END; index++) { int slot_id = EQ::invslot::EQUIPMENT_BEGIN;
if (!petinfo->Items[index]) { slot_id <= EQ::invslot::EQUIPMENT_END;
slot_id++
) {
if (!p->Items[slot_id]) {
continue; continue;
} }
item.char_id = client->CharacterID(); item.char_id = client->CharacterID();
item.pet = pet; item.pet = pet_info_type;
item.slot = index; item.slot = slot_id;
item.item_id = petinfo->Items[index]; item.item_id = p->Items[slot_id];
// add pet inventory to vector
inventory.push_back(item); inventory.push_back(item);
} }
} }
// Delete existing pet info CharacterPetInfoRepository::DeleteWhere(
CharacterPetInfoRepository::DeleteWhere(database, fmt::format("char_id = {}", client->CharacterID())); database,
fmt::format(
"`char_id` = {}",
client->CharacterID()
)
);
// insert pet info into database
if (!pet_infos.empty()) { if (!pet_infos.empty()) {
CharacterPetInfoRepository::InsertMany(database, pet_infos); CharacterPetInfoRepository::InsertMany(database, pet_infos);
} }
// Delete existing pet buffs CharacterPetBuffsRepository::DeleteWhere(
CharacterPetBuffsRepository::DeleteWhere(database, fmt::format("char_id = {}", client->CharacterID())); database,
fmt::format(
"`char_id` = {}",
client->CharacterID()
)
);
// insert pet buffs into database
if (!pet_buffs.empty()) { if (!pet_buffs.empty()) {
CharacterPetBuffsRepository::InsertMany(database, pet_buffs); CharacterPetBuffsRepository::InsertMany(database, pet_buffs);
} }
// Delete existing pet inventory CharacterPetInventoryRepository::DeleteWhere(
CharacterPetInventoryRepository::DeleteWhere(database, fmt::format("char_id = {}", client->CharacterID())); database,
fmt::format(
"`char_id` = {}",
client->CharacterID()
)
);
// insert pet inventory into database
if (!inventory.empty()) { if (!inventory.empty()) {
CharacterPetInventoryRepository::InsertMany(database, inventory); CharacterPetInventoryRepository::InsertMany(database, inventory);
} }
@ -3275,109 +3287,106 @@ void ZoneDatabase::DeleteItemRecast(uint32 character_id, uint32 recast_type)
void ZoneDatabase::LoadPetInfo(Client *client) void ZoneDatabase::LoadPetInfo(Client *client)
{ {
// Load current pet and suspended pet // Load current pet and suspended pet
PetInfo *petinfo = client->GetPetInfo(0); auto pet_info = client->GetPetInfo(PetInfoType::Current);
PetInfo *suspended = client->GetPetInfo(1); auto suspended_pet_info = client->GetPetInfo(PetInfoType::Suspended);
memset(petinfo, 0, sizeof(PetInfo)); memset(pet_info, 0, sizeof(PetInfo));
memset(suspended, 0, sizeof(PetInfo)); memset(suspended_pet_info, 0, sizeof(PetInfo));
std::string query = StringFormat("SELECT `pet`, `petname`, `petpower`, `spell_id`, " const auto& info = CharacterPetInfoRepository::GetWhere(
"`hp`, `mana`, `size` , `taunting` FROM `character_pet_info` " database,
"WHERE `char_id` = %u", fmt::format(
client->CharacterID()); "`char_id` = {}",
auto results = database.QueryDatabase(query); client->CharacterID()
if (!results.Success()) { )
);
if (info.empty()) {
return; return;
} }
PetInfo *pi; PetInfo* p;
for (auto& row = results.begin(); row != results.end(); ++row) {
uint16 pet = Strings::ToInt(row[0]);
if (pet == 0) for (const auto& e : info) {
pi = petinfo; if (e.pet == PetInfoType::Current) {
else if (pet == 1) p = pet_info;
pi = suspended; } else if (e.pet == PetInfoType::Suspended) {
else p = suspended_pet_info;
} else {
continue; continue;
}
strncpy(pi->Name, row[1], 64); strn0cpy(p->Name, e.petname.c_str(), sizeof(c->Name));
pi->petpower = Strings::ToInt(row[2]);
pi->SpellID = Strings::ToInt(row[3]); p->petpower = e.petpower;
pi->HP = Strings::ToUnsignedInt(row[4]); p->SpellID = e.spell_id;
pi->Mana = Strings::ToUnsignedInt(row[5]); p->HP = e.hp;
pi->size = Strings::ToFloat(row[6]); p->Mana = e.mana;
pi->taunting = (bool) Strings::ToInt(row[7]); p->size = e.size;
p->taunting = e.taunting;
} }
query = StringFormat("SELECT `pet`, `slot`, `spell_id`, `caster_level`, `castername`, " const auto& buffs = CharacterPetBuffsRepository::GetWhere(
"`ticsremaining`, `counters`, `instrument_mod` FROM `character_pet_buffs` " database,
"WHERE `char_id` = %u", fmt::format(
client->CharacterID()); "`char_id` = {}",
results = QueryDatabase(query); client->CharacterID()
if (!results.Success()) { )
return; );
if (!buffs.empty()) {
for (const auto& e : buffs) {
if (e.pet == PetInfoType::Current) {
p = pet_info;
} else if (e.pet == PetInfoType::Suspended) {
p = suspended_pet_info;
} else {
continue;
}
if (e.slot >= RuleI(Spells, MaxTotalSlotsPET)) {
continue;
}
if (!IsValidSpell(e.spell_id)) {
continue;
}
p->Buffs[e.slot].spellid = e.spell_id;
p->Buffs[e.slot].level = e.caster_level;
p->Buffs[e.slot].player_id = 0;
p->Buffs[e.slot].effect_type = BuffEffectType::Buff;
p->Buffs[e.slot].duration = e.ticsremaining;
p->Buffs[e.slot].counters = e.counters;
p->Buffs[e.slot].bard_modifier = e.instrument_mod;
}
} }
for (auto& row = results.begin(); row != results.end(); ++row) { const auto& inventory = CharacterPetInventoryRepository::GetWhere(
uint16 pet = Strings::ToInt(row[0]); database,
if (pet == 0) fmt::format(
pi = petinfo; "`char_id` = {}",
else if (pet == 1) client->CharacterID()
pi = suspended; )
else );
continue;
uint32 slot_id = Strings::ToUnsignedInt(row[1]); if (!inventory.empty()) {
if (slot_id >= RuleI(Spells, MaxTotalSlotsPET)) for (const auto& e : inventory) {
continue; if (e.pet == PetInfoType::Current) {
p = pet_info;
} else if (e.pet == PetInfoType::Suspended) {
p = suspended_pet_info;
} else {
continue;
}
uint32 spell_id = Strings::ToUnsignedInt(row[2]); if (!EQ::ValueWithin(e.slot, EQ::invslot::EQUIPMENT_BEGIN, EQ::invslot::EQUIPMENT_END)) {
if (!IsValidSpell(spell_id)) continue;
continue; }
uint32 caster_level = Strings::ToInt(row[3]); p->Items[e.slot] = e.item_id;
int caster_id = 0; }
// The castername field is currently unused
int32 ticsremaining = Strings::ToInt(row[5]);
uint32 counters = Strings::ToUnsignedInt(row[6]);
uint8 bard_mod = Strings::ToUnsignedInt(row[7]);
pi->Buffs[slot_id].spellid = spell_id;
pi->Buffs[slot_id].level = caster_level;
pi->Buffs[slot_id].player_id = caster_id;
pi->Buffs[slot_id].effect_type = 2; // Always 2 in buffs struct for real buffs
pi->Buffs[slot_id].duration = ticsremaining;
pi->Buffs[slot_id].counters = counters;
pi->Buffs[slot_id].bard_modifier = bard_mod;
}
query = StringFormat("SELECT `pet`, `slot`, `item_id` "
"FROM `character_pet_inventory` "
"WHERE `char_id`=%u",
client->CharacterID());
results = database.QueryDatabase(query);
if (!results.Success()) {
return;
}
for (auto& row = results.begin(); row != results.end(); ++row) {
uint16 pet = Strings::ToInt(row[0]);
if (pet == 0)
pi = petinfo;
else if (pet == 1)
pi = suspended;
else
continue;
int slot = Strings::ToInt(row[1]);
if (slot < EQ::invslot::EQUIPMENT_BEGIN || slot > EQ::invslot::EQUIPMENT_END)
continue;
pi->Items[slot] = Strings::ToUnsignedInt(row[2]);
} }
} }