// NPC shops void CUser::ItemTrade(Packet & pkt) { Packet result(WIZ_ITEM_TRADE, uint8(1)); uint32 transactionPrice; int itemid = 0, money = 0, group = 0; uint16 npcid; uint8 ibuy = 1; uint16 count, real_count = 0; _ITEM_TABLE* pTable = nullptr; CNpc* pNpc = nullptr; uint8 type, pos, destpos, errorCode = 1; bool bSuccess = true; _KNIGHTS_SIEGE_WARFARE *pSiegeWar = g_pMain->GetSiegeMasterKnightsPtr(1); CKingSystem *pKingSystem = g_pMain->m_KingSystemArray.GetData(GetNation()); if (isDead()) { errorCode = 1; goto send_packet; } pkt >> type; // Buy == 1, Sell == 2 if (type == 1 || type == 2) { pkt >> group >> npcid >>ibuy; if (!g_pMain->m_bPointCheckFlag || (pNpc = g_pMain->GetNpcPtr(npcid)) == nullptr || (pNpc->GetType() != NPC_MERCHANT && pNpc->GetType() != NPC_TINKER) || pNpc->m_iSellingGroup != group || !isInRange(pNpc, MAX_NPC_RANGE)) goto fail_return; }
// NPC shops void CUser::ItemTrade(Packet & pkt) { Packet result(WIZ_ITEM_TRADE); uint32 transactionPrice; int itemid = 0, money = 0, group = 0; uint16 npcid; uint16 count, real_count = 0; _ITEM_TABLE* pTable = nullptr; CNpc* pNpc = nullptr; uint8 type, pos, destpos, errorCode = 1; bool bSuccess = true; if (isDead()) { errorCode = 1; goto send_packet; } pkt >> type; // Buy == 1, Sell == 2 if (type == 1 || type == 2) { pkt >> group >> npcid; if (!g_pMain->m_bPointCheckFlag || (pNpc = g_pMain->GetNpcPtr(npcid)) == nullptr || (pNpc->GetType() != NPC_MERCHANT && pNpc->GetType() != NPC_TINKER) || pNpc->m_iSellingGroup != group || !isInRange(pNpc, MAX_NPC_RANGE)) goto fail_return; }
void CGameSocket::RecvGateOpen(Packet & pkt) { uint16 nid; bool byGateOpen; pkt >> nid >> byGateOpen; if (nid < NPC_BAND) { TRACE("#### RecvGateOpen() nid Fail --> nid = %d ####\n", nid); return; } CNpc* pNpc = g_pMain->m_arNpc.GetData(nid); if (pNpc == nullptr) return; if (!pNpc->isGate()) { TRACE("#### RecvGateOpen() NpcType Fail --> type = %d ####\n", pNpc->GetType()); return; } pNpc->m_byGateOpen = byGateOpen; TRACE("**** RecvGateOpen()---> nid = %d, byGateOpen = %d ******\n", nid, byGateOpen); }
void CUser::ItemRepair(Packet & pkt) { if (isDead()) return; Packet result(WIZ_ITEM_REPAIR); uint32 money, itemid; uint16 durability, quantity, sNpcID; _ITEM_TABLE* pTable = nullptr; CNpc *pNpc = nullptr; uint8 sPos, sSlot; pkt >> sPos >> sSlot >> sNpcID >> itemid; if (sPos == 1 ) { // SLOT if (sSlot >= SLOT_MAX) goto fail_return; if (m_sItemArray[sSlot].nNum != itemid) goto fail_return; } else if (sPos == 2 ) { // INVEN if (sSlot >= HAVE_MAX) goto fail_return; if (m_sItemArray[SLOT_MAX+sSlot].nNum != itemid) goto fail_return; } pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr || pNpc->GetType() != NPC_TINKER || !isInRange(pNpc, MAX_NPC_RANGE)) return; pTable = g_pMain->GetItemPtr( itemid ); if (pTable == nullptr || pTable->m_iSellPrice == SellTypeNoRepairs) goto fail_return; durability = pTable->m_sDuration; if( durability == 1 ) goto fail_return; if( sPos == 1 ) quantity = pTable->m_sDuration - m_sItemArray[sSlot].sDuration; else if( sPos == 2 ) quantity = pTable->m_sDuration - m_sItemArray[SLOT_MAX+sSlot].sDuration; money = (unsigned int)((((pTable->m_iBuyPrice-10) / 10000.0f) + pow((float)pTable->m_iBuyPrice, 0.75f)) * quantity / (double)durability); if (!GoldLose(money, false)) goto fail_return; if (sPos == 1) m_sItemArray[sSlot].sDuration = durability; else if( sPos == 2 ) m_sItemArray[SLOT_MAX+sSlot].sDuration = durability; result << uint8(1) << GetCoins(); Send(&result); return; fail_return: result << uint8(0) << GetCoins(); Send(&result); }
void CUser::ClientEvent(uint16 sNpcID) { // Ensure AI's loaded if (!g_pMain->m_bPointCheckFlag || isDead()) return; int32 iEventID = 0; CNpc *pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr || !isInRange(pNpc, MAX_NPC_RANGE)) return; m_sEventNid = sNpcID; m_sEventSid = pNpc->GetProtoID(); // For convenience purposes with Lua scripts. // Aww. if (pNpc->GetType() == NPC_KISS) { KissUser(); return; } FastGuard lock(g_pMain->m_questNpcLock); QuestNpcList::iterator itr = g_pMain->m_QuestNpcList.find(pNpc->GetProtoID()); if (itr == g_pMain->m_QuestNpcList.end()) return; // Copy it. We should really lock the list, but nevermind. QuestHelperList & pList = itr->second; _QUEST_HELPER * pHelper = nullptr; foreach(itr, pList) { if ((*itr) == nullptr || (*itr)->sEventDataIndex || (*itr)->bEventStatus || ((*itr)->bNation != 3 && (*itr)->bNation != GetNation()) || ((*itr)->bClass != 5 && !JobGroupCheck((*itr)->bClass))) continue; pHelper = (*itr); break; } if (pHelper == nullptr) return; QuestV2RunEvent(pHelper, pHelper->nEventTriggerIndex); }
void CUser::NpcEvent(Packet & pkt) { // Ensure AI is loaded first if (!g_pMain->m_bPointCheckFlag || isDead()) return; Packet result; uint8 bUnknown = pkt.read<uint8>(); uint16 sNpcID = pkt.read<uint16>(); int32 nQuestID = pkt.read<int32>(); CNpc *pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr || !isInRange(pNpc, MAX_NPC_RANGE)) return; switch (pNpc->GetType()) { case NPC_MERCHANT: case NPC_TINKER: result.SetOpcode(pNpc->GetType() == NPC_MERCHANT ? WIZ_TRADE_NPC : WIZ_REPAIR_NPC); result << pNpc->m_iSellingGroup; Send(&result); break; /*case NPC_MENU: result.SetOpcode(WIZ_QUEST); result << uint8(7) << uint16(SendNPCMenu(pNpc->m_sSid)) << uint16(0) << uint16(pNpc->m_sSid); Send(&result); break; */ case NPC_MARK: result.SetOpcode(WIZ_KNIGHTS_PROCESS); result << uint8(KNIGHTS_CAPE_NPC); Send(&result); break; case NPC_RENTAL: result.SetOpcode(WIZ_RENTAL); result << uint8(RENTAL_NPC) << uint16(1) // 1 = enabled, -1 = disabled << pNpc->m_iSellingGroup; Send(&result); break; case NPC_ELECTION: case NPC_TREASURY: { CKingSystem * pKingSystem = g_pMain->m_KingSystemArray.GetData(GetNation()); result.SetOpcode(WIZ_KING); if (pNpc->GetType() == NPC_ELECTION) { // Ensure this still works as per official without a row in the table. string strKingName = (pKingSystem == nullptr ? "" : pKingSystem->m_strKingName); result.SByte(); result << uint8(KING_NPC) << strKingName; } else { // Ensure this still works as per official without a row in the table. uint32 nTribute = (pKingSystem == nullptr ? 0 : pKingSystem->m_nTribute + pKingSystem->m_nTerritoryTax); uint32 nTreasury = (pKingSystem == nullptr ? 0 : pKingSystem->m_nNationalTreasury); result << uint8(KING_TAX) << uint8(1) // success << uint16(isKing() ? 1 : 2) // 1 enables king-specific stuff (e.g. scepter), 2 is normal user stuff << nTribute << nTreasury; } Send(&result); } break; case NPC_CAPTAIN: result.SetOpcode(WIZ_CLASS_CHANGE); result << uint8(CLASS_CHANGE_REQ); Send(&result); break; case NPC_WAREHOUSE: result.SetOpcode(WIZ_WAREHOUSE); result << uint8(WAREHOUSE_REQ); Send(&result); break; case NPC_CHAOTIC_GENERATOR: case NPC_CHAOTIC_GENERATOR2: SendAnvilRequest(sNpcID, ITEM_BIFROST_REQ); break; case NPC_CLAN: // this HAS to go. result << uint16(0); // page 0 CKnightsManager::AllKnightsList(this, result); default: ClientEvent(sNpcID); } }
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::ClientEvent(uint16 sNpcID) { // Ensure AI's loaded if (!g_pMain->m_bPointCheckFlag || isDead()) return; int32 iEventID = 0; CNpc *pNpc = g_pMain->GetNpcPtr(sNpcID); if (pNpc == nullptr || !isInRange(pNpc, MAX_NPC_RANGE)) return; m_sEventNid = sNpcID; m_sEventSid = pNpc->GetProtoID(); // For convenience purposes with Lua scripts. if (pNpc->GetProtoID() == SAW_BLADE_SSID) { HpChange(-5000 / 10); return; } else if (pNpc->GetProtoID() == CHAOS_CUBE_SSID && !pNpc->isDead()) { uint8 nEventRoomUserCount = g_pMain->TempleEventGetRoomUsers(GetEventRoom()); uint8 nItemRewardRankFirst = nEventRoomUserCount / 3; uint8 nItemRewardRankSecond = (nEventRoomUserCount - 1) * 2; int32 nUserRank = GetPlayerRank(RANK_TYPE_CHAOS_DUNGEON); uint32 nItemID = 0; if (nUserRank == 0) nItemID = ITEM_KILLING_BLADE; else if (nUserRank < nItemRewardRankFirst) nItemID = ITEM_LIGHT_PIT; else if (nUserRank >= nItemRewardRankFirst && nUserRank <= nItemRewardRankSecond) nItemID = ITEM_DRAIN_RESTORE; else if (nUserRank > nItemRewardRankSecond) nItemID = ITEM_KILLING_BLADE; GiveItem(nItemID); g_pMain->ShowNpcEffect(GetSocketID(),251,GetZoneID()); g_pMain->KillNpc(sNpcID); return; } else if (pNpc->GetType() == NPC_KISS) { KissUser(); return; } Guard lock(g_pMain->m_questNpcLock); QuestNpcList::iterator itr = g_pMain->m_QuestNpcList.find(pNpc->GetProtoID()); if (itr == g_pMain->m_QuestNpcList.end()) return; QuestHelperList & pList = itr->second; _QUEST_HELPER * pHelper = nullptr; foreach (itr, pList) { if ((*itr) == nullptr || (*itr)->sEventDataIndex || (*itr)->bEventStatus || ((*itr)->bNation != 3 && (*itr)->bNation != GetNation()) || ((*itr)->bClass != 5 && !JobGroupCheck((*itr)->bClass))) continue; pHelper = (*itr); break; } if (pHelper == nullptr) return; QuestV2RunEvent(pHelper, pHelper->nEventTriggerIndex); }