bool CHARACTER::MoveItem(TItemPos Cell, TItemPos DestCell,
#ifdef ENABLE_NEW_STACK_LIMIT
int
#else
BYTE
#endif
count)
{
bool stupid = false;
if (count < 0)
{
sys_err("I am a stupid hacker 3: %s %d", GetName(), count);
stupid = true;
}
count = abs(count);
if (stupid)
{
sys_err("I am a stupid hacker 4: %s %d", GetName(), count);
return false;
}
if (Cell.cell == DestCell.cell && Cell.window_type == DestCell.window_type)
{
return false;
}
LPITEM item = NULL;
if (!IsValidItemPosition(Cell))
return false;
if (!(item = GetItem(Cell)))
return false;
if (item->IsExchanging())
return false;
if (item->GetCount() < count)
return false;
if (INVENTORY == Cell.window_type && Cell.cell >= INVENTORY_MAX_NUM && IS_SET(item->GetFlag(), ITEM_FLAG_IRREMOVABLE))
return false;
if (true == item->isLocked())
return false;
if (!IsValidItemPosition(DestCell))
return false;
if (!CanHandleItem())
{
#ifdef TEXTS_IMPROVEMENT
if (NULL != DragonSoul_RefineWindow_GetOpener()) {
ChatPacketNew(CHAT_TYPE_INFO, 232, "");
}
#endif
return false;
}
#ifdef __ENABLE_NEW_OFFLINESHOP__
if (GetOfflineShopGuest() || GetAuctionGuest())
{
ChatPacket(CHAT_TYPE_INFO, "You cannot move the item if you have opened a private shop.");
return false;
}
#endif
if (DestCell.IsBeltInventoryPosition() && false == CBeltInventoryHelper::CanMoveIntoBeltInventory(item))
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 509, "");
#endif
return false;
}
#ifdef ENABLE_SWITCHBOT
if (Cell.IsSwitchbotPosition() && CSwitchbotManager::Instance().IsActive(GetPlayerID(), Cell.cell))
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 690, "");
#endif
return false;
}
if (DestCell.IsSwitchbotPosition() && !SwitchbotHelper::IsValidItem(item))
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 691, "");
#endif
return false;
}
if (Cell.IsSwitchbotPosition() && DestCell.IsEquipPosition())
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 2051, "");
#endif
return false;
}
if (DestCell.IsSwitchbotPosition() && Cell.IsEquipPosition())
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 2052, "");
#endif
return false;
}
#endif
if (Cell.IsEquipPosition())
{
if (!CanUnequipNow(item))
return false;
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
int iWearCell = item->FindEquipCell(this);
if (iWearCell == WEAR_WEAPON)
{
LPITEM costumeWeapon = GetWear(WEAR_COSTUME_WEAPON);
if (costumeWeapon && !UnequipItem(costumeWeapon))
{
#ifdef TEXTS_IMPROVEMENT
ChatPacketNew(CHAT_TYPE_INFO, 366, "");
#endif
return false;
}
if (!IsEmptyItemGrid(DestCell, item->GetSize(), Cell.cell))
return UnequipItem(item);
}
#endif
}
#ifdef ENABLE_EXTRA_INVENTORY
if (item->IsExtraItem())
{
if (DestCell.window_type != EXTRA_INVENTORY)
return false;
BYTE category = item->GetExtraCategory();
if (DestCell.cell < category * EXTRA_INVENTORY_CATEGORY_MAX_NUM || DestCell.cell >= (category + 1) * EXTRA_INVENTORY_CATEGORY_MAX_NUM)
return false;
}
else if (DestCell.window_type == EXTRA_INVENTORY)
return false;
#else
else if (DRAGON_SOUL_INVENTORY == DestCell.window_type)
return false;
#endif
LPITEM item2;
if ((item2 = GetItem(DestCell)) && item != item2 && item2->IsStackable() &&
!IS_SET(item2->GetAntiFlag(), ITEM_ANTIFLAG_STACK) &&
item2->GetVnum() == item->GetVnum() && !item2->IsExchanging())
{
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
if (item2->GetSocket(i) != item->GetSocket(i))
return false;
if (count == 0)
count = item->GetCount();
sys_log(0, "%s: ITEM_STACK %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell,
DestCell.window_type, DestCell.cell, count);
count = MIN(g_bItemCountLimit - item2->GetCount(), count);
item->SetCount(item->GetCount() - count);
item2->SetCount(item2->GetCount() + count);
return true;
}
#ifdef __SWAP_ITEM_SYSTEM__
if (count != 0 && count != item->GetCount())
return false;
bool isDefaultSwap = Cell.IsDefaultInventoryPosition() && DestCell.IsDefaultInventoryPosition();
#ifdef ENABLE_EXTRA_INVENTORY
bool isExtraSwap = (Cell.window_type == EXTRA_INVENTORY && DestCell.window_type == EXTRA_INVENTORY);
#else
bool isExtraSwap = false;
#endif
if (!isDefaultSwap && !isExtraSwap)
return false;
LPITEM targetItem = GetItem_NEW(DestCell);
if (targetItem && targetItem->GetVID() == item->GetVID())
return false;
if (targetItem)
{
DestCell = TItemPos(Cell.window_type, targetItem->GetCell());
}
if (item->IsExchanging() || (targetItem && targetItem->IsExchanging()))
return false;
if (isExtraSwap)
{
item->RemoveFromCharacter();
if (targetItem)
{
targetItem->RemoveFromCharacter();
SetItem(Cell, targetItem);
}
SetItem(DestCell, item);
#ifdef ENABLE_EXTRA_INVENTORY
SyncQuickslot(QUICKSLOT_TYPE_ITEM_EXTRA, Cell.cell, DestCell.cell);
#endif
return true;
}
else if (isDefaultSwap)
{
BYTE basePage = DestCell.cell / (INVENTORY_MAX_NUM / INVENTORY_PAGE_COUNT);
std::map<WORD, LPITEM> moveItemMap;
BYTE sizeLeft = item->GetSize();
for (WORD i = 0; i < item->GetSize(); ++i)
{
WORD cellNumber = DestCell.cell + i * 5;
BYTE cPage = cellNumber / (INVENTORY_MAX_NUM / INVENTORY_PAGE_COUNT);
if (basePage != cPage)
return false;
LPITEM mvItem = GetItem(TItemPos(INVENTORY, cellNumber));
if (mvItem)
{
if (mvItem->GetSize() > item->GetSize())
return false;
if (mvItem->IsExchanging())
return false;
moveItemMap.insert({ Cell.cell + i * 5, mvItem });
sizeLeft -= mvItem->GetSize();
if (mvItem->GetSize() > 1)
i += mvItem->GetSize() - 1;
}
else
{
sizeLeft -= 1;
}
}
if (sizeLeft != 0)
return false;
std::map<WORD, WORD> syncCells;
syncCells.insert({ GetQuickslotPosition(QUICKSLOT_TYPE_ITEM, item->GetCell()), DestCell.cell });
item->RemoveFromCharacter();
for (auto it = moveItemMap.begin(); it != moveItemMap.end(); ++it)
{
WORD toCellNumber = it->first;
LPITEM mvItem = it->second;
syncCells.insert({ GetQuickslotPosition(QUICKSLOT_TYPE_ITEM, mvItem->GetCell()), toCellNumber });
mvItem->RemoveFromCharacter();
SetItem(TItemPos(INVENTORY, toCellNumber), mvItem);
}
SetItem(DestCell, item);
for (auto& sCell : syncCells)
{
TQuickslot qs;
qs.type = QUICKSLOT_TYPE_ITEM;
qs.pos = sCell.second;
SetQuickslot(sCell.first, qs);
}
return true;
}
#endif
if (count == 0 || count >= item->GetCount() || !item->IsStackable() || IS_SET(item->GetAntiFlag(), ITEM_ANTIFLAG_STACK))
{
sys_log(0, "%s: ITEM_MOVE %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell,
DestCell.window_type, DestCell.cell, count);
item->RemoveFromCharacter();
SetItem(DestCell, item
#ifdef __HIGHLIGHT_SYSTEM__
, false
#endif
);
if (INVENTORY == Cell.window_type && INVENTORY == DestCell.window_type)
{
SyncQuickslot(QUICKSLOT_TYPE_ITEM, Cell.cell, DestCell.cell);
}
#ifdef ENABLE_EXTRA_INVENTORY
else if (EXTRA_INVENTORY == Cell.window_type && EXTRA_INVENTORY == DestCell.window_type)
{
SyncQuickslot(QUICKSLOT_TYPE_ITEM_EXTRA, Cell.cell, DestCell.cell);
}
#endif
}
else if (count < item->GetCount())
{
sys_log(0, "%s: ITEM_SPLIT %s (window: %d, cell : %d) -> (window:%d, cell %d) count %d", GetName(), item->GetName(), Cell.window_type, Cell.cell,
DestCell.window_type, DestCell.cell, count);
item->SetCount(item->GetCount() - count);
LPITEM item2 = ITEM_MANAGER::instance().CreateItem(item->GetVnum(), count);
FN_copy_item_socket(item2, item);
item2->AddToCharacter(this, DestCell
#ifdef __HIGHLIGHT_SYSTEM__
, false
#endif
);
char szBuf[51+1];
snprintf(szBuf, sizeof(szBuf), "%u %u %u %u ", item2->GetID(), item2->GetCount(), item->GetCount(), item->GetCount() + item2->GetCount());
LogManager::instance().ItemLog(this, item, "ITEM_SPLIT", szBuf);
}
return true;
}