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); }
BOOL CUser::CheckEventLogic(EVENT_DATA *pEventData) // This part reads all the 'A' parts and checks if the { // requirements for the 'E' parts are met. if( !pEventData ) return FALSE; BOOL bExact = TRUE; list<LOGIC_ELSE*>::iterator Iter; for( Iter = pEventData->m_arLogicElse.begin(); Iter != pEventData->m_arLogicElse.end(); Iter++ ) { bExact = FALSE; LOGIC_ELSE* pLE = (*Iter); if( !pLE ) return FALSE; switch( pLE->m_LogicElse ) { case LOGIC_CHECK_UNDER_WEIGHT: if( pLE->m_LogicElseInt[0]+m_sItemWeight >= m_sMaxWeight ) bExact = TRUE; break; case LOGIC_CHECK_OVER_WEIGHT: if( pLE->m_LogicElseInt[0]+m_sItemWeight < m_sMaxWeight ) bExact = TRUE; break; case LOGIC_CHECK_SKILL_POINT: if( CheckSkillPoint(pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1], pLE->m_LogicElseInt[2]) ) bExact = TRUE; break; case LOGIC_EXIST_ITEM: if ( CheckExistItem(pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1]) ) bExact = TRUE; break; case LOGIC_CHECK_CLASS: if (CheckClass( pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1], pLE->m_LogicElseInt[2], pLE->m_LogicElseInt[3], pLE->m_LogicElseInt[4], pLE->m_LogicElseInt[5])) { bExact = TRUE; } break; case LOGIC_CHECK_WEIGHT: if (!CheckWeight( pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1])) { bExact = TRUE; } break; case LOGIC_RAND: if (CheckRandom(pLE->m_LogicElseInt[0])) { bExact = TRUE; } break; // // ????? ???? >.< case LOGIC_CHECK_LEVEL: if( m_pUserData->m_bLevel >= pLE->m_LogicElseInt[0] && m_pUserData->m_bLevel <= pLE->m_LogicElseInt[1] ) { bExact = TRUE; } break; case LOGIC_NOEXIST_COM_EVENT: if (!ExistComEvent(pLE->m_LogicElseInt[0])) { bExact = TRUE; } break; case LOGIC_EXIST_COM_EVENT: if (ExistComEvent(pLE->m_LogicElseInt[0])) { bExact = TRUE; } break; case LOGIC_HOWMUCH_ITEM: if ( CheckItemCount(pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1], pLE->m_LogicElseInt[2]) ) { bExact = TRUE; } break; case LOGIC_CHECK_NOAH: if ( m_pUserData->m_iGold >= pLE->m_LogicElseInt[0] && m_pUserData->m_iGold <= pLE->m_LogicElseInt[1] ) { bExact = TRUE; } break; // // /* case LOGIC_CHECK_NATION: if( pLE->m_LogicElseInt[0] == m_pUserData->m_bNation ) { bExact = TRUE; } break; case LOGIC_CHECK_LEVEL: if( m_pUserData->m_bLevel >= pLE->m_LogicElseInt[0] && m_pUserData->m_bLevel <= pLE->m_LogicElseInt[1] ) { bExact = TRUE; } break; case LOGIC_NOEXIST_ITEM: if (ItemCountChange(pLE->m_LogicElseInt[0], 1, 0) < 2) { bExact = TRUE; } break; case LOGIC_QUEST_END: break; case LOGIC_QUEST_LOG: break; case LOGIC_CHECK_NOAH: if(m_pUserData->m_iGold >= pLE->m_LogicElseInt[0]) { bExact = TRUE; } break; case LOGIC_CHECK_RACE: if (pLE->m_LogicElseInt[0] == m_pUserData->m_bRace) { bExact = TRUE; } break; ///////// These logics are for the test quest. case LOGIC_EXIST_ITEM: if (CheckExistItem(pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1])) { bExact = TRUE; } break; case LOGIC_CHECK_CLASS: if (CheckClass( pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1], pLE->m_LogicElseInt[2], pLE->m_LogicElseInt[3], pLE->m_LogicElseInt[4], pLE->m_LogicElseInt[5])) { bExact = TRUE; } break; case LOGIC_CHECK_WEIGHT: if (CheckWeight( pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1])) { bExact = TRUE; } break; case LOGIC_CHECK_SKILLPOINT: if (CheckSkillPoint(pLE->m_LogicElseInt[0], pLE->m_LogicElseInt[1], pLE->m_LogicElseInt[2])) { bExact = TRUE; } break; */ default: return FALSE; } if( !pLE->m_bAnd ) { // OR ????? ??? bExact?? TRUE??? ??ü?? TRUE??? if(bExact) return TRUE; } else { // AND ????? ??? bExact?? FALSE??? ??ü?? FALSE??? if(!bExact) return FALSE; } } return bExact; }
bool CUser::CheckWeight(uint32 nItemID, uint16 sCount) { _ITEM_TABLE * pTable = g_pMain->GetItemPtr(nItemID); return CheckWeight(pTable, nItemID, sCount); }