/* Regular merchants */ void CUser::MerchantOpen() { int16 errorCode = 0; if (isDead()) errorCode = MERCHANT_OPEN_DEAD; else if (isStoreOpen()) errorCode = MERCHANT_OPEN_SHOPPING; else if (isTrading()) errorCode = MERCHANT_OPEN_TRADING; else if (GetZoneID() > 21 || GetZoneID() <= ELMORAD) errorCode = MERCHANT_OPEN_INVALID_ZONE; else if (GetLevel() < 30) errorCode = MERCHANT_OPEN_UNDERLEVELED; else if (isMerchanting()) errorCode = MERCHANT_OPEN_MERCHANTING; else errorCode = MERCHANT_OPEN_SUCCESS; Packet result(WIZ_MERCHANT, uint8(MERCHANT_OPEN)); result << errorCode; Send(&result); // If we're already merchanting, user may be desynced // so we need to close our current merchant first. if (errorCode == MERCHANT_OPEN_MERCHANTING) MerchantClose(); }
/* Buying merchants: 1.7XX only */ void CUser::BuyingMerchantOpen(Packet & pkt) { int16 errorCode = 0; if (isDead()) errorCode = MERCHANT_OPEN_DEAD; else if (isStoreOpen()) errorCode = MERCHANT_OPEN_SHOPPING; else if (isTrading()) errorCode = MERCHANT_OPEN_TRADING; else if (GetZoneID() > 21 || GetZoneID() <= ELMORAD) errorCode = MERCHANT_OPEN_INVALID_ZONE; else if (GetLevel() < 30) errorCode = MERCHANT_OPEN_UNDERLEVELED; else if (isMerchanting()) errorCode = MERCHANT_OPEN_MERCHANTING; else errorCode = MERCHANT_OPEN_SUCCESS; Packet result(WIZ_MERCHANT, uint8(MERCHANT_BUY_OPEN)); result << errorCode; Send(&result); if (errorCode == MERCHANT_OPEN_MERCHANTING) BuyingMerchantClose(); memset(&m_arMerchantItems, 0, sizeof(m_arMerchantItems)); }
void CUser::ItemMove(Packet & pkt) { _ITEM_TABLE *pTable; _ITEM_DATA *pSrcItem, *pDstItem, tmpItem; uint32 nItemID; uint8 dir, bSrcPos, bDstPos; pkt >> dir >> nItemID >> bSrcPos >> bDstPos; if (isTrading() || isMerchanting()) goto fail_return; pTable = g_pMain->GetItemPtr(nItemID); if (pTable == nullptr // || dir == ITEM_INVEN_SLOT && ((pTable->m_sWeight + m_sItemWeight) > m_sMaxWeight)) // || dir > ITEM_MBAG_TO_MBAG || bSrcPos >= SLOT_MAX+HAVE_MAX+COSP_MAX+MBAG_MAX || bDstPos >= SLOT_MAX+HAVE_MAX+COSP_MAX+MBAG_MAX || ((dir == ITEM_INVEN_SLOT || dir == ITEM_SLOT_SLOT) && (bDstPos > SLOT_MAX || !ItemEquipAvailable(pTable))) || (dir == ITEM_SLOT_INVEN && bSrcPos > SLOT_MAX) || (dir == ITEM_INVEN_SLOT && bDstPos == RESERVED) || (dir == ITEM_SLOT_INVEN && bDstPos == RESERVED)) goto fail_return; switch (dir) { case ITEM_MBAG_TO_MBAG: if (bDstPos >= MBAG_TOTAL || bSrcPos >= MBAG_TOTAL // We also need to make sure that if we're setting an item in a magic bag, we need to actually // have a magic back to put the item in! || (INVENTORY_MBAG+bDstPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG+bDstPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_MBAG + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_MBAG + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_MBAG + bDstPos]; break; case ITEM_MBAG_TO_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= MBAG_TOTAL // We also need to make sure that if we're taking an item from a magic bag, we need to actually // have a magic back to take it from! || (INVENTORY_MBAG+bSrcPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG+bSrcPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_MBAG + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_MBAG + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_INVEN_TO_MBAG: if (bDstPos >= MBAG_TOTAL || bSrcPos >= HAVE_MAX // We also need to make sure that if we're adding an item to a magic bag, we need to actually // have a magic back to put the item in! || (INVENTORY_MBAG + bDstPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG + bDstPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_MBAG + bDstPos]; break; case ITEM_COSP_TO_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= COSP_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_COSP + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_COSP + bSrcPos]; pDstItem = &m_sItemArray[SLOT_MAX + bDstPos]; break; case ITEM_INVEN_TO_COSP: if (bDstPos >= COSP_MAX+MBAG_COUNT || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[SLOT_MAX + bSrcPos].nNum || !IsValidSlotPos(pTable, bDstPos)) goto fail_return; pSrcItem = &m_sItemArray[SLOT_MAX + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_COSP + bDstPos]; // If we're setting a magic bag... if (bDstPos == COSP_BAG1 || bDstPos == COSP_BAG2) { // Can't replace existing magic bag. if (pDstItem->nNum != 0 // Can't set any old item in the bag slot, it must be a bag. || pTable->m_bSlot != ItemSlotBag) goto fail_return; } break; case ITEM_INVEN_SLOT: if (bDstPos >= SLOT_MAX || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum // Ensure the item is able to be equipped in that slot || !IsValidSlotPos(pTable, bDstPos)) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[bDstPos]; break; case ITEM_SLOT_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= SLOT_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_INVEN_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_SLOT_SLOT: if (bDstPos >= SLOT_MAX || bSrcPos >= SLOT_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[bSrcPos].nNum // Ensure the item is able to be equipped in that slot || !IsValidSlotPos(pTable, bDstPos)) goto fail_return; pSrcItem = &m_sItemArray[bSrcPos]; pDstItem = &m_sItemArray[bDstPos]; break; default: return; } // If there's an item already in the target slot already, we need to just swap the items if (pDstItem->nNum != 0) { memcpy(&tmpItem, pDstItem, sizeof(_ITEM_DATA)); // Temporarily store the target item memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); // Replace the target item with the source memcpy(pSrcItem, &tmpItem, sizeof(_ITEM_DATA)); // Now replace the source with the old target (swapping them) } // Since there's no way to move a partial stack using this handler, just overwrite the destination. else { memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); // Shift the item over memset(pSrcItem, 0, sizeof(_ITEM_DATA)); // Clear out the source item's data } // If we're equipping a 2-handed weapon, we need to ensure that if there's // an item in the other weapon slot (2-handed or not), it's unequipped. if (dir == ITEM_INVEN_SLOT) { uint8 bOtherWeaponSlot = 0; if (bDstPos == LEFTHAND && pTable->m_bSlot == ItemSlot2HLeftHand) bOtherWeaponSlot = RIGHTHAND; else if (bDstPos == RIGHTHAND && pTable->is2Handed()) bOtherWeaponSlot = LEFTHAND; if (bOtherWeaponSlot != 0) { _ITEM_DATA * pUnequipItem = GetItem(bOtherWeaponSlot); if (pUnequipItem->nNum != 0) { // Place item where item that we just equipped was. memcpy(pSrcItem, pUnequipItem, sizeof(_ITEM_DATA)); memset(pUnequipItem, 0, sizeof(_ITEM_DATA)); UserLookChange(bOtherWeaponSlot, 0, 0); } } } // If equipping/de-equipping an item if (dir == ITEM_INVEN_SLOT || dir == ITEM_SLOT_INVEN // or moving an item to/from our cospre item slots || dir == ITEM_INVEN_TO_COSP || dir == ITEM_COSP_TO_INVEN || dir == ITEM_SLOT_SLOT) { // Re-update item stats SetUserAbility(false); } SendItemMove(1); SendItemWeight(); // Update everyone else, so that they can see your shiny new items (you didn't take them off did you!? DID YOU!?) switch (dir) { case ITEM_INVEN_SLOT: case ITEM_INVEN_TO_COSP: UserLookChange(bDstPos, nItemID, pDstItem->sDuration); break; case ITEM_SLOT_INVEN: case ITEM_COSP_TO_INVEN: UserLookChange(bSrcPos, 0, 0); break; case ITEM_SLOT_SLOT: UserLookChange(bSrcPos, pSrcItem->nNum, pSrcItem->sDuration); UserLookChange(bDstPos, pDstItem->nNum, pDstItem->sDuration); break; } Send2AI_UserUpdateInfo(); return; fail_return: SendItemMove(0); }
void CUser::WarehouseProcess(Packet & pkt) { Packet result(WIZ_WAREHOUSE); uint32 nItemID, nCount; uint16 sNpcId, reference_pos; uint8 page, bSrcPos, bDstPos; CNpc * pNpc = nullptr; _ITEM_TABLE * pTable = nullptr; _ITEM_DATA * pSrcItem = nullptr, * pDstItem = nullptr; uint8 opcode; bool bResult = false; if (isDead()) return; if (isTrading()) goto fail_return; pkt >> opcode; if (opcode == WAREHOUSE_OPEN) { result << uint8(WAREHOUSE_OPEN) << uint8(WAREHOUSE_OPEN) << GetInnCoins(); for (int i = 0; i < WAREHOUSE_MAX; i++) { _ITEM_DATA *pItem = &m_sWarehouseArray[i]; result << pItem->nNum << pItem->sDuration << pItem->sCount << pItem->bFlag << pItem->sRemainingRentalTime << uint32(0) << pItem->nExpirationTime; } Send(&result); return; } pkt >> sNpcId >> nItemID >> page >> bSrcPos >> bDstPos; pNpc = g_pMain->m_arNpcArray.GetData(sNpcId); if (pNpc == nullptr || pNpc->GetType() != NPC_WAREHOUSE || !isInRange(pNpc, MAX_NPC_RANGE)) goto fail_return; pTable = g_pMain->GetItemPtr(nItemID); if (pTable == nullptr) goto fail_return; reference_pos = 24 * page; switch (opcode) { // Inventory -> inn case WAREHOUSE_INPUT: pkt >> nCount; // Handle coin input. if (nItemID == ITEM_GOLD) { if (!hasCoins(nCount) || GetInnCoins() + nCount > COIN_MAX) goto fail_return; m_iBank += nCount; m_iGold -= nCount; break; } // Check for invalid slot IDs. if (bSrcPos > HAVE_MAX || reference_pos + bDstPos > WAREHOUSE_MAX // Cannot be traded, sold or stored (note: don't check the race, as these items CAN be stored). || nItemID >= ITEM_NO_TRADE // Check that the source item we're moving is what the client says it is. || (pSrcItem = GetItem(SLOT_MAX + bSrcPos))->nNum != nItemID // Rented items cannot be placed in the inn. || pSrcItem->isRented()) goto fail_return; pDstItem = &m_sWarehouseArray[reference_pos + bDstPos]; // Forbid users from moving non-stackable items into a slot already occupied by an item. if ((!pTable->isStackable() && pDstItem->nNum != 0) // Forbid users from moving stackable items into a slot already occupied by a different item. || (pTable->isStackable() && pDstItem->nNum != 0 // slot in use && pDstItem->nNum != pSrcItem->nNum) // ... by a different item. // Ensure users have enough of the specified item to move. || pSrcItem->sCount < nCount) goto fail_return; pDstItem->nNum = pSrcItem->nNum; pDstItem->sDuration = pSrcItem->sDuration; pDstItem->sCount = (uint16) nCount; pSrcItem->sCount -= nCount; pDstItem->bFlag = pSrcItem->bFlag; pDstItem->sRemainingRentalTime = pSrcItem->sRemainingRentalTime; pDstItem->nExpirationTime = pSrcItem->nExpirationTime; if (!pTable->isStackable() || nCount == pDstItem->sCount) pDstItem->nSerialNum = pSrcItem->nSerialNum; if (!pTable->isStackable() && pDstItem->nSerialNum == 0) pDstItem->nSerialNum = g_pMain->GenerateItemSerial(); if (pSrcItem->sCount == 0) memset(pSrcItem, 0, sizeof(_ITEM_DATA)); SendItemWeight(); break; // Inn -> inventory case WAREHOUSE_OUTPUT: pkt >> nCount; if (nItemID == ITEM_GOLD) { if (!hasInnCoins(nCount) || GetCoins() + nCount > COIN_MAX) goto fail_return; m_iGold += nCount; m_iBank -= nCount; break; } // Ensure we're not being given an invalid slot ID. if (reference_pos + bSrcPos > WAREHOUSE_MAX || bDstPos > HAVE_MAX // Check that the source item we're moving is what the client says it is. || (pSrcItem = &m_sWarehouseArray[reference_pos + bSrcPos])->nNum != nItemID // Does the player have enough room in their inventory? || !CheckWeight(pTable, nItemID, (uint16) nCount)) goto fail_return; pDstItem = GetItem(SLOT_MAX + bDstPos); // Forbid users from moving non-stackable items into a slot already occupied by an item. if ((!pTable->isStackable() && pDstItem->nNum != 0) // Forbid users from moving stackable items into a slot already occupied by a different item. || (pTable->isStackable() && pDstItem->nNum != 0 // slot in use && pDstItem->nNum != pSrcItem->nNum) // ... by a different item. // Ensure users have enough of the specified item to move. || pSrcItem->sCount < nCount) goto fail_return; pDstItem->nNum = pSrcItem->nNum; pDstItem->sDuration = pSrcItem->sDuration; pDstItem->sCount = (uint16) nCount; pSrcItem->sCount -= nCount; pDstItem->bFlag = pSrcItem->bFlag; pDstItem->sRemainingRentalTime = pSrcItem->sRemainingRentalTime; pDstItem->nExpirationTime = pSrcItem->nExpirationTime; if (!pTable->isStackable() || nCount == pDstItem->sCount) pDstItem->nSerialNum = pSrcItem->nSerialNum; if (!pTable->isStackable() && pDstItem->nSerialNum == 0) pDstItem->nSerialNum = g_pMain->GenerateItemSerial(); if (pSrcItem->sCount == 0) memset(pSrcItem, 0, sizeof(_ITEM_DATA)); SendItemWeight(); break; // Inn -> inn case WAREHOUSE_MOVE: // Ensure we're not being given an invalid slot ID. if (reference_pos + bSrcPos > WAREHOUSE_MAX || reference_pos + bDstPos > WAREHOUSE_MAX) goto fail_return; pSrcItem = &m_sWarehouseArray[reference_pos + bSrcPos]; pDstItem = &m_sWarehouseArray[reference_pos + bDstPos]; // Check that the source item we're moving is what the client says it is. if (pSrcItem->nNum != nItemID // You can't move a partial stack in the inn (the whole stack is moved). || pDstItem->nNum != 0) goto fail_return; memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); memset(pSrcItem, 0, sizeof(_ITEM_DATA)); break; // Inventory -> inventory (using the inn dialog) case WAREHOUSE_INVENMOVE: // Ensure we're not being given an invalid slot ID. if (bSrcPos > HAVE_MAX || bDstPos > HAVE_MAX) goto fail_return; pSrcItem = GetItem(SLOT_MAX + bSrcPos); pDstItem = GetItem(SLOT_MAX + bDstPos); // Check that the source item we're moving is what the client says it is. if (pSrcItem->nNum != nItemID // You can't move a partial stack in the inventory (the whole stack is moved). || pDstItem->nNum != 0) goto fail_return; memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); memset(pSrcItem, 0, sizeof(_ITEM_DATA)); break; } bResult = true; fail_return: // hmm... result << opcode << bResult; Send(&result); }
void CUser::WarehouseProcess(Packet & pkt) { Packet result(WIZ_WAREHOUSE); CNpc * pNpc; uint32 itemid, count; uint16 npcid, reference_pos; uint8 page, srcpos, destpos; _ITEM_TABLE* pTable = nullptr; uint8 command = pkt.read<uint8>(); bool bResult = false; if (isDead()) return; if (isTrading()) goto fail_return; if (command == WAREHOUSE_OPEN) { result << uint8(WAREHOUSE_OPEN) << uint8(WAREHOUSE_OPEN) << GetInnCoins(); for (int i = 0; i < WAREHOUSE_MAX; i++) { _ITEM_DATA *pItem = &m_sWarehouseArray[i]; result << pItem->nNum << pItem->sDuration << pItem->sCount << uint8(0) << uint16(0) << uint16(0) << uint16(0) << uint16(0); } Send(&result); return; } pkt >> npcid >> itemid >> page >> srcpos >> destpos; pNpc = g_pMain->m_arNpcArray.GetData(npcid); if (pNpc == nullptr || pNpc->GetType() != NPC_WAREHOUSE || !isInRange(pNpc, MAX_NPC_RANGE)) goto fail_return; pTable = g_pMain->GetItemPtr( itemid ); if( !pTable ) goto fail_return; reference_pos = 24 * page; // TO-DO: Clean up this entire method. It's horrendous! switch (command) { /* stuff going into the inn */ case WAREHOUSE_INPUT: pkt >> count; // Handle coin input. if (itemid == ITEM_GOLD) { if (!hasCoins(count) || GetInnCoins() + count > COIN_MAX) goto fail_return; m_iBank += count; m_iGold -= count; break; } if (srcpos > HAVE_MAX || reference_pos + destpos > WAREHOUSE_MAX || itemid >= ITEM_NO_TRADE) // Cannot be traded, sold or stored (note: don't check the race, as these items CAN be stored). goto fail_return; if (m_sItemArray[SLOT_MAX+srcpos].isSealed() || m_sItemArray[SLOT_MAX+srcpos].isRented()) goto fail_return; if( m_sItemArray[SLOT_MAX+srcpos].nNum != itemid ) goto fail_return; if( m_sWarehouseArray[reference_pos+destpos].nNum && !pTable->m_bCountable ) goto fail_return; if( m_sItemArray[SLOT_MAX+srcpos].sCount < count ) goto fail_return; m_sWarehouseArray[reference_pos+destpos].nNum = itemid; m_sWarehouseArray[reference_pos+destpos].sDuration = m_sItemArray[SLOT_MAX+srcpos].sDuration; m_sWarehouseArray[reference_pos+destpos].nSerialNum = m_sItemArray[SLOT_MAX+srcpos].nSerialNum; if( pTable->m_bCountable == 0 && m_sWarehouseArray[reference_pos+destpos].nSerialNum == 0 ) m_sWarehouseArray[reference_pos+destpos].nSerialNum = g_pMain->GenerateItemSerial(); if( pTable->m_bCountable ) { m_sWarehouseArray[reference_pos+destpos].sCount += (unsigned short)count; } else { m_sWarehouseArray[reference_pos+destpos].sCount = m_sItemArray[SLOT_MAX+srcpos].sCount; } if( !pTable->m_bCountable ) { m_sItemArray[SLOT_MAX+srcpos].nNum = 0; m_sItemArray[SLOT_MAX+srcpos].sDuration = 0; m_sItemArray[SLOT_MAX+srcpos].sCount = 0; m_sItemArray[SLOT_MAX+srcpos].nSerialNum = 0; } else { m_sItemArray[SLOT_MAX+srcpos].sCount -= (unsigned short)count; if( m_sItemArray[SLOT_MAX+srcpos].sCount <= 0 ) { m_sItemArray[SLOT_MAX+srcpos].nNum = 0; m_sItemArray[SLOT_MAX+srcpos].sDuration = 0; m_sItemArray[SLOT_MAX+srcpos].sCount = 0; m_sItemArray[SLOT_MAX+srcpos].nSerialNum = 0; } } SendItemWeight(); break; /* stuff being taken out of the inn */ case WAREHOUSE_OUTPUT: pkt >> count; if (itemid == ITEM_GOLD) { if (!hasInnCoins(count) || GetCoins() + count > COIN_MAX) goto fail_return; m_iGold += count; m_iBank -= count; break; } if (reference_pos + srcpos > WAREHOUSE_MAX || destpos > HAVE_MAX) goto fail_return; if (pTable->m_bCountable) { // Check weight of countable item. if (((pTable->m_sWeight * count) + m_sItemWeight) > m_sMaxWeight) { goto fail_return; } } else { // Check weight of non-countable item. if ((pTable->m_sWeight + m_sItemWeight) > m_sMaxWeight) { goto fail_return; } } if( m_sWarehouseArray[reference_pos+srcpos].nNum != itemid ) goto fail_return; if( m_sItemArray[SLOT_MAX+destpos].nNum && !pTable->m_bCountable ) goto fail_return; if( m_sWarehouseArray[reference_pos+srcpos].sCount < count ) goto fail_return; m_sItemArray[SLOT_MAX+destpos].nNum = itemid; m_sItemArray[SLOT_MAX+destpos].sDuration = m_sWarehouseArray[reference_pos+srcpos].sDuration; m_sItemArray[SLOT_MAX+destpos].nSerialNum = m_sWarehouseArray[reference_pos+srcpos].nSerialNum; if( pTable->m_bCountable ) m_sItemArray[SLOT_MAX+destpos].sCount += (unsigned short)count; else { if( m_sItemArray[SLOT_MAX+destpos].nSerialNum == 0 ) m_sItemArray[SLOT_MAX+destpos].nSerialNum = g_pMain->GenerateItemSerial(); m_sItemArray[SLOT_MAX+destpos].sCount = m_sWarehouseArray[reference_pos+srcpos].sCount; } if( !pTable->m_bCountable ) { m_sWarehouseArray[reference_pos+srcpos].nNum = 0; m_sWarehouseArray[reference_pos+srcpos].sDuration = 0; m_sWarehouseArray[reference_pos+srcpos].sCount = 0; m_sWarehouseArray[reference_pos+srcpos].nSerialNum = 0; } else { m_sWarehouseArray[reference_pos+srcpos].sCount -= (unsigned short)count; if( m_sWarehouseArray[reference_pos+srcpos].sCount <= 0 ) { m_sWarehouseArray[reference_pos+srcpos].nNum = 0; m_sWarehouseArray[reference_pos+srcpos].sDuration = 0; m_sWarehouseArray[reference_pos+srcpos].sCount = 0; m_sWarehouseArray[reference_pos+srcpos].nSerialNum = 0; } } SendItemWeight(); //TRACE("WARE OUTPUT : %s %s %d %d %d %d %d", m_id, m_Accountid, ITEM_WAREHOUSE_GET, 0, itemid, count, m_sItemArray[SLOT_MAX+destpos].sDuration ); break; case WAREHOUSE_MOVE: if( reference_pos+srcpos > WAREHOUSE_MAX ) goto fail_return; if( m_sWarehouseArray[reference_pos+srcpos].nNum != itemid ) goto fail_return; if( m_sWarehouseArray[reference_pos+destpos].nNum ) goto fail_return; m_sWarehouseArray[reference_pos+destpos].nNum = itemid; m_sWarehouseArray[reference_pos+destpos].sDuration = m_sWarehouseArray[reference_pos+srcpos].sDuration; m_sWarehouseArray[reference_pos+destpos].sCount = m_sWarehouseArray[reference_pos+srcpos].sCount; m_sWarehouseArray[reference_pos+destpos].nSerialNum = m_sWarehouseArray[reference_pos+srcpos].nSerialNum; m_sWarehouseArray[reference_pos+srcpos].nNum = 0; m_sWarehouseArray[reference_pos+srcpos].sDuration = 0; m_sWarehouseArray[reference_pos+srcpos].sCount = 0; m_sWarehouseArray[reference_pos+srcpos].nSerialNum = 0; break; case WAREHOUSE_INVENMOVE: if( itemid != m_sItemArray[SLOT_MAX+srcpos].nNum ) goto fail_return; { short duration = m_sItemArray[SLOT_MAX+srcpos].sDuration; short itemcount = m_sItemArray[SLOT_MAX+srcpos].sCount; uint64 serial = m_sItemArray[SLOT_MAX+srcpos].nSerialNum; m_sItemArray[SLOT_MAX+srcpos].nNum = m_sItemArray[SLOT_MAX+destpos].nNum; m_sItemArray[SLOT_MAX+srcpos].sDuration = m_sItemArray[SLOT_MAX+destpos].sDuration; m_sItemArray[SLOT_MAX+srcpos].sCount = m_sItemArray[SLOT_MAX+destpos].sCount; m_sItemArray[SLOT_MAX+srcpos].nSerialNum = m_sItemArray[SLOT_MAX+destpos].nSerialNum; m_sItemArray[SLOT_MAX+destpos].nNum = itemid; m_sItemArray[SLOT_MAX+destpos].sDuration = duration; m_sItemArray[SLOT_MAX+destpos].sCount = itemcount; m_sItemArray[SLOT_MAX+destpos].nSerialNum = serial; } break; } bResult = true; fail_return: // hmm... result << uint8(command) << bResult; Send(&result); }
void CUser::ItemMove(Packet & pkt) { _ITEM_DATA *pSrcItem, *pDstItem, tmpItem; uint32 nItemID; uint8 dir, bSrcPos, bDstPos; pkt >> dir >> nItemID >> bSrcPos >> bDstPos; if (isTrading() || isMerchanting()) goto fail_return; _ITEM_TABLE *pTable = g_pMain->GetItemPtr(nItemID); if (pTable == NULL // || dir == ITEM_INVEN_SLOT && ((pTable->m_sWeight + m_sItemWeight) > m_sMaxWeight)) // || dir > ITEM_MBAG_TO_MBAG || bSrcPos >= SLOT_MAX+HAVE_MAX+COSP_MAX+MBAG_MAX || bDstPos >= SLOT_MAX+HAVE_MAX+COSP_MAX+MBAG_MAX || ((dir == ITEM_INVEN_SLOT || dir == ITEM_SLOT_SLOT) && (bDstPos > SLOT_MAX || !ItemEquipAvailable(pTable))) || (dir == ITEM_SLOT_INVEN && bSrcPos > SLOT_MAX) || (dir == ITEM_INVEN_SLOT && bDstPos == RESERVED) || (dir == ITEM_SLOT_INVEN && bDstPos == RESERVED)) goto fail_return; switch (dir) { case ITEM_MBAG_TO_MBAG: if (bDstPos >= MBAG_TOTAL || bSrcPos >= MBAG_TOTAL // We also need to make sure that if we're setting an item in a magic bag, we need to actually // have a magic back to put the item in! || (INVENTORY_MBAG+bDstPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG+bDstPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_MBAG + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_MBAG + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_MBAG + bDstPos]; break; case ITEM_MBAG_TO_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= MBAG_TOTAL // We also need to make sure that if we're taking an item from a magic bag, we need to actually // have a magic back to take it from! || (INVENTORY_MBAG+bSrcPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG+bSrcPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_MBAG + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_MBAG + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_INVEN_TO_MBAG: if (bDstPos >= MBAG_TOTAL || bSrcPos >= HAVE_MAX // We also need to make sure that if we're adding an item to a magic bag, we need to actually // have a magic back to put the item in! || (INVENTORY_MBAG + bDstPos < INVENTORY_MBAG2 && m_sItemArray[BAG1].nNum == 0) || (INVENTORY_MBAG + bDstPos >= INVENTORY_MBAG2 && m_sItemArray[BAG2].nNum == 0) // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_MBAG + bDstPos]; break; case ITEM_COSP_TO_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= COSP_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_COSP + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_COSP + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_INVEN_TO_COSP: // TO-DO: Update IsValidSlotPos() for cospre items? if (bDstPos >= COSP_MAX || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_COSP + bDstPos]; break; case ITEM_INVEN_SLOT: if (bDstPos >= SLOT_MAX || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum // Ensure the item is able to be equipped in that slot || !IsValidSlotPos(pTable, bDstPos)) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[bDstPos]; break; case ITEM_SLOT_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= SLOT_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_INVEN_INVEN: if (bDstPos >= HAVE_MAX || bSrcPos >= HAVE_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[INVENTORY_INVENT + bSrcPos].nNum) goto fail_return; pSrcItem = &m_sItemArray[INVENTORY_INVENT + bSrcPos]; pDstItem = &m_sItemArray[INVENTORY_INVENT + bDstPos]; break; case ITEM_SLOT_SLOT: if (bDstPos >= SLOT_MAX || bSrcPos >= SLOT_MAX // Make sure that the item actually exists there. || nItemID != m_sItemArray[bSrcPos].nNum // Ensure the item is able to be equipped in that slot || !IsValidSlotPos(pTable, bDstPos)) goto fail_return; pSrcItem = &m_sItemArray[bSrcPos]; pDstItem = &m_sItemArray[bDstPos]; break; default: return; } // If there's an item already in the target slot already, we need to just swap the items if (pDstItem->nNum != 0) { memcpy(&tmpItem, pDstItem, sizeof(_ITEM_DATA)); // Temporarily store the target item memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); // Replace the target item with the source memcpy(pSrcItem, &tmpItem, sizeof(_ITEM_DATA)); // Now replace the source with the old target (swapping them) } // Since there's no way to move a partial stack using this handler, just overwrite the destination. else { memcpy(pDstItem, pSrcItem, sizeof(_ITEM_DATA)); // Shift the item over memset(pSrcItem, 0, sizeof(_ITEM_DATA)); // Clear out the source item's data } // If equipping/de-equipping an item if (dir == ITEM_INVEN_SLOT || dir == ITEM_SLOT_INVEN // or moving an item to/from our cospre item slots || dir == ITEM_INVEN_TO_COSP || dir == ITEM_COSP_TO_INVEN || dir == ITEM_SLOT_SLOT) { // Re-update item stats SetSlotItemValue(); SetUserAbility(false); } SendItemMove(1); SendItemWeight(); // Update everyone else, so that they can see your shiny new items (you didn't take them off did you!? DID YOU!?) if (dir == ITEM_INVEN_SLOT) UserLookChange(bDstPos, nItemID, pDstItem->sDuration); if (dir == ITEM_SLOT_INVEN) UserLookChange(bSrcPos, 0, 0); if (dir == ITEM_SLOT_SLOT) { UserLookChange(bSrcPos, pSrcItem->nNum, pSrcItem->sDuration); UserLookChange(bDstPos, pDstItem->nNum, pDstItem->sDuration); } if (dir == ITEM_INVEN_TO_COSP) UserLookChange(INVENTORY_COSP + bDstPos, nItemID, pDstItem->sDuration); if (dir == ITEM_COSP_TO_INVEN) UserLookChange(INVENTORY_INVENT + bSrcPos, 0, 0); Send2AI_UserUpdateInfo(); return; fail_return: SendItemMove(0); }