Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: buyback inventory live accuracy #1607

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 50 additions & 18 deletions dGame/dComponents/InventoryComponent.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "InventoryComponent.h"

#include <sstream>
#include <ranges>

#include "Entity.h"
#include "Item.h"
Expand Down Expand Up @@ -175,17 +176,14 @@ void InventoryComponent::AddItem(
const int32_t sourceType,
const bool bound,
int32_t preferredSlot) {
if (count == 0) {
LOG("Attempted to add 0 of item (%i) to the inventory!", lot);

if (count == 0) {
return;
}

if (!Inventory::IsValidItem(lot)) {
if (lot > 0) {
LOG("Attempted to add invalid item (%i) to the inventory!", lot);
}

return;
}

Expand All @@ -197,16 +195,22 @@ void InventoryComponent::AddItem(

Tiernan-Alderman marked this conversation as resolved.
Show resolved Hide resolved
auto* inventory = GetInventory(inventoryType);


if (!config.empty() || bound) {
if (inventoryType == eInventoryType::VENDOR_BUYBACK && buybackItems.size() >= 27) {
RemoveItem(buybackItems.back());
buybackItems.pop_back();
}
const auto slot = preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot) ? preferredSlot : inventory->FindEmptySlot();

if (slot == -1) {
LOG("Failed to find empty slot for inventory (%i)!", inventoryType);

return;
}

auto* item = new Item(lot, inventory, slot, count, config, parent, showFlyingLoot, isModMoveAndEquip, subKey, bound, lootSourceType);
if (inventoryType == eInventoryType::VENDOR_BUYBACK && buybackItems.size() <= 27) {
buybackItems.push_front(item->GetId());
}

if (missions != nullptr && !IsTransferInventory(inventoryType)) {
missions->Progress(eMissionTaskType::GATHER, lot, LWOOBJID_EMPTY, "", count, IsTransferInventory(inventorySourceType));
Expand All @@ -232,67 +236,72 @@ void InventoryComponent::AddItem(
stack = 1;
}

auto* existing = FindItemByLot(lot, inventoryType);

auto* existing = FindItemByLot(lot, inventoryType);
if (existing != nullptr) {
const auto delta = std::min<uint32_t>(left, stack - existing->GetCount());

left -= delta;

existing->SetCount(existing->GetCount() + delta, false, true, showFlyingLoot, lootSourceType);

if (isModMoveAndEquip) {
existing->Equip();

isModMoveAndEquip = false;
}
}

// If we have some leftover and we aren't bricks, make a new stack
while (left > 0 && (!isBrick || (isBrick && !existing))) {
const auto size = std::min(left, stack);

left -= size;

int32_t slot;
if (inventoryType == eInventoryType::VENDOR_BUYBACK && buybackItems.size() >= 27) {
RemoveItem(buybackItems.back());
buybackItems.pop_back();
}

int32_t slot;
if (preferredSlot != -1 && inventory->IsSlotEmpty(preferredSlot)) {
slot = preferredSlot;

preferredSlot = -1;
} else {
slot = inventory->FindEmptySlot();
}

if (slot == -1) {
outOfSpace += size;
LOG("No empty slot found, out of space for %u items of LOT %i", size, lot);

switch (sourceType) {
case 0:
Mail::SendMail(LWOOBJID_EMPTY, "Darkflame Universe", m_Parent, "Lost Reward", "You received an item and didn&apos;t have room for it.", lot, size);
Mail::SendMail(LWOOBJID_EMPTY, "Darkflame Universe", m_Parent, "Lost Reward", "You received an item and didn't have room for it.", lot, size);
LOG("Sent mail for lost reward: LOT %i, count %u", lot, size);
break;

case 1:
for (size_t i = 0; i < size; i++) {
GameMessages::SendDropClientLoot(this->m_Parent, this->m_Parent->GetObjectID(), lot, 0, this->m_Parent->GetPosition(), 1);
}

LOG("Dropped client loot for LOT %i, count %u", lot, size);
break;

default:
break;
}

continue;
}

auto* item = new Item(lot, inventory, slot, size, {}, parent, showFlyingLoot, isModMoveAndEquip, subKey, false, lootSourceType);
if (inventoryType == eInventoryType::VENDOR_BUYBACK && buybackItems.size() <= 27) {
buybackItems.push_front(item->GetId());
}

isModMoveAndEquip = false;
}

if (missions != nullptr && !IsTransferInventory(inventoryType)) {
LOG("Progressing mission for adding item with LOT %i, count %u", lot, count - outOfSpace);
missions->Progress(eMissionTaskType::GATHER, lot, LWOOBJID_EMPTY, "", count - outOfSpace, IsTransferInventory(inventorySourceType));
}

return;
}

bool InventoryComponent::RemoveItem(const LOT lot, const uint32_t count, eInventoryType inventoryType, const bool ignoreBound, const bool silent) {
Expand Down Expand Up @@ -323,6 +332,9 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
}

auto* origin = item->GetInventory();
if (origin->GetType() == eInventoryType::VENDOR_BUYBACK) {
buybackItems.erase(std::ranges::find(buybackItems, item->GetId()));
}

const auto lot = item->GetLot();

Expand Down Expand Up @@ -364,6 +376,16 @@ void InventoryComponent::MoveItemToInventory(Item* item, const eInventoryType in
item->SetCount(item->GetCount() - delta, false, false);
}


// if (origin->GetType() == eInventoryType::VENDOR_BUYBACK) {
// auto& items = origin->GetItems();
// int32_t slotItr = 0;
// for (auto* item : items | std::views::values) {
// GameMessages::SendMoveItemInInventory(m_Parent->GetObjectID(), m_Parent->GetSystemAddress(), inventory, item->GetId(), origin->GetType(), 0, slotItr);
// item->SetSlot(slotItr);
// slotItr++;
// }
// }
auto* missionComponent = m_Parent->GetComponent<MissionComponent>();

if (missionComponent != nullptr) {
Expand Down Expand Up @@ -1603,3 +1625,13 @@ bool InventoryComponent::SetSkill(BehaviorSlot slot, uint32_t skillId) {
m_Skills.insert_or_assign(slot, skillId);
return true;
}

void InventoryComponent::RemoveItem(LWOOBJID itemId) {
auto* item = FindItemById(itemId);
if (item) {
item->SetCount(0);
LOG("Item with ItemId %llu removed (count set to 0)", itemId);
} else {
LOG("Item with ItemId %llu not found, cannot remove", itemId);
}
}
16 changes: 13 additions & 3 deletions dGame/dComponents/InventoryComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

#include <map>
#include <stack>

#include <queue>

#include "BehaviorSlot.h"
#include "tinyxml2.h"
Expand Down Expand Up @@ -367,19 +367,29 @@ class InventoryComponent final : public Component {
*/
void UnequipScripts(Item* unequippedItem);

std::map<BehaviorSlot, uint32_t> GetSkills(){ return m_Skills; };
std::map<BehaviorSlot, uint32_t> GetSkills() { return m_Skills; };

bool SetSkill(int slot, uint32_t skillId);
bool SetSkill(BehaviorSlot slot, uint32_t skillId);

/**
* Called in ManageVendorBuybackInventory to remove an item given the ItemId
*
* @param itemId item ID for item being removed
*/
void RemoveItem(LWOOBJID itemId);

~InventoryComponent() override;

private:
/**
* All the inventory this entity possesses
*/
std::map<eInventoryType, Inventory*> m_Inventories;

/**
*A queue of LWOOBJIDs representing the buybackItems which are sold to a vendor
*/
std::deque<LWOOBJID> buybackItems;
/**
* The skills that this entity currently has active
*/
Expand Down
32 changes: 28 additions & 4 deletions dGame/dGameMessages/GameMessages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -980,7 +980,7 @@ void GameMessages::SendResurrect(Entity* entity) {
destroyableComponent->SetImagination(imaginationToRestore);
}
}
});
});

