#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( evolving_items_manager.GetEvolvingItemsCache(), evolving_items_manager.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 (!evolving_items_manager.GetEvolvingItemsCache().contains(item_id)) { return 0; } return evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount > 0 ? static_cast(current_amount) / static_cast(evolving_items_manager.GetEvolvingItemsCache().at(item_id).required_amount) * 100 : 0; } void EvolvingItemsManager::DoLootChecks(const uint32 char_id, const uint16 slot_id, const EQ::ItemInstance &inst) const { 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 = evolving_items_manager.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 { const auto start_iterator = std::ranges::find_if( evolving_items_manager.GetEvolvingItemsCache().cbegin(), evolving_items_manager.GetEvolvingItemsCache().cend(), [&](const std::pair &a) { return a.second.item_evo_id == inst.GetEvolveLoreID(); } ); if (start_iterator == std::end(evolving_items_manager.GetEvolvingItemsCache())) { return 0; } const auto final_id = std::ranges::max_element( start_iterator, evolving_items_manager.GetEvolvingItemsCache().cend(), [&]( const std::pair &a, const std::pair &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 { int8 const current_level = inst.GetEvolveLvl(); const auto iterator = std::ranges::find_if( evolving_items_manager.GetEvolvingItemsCache().cbegin(), evolving_items_manager.GetEvolvingItemsCache().cend(), [&](const std::pair &a) { return a.second.item_evo_id == inst.GetEvolveLoreID() && a.second.item_evolve_level == current_level + 1; } ); if (iterator == std::end(evolving_items_manager.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 EvolvingItemsManager::GetEvolveIDItems( const uint32 evolve_id ) { std::vector 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{}; 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{}; auto evolving_details_inst_from = evolving_items_manager.GetEvolveItemDetails(inst_from.GetID()); auto evolving_details_inst_to = evolving_items_manager.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 = evolving_items_manager.GetTotalEarnedXP(inst_from) * compatibility / 100; auto results = evolving_items_manager.GetNextItemByXP(inst_to, xp); ets.item_from_id = evolving_items_manager.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) { 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(); }