mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
327 lines
8.8 KiB
C++
327 lines
8.8 KiB
C++
#include "evolving_items.h"
|
|
#include "item_instance.h"
|
|
#include "events/player_event_logs.h"
|
|
#include "repositories/character_evolving_items_repository.h"
|
|
|
|
EvolvingItemsManager::EvolvingItemsManager()
|
|
{
|
|
m_db = nullptr;
|
|
m_content_db = nullptr;
|
|
}
|
|
|
|
void EvolvingItemsManager::LoadEvolvingItems() const
|
|
{
|
|
auto const &results = ItemsEvolvingDetailsRepository::All(*m_content_db);
|
|
|
|
if (results.empty()) {
|
|
return;
|
|
}
|
|
|
|
std::ranges::transform(
|
|
results.begin(),
|
|
results.end(),
|
|
std::inserter(
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache(),
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().end()
|
|
),
|
|
[](const ItemsEvolvingDetailsRepository::ItemsEvolvingDetails &x) {
|
|
return std::make_pair(x.item_id, x);
|
|
}
|
|
);
|
|
}
|
|
|
|
void EvolvingItemsManager::SetDatabase(Database *db)
|
|
{
|
|
m_db = db;
|
|
}
|
|
|
|
void EvolvingItemsManager::SetContentDatabase(Database *db)
|
|
{
|
|
m_content_db = db;
|
|
}
|
|
|
|
double EvolvingItemsManager::CalculateProgression(const uint64 current_amount, const uint32 item_id)
|
|
{
|
|
if (!EvolvingItemsManager::Instance()->GetEvolvingItemsCache().contains(item_id)) {
|
|
return 0;
|
|
}
|
|
|
|
return EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount > 0
|
|
? static_cast<double>(current_amount)
|
|
/ static_cast<double>(EvolvingItemsManager::Instance()->GetEvolvingItemsCache().at(item_id).required_amount) * 100
|
|
: 0;
|
|
}
|
|
|
|
void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_id, const EQ::ItemInstance &inst) const
|
|
{
|
|
if (!inst) {
|
|
return;
|
|
}
|
|
|
|
inst.SetEvolveEquipped(false);
|
|
if (inst.IsEvolving() && slot_id <= EQ::invslot::EQUIPMENT_END && slot_id >= EQ::invslot::EQUIPMENT_BEGIN) {
|
|
inst.SetEvolveEquipped(true);
|
|
}
|
|
|
|
if (!inst.IsEvolving()) {
|
|
return;
|
|
}
|
|
|
|
if (!inst.GetEvolveUniqueID()) {
|
|
auto e = CharacterEvolvingItemsRepository::NewEntity();
|
|
|
|
e.character_id = char_id;
|
|
e.item_id = inst.GetID();
|
|
e.equipped = inst.GetEvolveEquipped();
|
|
e.final_item_id = EvolvingItemsManager::Instance()->GetFinalItemID(inst);
|
|
|
|
auto r = CharacterEvolvingItemsRepository::InsertOne(*m_db, e);
|
|
e.id = r.id;
|
|
|
|
inst.SetEvolveUniqueID(e.id);
|
|
inst.SetEvolveCharID(e.character_id);
|
|
inst.SetEvolveItemID(e.item_id);
|
|
inst.SetEvolveFinalItemID(e.final_item_id);
|
|
|
|
return;
|
|
}
|
|
|
|
CharacterEvolvingItemsRepository::SetEquipped(*m_db, inst.GetEvolveUniqueID(), inst.GetEvolveEquipped());
|
|
}
|
|
|
|
uint32 EvolvingItemsManager::GetFinalItemID(const EQ::ItemInstance &inst) const
|
|
{
|
|
if (!inst) {
|
|
return 0;
|
|
}
|
|
|
|
const auto start_iterator = std::ranges::find_if(
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
|
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
|
|
return a.second.item_evo_id == inst.GetEvolveLoreID();
|
|
}
|
|
);
|
|
|
|
if (start_iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
|
|
return 0;
|
|
}
|
|
|
|
const auto final_id = std::ranges::max_element(
|
|
start_iterator,
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
|
[&](
|
|
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a,
|
|
const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &b
|
|
) {
|
|
return a.second.item_evo_id == b.second.item_evo_id &&
|
|
a.second.item_evolve_level < b.second.item_evolve_level;
|
|
}
|
|
);
|
|
|
|
return final_id->first;
|
|
}
|
|
|
|
uint32 EvolvingItemsManager::GetNextEvolveItemID(const EQ::ItemInstance &inst) const
|
|
{
|
|
if (!inst) {
|
|
return 0;
|
|
}
|
|
|
|
int8 const current_level = inst.GetEvolveLvl();
|
|
|
|
const auto iterator = std::ranges::find_if(
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cbegin(),
|
|
EvolvingItemsManager::Instance()->GetEvolvingItemsCache().cend(),
|
|
[&](const std::pair<uint32, ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> &a) {
|
|
return a.second.item_evo_id == inst.GetEvolveLoreID() &&
|
|
a.second.item_evolve_level == current_level + 1;
|
|
}
|
|
);
|
|
|
|
if (iterator == std::end(EvolvingItemsManager::Instance()->GetEvolvingItemsCache())) {
|
|
return 0;
|
|
}
|
|
|
|
return iterator->first;
|
|
}
|
|
|
|
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails EvolvingItemsManager::GetEvolveItemDetails(const uint64 unique_id)
|
|
{
|
|
if (GetEvolvingItemsCache().contains(unique_id)) {
|
|
return GetEvolvingItemsCache().at(unique_id);
|
|
}
|
|
|
|
return ItemsEvolvingDetailsRepository::NewEntity();
|
|
}
|
|
|
|
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> EvolvingItemsManager::GetEvolveIDItems(
|
|
const uint32 evolve_id
|
|
)
|
|
{
|
|
std::vector<ItemsEvolvingDetailsRepository::ItemsEvolvingDetails> e{};
|
|
|
|
for (auto const &[key, value]: GetEvolvingItemsCache()) {
|
|
if (value.item_evo_id == evolve_id) {
|
|
e.push_back(value);
|
|
}
|
|
}
|
|
|
|
std::ranges::sort(
|
|
e.begin(),
|
|
e.end(),
|
|
[&](
|
|
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails const &a,
|
|
ItemsEvolvingDetailsRepository::ItemsEvolvingDetails const &b
|
|
) {
|
|
return a.item_evolve_level < b.item_evolve_level;
|
|
}
|
|
);
|
|
|
|
return e;
|
|
}
|
|
|
|
uint64 EvolvingItemsManager::GetTotalEarnedXP(const EQ::ItemInstance &inst)
|
|
{
|
|
if (!inst) {
|
|
return 0;
|
|
}
|
|
|
|
uint64 xp = inst.GetEvolveCurrentAmount();
|
|
auto evolve_id_item_cache = GetEvolveIDItems(inst.GetEvolveLoreID());
|
|
auto current_level = inst.GetEvolveLvl();
|
|
|
|
for (auto const &i: evolve_id_item_cache) {
|
|
if (i.item_evolve_level < current_level) {
|
|
xp += i.required_amount;
|
|
}
|
|
}
|
|
|
|
return xp;
|
|
}
|
|
|
|
EvolveGetNextItem EvolvingItemsManager::GetNextItemByXP(const EQ::ItemInstance &inst_in, const int64 in_xp)
|
|
{
|
|
EvolveGetNextItem ets{};
|
|
if (!inst_in) {
|
|
return ets;
|
|
}
|
|
|
|
const auto evolve_items = GetEvolveIDItems(inst_in.GetEvolveLoreID());
|
|
uint32 max_transfer_level = 0;
|
|
int64 xp = in_xp;
|
|
|
|
for (auto const &e: evolve_items) {
|
|
if (e.item_evolve_level < inst_in.GetEvolveLvl()) {
|
|
continue;
|
|
}
|
|
|
|
int64 have = 0;
|
|
if (e.item_evolve_level == inst_in.GetEvolveLvl()) {
|
|
have = inst_in.GetEvolveCurrentAmount();
|
|
}
|
|
|
|
const auto required = e.required_amount;
|
|
const int64 need = required - have;
|
|
const int64 balance = xp - need;
|
|
|
|
if (balance <= 0) {
|
|
ets.new_current_amount = have + xp;
|
|
ets.new_item_id = e.item_id;
|
|
ets.from_current_amount = 0;
|
|
ets.max_transfer_level = max_transfer_level;
|
|
return ets;
|
|
}
|
|
|
|
xp = balance;
|
|
max_transfer_level += 1;
|
|
|
|
ets.new_current_amount = required;
|
|
ets.new_item_id = e.item_id;
|
|
ets.from_current_amount = balance - required;
|
|
ets.max_transfer_level = max_transfer_level;
|
|
}
|
|
|
|
return ets;
|
|
}
|
|
|
|
EvolveTransfer EvolvingItemsManager::DetermineTransferResults(
|
|
const EQ::ItemInstance &inst_from,
|
|
const EQ::ItemInstance &inst_to
|
|
)
|
|
{
|
|
EvolveTransfer ets{};
|
|
if (!inst_from || !inst_to) {
|
|
return ets;
|
|
}
|
|
|
|
auto evolving_details_inst_from = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_from.GetID());
|
|
auto evolving_details_inst_to = EvolvingItemsManager::Instance()->GetEvolveItemDetails(inst_to.GetID());
|
|
|
|
if (!evolving_details_inst_from.id || !evolving_details_inst_to.id) {
|
|
return ets;
|
|
}
|
|
|
|
if (evolving_details_inst_from.type == evolving_details_inst_to.type) {
|
|
uint32 compatibility = 0;
|
|
uint64 xp = 0;
|
|
if (evolving_details_inst_from.sub_type == evolving_details_inst_to.sub_type) {
|
|
compatibility = 100;
|
|
}
|
|
else {
|
|
compatibility = 30;
|
|
}
|
|
|
|
xp = EvolvingItemsManager::Instance()->GetTotalEarnedXP(inst_from) * compatibility / 100;
|
|
auto results = EvolvingItemsManager::Instance()->GetNextItemByXP(inst_to, xp);
|
|
|
|
ets.item_from_id = EvolvingItemsManager::Instance()->GetFirstItemInLoreGroup(inst_from.GetEvolveLoreID());
|
|
ets.item_from_current_amount = results.from_current_amount;
|
|
ets.item_to_id = results.new_item_id;
|
|
ets.item_to_current_amount = results.new_current_amount;
|
|
ets.compatibility = compatibility;
|
|
ets.max_transfer_level = results.max_transfer_level;
|
|
}
|
|
|
|
return ets;
|
|
}
|
|
|
|
uint32 EvolvingItemsManager::GetFirstItemInLoreGroup(const uint32 lore_id)
|
|
{
|
|
for (auto const &[key, value]: GetEvolvingItemsCache()) {
|
|
if (value.item_evo_id == lore_id && value.item_evolve_level == 1) {
|
|
return key;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
uint32 EvolvingItemsManager::GetFirstItemInLoreGroupByItemID(const uint32 item_id)
|
|
{
|
|
for (auto const &[key, value]: GetEvolvingItemsCache()) {
|
|
if (value.item_id == item_id) {
|
|
for (auto const &[key2, value2]: GetEvolvingItemsCache()) {
|
|
if (value2.item_evo_id == value.item_evo_id && value2.item_evolve_level == 1) {
|
|
return key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void EvolvingItemsManager::LoadPlayerEvent(const EQ::ItemInstance &inst, PlayerEvent::EvolveItem &e)
|
|
{
|
|
if (!inst) {
|
|
return;
|
|
}
|
|
|
|
e.item_id = inst.GetID();
|
|
e.item_name = inst.GetItem() ? inst.GetItem()->Name : std::string();
|
|
e.level = inst.GetEvolveLvl();
|
|
e.progression = inst.GetEvolveProgression();
|
|
e.unique_id = inst.GetEvolveUniqueID();
|
|
}
|