CBITSTREAM;
CMSGHEADER;
Expand Down Expand Up @@ -5110,12 +5110,12 @@ void GameMessages::HandleMissionDialogOK(RakNet::BitStream& inStream, Entity* en
}

if (Game::config->GetValue("allow_players_to_skip_cinematics") != "1"
|| !player->GetCharacter()
|| !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
|| !player->GetCharacter()
|| !player->GetCharacter()->GetPlayerFlag(ePlayerFlag::DLU_SKIP_CINEMATICS)) return;
player->AddCallbackTimer(0.5f, [player]() {
if (!player) return;
GameMessages::SendEndCinematic(player->GetObjectID(), u"", player->GetSystemAddress());
});
});
}

void GameMessages::HandleRequestLinkedMission(RakNet::BitStream& inStream, Entity* entity) {
Expand Down Expand Up @@ -6210,3 +6210,27 @@ void GameMessages::SendSlashCommandFeedbackText(Entity* entity, std::u16string t
auto sysAddr = entity->GetSystemAddress();
SEND_PACKET;
}

void GameMessages::SendMoveItemInInventory(
const LWOOBJID objectId,
const SystemAddress& sysAddr,
eInventoryType destination,
const LWOOBJID item,
const eInventoryType source,
const int32_t responseCode,
const int32_t slot) {
CBITSTREAM;
CMSGHEADER;

bitStream.Write(objectId);
bitStream.Write(eGameMessageType::MOVE_ITEM_IN_INVENTORY);

bitStream.Write(destination != eInventoryType::INVALID);
if (destination != eInventoryType::INVALID) bitStream.Write(destination);
bitStream.Write(item);
bitStream.Write(source);
bitStream.Write(responseCode);
bitStream.Write(slot);

SEND_PACKET;
}
10 changes: 10 additions & 0 deletions dGame/dGameMessages/GameMessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,16 @@ namespace GameMessages {
void HandleCancelDonationOnPlayer(RakNet::BitStream& inStream, Entity* entity);

void SendSlashCommandFeedbackText(Entity* entity, std::u16string text);

void SendMoveItemInInventory(
const LWOOBJID objectId,
const SystemAddress& sysAddr,
eInventoryType destination,
const LWOOBJID item,
const eInventoryType source,
const int32_t responseCode,
const int32_t slot
);
};

#endif // GAMEMESSAGES_H
4 changes: 1 addition & 3 deletions dGame/dInventory/Inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,11 @@ void Inventory::SetSize(const uint32_t value) {
int32_t Inventory::FindEmptySlot() {
if (free <= 6) // Up from 1
{
if (type != ITEMS && type != VAULT_ITEMS && type != eInventoryType::VAULT_MODELS) {
if (type != ITEMS && type != VAULT_ITEMS && type != eInventoryType::VAULT_MODELS && type != eInventoryType::VENDOR_BUYBACK) {
uint32_t newSize = size;

if (type == MODELS) {
newSize = 240;
} else if (type == eInventoryType::VENDOR_BUYBACK) {
newSize += 9u;
} else {
newSize += 10u;
}
Expand Down