Pe scurt: cand cumpai un item stackable dintr-un shop/npc (magazin general, samd) itemele nu se puneau automat pe stack-ul existent din inventar, ci crea un slot nou. Daca inventarul era plin, itemele dispareau sau cauza comportament nedefinit.
Testat pe serverul propriu:
- Cumparare normala din NPC shop → item in inventar, banii scazuti corect.
- Item stackable cu slot existent → se adauga pe stack, fara slot nou creat.
- Cumperi 10x licori dar ai deja 4990x in inventar (bCount = 0) → se completeaza la 5000x automat, banii scazuti corect.
- Inventar plin + item non-stackable → mesaj eroare, banii nu se scad.
- Inventar plin + item stackable cu stack posibil → se adauga pe stack existent.
- Dragon Soul → apare in DS inventory corect, cu ItemLog si SendMoneyLog.
- FlushDelayedSave apelat corect pentru toate cazurile.
- Niciun item pierdut, niciun yang scazut fara sa primesti item.
*Instructiuni:Testat pe Martysama 5.8 P23. Dacă folositi mainline, lasati un reply cu rezultatul + sugestii pentru imbunatatirea codului sau eventuale erori de cod.
1. CommonDefines.h
Adauga:
Code:
#define ENABLE_CHAMP_SHOP_AUTO_STACKCauta:
Code:
int iEmptyPos = ch->GetEmptyInventoryEx(item);
if (iEmptyPos < 0)
{
if (m_pkPC)
{
sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
else
{
sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}Code:
int iEmptyPos = ch->GetEmptyInventoryEx(item);
if (iEmptyPos < 0)
{
if (m_pkPC)
{
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
if (!IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE))
#endif
{
sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}
else
{
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
if (!IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE))
#endif
{
sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}
}Code:
int iEmptyPos = ch->GetEmptyInventoryEx(item);
if (iEmptyPos < 0)
{
if (m_pkPC)
{
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
if (!IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE))
#endif
{
sys_log(1, "Shop::Buy at PC Shop : Inventory full : %s size %d", ch->GetName(), item->GetSize());
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}
else
{
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
if (!IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE))
#endif
{
sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
}
}Code:
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
WORD bCount = item->GetCount();
if (!m_pkPC && !item->IsDragonSoul() && IS_SET(item->GetFlag(), ITEM_FLAG_STACKABLE))
{
for (WORD i = 0; i < INVENTORY_MAX_NUM; ++i)
{
LPITEM item2 = ch->GetInventoryItem(i);
if (!item2)
continue;
if (item2->GetVnum() != item->GetVnum())
continue;
int j;
for (j = 0; j < ITEM_SOCKET_MAX_NUM; ++j)
if (item2->GetSocket(j) != item->GetSocket(j))
break;
if (j != ITEM_SOCKET_MAX_NUM)
continue;
WORD bCount2 = MIN(g_bItemCountLimit - item2->GetCount(), bCount);
bCount -= bCount2;
item2->SetCount(item2->GetCount() + bCount2);
if (bCount == 0)
break;
}
item->SetCount(bCount);
iEmptyPos = ch->GetEmptyInventoryEx(item);
if (bCount > 0 && iEmptyPos < 0)
{
sys_log(1, "Shop::Buy : Inventory full : %s size %d", ch->GetName(), item->GetSize());
M2_DESTROY_ITEM(item);
return SHOP_SUBHEADER_GC_INVENTORY_FULL;
}
if (bCount == 0)
{
M2_DESTROY_ITEM(item);
ch->PointChange(POINT_GOLD, -dwPrice, false);
DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, r_item.vnum, -dwPrice);
ch->Save();
return SHOP_SUBHEADER_GC_OK;
}
}
#endifCode:
else
{
item->AddToCharacter(ch, TItemPos(item->GetWindowInventoryEx(), iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());Code:
else
#ifdef ENABLE_CHAMP_SHOP_AUTO_STACK
// MODIFIED
{
if (item->IsDragonSoul())
{
item->AddToCharacter(ch, TItemPos(DRAGON_SOUL_INVENTORY, iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
}
else
{
if (bCount > 0)
{
item->AddToCharacter(ch, TItemPos(item->GetWindowInventoryEx(), iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
}
else
{
M2_DESTROY_ITEM(item);
item = nullptr;
}
}
}
#else
// ORIGINAL
{
item->AddToCharacter(ch, TItemPos(item->GetWindowInventoryEx(), iEmptyPos));
ITEM_MANAGER::instance().FlushDelayedSave(item);
LogManager::instance().ItemLog(ch, item, "BUY", item->GetName());
if (item->GetVnum() >= 80003 && item->GetVnum() <= 80007)
{
LogManager::instance().GoldBarLog(ch->GetPlayerID(), item->GetID(), PERSONAL_SHOP_BUY, "");
}
DBManager::instance().SendMoneyLog(MONEY_LOG_SHOP, item->GetVnum(), -dwPrice);
}
#endif
