예제 #1
0
// 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;
	}
예제 #2
0
// 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;
	}
예제 #3
0
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);
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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);
	}
}
예제 #7
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);
}
예제 #8
0
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);
}
예제 #9
0
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);
}