DragonNest/Server/DNGameServer/DnItemTask.cpp
2024-12-20 16:56:44 +08:00

2686 lines
179 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "DnItemTask.h"
#include "GameSendPacket.h"
#include "DnPlayerActor.h"
#include "DnDropItem.h"
#include "DNUserSession.h"
#include "DNLogConnection.h"
#include "DnEmblemFactory.h"
#include "DNMasterConnectionManager.h"
#include "DNLogConnection.h"
#include "DNUserSession.h"
#include "DNGameDataManager.h"
#include "TaskManager.h"
#include "DnGameTask.h"
#include "DNMissionSystem.h"
#include "DNDBConnectionManager.h"
#include "DnStateBlow.h"
#include "DnNPCActor.h"
#include "DNRestraint.h"
#include "DnSkillTask.h"
#include "DnPartyTask.h"
#include "DNDBConnection.h"
CDnItemTask::CDnItemTask(CDNGameRoom * pRoom)
: CTask( pRoom )
, CMultiSingleton<CDnItemTask, MAX_SESSION_COUNT>( pRoom )
{
}
CDnItemTask::~CDnItemTask()
{
}
bool CDnItemTask::Initialize()
{
return true;
}
void CDnItemTask::Process( LOCAL_TIME LocalTime, float fDelta )
{
}
int CDnItemTask::OnDispatchMessage( CDNUserSession * pSession, int nMainCmd, int nSubCmd, char *pData, int nLen )
{
if (pSession->IsCertified() == false)
{
g_Log.Log(LogType::_MOVEPACKET_SEQ, pSession, L"CDnItemTask::OnDispatchMessage RState[%d] UState[%d] SCMD[%d]\n", GetRoom()->GetRoomState(), pSession->GetState(), nSubCmd);
return ERROR_NONE;
}
switch( nMainCmd ) {
case CS_ITEM: return OnRecvItemMessage( pSession, nSubCmd, pData, nLen );
case CS_ITEMGOODS: return OnRecvItemGoodsMessage( pSession, nSubCmd, pData, nLen );
}
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemMessage( CDNUserSession * pSession, int nSubCmd, char *pData, int nLen )
{
switch( nSubCmd ) {
case eItem::CS_MOVEITEM: return OnRecvItemMoveItem( pSession, (CSMoveItem*)pData, nLen );
case eItem::CS_MOVECASHITEM: return OnRecvItemMoveCashItem( pSession, (CSMoveCashItem*)pData, nLen );
case eItem::CS_REMOVEITEM: return OnRecvItemRemoveItem( pSession, (CSRemoveItem*)pData, nLen );
case eItem::CS_REMOVECASH: return pSession->OnRecvItemMessage(nSubCmd, pData, nLen);
case eItem::CS_USEITEM: return OnRecvItemUseItem( pSession, (CSUseItem*)pData, nLen);
case eItem::CS_REBIRTH: return OnRecvRebirth( pSession, nLen );
case eItem::CS_REBIRTH_COIN: return OnRecvRebirthCoin( pSession, nLen );
#ifdef _ADD_NEWDISJOINT
case eItem::CS_DISJOINT_REQ: return OnRecvItemDisjoint( pSession, (CSItemDisjointReqNew* )pData, nLen );
#else
case eItem::CS_DISJOINT_REQ: return OnRecvItemDisjoint(pSession, (CSItemDisjointReq*)pData, nLen);
#endif
case eItem::CS_COMPLETE_RANDOMITEM: return OnRecvItemCompleteRandomItem( pSession, (CSCompleteRandomItem *)pData, nLen );
case eItem::CS_CANCEL_RANDOMITEM: return OnRecvItemCancelRandomItem( pSession, pData, nLen );
case eItem::CS_SORTINVENTORY: return OnRecvItemSortInventory( pSession, (CSSortInventory*)pData, nLen );
case eItem::CS_ENCHANT: return OnRecvItemEnchant( pSession, (CSEnchantItem*)pData, nLen );
case eItem::CS_ENCHANTCOMPLETE: return OnRecvItemEnchantComplete( pSession, (CSEnchantItem*)pData, nLen );
case eItem::CS_ENCHANTCANCEL: return OnRecvItemEnchantCancel( pSession, nLen );
case eItem::CS_ITEM_COMPOUND_OPEN_REQ: return OnRecvItemCompoundOpenReq( pSession, reinterpret_cast<CSItemCompoundOpenReq*>(pData), nLen );
case eItem::CS_ITEM_COMPOUND_REQ: return OnrecvItemCompoundReq( pSession, reinterpret_cast<CSCompoundItemReq*>(pData), nLen );
case eItem::CS_ITEM_COMPOUND_CANCEL_REQ: return OnRecvItemCompoundCancelReq( pSession, reinterpret_cast<CSItemCompoundCancelReq*>(pData), nLen );
case eItem::CS_MODITEMEXPIREDATE: return OnRecvItemModitemExpireDate(pSession, (CSModItemExpireDate*)pData, nLen);
case eItem::CS_DELETE_PET_SKILL: return OnRecvItemDeletePetSkill(pSession, (CSPetSkillDelete*)pData, nLen);
// 서버 Item 쪽에서 알려주는 것들
case eItem::SC_PICKUP: return OnRecvItemPickupItem( pSession, (SCPickUp*)pData, nLen );
case eItem::SC_REFRESHQUESTINVEN: return OnRecvItemRefreshQItem( pSession, (SCRefreshQuestInven *)pData, nLen );
case eItem::SC_REMOVEQUESTITEM: return OnRecvItemRemoveQItem( pSession, (SCRemoveItem *)pData, nLen );
case eItem::SC_REFRESHINVEN: return OnRecvItemRefreshInven( pSession, (SCRefreshInven *)pData, nLen );
case eItem::SC_REFRESHCASHINVEN: return OnRecvItemRefreshCashInven( pSession, (SCRefreshCashInven *)pData, nLen );
case eItem::SC_REFRESHEQUIP: return OnRecvItemRefreshEquip( pSession, (SCRefreshEquip *)pData, nLen );
case eItem::CS_SORTWAREHOUSE: return OnRecvItemWarehouseSort(pSession, (CSSortWarehouse*)pData, nLen);
#if defined(PRE_ADD_EQUIPLOCK)
case eItem::CS_ITEM_LOCK_REQ: return pSession->OnRecvItemMessage(nSubCmd, pData, nLen);
case eItem::CS_ITEM_UNLOCK_REQ:return pSession->OnRecvItemMessage(nSubCmd, pData, nLen);
#endif // #if defined(PRE_ADD_EQUIPLOCK)
default: return ERROR_UNKNOWN_HEADER; //상위에서 리턴이 되지 않았다면 진짜 처리 않하는 패킷 수신이 된거다
}
}
int CDnItemTask::OnRecvItemGoodsMessage( CDNUserSession * pSession, int nSubCmd, char *pData, int nLen )
{
return pSession->OnRecvItemGoodsMessage(nSubCmd, pData, nLen);
}
int CDnItemTask::OnRecvItemMoveItem( CDNUserSession *pSession, CSMoveItem *pPacket, int nLen )
{
if (sizeof(CSMoveItem) != nLen)
return ERROR_INVALIDPACKET;
// 창고 관련한 애들은 Blind상태로 들어옴..
if (!pSession->IsNoneWindowState() && !pSession->IsWindowState(WINDOW_BLIND))
{
int nRet = ERROR_ITEM_FAIL;
switch(pPacket->cMoveType)
{
case MoveType_EquipToInven: nRet = ERROR_ITEM_EQUIPTOINVEN_FAIL; break;
case MoveType_InvenToEquip: nRet = ERROR_ITEM_INVENTOEQUIP_FAIL; break;
}
pSession->SendMoveItem(pPacket->cMoveType, pPacket->cSrcIndex, pPacket->cDestIndex, NULL, NULL, nRet);
return ERROR_NONE;
}
// SyncWait 상태에서 아이템 이동시 에러 처리합니다. ( 클라에서도 한번 막지만 서버에서도 한번더 체크합니다. )
if( CDnPartyTask::IsActive(GetRoom()) && !CDnPartyTask::GetInstance( GetRoom() ).IsSyncComplete() ) {
pSession->SendMoveItem(pPacket->cMoveType, pPacket->cSrcIndex, pPacket->cDestIndex, NULL, NULL, ERROR_ITEM_FAIL);
return ERROR_NONE;
}
switch(pPacket->cMoveType)
{
case MoveType_Ware:
case MoveType_InvenToWare:
case MoveType_WareToInven:
{
if( pSession->GetItem()->OnRecvMoveItem( pPacket ) == true )
{
switch( pPacket->cMoveType )
{
case MoveType_InvenToWare:
{
if( pPacket->cSrcIndex != -1 )
RemoveInventoryItem( pSession, pPacket->cSrcIndex );
break;
}
case MoveType_WareToInven:
{
if( pPacket->cDestIndex != -1 )
{
const TItem* pItemData = pSession->GetItem()->GetInventory( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 )
{
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cDestIndex, pItem );
}
}
break;
}
}
}
return ERROR_NONE;
}
case MoveType_Equip:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 ) {
if( pPacket->cSrcIndex < EQUIP_WEAPON1 )
pActor->DetachParts( (CDnParts::PartsTypeEnum)pPacket->cSrcIndex );
else
pActor->DetachWeapon( pPacket->cSrcIndex - EQUIP_WEAPON1 );
RemoveEquipItem( pSession, pPacket->cSrcIndex );
}
if( pPacket->cDestIndex != -1 ) {
if( pPacket->cDestIndex < EQUIP_WEAPON1 )
pActor->DetachParts( (CDnParts::PartsTypeEnum)pPacket->cDestIndex );
else
pActor->DetachWeapon( pPacket->cDestIndex - EQUIP_WEAPON1 );
RemoveEquipItem( pSession, pPacket->cDestIndex );
}
const TItem *pItemData = pSession->GetItem()->GetEquip( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertEquipItem( pSession, pPacket->cSrcIndex, pItem );
if( pItem ) {
if( pPacket->cSrcIndex < EQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cSrcIndex );
}
else {
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cSrcIndex - EQUIP_WEAPON1 );
}
}
}
pItemData = pSession->GetItem()->GetEquip( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertEquipItem( pSession, pPacket->cDestIndex, pItem );
if( pItem ) {
if( pPacket->cDestIndex < EQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cDestIndex );
}
else {
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cDestIndex - EQUIP_WEAPON1 );
}
}
}
pActor->RefreshState();
return ERROR_NONE;
}
break;
}
case MoveType_Inven:
{
if( pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
if( pPacket->cSrcIndex != -1 ) RemoveInventoryItem( pSession, pPacket->cSrcIndex );
if( pPacket->cDestIndex != -1 ) RemoveInventoryItem( pSession, pPacket->cDestIndex );
const TItem *pItemData = pSession->GetItem()->GetInventory( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cSrcIndex, pItem );
}
pItemData = pSession->GetItem()->GetInventory( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cDestIndex, pItem );
}
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_QuestInven:
{
if( pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
return ERROR_NONE;
}
return ERROR_NONE;
}
break;
case MoveType_EquipToInven:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 ) {
if( pPacket->cSrcIndex < EQUIP_WEAPON1 )
pActor->DetachParts( (CDnParts::PartsTypeEnum)pPacket->cSrcIndex );
else
pActor->DetachWeapon( pPacket->cSrcIndex - EQUIP_WEAPON1 );
RemoveEquipItem( pSession, pPacket->cSrcIndex );
}
if( pPacket->cDestIndex != -1 ) {
RemoveInventoryItem( pSession, pPacket->cDestIndex );
}
const TItem *pItemData = pSession->GetItem()->GetEquip( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertEquipItem( pSession, pPacket->cSrcIndex, pItem );
if( pItem ) {
if( pPacket->cSrcIndex < EQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cSrcIndex );
}
else {
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cSrcIndex - EQUIP_WEAPON1 );
}
}
}
pItemData = pSession->GetItem()->GetInventory( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cDestIndex, pItem );
}
pActor->RefreshState();
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_InvenToEquip:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 ) {
RemoveInventoryItem( pSession, pPacket->cSrcIndex );
}
if( pPacket->cDestIndex != -1 ) {
if( pPacket->cDestIndex < EQUIP_WEAPON1 )
pActor->DetachParts( (CDnParts::PartsTypeEnum)pPacket->cDestIndex );
else
pActor->DetachWeapon( pPacket->cDestIndex - EQUIP_WEAPON1 );
RemoveEquipItem( pSession, pPacket->cDestIndex );
}
const TItem *pItemData = pSession->GetItem()->GetInventory( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cSrcIndex, pItem );
}
pItemData = pSession->GetItem()->GetEquip( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertEquipItem( pSession, pPacket->cDestIndex, pItem );
if( pItem ) {
if( pPacket->cDestIndex < EQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cDestIndex );
}
else {
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cDestIndex - EQUIP_WEAPON1 );
}
}
}
pActor->RefreshState();
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_Glyph:
{
if( pSession->GetActorHandle() )
pSession->GetItem()->OnRecvMoveItem(pPacket);
return ERROR_NONE;
}
break;
case MoveType_GlyphToInven:
{
if( pSession->GetActorHandle() )
pSession->GetItem()->OnRecvMoveItem(pPacket);
return ERROR_NONE;
}
break;
case MoveType_InvenToGlyph:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 ) {
RemoveInventoryItem( pSession, pPacket->cSrcIndex );
}
if( pPacket->cDestIndex != -1 ) {
pActor->DetachGlyph( (CDnGlyph::GlyphSlotEnum)pPacket->cDestIndex );
RemoveGlyphItem( pSession, pPacket->cDestIndex );
}
const TItem *pItemData = pSession->GetItem()->GetInventory( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cSrcIndex, pItem );
}
pItemData = pSession->GetItem()->GetGlyph( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertGlyphItem( pSession, pPacket->cDestIndex, pItem );
if( pItem ) {
pActor->AttachGlyph( ((CDnGlyph*)pItem)->GetMySmartPtr(), (CDnGlyph::GlyphSlotEnum)pPacket->cDestIndex );
}
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
#if defined(PRE_ADD_TALISMAN_SYSTEM)
case MoveType_Talisman:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true )
{
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 )
{
pActor->DetachTalisman( pPacket->cSrcIndex );
RemoveTalismanItem( pSession, pPacket->cSrcIndex );
}
if( pPacket->cDestIndex != -1 )
{
pActor->DetachTalisman( pPacket->cDestIndex );
RemoveTalismanItem( pSession, pPacket->cDestIndex );
}
const TItem *pItemData = pSession->GetItem()->GetTalisman( pPacket->cSrcIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
if( pItem ) pActor->AttachTalisman(((CDnTalisman*)pItem)->GetMySmartPtr(), pPacket->cSrcIndex, g_pDataManager->GetTalismanSlotEfficiency(pPacket->cSrcIndex));
InsertTalismanItem( pSession, pPacket->cSrcIndex, pItem );
}
pItemData = pSession->GetItem()->GetTalisman( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
if( pItem ) pActor->AttachTalisman(((CDnTalisman*)pItem)->GetMySmartPtr(), pPacket->cDestIndex, g_pDataManager->GetTalismanSlotEfficiency(pPacket->cDestIndex));
InsertTalismanItem( pSession, pPacket->cDestIndex, pItem );
}
pActor->RefreshState();
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_TalismanToInven:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
pActor->DetachTalisman( pPacket->cSrcIndex );
RemoveTalismanItem( pSession, pPacket->cSrcIndex );
const TItem *pItemData = pSession->GetItem()->GetInventory( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cDestIndex, pItem );
}
pActor->RefreshState();
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_InvenToTalisman:
{
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSrcIndex != -1 ) {
RemoveInventoryItem( pSession, pPacket->cSrcIndex );
}
const TItem *pItemData = pSession->GetItem()->GetTalisman( pPacket->cDestIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertTalismanItem( pSession, pPacket->cDestIndex, pItem );
if( pItem ) pActor->AttachTalisman( ((CDnTalisman*)pItem)->GetMySmartPtr(), pPacket->cDestIndex, g_pDataManager->GetTalismanSlotEfficiency(pPacket->cDestIndex) );
}
pActor->RefreshState();
} else
_DANGER_POINT();
return ERROR_NONE;
}
break;
#endif
}
return ERROR_UNKNOWN_HEADER;
}
int CDnItemTask::OnRecvItemMoveCashItem( CDNUserSession * pSession, CSMoveCashItem *pPacket, int nLen )
{
if (sizeof(CSMoveCashItem) != nLen)
return ERROR_INVALIDPACKET;
if (!pSession->IsNoneWindowState())
{
int nRet = ERROR_ITEM_FAIL;
switch(pPacket->cMoveType)
{
case MoveType_CashEquipToCashInven: nRet = ERROR_ITEM_EQUIPTOINVEN_FAIL; break;
case MoveType_CashInvenToCashEquip: nRet = ERROR_ITEM_INVENTOEQUIP_FAIL; break;
case MoveType_VehicleBodyToVehicleInven:
case MoveType_VehicleInvenToVehicleBody:
case MoveType_VehiclePartsToCashInven:
case MoveType_CashInvenToVehicleParts:
nRet = ERROR_ITEM_INVENTOEQUIP_FAIL;
break;
case MoveType_PetInvenToPetBody:
{
nRet = ERROR_CANT_RECALL_PET_STATUS;
break;
}
}
pSession->SendMoveCashItem(pPacket->cMoveType, pPacket->cCashEquipIndex, NULL, pPacket->biCashInvenSerial, NULL, nRet);
return ERROR_NONE;
}
// SyncWait 상태에서 아이템 이동시 에러 처리합니다. ( 클라에서도 한번 막지만 서버에서도 한번더 체크합니다. )
if( CDnPartyTask::IsActive(GetRoom()) && !CDnPartyTask::GetInstance( GetRoom() ).IsSyncComplete() ) {
pSession->SendMoveCashItem(pPacket->cMoveType, pPacket->cCashEquipIndex, NULL, pPacket->biCashInvenSerial, NULL, ERROR_ITEM_FAIL);
return ERROR_NONE;
}
switch(pPacket->cMoveType)
{
case MoveType_CashEquip:
{
if (pSession->GetActorHandle())
pSession->GetItem()->OnRecvMoveCashItem(pPacket);
return ERROR_NONE;
}
break;
case MoveType_CashInven:
{
if (pSession->GetActorHandle())
pSession->GetItem()->OnRecvMoveCashItem(pPacket);
return ERROR_NONE;
}
break;
case MoveType_CashEquipToCashInven:
{
const TItem *pBeforeEquip = pSession->GetItem()->GetCashEquip( pPacket->cCashEquipIndex );
INT64 biEquipSerial = (pBeforeEquip == NULL) ? 0 : pBeforeEquip->nSerial;
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveCashItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cCashEquipIndex != -1 ) {
if( pPacket->cCashEquipIndex < CASHEQUIP_WEAPON1 )
pActor->DetachCashParts( (CDnParts::PartsTypeEnum)pPacket->cCashEquipIndex );
else if(pPacket->cCashEquipIndex == CASHEQUIP_WEAPON1 || pPacket->cCashEquipIndex == CASHEQUIP_WEAPON2)
{
pActor->DetachCashWeapon( pPacket->cCashEquipIndex - CASHEQUIP_WEAPON1 );
}
// 게임서버 이큅 디테치
else if(pPacket->cCashEquipIndex == CASHEQUIP_EFFECT)
{
pActor->SetVehicleEffectIndex(0);
}
RemoveCashEquipItem( pSession, pPacket->cCashEquipIndex );
}
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
const TItem *pEquip = pSession->GetItem()->GetCashEquip( pPacket->cCashEquipIndex );
if( pEquip && pEquip->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pEquip );
InsertCashEquipItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem ) {
if( pPacket->cCashEquipIndex < CASHEQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachCashParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cCashEquipIndex );
}
else if(pPacket->cCashEquipIndex == CASHEQUIP_WEAPON1 || pPacket->cCashEquipIndex == CASHEQUIP_WEAPON2)
{
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachCashWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cCashEquipIndex - CASHEQUIP_WEAPON1 );
}
// 게임서버 이큅 어태치
else if(pPacket->cCashEquipIndex == CASHEQUIP_EFFECT)
{
if(pItem->GetItemType() == ITEMTYPE_VEHICLEEFFECT)
pActor->SetVehicleEffectIndex(pItem->GetClassID());
}
}
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biEquipSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pInven->nSerial, pItem );
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_CashInvenToCashEquip:
{
const TItem *pBeforeEquip = pSession->GetItem()->GetCashEquip( pPacket->cCashEquipIndex );
INT64 biSerial = (pBeforeEquip && (pBeforeEquip->nSerial > 0)) ? pBeforeEquip->nSerial : pPacket->biCashInvenSerial;
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveCashItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
if( pPacket->cCashEquipIndex != -1 ) {
if( pPacket->cCashEquipIndex < CASHEQUIP_WEAPON1 )
pActor->DetachCashParts( (CDnParts::PartsTypeEnum)pPacket->cCashEquipIndex );
else if(pPacket->cCashEquipIndex == CASHEQUIP_WEAPON1 || pPacket->cCashEquipIndex == CASHEQUIP_WEAPON2)
{
pActor->DetachCashWeapon( pPacket->cCashEquipIndex - CASHEQUIP_WEAPON1 );
}
// 게임서버 이큅 디테치
else if(pPacket->cCashEquipIndex == CASHEQUIP_EFFECT)
{
pActor->SetVehicleEffectIndex(0);
}
RemoveCashEquipItem( pSession, pPacket->cCashEquipIndex );
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pPacket->biCashInvenSerial, pItem );
}
const TItem *pEquip = pSession->GetItem()->GetCashEquip( pPacket->cCashEquipIndex );
if( pEquip && pEquip->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pEquip );
InsertCashEquipItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem ) {
if( pPacket->cCashEquipIndex < CASHEQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachCashParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cCashEquipIndex );
}
else if(pPacket->cCashEquipIndex == CASHEQUIP_WEAPON1 || pPacket->cCashEquipIndex == CASHEQUIP_WEAPON2)
{
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachCashWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cCashEquipIndex - CASHEQUIP_WEAPON1 );
}
// 게임서버 이큅 어테치
else if(pPacket->cCashEquipIndex == CASHEQUIP_EFFECT)
{
if(pItem->GetItemType() == ITEMTYPE_VEHICLEEFFECT)
pActor->SetVehicleEffectIndex(pItem->GetClassID());
}
}
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_CashGlyph:
{
if (pSession->GetActorHandle())
pSession->GetItem()->OnRecvMoveCashItem(pPacket);
return ERROR_NONE;
}
break;
case MoveType_CashGlyphToCashInven:
{
const TItem *pBeforeGlyph = pSession->GetItem()->GetGlyph( pPacket->cCashEquipIndex );
INT64 biGlyphSerial = (pBeforeGlyph == NULL) ? 0 : pBeforeGlyph->nSerial;
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveCashItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cCashEquipIndex != -1 ) {
pActor->DetachGlyph( (CDnGlyph::GlyphSlotEnum)pPacket->cCashEquipIndex );
RemoveGlyphItem( pSession, pPacket->cCashEquipIndex );
}
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
const TItem *pEquip = pSession->GetItem()->GetGlyph( pPacket->cCashEquipIndex );
if( pEquip && pEquip->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pEquip );
InsertGlyphItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem ) {
pActor->AttachGlyph( ((CDnGlyph*)pItem)->GetMySmartPtr(), (CDnGlyph::GlyphSlotEnum)pPacket->cCashEquipIndex );
}
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biGlyphSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pInven->nSerial, pItem );
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_CashInvenToCashGlyph:
{
const TItem *pBeforeGlyph = pSession->GetItem()->GetGlyph( pPacket->cCashEquipIndex );
INT64 biSerial = (pBeforeGlyph && (pBeforeGlyph->nSerial > 0)) ? pBeforeGlyph->nSerial : pPacket->biCashInvenSerial;
if( pSession->GetActorHandle() && pSession->GetItem()->OnRecvMoveCashItem(pPacket) == true ) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
if( pPacket->cCashEquipIndex != -1 ) {
pActor->DetachGlyph( (CDnGlyph::GlyphSlotEnum)pPacket->cCashEquipIndex );
RemoveGlyphItem( pSession, pPacket->cCashEquipIndex );
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pPacket->biCashInvenSerial, pItem );
}
const TItem *pEquip = pSession->GetItem()->GetGlyph( pPacket->cCashEquipIndex );
if( pEquip && pEquip->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pEquip );
InsertGlyphItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem ) {
pActor->AttachGlyph( ((CDnGlyph*)pItem)->GetMySmartPtr(), (CDnGlyph::GlyphSlotEnum)pPacket->cCashEquipIndex );
}
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
// Dungeon 타입에서는 탈것을 장착하거나 , 탈것 장착템을 사용할수 없습니다.
// 현재 클라이언트에서 Dungeon 상태라면 패킷을 보내지 않도록 설정해두었습니다.
// 하지만 만약 Dungeon에서 아이템을 이동하는 현상이 생기면 이곳에서도 막아주어야 하겟지만
// 그럴일은 거의 없으니 아직 따로 처리는 하지않겠습니다.
case MoveType_VehicleBodyToVehicleInven:
{
TVehicle *pBeforeVehicleEquip = pSession->GetItem()->GetVehicleEquip();
INT64 biEquipSerial = (pBeforeVehicleEquip == NULL) ? 0 : pBeforeVehicleEquip->Vehicle[Vehicle::Slot::Body].nSerial;
if( pSession->GetActorHandle()) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if(!pActor)
return ERROR_ITEM_DONTMOVE; // 이러면 안됩니다.
CDnVehicleActor *pVehicleActor = pActor->GetMyVehicleActor();
if (!pVehicleActor || !pActor->IsVehicleMode()) return ERROR_ITEM_DONTMOVE; // 안탔는데 내리라고하는경우 !!
if (pSession->GetItem()->OnRecvMoveCashItem(pPacket) != true) return ERROR_NONE;
if (pPacket->cCashEquipIndex != -1) {
for (int i = 0; i < Vehicle::Slot::Max; i++){
RemoveVehicleEquipItem(pSession, i);
}
}
if (pPacket->biCashInvenSerial > 0) {
RemoveVehicleInventoryItem(pSession, pPacket->biCashInvenSerial);
}
TVehicle *pEquipVehicle = pSession->GetItem()->GetVehicleEquip();
if (pEquipVehicle){
for (int i = 0; i < Vehicle::Slot::Max; i++){
if (pEquipVehicle->Vehicle[i].nItemID <= 0) continue;
CDnItem *pItem = CreateItem(&(pEquipVehicle->Vehicle[i]));
InsertVehicleEquipItem(pSession, pPacket->cCashEquipIndex, pItem);
}
}
const TItem *pInven = pSession->GetItem()->GetCashInventory(biEquipSerial);
if (pInven && pInven->nItemID > 0) {
CDnItem *pItem = CreateItem(pInven);
InsertCashInventoryItem(pSession, pInven->nSerial, pItem);
}
// Rotha - 이경우에는 탈것을 내리라는 메세지 : 내려주면됩니다
pActor->UnRideVehicle();
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_VehicleInvenToVehicleBody:
{
TVehicle *pBeforeVehicleEquip = pSession->GetItem()->GetVehicleEquip();
INT64 biEquipSerial = (pBeforeVehicleEquip && (pBeforeVehicleEquip->Vehicle[Vehicle::Slot::Body].nSerial > 0)) ? pBeforeVehicleEquip->Vehicle[Vehicle::Slot::Body].nSerial : pPacket->biCashInvenSerial;
if (pSession->GetActorHandle()) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if(!pActor)
return ERROR_ITEM_DONTMOVE; // 이러면 안됩니다.
if (pActor->IsVehicleMode() && pActor->GetMyVehicleActor() )
pActor->UnRideVehicle();
if (pSession->GetItem()->OnRecvMoveCashItem(pPacket) != true) return ERROR_NONE;
if (pPacket->biCashInvenSerial > 0) {
RemoveVehicleInventoryItem(pSession, pPacket->biCashInvenSerial);
}
if (pPacket->cCashEquipIndex != -1) {
RemoveVehicleEquipItem(pSession, pPacket->cCashEquipIndex);
}
const TItem *pInven = pSession->GetItem()->GetVehicleBodyInventory(biEquipSerial);
if (pInven) {
CDnItem *pItem = CreateItem(pInven);
InsertVehicleInventoryItem(pSession, pPacket->biCashInvenSerial, pItem);
}
TVehicle *pEquipVehicle = pSession->GetItem()->GetVehicleEquip();
if (pEquipVehicle) {
for (int i = 0; i < Vehicle::Slot::Max; i++){
if (pEquipVehicle->Vehicle[i].nItemID <= 0) continue;
CDnItem *pItem = CreateItem(&(pEquipVehicle->Vehicle[i]));
InsertVehicleEquipItem(pSession, pPacket->cCashEquipIndex, pItem);
}
// Rotha - 탈것을 태웁니다. //
pActor->RideVehicle(pEquipVehicle); // Tvehicle에 탈것파츠정보 포함하기때문에 탈것 장착 및 파츠및 색상도 알아서 장착
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_VehiclePartsToCashInven:
{
const TItem *pBeforeParts = pSession->GetItem()->GetVehiclePartsEquip( pPacket->cCashEquipIndex );
INT64 biPartsSerial = (pBeforeParts == NULL) ? 0 : pBeforeParts->nSerial;
if (pSession->GetActorHandle()) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if(!pActor)
return ERROR_ITEM_DONTMOVE; // 이러면 안됩니다.
CDnVehicleActor *pVehicleActor = pActor->GetMyVehicleActor();
if (!pVehicleActor || !pActor->IsVehicleMode()) return ERROR_ITEM_DONTMOVE; // Rotha - 탈것 장착은 무조건 탈것을 탄상태에서 작동 합니다.
if (pSession->GetItem()->OnRecvMoveCashItem(pPacket) != true) return ERROR_NONE;
if( pPacket->cCashEquipIndex != -1 ) {
pVehicleActor->UnEquipItem(pPacket->cCashEquipIndex); // Rotha - 장착해제
RemoveVehicleEquipItem( pSession, pPacket->cCashEquipIndex );
}
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
const TItem *pParts = pSession->GetItem()->GetVehiclePartsEquip( pPacket->cCashEquipIndex );
if( pParts && pParts->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pParts );
InsertVehicleEquipItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem )
pVehicleActor->EquipItem(*pParts); // Rotha - 장착
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biPartsSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pInven->nSerial, pItem );
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_CashInvenToVehicleParts:
{
const TItem *pBeforeParts = pSession->GetItem()->GetVehiclePartsEquip( pPacket->cCashEquipIndex );
INT64 biSerial = (pBeforeParts && (pBeforeParts->nSerial > 0)) ? pBeforeParts->nSerial : pPacket->biCashInvenSerial;
if( pSession->GetActorHandle()) {
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if(!pActor)
return ERROR_ITEM_DONTMOVE; // 이러면 안됩니다.
CDnVehicleActor *pVehicleActor = pActor->GetMyVehicleActor();
if (!pVehicleActor || !pActor->IsVehicleMode()) return ERROR_ITEM_DONTMOVE; // Rotha - 탄 상태에서만 가능
if (pSession->GetItem()->OnRecvMoveCashItem(pPacket) != true) return ERROR_NONE;
if( pPacket->biCashInvenSerial > 0 ) {
RemoveCashInventoryItem( pSession, pPacket->biCashInvenSerial );
}
if( pPacket->cCashEquipIndex != -1 ) {
pVehicleActor->UnEquipItem(pPacket->cCashEquipIndex); // Rotha - 장착해제
RemoveVehicleEquipItem( pSession, pPacket->cCashEquipIndex );
}
const TItem *pInven = pSession->GetItem()->GetCashInventory( biSerial );
if( pInven && pInven->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pInven );
InsertCashInventoryItem( pSession, pPacket->biCashInvenSerial, pItem );
}
const TItem *pEquip = pSession->GetItem()->GetVehiclePartsEquip( pPacket->cCashEquipIndex );
if( pEquip && pEquip->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pEquip );
InsertVehicleEquipItem( pSession, pPacket->cCashEquipIndex, pItem );
if( pItem )
pVehicleActor->EquipItem(*pEquip); // Rotha - 장착 }
}
pActor->RefreshState();
}
else
_DANGER_POINT();
return ERROR_NONE;
}
break;
case MoveType_PetBodyToPetInven:
case MoveType_PetInvenToPetBody:
case MoveType_PetPartsToCashInven:
case MoveType_CashInvenToPetParts:
{
if (pSession->GetItem()->OnRecvMoveCashItem(pPacket) != true)
return ERROR_NONE;
break;
}
}
return ERROR_UNKNOWN_HEADER;
}
int CDnItemTask::OnRecvItemRemoveItem( CDNUserSession *pSession, CSRemoveItem *pPacket, int nLen )
{
if (sizeof(CSRemoveItem) != nLen)
return ERROR_INVALIDPACKET;
if (pSession->IsTutorial()){
pSession->SendRemoveItem(pPacket->cType, pPacket->cSlotIndex, NULL, ERROR_ITEM_FAIL);
return ERROR_NONE;
}
if (!pSession->IsNoneWindowState() && !pSession->IsWindowState(WINDOW_BLIND))
{
pSession->SendRemoveItem(pPacket->cType, pPacket->cSlotIndex, NULL, ERROR_ITEM_FAIL);
return ERROR_NONE;
}
if (pSession->GetRestraint()->CheckRestraint(_RESTRAINTTYPE_TRADE) == false)
return ERROR_NONE;
if( !pSession->GetActorHandle() )
return ERROR_NONE;
#if defined(PRE_ADD_EQUIPLOCK)
//게임 모드가 구울모드면 아이템 파괴를 막아버린다
if (!GetRoom() || GetRoom()->bIsZombieMode())
{
pSession->SendRemoveItem(pPacket->cType, pPacket->cSlotIndex, NULL, ERROR_ITEM_FAIL);
return ERROR_NONE;
}
#endif // #if defined(PRE_ADD_EQUIPLOCK)
if( pSession->GetItem()->OnRecvRemoveItem( pPacket ) == false )
return ERROR_NONE;
switch( pPacket->cType ) {
case ITEMPOSITION_EQUIP:
{
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
if( pPacket->cSlotIndex < EQUIP_WEAPON1 )
pActor->DetachParts( (CDnParts::PartsTypeEnum)pPacket->cSlotIndex );
else
pActor->DetachWeapon( pPacket->cSlotIndex - EQUIP_WEAPON1 );
RemoveEquipItem( pSession, pPacket->cSlotIndex );
// 여기 코드는 필요없는데..흐음.. ( 에러났을때 대비였나.. )
const TItem *pItemData = pSession->GetItem()->GetEquip( pPacket->cSlotIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertEquipItem( pSession, pPacket->cSlotIndex, pItem );
if( pItem ) {
if( pPacket->cSlotIndex < EQUIP_WEAPON1 ) {
if( pItem->GetItemType() == ITEMTYPE_PARTS )
pActor->AttachParts( ((CDnParts*)pItem)->GetMySmartPtr(), (CDnParts::PartsTypeEnum)pPacket->cSlotIndex );
}
else {
if( pItem->GetItemType() == ITEMTYPE_WEAPON )
pActor->AttachWeapon( ((CDnWeapon*)pItem)->GetMySmartPtr(), pPacket->cSlotIndex - EQUIP_WEAPON1 );
}
}
}
//
pActor->RefreshState();
return ERROR_NONE;
}
break;
case ITEMPOSITION_INVEN:
{
RemoveInventoryItem( pSession, pPacket->cSlotIndex );
const TItem *pItemData = pSession->GetItem()->GetEquip( pPacket->cSlotIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertInventoryItem( pSession, pPacket->cSlotIndex, pItem );
}
if( CDnPartyTask::IsActive(GetRoom()) ) CDnPartyTask::GetInstance(GetRoom()).UpdateGateInfo();
return ERROR_NONE;
}
break;
case ITEMPOSITION_GLYPH:
{
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
pActor->DetachGlyph( (CDnGlyph::GlyphSlotEnum)pPacket->cSlotIndex );
RemoveGlyphItem( pSession, pPacket->cSlotIndex );
// 여기 코드는 필요없는데..흐음.. ( 에러났을때 대비였나.. )
const TItem *pItemData = pSession->GetItem()->GetGlyph( (CDnGlyph::GlyphSlotEnum)pPacket->cSlotIndex );
if( pItemData && pItemData->nItemID > 0 ) {
CDnItem *pItem = CreateItem( pItemData );
InsertGlyphItem( pSession, pPacket->cSlotIndex, pItem );
if( pItem ) {
pActor->AttachGlyph( ((CDnGlyph*)pItem)->GetMySmartPtr(), (CDnGlyph::GlyphSlotEnum)pPacket->cSlotIndex );
}
}
//
pActor->RefreshState();
return ERROR_NONE;
}
break;
#if defined(PRE_ADD_TALISMAN_SYSTEM)
case ITEMPOSITION_TALISMAN:
{
CDnPlayerActor *pActor = (CDnPlayerActor*)pSession->GetActorHandle().GetPointer();
pActor->DetachTalisman( pPacket->cSlotIndex );
RemoveTalismanItem( pSession, pPacket->cSlotIndex );
pActor->RefreshState();
return ERROR_NONE;
}
break;
#endif
case ITEMPOSITION_QUESTINVEN:
{
return ERROR_NONE;
}
break;
}
return ERROR_UNKNOWN_HEADER;
}
int CDnItemTask::OnRecvItemPickupItem( CDNUserSession *pSession, SCPickUp *pPacket, int nLen )
{
switch( pPacket->nRetCode ) {
case ERROR_NONE:
{
const TItem *pItemData = pSession->GetItem()->GetInventory( pPacket->PickUpItem.cSlotIndex );
if( pPacket->PickUpItem.cSlotIndex != -1 ) {
RemoveInventoryItem( pSession, pPacket->PickUpItem.cSlotIndex );
}
if (pItemData)
{
CDnItem *pItem = CreateItem( pItemData );
if( pItem ) {
InsertInventoryItem( pSession, pPacket->PickUpItem.cSlotIndex, pItem );
}
}
}
break;
default:
break;
}
// 느릴 수 도 있다.
if( CDnPartyTask::IsActive(GetRoom()) ) CDnPartyTask::GetInstance(GetRoom()).UpdateGateInfo();
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemUseItem( CDNUserSession *pSession, CSUseItem *pPacket, int nLen )
{
if (sizeof(CSUseItem) != nLen)
return ERROR_INVALIDPACKET;
// 제제검사
if( pSession->GetRestraint()->CheckRestraint(_RESTRAINTTYPE_TRADE) == false )
return ERROR_NONE;
// 죽은상태에서 사용가능한 요리아이템이 생김 게임서버에서 판단시점 OnRecvUseItem단으로 옮김
// Note 한기: 죽은 상태에선 아이템 사용 불가. 물약 같은 거 못 먹음.
/*if( !pSession->GetActorHandle() )
return ERROR_NONE;
if( pSession->GetActorHandle()->IsDie() )
return ERROR_NONE;*/
pSession->GetItem()->OnRecvUseItem(pPacket);
return ERROR_GENERIC_INVALIDREQUEST;
}
int CDnItemTask::OnRecvItemRefreshQItem( CDNUserSession *pSession, SCRefreshQuestInven *pPacket, int nLen )
{
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemRemoveQItem( CDNUserSession *pSession, SCRemoveItem *pPacket, int nLen )
{
return ERROR_NONE;
}
int CDnItemTask::OnRecvRebirth( CDNUserSession* pSession, int nLen )
{
if (nLen != 0)
return ERROR_INVALIDPACKET;
if (GetRoom()->GetRoomState() != _GAME_STATE_PLAY || pSession->GetState() != SESSION_STATE_GAME_PLAY)
{
_DANGER_POINT_MSG(L"if (GetRoom()->GetRoomState() != _GAME_STATE_PLAY)");
return ERROR_NONE;
}
pSession->SendBackToVillage(true);
return ERROR_NONE;
}
// 부활 가능한지 검사
bool CDnItemTask::_bIsRebirth()
{
// 미션 Fail 상태이기 때문에 부활 불가능합니다.
CDnGameTask* pTask = (CDnGameTask*)CTaskManager::GetInstance(GetRoom()).GetTask( "GameTask" );
if( !pTask || pTask->IsDungeonFailed() )
return false;
// PvP방에서는 부활 불가능합니다.
if( !GetRoom() || GetRoom()->bIsPvPRoom() )
return false;
return true;
}
//아이템아이디로 체크
CDnItem* CDnItemTask::FindRebirthItem(CDNUserSession* pSession, int nAllowMapType, int nItemID)
{
std::vector<CDnItem *> rebirthItems;
ScanItemFromID(pSession->GetActorHandle(), nItemID, &rebirthItems);
if (rebirthItems.empty())
return false;
std::vector<CDnItem *>::iterator iter = rebirthItems.begin();
std::vector<CDnItem *>::iterator endIter = rebirthItems.end();
for (; iter != endIter; ++iter)
{
CDnItem* pItem = (*iter);
TItemData* pItemData = g_pDataManager->GetItemData( pItem->GetClassID() );
if (NULL == pItemData)
continue;
//이 맵에서 사용할 수 있는 부활 아이템이 있으면
if (pItemData->nAllowMapType & nAllowMapType)
return pItem;
}
//아이템중 이 맵에서 사용할 아이템이 없으면 부활 불가
return NULL;
}
int CDnItemTask::OnRecvRebirthCoin( CDNUserSession* pSession, int nLen )
{
if (nLen != 0)
return ERROR_INVALIDPACKET;
if( pSession->GetState() != SESSION_STATE_GAME_PLAY)
return ERROR_NONE;
bool bIsPartyRestore = false;
CDNGameRoom::PartyBackUpStruct BackupInfo;
if( GetRoom()->GetBackupPartyInfo( pSession->GetCharacterDBID(), BackupInfo ) == true )
{
if( BackupInfo.nHPPercent > 0 )
bIsPartyRestore = true;
}
if( bIsPartyRestore == false && GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin == 0 && GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin == 0 )
return ERROR_NONE;
// 부활가능한지 검사
if( !_bIsRebirth() )
return ERROR_NONE;
DnActorHandle hActor = pSession->GetActorHandle();
// 씨드래곤 맵상에서는 부활 아이템이 있어야 함 [2010/12/21 semozz]
const TMapInfo* pMapData = g_pDataManager->GetMapInfo( pSession->GetMapIndex() );
if (NULL == pMapData)
return ERROR_NONE;
CDnWorld *pWorld = GetRoom()->GetWorld();
if (NULL == pWorld)
return ERROR_NONE;
eDragonNestType _dragonNestType = pWorld->GetDragonNestType();
//씨드래곤네스트 맵이면
bool isDragonNestMap = _dragonNestType == eDragonNestType::SeaDragon;
CDnItem* pRebirthItem = NULL;
if( !hActor->IsDie() || hActor->IsAppliedThisStateBlow(STATE_BLOW::BLOW_057))
return ERROR_NONE;
bool isRebirthAble = false;
bool bUseRebirthItem = false;
//코인 부활 먼저 체크
if( bIsPartyRestore == false && GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin == -1 )
{
//부활 횟수 제한없음
isRebirthAble = pSession->DecreaseRebirthCoin(1);
}
else if ( bIsPartyRestore == false && GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin > 0 )
{
//부활 횟수 제한
isRebirthAble = pSession->DecreaseRebirthCoin(1);
}
if ( bIsPartyRestore == false && !isRebirthAble && GetRoom()->GetPartyData(pSession)->ReverseItemList.size() > 0 && GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin > 0 )
{
//아이템 부활 체크
for( std::list<int>::iterator itor = GetRoom()->GetPartyData(pSession)->ReverseItemList.begin(); itor != GetRoom()->GetPartyData(pSession)->ReverseItemList.end(); itor++ )
{
pRebirthItem = FindRebirthItem(pSession, pMapData->nAllowMapType, *itor);
if( pRebirthItem )
{
isRebirthAble = true;
bUseRebirthItem = true;
break;
}
}
}
if (isRebirthAble || bIsPartyRestore == true )
{
// Note : 이벤토리에서 부활 코인이 남아 있는지 확인한다.
// 남아 있다면 코인을 하나 소모하고 부활 상태효과를 추가한다.
if( hActor )
{
std::string strParam = "Coin";
if( bIsPartyRestore == true )
{
if( BackupInfo.nHPPercent > 0 )
{
if( BackupInfo.nHPPercent < 100 )
{
strParam.append("/");
strParam.append(boost::lexical_cast<std::string>(BackupInfo.nHPPercent));
}
if( BackupInfo.nSPPercent < 100 )
{
strParam.append("/");
strParam.append(boost::lexical_cast<std::string>(BackupInfo.nSPPercent));
}
}
}
hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_057, 5000, strParam.c_str() );
// Note 한기: 부활 누르자마자 스킬 쓰는 경우 클라이언트에서 날아온 스킬 사용 요청 패킷이 서버에 도착했을 때,
// 서버에서는 아직 "Die" 액션 실행중이라서 스킬 사용 실패가 되고 클라이언트는 스킬 사용으로 될 수 있으므로
// "Stand" 액션을 실행해줌. (유령된 후에 움직이면 서버쪽에서 "Stand" 액션이 들어가는데 그 전엔 "Die" 상태임)
hActor->SetActionQueue( "Stand" );
}
pSession->GetEventSystem()->OnEvent( EventSystem::OnRebirth );
}
if( GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin > 0 && bUseRebirthItem == false )
{
//코인사용
if( bIsPartyRestore == false )
{
GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin -= 1;
}
if (GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin <= 0)
GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin = 0;
}
else if( GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin > 0 && bUseRebirthItem == true )
{
//아이템 부활
if (!pSession->GetItem()->DeleteInventoryByItemID(pRebirthItem->GetClassID(), 1, DBDNWorldDef::UseItem::Use))
return ERROR_ITEM_FAIL;
GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin -= 1;
if (GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin <= 0)
GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin = 0;
for( std::list<int>::iterator itor = GetRoom()->GetPartyData(pSession)->ReverseItemList.begin(); itor != GetRoom()->GetPartyData(pSession)->ReverseItemList.end(); itor++ )
pSession->SendSpecialRebirthItem( *itor, GetRoom()->GetPartyData(pSession)->nUsableRebirthItemCoin );
}
pSession->SendRebirthCoin(ERROR_NONE, GetRoom()->GetPartyData(pSession)->nUsableRebirthCoin, _REBIRTH_SELF, pSession->GetSessionID()); // 코인 결과값을 날려준다
if( bIsPartyRestore == true )
GetRoom()->DelBackupPartyInfo( pSession->GetCharacterDBID() );
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemRefreshInven( CDNUserSession *pSession, SCRefreshInven *pPacket, int nLen )
{
RemoveInventoryItem( pSession, pPacket->ItemInfo.cSlotIndex );
if( pPacket->ItemInfo.Item.nItemID > 0 ) {
CDnItem *pItem = CreateItem( &pPacket->ItemInfo.Item );
InsertInventoryItem( pSession, pPacket->ItemInfo.cSlotIndex, pItem );
}
if( pPacket->bNewSign ) {
if( CDnPartyTask::IsActive(GetRoom()) ) CDnPartyTask::GetInstance(GetRoom()).UpdateGateInfo();
}
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemRefreshCashInven( CDNUserSession *pSession, SCRefreshCashInven *pPacket, int nLen )
{
for (int i = 0; i < pPacket->nCount; i++){
RemoveCashInventoryItem( pSession, pPacket->ItemList[i].nSerial );
if( pPacket->ItemList[i].nItemID > 0 && pPacket->ItemList[i].wCount > 0 ) {
CDnItem *pItem = CreateItem( &(pPacket->ItemList[i]) );
InsertCashInventoryItem( pSession, pPacket->ItemList[i].nSerial, pItem );
}
}
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemRefreshEquip( CDNUserSession *pSession, SCRefreshEquip *pPacket, int nLen )
{
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemWarehouseSort(CDNUserSession *pSession, CSSortWarehouse * pPacket, int nLen)
{
if (sizeof(CSSortWarehouse) - sizeof(pPacket->SlotInfo) + (sizeof(TSortSlot) * pPacket->cTotalCount) != nLen)
return ERROR_INVALIDPACKET;
if( !pSession->IsWindowState(WINDOW_BLIND) )
{
pSession->SendSortWarehouse(ERROR_GENERIC_INVALIDREQUEST);
return ERROR_NONE;
}
if (pPacket->cTotalCount > WAREHOUSEMAX)
{
pSession->SendSortWarehouse(ERROR_GENERIC_INVALIDREQUEST);
return ERROR_NONE;
}
if (pSession->GetItem()->SortWarehouse(pPacket)) pSession->SendSortWarehouse(ERROR_NONE);
else pSession->SendSortWarehouse(ERROR_GENERIC_INVALIDREQUEST);
return ERROR_NONE;
}
#ifdef _ADD_NEWDISJOINT
int CDnItemTask::OnRecvItemDisjoint(CDNUserSession* pSession, CSItemDisjointReqNew* pPacket, int nLen)
{
if (sizeof(CSItemDisjointReqNew) != nLen)
return ERROR_INVALIDPACKET;
if (pSession->GetRestraint()->CheckRestraint(_RESTRAINTTYPE_TRADE) == false)
return ERROR_NONE;
int iResult = ERROR_NONE;
#ifdef _ADD_NEWDISJOINT
SCItemDisjointResNew *pResultPacket = new SCItemDisjointResNew();
ZeroMemory(pResultPacket, sizeof(SCItemDisjointResNew));
#endif
int nLastIndex = 0;
for (int k = 0; k < 4; k++)
{
if (pPacket->cSlotIndex[k] == 0 || pPacket->biItemSerial[k] == 0)
continue;
CDnItem* pItem = GetInventoryItem(pSession, pPacket->cSlotIndex[k]);
if (!pItem)
{
_DANGER_POINT();
return ERROR_NONE;
}
if (pItem->GetSerialID() != pPacket->biItemSerial[k]) return ERROR_ITEM_FAIL;
TItemData *pItemData = g_pDataManager->GetItemData(pItem->GetClassID());
int nItemID = pItem->GetClassID();
bool bSuccessDisjoint = false;
if (pItem && pItemData)
{
// 아이템 분해기 프랍의 정확한 위치가 필요할 듯.
// 일단 지금은 자신의 플레이어의 위치로 하면 될까나.
DnActorHandle hNpc = CDnActor::FindActorFromUniqueID(pSession->GetGameRoom(), pPacket->nNpcUniqueID);
if (hNpc) {
int nDisjointType = 0;
if (hNpc->IsNpcActor()) {
CDnNPCActor *pNpc = static_cast<CDnNPCActor *>(hNpc.GetPointer());
nDisjointType = (pNpc->GetNpcData()) ? pNpc->GetNpcData()->nParam[0] : 0;
}
if (pItem->CanDisjoint() && pItem->CanDisjointType(nDisjointType) && pItem->CanDisjointLevel(pSession->GetLevel()))
{
// 귀속이면서 봉인상태의 아이템인지 검사
bool bSealedItem = false;
if (pItemData->cReversion == ITEMREVERSION_BELONG && pItem->IsSoulbBound() == false)
bSealedItem = true;
if (!bSealedItem)
{
for (int i = 0; i < pPacket->nCount[k]; ++i)
{
bSuccessDisjoint = false;
iResult = ERROR_NONE;
// 분해는 가능한 아이템인가. 돈이 충분한가.
if (pSession->CheckEnoughCoin(pItem->GetDisjointCost()))
{
// 아이템 드랍되면 알아서 줏어가므로 성공 여부만 보내주면 됨.
// 갖고 있던 아이템은 삭제.
DNVector(CDnItem::DropItemStruct) VecDisjointItems;
pItem->GetDisjointItems(VecDisjointItems);
if (!VecDisjointItems.empty())
bSuccessDisjoint = true;
int nLocalItemID = pItem->GetClassID();
bool bDeleteItemResult = pSession->GetItem()->DeleteInventoryBySlot(pPacket->cSlotIndex[k], 1, pPacket->biItemSerial[k], DBDNWorldDef::UseItem::DeCompose);
_ASSERT(bDeleteItemResult);
if (bDeleteItemResult)
{
EtVector3 vPos = *hNpc->GetPosition();
// npc 바라보는 위치에서 2 미터 정도 앞으로 밀어서 생성시킴
vPos += (hNpc->GetMatEx()->m_vZAxis * 200.0f);
for (DWORD i = 0; i < VecDisjointItems.size(); ++i)
{
pResultPacket->nItemID[i + nLastIndex] = VecDisjointItems[i].nItemID;
pResultPacket->nCount[i + nLastIndex] = VecDisjointItems[i].nCount;
nLastIndex++;
//int nRotate = (int)(((VecDisjointItems[i].nSeed % 360) / (float)VecDisjointItems.size()) * i);
pSession->GetItem()->CreateInvenItem1(VecDisjointItems[i].nItemID, VecDisjointItems[i].nCount, -1, -1, DBDNWorldDef::AddMaterializedItem::ItemDecompose, 0, CREATEINVEN_ETC);
//RequestDropItem(STATIC_INSTANCE(CDnDropItem::s_dwUniqueCount)++, vPos, VecDisjointItems[i].nItemID,
// VecDisjointItems[i].nSeed, VecDisjointItems[i].nCount, nRotate, pSession->GetSessionID());
}
pSession->DelCoin(pItem->GetDisjointCost(), DBDNWorldDef::CoinChangeCode::DisjointTax, pSession->m_nClickedNpcID);
pSession->GetEventSystem()->OnEvent(EventSystem::OnItemDisjoint, 1, EventSystem::ItemID, nLocalItemID);
}
else
iResult = ERROR_ITEM_FAIL; // 아이템 삭제가 안되는 이상한 에러.
}
else
{
iResult = ERROR_ITEM_INSUFFICIENCY_MONEY;
}
if (iResult != ERROR_NONE)
break;
}
}
else
iResult = ERROR_ITEM_CAN_NOT_DISJOINT;
}
else
iResult = ERROR_ITEM_CAN_NOT_DISJOINT;
}
else iResult = ERROR_ITEM_FAIL;
}
else
iResult = ERROR_ITEM_NOTFOUND; // 존재하지 않는 아이템을 분해하려고..
pResultPacket->bSuccess = bSuccessDisjoint;
// 아이템 분해 성공. 클라로 결과 보냄.
}
if (ERROR_NONE == iResult)
SendItemDisjointResNew(pSession, pResultPacket); //wtf
else
SendItemDisjointResNew(pSession, pResultPacket); // 0 은 실패
return iResult;
}
#else
int CDnItemTask::OnRecvItemDisjoint(CDNUserSession* pSession, CSItemDisjointReq* pPacket, int nLen)
{
if (sizeof(CSItemDisjointReq) != nLen)
return ERROR_INVALIDPACKET;
if (pSession->GetRestraint()->CheckRestraint(_RESTRAINTTYPE_TRADE) == false)
return ERROR_NONE;
int iResult = ERROR_NONE;
CDnItem* pItem = GetInventoryItem(pSession, pPacket->cSlotIndex);
if (!pItem)
{
_DANGER_POINT();
return ERROR_NONE;
}
if (pItem->GetSerialID() != pPacket->biItemSerial) return ERROR_ITEM_FAIL;
#ifdef _ADD_NEWDISJOINT
SCItemDisjointResNew *pResultPacket = new SCItemDisjointResNew();
ZeroMemory(pResultPacket, sizeof(SCItemDisjointResNew));
#endif
TItemData *pItemData = g_pDataManager->GetItemData(pItem->GetClassID());
int nItemID = pItem->GetClassID();
bool bSuccessDisjoint = false;
if (pItem && pItemData)
{
// 아이템 분해기 프랍의 정확한 위치가 필요할 듯.
// 일단 지금은 자신의 플레이어의 위치로 하면 될까나.
DnActorHandle hNpc = CDnActor::FindActorFromUniqueID(pSession->GetGameRoom(), pPacket->nNpcUniqueID);
if (hNpc) {
int nDisjointType = 0;
if (hNpc->IsNpcActor()) {
CDnNPCActor *pNpc = static_cast<CDnNPCActor *>(hNpc.GetPointer());
nDisjointType = (pNpc->GetNpcData()) ? pNpc->GetNpcData()->nParam[0] : 0;
}
if (pItem->CanDisjoint() && pItem->CanDisjointType(nDisjointType) && pItem->CanDisjointLevel(pSession->GetLevel()))
{
// 귀속이면서 봉인상태의 아이템인지 검사
bool bSealedItem = false;
if (pItemData->cReversion == ITEMREVERSION_BELONG && pItem->IsSoulbBound() == false)
bSealedItem = true;
if (!bSealedItem)
{
for (int i = 0; i<pPacket->nCount; ++i)
{
bSuccessDisjoint = false;
iResult = ERROR_NONE;
// 분해는 가능한 아이템인가. 돈이 충분한가.
if (pSession->CheckEnoughCoin(pItem->GetDisjointCost()))
{
// 아이템 드랍되면 알아서 줏어가므로 성공 여부만 보내주면 됨.
// 갖고 있던 아이템은 삭제.
DNVector(CDnItem::DropItemStruct) VecDisjointItems;
pItem->GetDisjointItems(VecDisjointItems);
if (!VecDisjointItems.empty())
bSuccessDisjoint = true;
int nLocalItemID = pItem->GetClassID();
bool bDeleteItemResult = pSession->GetItem()->DeleteInventoryBySlot(pPacket->cSlotIndex, 1, pPacket->biItemSerial, DBDNWorldDef::UseItem::DeCompose);
_ASSERT(bDeleteItemResult);
if (bDeleteItemResult)
{
EtVector3 vPos = *hNpc->GetPosition();
// npc 바라보는 위치에서 2 미터 정도 앞으로 밀어서 생성시킴
vPos += (hNpc->GetMatEx()->m_vZAxis * 200.0f);
for (DWORD i = 0; i < VecDisjointItems.size(); ++i)
{
#ifdef _ADD_NEWDISJOINT
pResultPacket->nItemID[i] = VecDisjointItems[i].nItemID;
pResultPacket->nCount[i] = VecDisjointItems[i].nCount;
#endif
int nRotate = (int)(((VecDisjointItems[i].nSeed % 360) / (float)VecDisjointItems.size()) * i);
RequestDropItem(STATIC_INSTANCE(CDnDropItem::s_dwUniqueCount)++, vPos, VecDisjointItems[i].nItemID,
VecDisjointItems[i].nSeed, VecDisjointItems[i].nCount, nRotate, pSession->GetSessionID());
}
pSession->DelCoin(pItem->GetDisjointCost(), DBDNWorldDef::CoinChangeCode::DisjointTax, pSession->m_nClickedNpcID);
pSession->GetEventSystem()->OnEvent(EventSystem::OnItemDisjoint, 1, EventSystem::ItemID, nLocalItemID);
}
else
iResult = ERROR_ITEM_FAIL; // 아이템 삭제가 안되는 이상한 에러.
}
else
{
iResult = ERROR_ITEM_INSUFFICIENCY_MONEY;
}
if (iResult != ERROR_NONE)
break;
}
}
else
iResult = ERROR_ITEM_CAN_NOT_DISJOINT;
}
else
iResult = ERROR_ITEM_CAN_NOT_DISJOINT;
}
else iResult = ERROR_ITEM_FAIL;
}
else
iResult = ERROR_ITEM_NOTFOUND; // 존재하지 않는 아이템을 분해하려고..
#ifdef _ADD_NEWDISJOINT
pResultPacket->bSuccess = bSuccessDisjoint;
// 아이템 분해 성공. 클라로 결과 보냄.
if (ERROR_NONE == iResult)
SendItemDisjointResNew(pSession, pResultPacket); //wtf
else
SendItemDisjointResNew(pSession, pResultPacket); // 0 은 실패
#else
// 아이템 분해 성공. 클라로 결과 보냄.
if (ERROR_NONE == iResult)
SendItemDisjointRes(pSession, nItemID, bSuccessDisjoint);
else
SendItemDisjointRes(pSession, nItemID, bSuccessDisjoint); // 0 은 실패
#endif
return iResult;
}
#endif
int CDnItemTask::OnRecvItemCompleteRandomItem( CDNUserSession* pSession, CSCompleteRandomItem *pPacket, int nLen )
{
if (sizeof(CSCompleteRandomItem) != nLen)
return ERROR_INVALIDPACKET;
if( !pSession->GetItem()->IsValidRequestTimer( CDNUserItem::RequestType_UseRandomItem ) ) {
// 나쁜놈.
return ERROR_NONE;
}
pSession->GetItem()->CalcRandomItem( pPacket );
//UseItem에서 WINDOW_PROGRESS상태로 변경되어 있음.
pSession->IsWindowStateNoneSet(WINDOW_PROGRESS);
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemCancelRandomItem( CDNUserSession* pSession, char *pPacket, int nLen )
{
if (nLen != 0)
return ERROR_INVALIDPACKET;
pSession->GetItem()->SetRequestTimer( CDNUserItem::RequestType_None, 0 );
pSession->BroadcastingEffect( EffectType_Random, EffectState_Cancel );
//UseItem에서 WINDOW_PROGRESS상태로 변경되어 있음.
pSession->IsWindowStateNoneSet(WINDOW_PROGRESS);
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemSortInventory( CDNUserSession* pSession, CSSortInventory *pPacket, int nLen )
{
if (sizeof(CSSortInventory) - sizeof(pPacket->SlotInfo) + (sizeof(TSortSlot) * pPacket->cTotalCount) != nLen)
return ERROR_INVALIDPACKET;
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if (!pStruct) return ERROR_GENERIC_UNKNOWNERROR;
if ((pSession->GetItem()->SortInventory(pPacket)) && SortInventory(pSession, pPacket)){
pSession->SendSortInventory(ERROR_NONE);
}
else pSession->SendSortInventory(ERROR_GENERIC_INVALIDREQUEST);
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemEnchant( CDNUserSession* pSession, CSEnchantItem* pPacket, int nLen )
{
return pSession->ParseEnchant( pPacket, nLen );
}
int CDnItemTask::OnRecvItemEnchantComplete( CDNUserSession* pSession, CSEnchantItem* pPacket, int nLen )
{
return pSession->ParseEnchantComplete( pPacket, nLen );
}
int CDnItemTask::OnRecvItemEnchantCancel( CDNUserSession* pSession, int nLen )
{
return pSession->ParseEnchantCancel( nLen );
}
int CDnItemTask::OnRecvItemCompoundOpenReq( CDNUserSession* pSession, CSItemCompoundOpenReq* pPacket, int nLen )
{
return pSession->ParseItemCompound( pPacket, nLen );
}
int CDnItemTask::OnrecvItemCompoundReq( CDNUserSession* pSession, CSCompoundItemReq* pPacket, int nLen )
{
return pSession->ParseItemCompoundComplete( pPacket, nLen );
}
int CDnItemTask::OnRecvItemCompoundCancelReq( CDNUserSession* pSession, CSItemCompoundCancelReq* pPacket, int nLen )
{
return pSession->ParseItemCompoundCancel( pPacket, nLen );
}
void CDnItemTask::PickUpItem( DnActorHandle hActor, DnDropItemHandle hDropItem, TPARTYITEMLOOTRULE LootRule )
{
#if defined(_CH)
CDNUserSession *pSession = NULL;
if( hActor && hActor->IsPlayerActor() ) pSession = ((CDnPlayerActor*)hActor.GetPointer())->GetUserSession();
if (pSession && (pSession->GetFCMState() != FCMSTATE_NONE)){ // 3시간 이상 게임하면 아이템 줏기 못함 090624
return;
}
#endif
bool bPickup = true;
// ItemID 가 0 이면 돈이다!!
if( hDropItem->GetItemID() == 0 ) {
if( hDropItem->GetOverlapCount() < 1 ) return;
if( hDropItem->GetOverlapCount() < (int)GetPartyUserCount(CDNGameRoom::ePICKUPITEM) ) {
if( hActor )
{
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(hActor.GetPointer());
if (!pPlayer->GetUserSession()->CheckMaxCoin(hDropItem->GetOverlapCount())){
pPlayer->GetUserSession()->SendPickUp(ERROR_ITEM_OVERFLOWMONEY, -1, NULL, 0);
return;
}
pPlayer->CmdAddCoin( hDropItem->GetOverlapCount(), DBDNWorldDef::CoinChangeCode::PickUp, 0, true );
}
}
else
{
int nLiveUserCount = GetPartyUserCount(CDNGameRoom::ePICKUPITEM);
if( nLiveUserCount == 0 ) return;
int nCoin = hDropItem->GetOverlapCount() / nLiveUserCount;
int nDivide = hDropItem->GetOverlapCount() % nLiveUserCount;
for( DWORD i=0; i<GetUserCount(); i++ ) {
if( !GetUserData(i)->GetActorHandle() )
continue;
CDnPlayerActor *pPlayer = static_cast<CDnPlayerActor *>(GetUserData(i)->GetActorHandle().GetPointer());
if( pPlayer->IsDie() ) continue;
if( GetUserData(i)->bIsGMTrace() ) continue;
CDNUserSession* pUserSession = GetUserData(i);
if (pUserSession == NULL
#ifdef _CH
|| pUserSession->GetFCMState() != FCMSTATE_NONE
#endif
)
continue;
int nDropCoin = 0;
if( hActor == pPlayer ) {
nDropCoin = nCoin + nDivide;
if (!pPlayer->GetUserSession()->CheckMaxCoin(nCoin + nDivide)){
pPlayer->GetUserSession()->SendPickUp(ERROR_ITEM_OVERFLOWMONEY, -1, NULL, 0);
continue;
}
pPlayer->CmdAddCoin( nCoin + nDivide, DBDNWorldDef::CoinChangeCode::PickUp, 0, true );
}
else {
if (!pPlayer->GetUserSession()->CheckMaxCoin(nCoin)){
pPlayer->GetUserSession()->SendPickUp(ERROR_ITEM_OVERFLOWMONEY, -1, NULL, 0);
continue;
}
pPlayer->CmdAddCoin( nCoin, DBDNWorldDef::CoinChangeCode::PickUp, 0, true );
}
}
}
hDropItem->Send( CDnDropItem::DPT_PICKUP, NULL );
if( hActor && hActor->IsPlayerActor() )
((CDnPlayerActor*)hActor.GetPointer())->UpdateGetItem();
SAFE_RELEASE_SPTR( hDropItem );
return;
}
// 여기서 아이템을 집어넣는거 체크 해주시고
eItemTypeEnum Type = CDnItem::GetItemType( hDropItem->GetItemID() );
if( Type == ITEMTYPE_INSTANT ) {
int nItemID = hDropItem->GetItemID();
int nSeed = hDropItem->GetRandomSeed();
CDnItem *pItem = CDnItem::CreateItem( hActor->GetRoom(), nItemID, nSeed );
if( pItem ) {
pItem->ActivateSkillEffect( hActor );
SAFE_DELETE( pItem );
char szBuf[16] = { 0, };
DWORD dwUniqueID = hActor->GetUniqueID();
CMemoryStream Stream( szBuf, 16 );
Stream.Write( &dwUniqueID, sizeof(DWORD) );
Stream.Write( &nItemID, sizeof(int) );
Stream.Write( &nSeed, sizeof(int) );
hDropItem->Send( CDnDropItem::DPT_PICKUPINSTANT, &Stream );
if( hActor && hActor->IsPlayerActor() )
((CDnPlayerActor*)hActor.GetPointer())->UpdateGetItem();
SAFE_RELEASE_SPTR( hDropItem );
if( hActor && hActor->IsPlayerActor() )
((CDnPlayerActor*)hActor.GetPointer())->GetUserSession()->GetEventSystem()->OnEvent( EventSystem::OnItemUse, 1,EventSystem::ItemID, nItemID );
}
else hDropItem->Send( CDnDropItem::DPT_NOPICKUP, NULL );
}
else {
CDNUserSession *pSession = NULL;
if( hActor && hActor->IsPlayerActor() ) pSession = ((CDnPlayerActor*)hActor.GetPointer())->GetUserSession();
if( pSession == NULL ) return;
int nItemID = hDropItem->GetItemID();
short wCount = hDropItem->GetOverlapCount();
int nRandomSeed = hDropItem->GetRandomSeed();
TItemData *pItemData = g_pDataManager->GetItemData(nItemID);
bool bProcessPickup = false;
int itemShareEnableCount = GetPartyUserCount(CDNGameRoom::ePICKUPITEM);
if (itemShareEnableCount > 1 && hDropItem->GetOwnerUniqueID() == -1 )
{
if (pItemData)
{
if (pItemData->cReversion == ITEMREVERSION_BELONG) // todo : Check the dice game history of dropitem.
{
if (hDropItem->IsReversionItem() == false)
{
hDropItem->SetReversionItem(true);
hDropItem->LockReversionItem(true);
}
if (hDropItem->IsReversionLocked())
{
if (pSession->GetGameRoom()->IsEnableAddRequestGetReversionItem(hDropItem))
{
TItem itemInfo;
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
pSession->GetItem()->MakeItemStruct(nItemID, itemInfo, 0, hDropItem->GetEnchantID());
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
pSession->GetItem()->MakeItemStruct(nItemID, itemInfo);
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
hDropItem->MakeItemStruct( itemInfo );
TItemData *pItemData = g_pDataManager->GetItemData(nItemID);
if (pItemData)
{
if (pItemData->cReversion == ITEMREVERSION_BELONG)
itemInfo.bSoulbound = pItemData->IsSealed ? false : true;
}
pSession->GetGameRoom()->AddRequestGetReversionItem(itemInfo, hDropItem);
}
bPickup = false;
bProcessPickup = true;
}
}
}
}
TItem pickupItemInfo;
if (bProcessPickup == false)
{
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
bPickup = pSession->GetItem()->OnRecvPickUp(pickupItemInfo, hDropItem->GetItemID(), hDropItem->GetOverlapCount(), hDropItem->GetRandomSeed(), hDropItem->GetOption(), hDropItem->GetEnchantID());
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
bPickup = pSession->GetItem()->OnRecvPickUp(pickupItemInfo, hDropItem->GetItemID(), hDropItem->GetOverlapCount(), hDropItem->GetRandomSeed(), hDropItem->GetOption());
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
}
if( bPickup ) {
// 실제로 아이템 먹은놈에게만 SC_ITEM 관련 메세지가 가고
// [누가] [어떤 아아템]을 먹었습니다. 라는 메세지를 따로 보내기도 뭐하니
// DropItem 에게 보낼때 정보를 가치 보내주도록 한다.
char pBuffer[32];
CPacketCompressStream Stream( pBuffer, 32 );
bool bNameLink = true;
Stream.Write(&bNameLink, sizeof(bool));
// item information for name link.
Stream.Write(&pickupItemInfo.cLevel, sizeof(char));
Stream.Write(&pickupItemInfo.nRandomSeed, sizeof(int));
Stream.Write(&pickupItemInfo.wDur, sizeof(USHORT));
Stream.Write(&pickupItemInfo.cPotential, sizeof(char));
Stream.Write(&pickupItemInfo.cOption, sizeof(char));
Stream.Write(&pickupItemInfo.cSealCount, sizeof(char));
DWORD dwUniqueID = hActor->GetUniqueID();
Stream.Write( &LootRule, sizeof(char) );
switch( LootRule ) {
case ITEMLOOTRULE_RANDOM:
case ITEMLOOTRULE_NONE:
case ITEMLOOTRULE_OWNER:
case ITEMLOOTRULE_INORDER:
Stream.Write( &dwUniqueID, sizeof(DWORD) );
break;
default:
break;
}
hDropItem->Send( CDnDropItem::DPT_PICKUP, &Stream );
if( hActor && hActor->IsPlayerActor() )
((CDnPlayerActor*)hActor.GetPointer())->UpdateGetItem();
SAFE_RELEASE_SPTR( hDropItem );
}
else hDropItem->Send( CDnDropItem::DPT_NOPICKUP, NULL );
}
}
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
DnDropItemHandle CDnItemTask::RequestDropItem( DWORD dwUniqueID, EtVector3 &vPos, int nItemID, int nSeed, int nCount, short nRotate, UINT nOwnerSessionID, int nEchantID )
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
DnDropItemHandle CDnItemTask::RequestDropItem( DWORD dwUniqueID, EtVector3 &vPos, int nItemID, int nSeed, int nCount, short nRotate, UINT nOwnerSessionID)
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
{
#if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
DnDropItemHandle hDropItemHandle = CDnDropItem::DropItem( GetRoom(), vPos, dwUniqueID, nItemID, nSeed, -1, nCount, nRotate, nOwnerSessionID, nEchantID );
#else // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
DnDropItemHandle hDropItemHandle = CDnDropItem::DropItem( GetRoom(), vPos, dwUniqueID, nItemID, nSeed, -1, nCount, nRotate, nOwnerSessionID );
#endif // #if defined(PRE_ADD_STAGE_CLEAR_ENCHANT_REWARD)
if( hDropItemHandle )
{
for( DWORD i=0; i<GetUserCount(); i++ )
{
CDNUserSession* pGameSession = GetUserData(i);
if( pGameSession && pGameSession->GetState() == SESSION_STATE_GAME_PLAY )
SendGameCreateDropItem( pGameSession, dwUniqueID, vPos, nItemID, nSeed, hDropItemHandle->GetOption(), nCount, nRotate, nOwnerSessionID );
}
}
return hDropItemHandle;
}
CDnItem *CDnItemTask::CreateItem( const TItem *pInfo )
{
int nItemID = pInfo->nItemID;
eItemTypeEnum Type = CDnItem::GetItemType( nItemID );
CDnItem *pItem = NULL;
if( nItemID == 0 ) return NULL;
switch( Type ) {
case ITEMTYPE_WEAPON:
pItem = CDnWeapon::CreateWeapon( GetRoom(), nItemID, pInfo->nRandomSeed, pInfo->cOption, pInfo->cLevel, pInfo->cPotential, false, false, pInfo->cSealCount, pInfo->bSoulbound );
break;
case ITEMTYPE_PARTS:
pItem = CDnParts::CreateParts( GetRoom(), nItemID, pInfo->nRandomSeed, pInfo->cOption, pInfo->cLevel, pInfo->cPotential, pInfo->cSealCount, pInfo->bSoulbound );
break;
case ITEMTYPE_GLYPH:
pItem = CDnGlyph::CreateGlyph( GetRoom(), nItemID, pInfo->nRandomSeed, pInfo->cOption, pInfo->cLevel, pInfo->cPotential, pInfo->cSealCount, pInfo->bSoulbound );
break;
#if defined(PRE_ADD_TALISMAN_SYSTEM)
case ITEMTYPE_TALISMAN:
pItem = CDnTalisman::CreateTalisman( GetRoom(), nItemID, pInfo->nRandomSeed, pInfo->cOption, pInfo->cLevel, pInfo->cPotential, pInfo->cSealCount, pInfo->bSoulbound );
break;
#endif
default:
pItem = CDnItem::CreateItem( GetRoom(), nItemID, pInfo->nRandomSeed );
break;
}
if( pItem == NULL ) {
#if defined (_WORK)
GetRoom()->GetDBConnection()->QueryUseItemEx( GetRoom()->GetDBThreadID(), GetRoom()->GetWorldSetID(), 0, DBDNWorldDef::UseItem::Destroy, pInfo->nSerial, pInfo->wCount, 0, 0, L"", true );
#else
_ASSERT( !"아이템 생성 실패" );
#endif // #if defined (_WORK)
return NULL;
}
*pItem = *const_cast<TItem*>(pInfo);
return pItem;
}
bool CDnItemTask::InsertEquipItem( CDNUserSession *pSession, int nEquipIndex, CDnItem *pItem, bool bGenerationEvent )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= EQUIPMAX ) return false;
if( pStruct->pEquip[nEquipIndex] ) return false;
#ifdef _DEBUG
if (nEquipIndex >= EQUIPMAX)
_ASSERT(0);
for (int i = 0; i < EQUIPMAX; i++)
if (pStruct->pEquip[i] == pItem)
_ASSERT(0);
#endif
pStruct->pEquip[nEquipIndex] = pItem;
if( bGenerationEvent ) {
pSession->GetEventSystem()->OnEvent( EventSystem::OnItemEquip, 1,
EventSystem::ItemID, pItem->GetClassID() );
char cLevel = 99;
for (int i = EQUIP_HELMET; i <= EQUIP_FOOT; i++){
if (!pStruct->pEquip[i]) cLevel = 0;
else if (cLevel > pStruct->pEquip[i]->GetEnchantLevel()) cLevel = pStruct->pEquip[i]->GetEnchantLevel();
if (cLevel == 0) break;
}
if (cLevel > 0)
{
pSession->GetEventSystem()->OnEvent( EventSystem::OnItemEquip, 1,
EventSystem::AllPartsMinLevel, cLevel );
}
}
return true;
}
bool CDnItemTask::RemoveEquipItem( CDNUserSession *pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= EQUIPMAX ) return false;
if( !pStruct->pEquip[nEquipIndex] ) return false;
SAFE_DELETE( pStruct->pEquip[nEquipIndex] );
return true;
}
CDnItem *CDnItemTask::GetEquipItem( CDNUserSession *pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nEquipIndex < 0 || nEquipIndex >= EQUIPMAX ) return NULL;
return pStruct->pEquip[nEquipIndex];
}
bool CDnItemTask::InsertCashEquipItem( CDNUserSession * pSession, int nEquipIndex, CDnItem *pItem, bool bGenerationEvent )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= CASHEQUIPMAX ) return false;
if( pStruct->pCashEquip[nEquipIndex] ) return false;
#ifdef _DEBUG
if (nEquipIndex >= CASHEQUIPMAX)
_ASSERT(0);
for (int i = 0; i < CASHEQUIPMAX; i++)
if (pStruct->pCashEquip[i] == pItem)
_ASSERT(0);
#endif
pStruct->pCashEquip[nEquipIndex] = pItem;
return true;
}
bool CDnItemTask::RemoveCashEquipItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= CASHEQUIPMAX ) return false;
if( !pStruct->pCashEquip[nEquipIndex] ) return false;
SAFE_DELETE( pStruct->pCashEquip[nEquipIndex] );
return true;
}
CDnItem *CDnItemTask::GetCashEquipItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nEquipIndex < 0 || nEquipIndex >= CASHEQUIPMAX ) return NULL;
return pStruct->pCashEquip[nEquipIndex];
}
bool CDnItemTask::InsertGlyphItem( CDNUserSession * pSession, int nEquipIndex, CDnItem *pItem, bool bGenerationEvent )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= GLYPHMAX ) return false;
if( pStruct->pGlyph[nEquipIndex] ) return false;
#ifdef _DEBUG
if (nEquipIndex >= GLYPHMAX)
_ASSERT(0);
for (int i = 0; i < GLYPHMAX; i++)
if (pStruct->pGlyph[i] == pItem)
_ASSERT(0);
#endif
pStruct->pGlyph[nEquipIndex] = pItem;
return true;
}
bool CDnItemTask::RemoveGlyphItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= GLYPHMAX ) return false;
if( !pStruct->pGlyph[nEquipIndex] ) return false;
SAFE_DELETE( pStruct->pGlyph[nEquipIndex] );
return true;
}
CDnItem *CDnItemTask::GetGlyphItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nEquipIndex < 0 || nEquipIndex >= GLYPHMAX ) return NULL;
return pStruct->pGlyph[nEquipIndex];
}
#if defined(PRE_ADD_TALISMAN_SYSTEM)
bool CDnItemTask::InsertTalismanItem( CDNUserSession * pSession, int nEquipIndex, CDnItem *pItem )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= TALISMAN_MAX ) return false;
if( pStruct->pTalisman[nEquipIndex] ) return false;
#ifdef _DEBUG
if (nEquipIndex >= TALISMAN_MAX)
_ASSERT(0);
for (int i = 0; i < TALISMAN_MAX; i++)
if (pStruct->pTalisman[i] == pItem)
_ASSERT(0);
#endif
pStruct->pTalisman[nEquipIndex] = pItem;
return true;
}
bool CDnItemTask::RemoveTalismanItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < 0 || nEquipIndex >= TALISMAN_MAX ) return false;
if( !pStruct->pTalisman[nEquipIndex] ) return false;
SAFE_DELETE( pStruct->pTalisman[nEquipIndex] );
return true;
}
CDnItem *CDnItemTask::GetTalismanItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nEquipIndex < 0 || nEquipIndex >= TALISMAN_MAX ) return NULL;
return pStruct->pTalisman[nEquipIndex];
}
#endif
bool CDnItemTask::InsertInventoryItem( CDNUserSession *pSession, int nSlotIndex, CDnItem *pItem )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nSlotIndex < 0 || nSlotIndex >= INVENTORYMAX ) return false;
if( pStruct->pInventory[nSlotIndex] ) {
SAFE_DELETE( pStruct->pInventory[nSlotIndex] );
}
#ifdef _DEBUG
if (nSlotIndex >= INVENTORYMAX)
_ASSERT(0);
for (int i = 0; i < INVENTORYMAX; i++)
if (pStruct->pInventory[i] == pItem)
_ASSERT(0);
#endif
pStruct->pInventory[nSlotIndex] = pItem;
return true;
}
bool CDnItemTask::RemoveInventoryItem( CDNUserSession *pSession, int nSlotIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nSlotIndex < 0 || nSlotIndex >= INVENTORYMAX ) return false;
if( pStruct->pInventory[nSlotIndex] ) {
SAFE_DELETE( pStruct->pInventory[nSlotIndex] );
return true;
}
return false;
}
CDnItem *CDnItemTask::GetInventoryItem( CDNUserSession *pSession, int nSlotIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nSlotIndex < 0 || nSlotIndex >= INVENTORYMAX ) return NULL;
return pStruct->pInventory[nSlotIndex];
}
bool CDnItemTask::InsertCashInventoryItem( CDNUserSession * pSession, INT64 biItemSerial, CDnItem *pItem )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if (biItemSerial <= 0) return false;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapCashInventory.find(biItemSerial);
if (iter != pStruct->pMapCashInventory.end()){
SAFE_DELETE(iter->second);
}
pStruct->pMapCashInventory[biItemSerial] = pItem;
return true;
}
bool CDnItemTask::RemoveCashInventoryItem( CDNUserSession * pSession, INT64 biItemSerial )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if (biItemSerial <= 0) return NULL;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapCashInventory.find(biItemSerial);
if (iter != pStruct->pMapCashInventory.end()){
SAFE_DELETE(iter->second);
pStruct->pMapCashInventory.erase(iter);
return true;
}
return false;
}
CDnItem *CDnItemTask::GetCashInventoryItem( CDNUserSession * pSession, INT64 biItemSerial )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if (biItemSerial <= 0) return NULL;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapCashInventory.find(biItemSerial);
if (iter == pStruct->pMapCashInventory.end()) return NULL;
return iter->second;
}
bool CDnItemTask::InsertVehicleEquipItem( CDNUserSession * pSession, int nEquipIndex, CDnItem *pItem, bool bGenerationEvent/* = true*/ )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < Vehicle::Slot::Body || nEquipIndex >= Vehicle::Slot::Max ) return false;
if( pStruct->pVehicleEquip[nEquipIndex] ) return false;
#ifdef _DEBUG
if (nEquipIndex >= Vehicle::Slot::Max)
_ASSERT(0);
for (int i = 0; i < Vehicle::Slot::Max; i++)
if (pStruct->pVehicleEquip[i] == pItem)
_ASSERT(0);
#endif
pStruct->pVehicleEquip[nEquipIndex] = pItem;
return true;
}
bool CDnItemTask::RemoveVehicleEquipItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if( nEquipIndex < Vehicle::Slot::Body || nEquipIndex >= Vehicle::Slot::Max ) return false;
if( !pStruct->pVehicleEquip[nEquipIndex] ) return false;
SAFE_DELETE( pStruct->pVehicleEquip[nEquipIndex] );
return true;
}
CDnItem *CDnItemTask::GetVehicleEquipItem( CDNUserSession * pSession, int nEquipIndex )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if( nEquipIndex < Vehicle::Slot::Body || nEquipIndex >= Vehicle::Slot::Max ) return false;
return pStruct->pVehicleEquip[nEquipIndex];
}
bool CDnItemTask::InsertVehicleInventoryItem( CDNUserSession * pSession, INT64 biItemSerial, CDnItem *pItem )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if (biItemSerial <= 0) return false;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapVehicleInventory.find(biItemSerial);
if (iter != pStruct->pMapVehicleInventory.end()){
SAFE_DELETE(iter->second);
}
pStruct->pMapVehicleInventory[biItemSerial] = pItem;
return true;
}
bool CDnItemTask::RemoveVehicleInventoryItem( CDNUserSession * pSession, INT64 biItemSerial )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
if (biItemSerial <= 0) return NULL;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapVehicleInventory.find(biItemSerial);
if (iter != pStruct->pMapVehicleInventory.end()){
SAFE_DELETE(iter->second);
pStruct->pMapVehicleInventory.erase(iter);
return true;
}
return false;
}
CDnItem *CDnItemTask::GetVehicleInventoryItem( CDNUserSession * pSession, INT64 biItemSerial )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return NULL;
if (biItemSerial <= 0) return NULL;
std::map<INT64, CDnItem*>::iterator iter = pStruct->pMapVehicleInventory.find(biItemSerial);
if (iter == pStruct->pMapVehicleInventory.end()) return NULL;
return iter->second;
}
bool CDnItemTask::SortInventory( CDNUserSession *pSession, CSSortInventory *pSort)
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( pStruct == NULL ) return false;
// 정말 하기싫은 정렬이구나 ;ㅅ;
CDnItem* pNewInventory[INVENTORYMAX] = { 0, };
for (int i = 0; i < pSort->cTotalCount; i++){
if (pSort->SlotInfo[i].cCurrent < 0) continue;
pNewInventory[pSort->SlotInfo[i].cNew] = pStruct->pInventory[pSort->SlotInfo[i].cCurrent];
}
for (int i = 0; i < INVENTORYMAX; i++){
pStruct->pInventory[i] = pNewInventory[i];
}
return true;
}
bool CDnItemTask::InitializePlayerItem( CDNUserSession* pSession )
{
const TItem *pItemData;
CDnItem *pItem;
for( int j=0; j<EQUIPMAX; j++ )
{
pItemData = pSession->GetItem()->GetEquip( j );
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem )
{
_ASSERT(0);
continue;
}
InsertEquipItem( pSession, j, pItem, false );
}
for( int j=0; j<CASHEQUIPMAX; j++ )
{
pItemData = pSession->GetItem()->GetCashEquip( j );
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem )
{
_ASSERT(0);
continue;
}
InsertCashEquipItem( pSession, j, pItem, false );
}
for( int j=0; j<GLYPHMAX; j++ ) {
pItemData = pSession->GetItem()->GetGlyph(j);
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem )
{
_ASSERT(0);
continue;
}
InsertGlyphItem( pSession, j, pItem, false );
}
#if defined(PRE_ADD_TALISMAN_SYSTEM)
for( int j=0; j<TALISMAN_MAX; j++ ) {
pItemData = pSession->GetItem()->GetTalisman(j);
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem )
{
_ASSERT(0);
continue;
}
InsertTalismanItem( pSession, j, pItem );
}
#endif
for( int j=0; j<INVENTORYMAX; j++ )
{
pItemData = pSession->GetItem()->GetInventory( j );
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem )
{
#if defined( _WORK )
const_cast<TItem*>(pItemData)->nItemID = 0;
#else
_ASSERT(0);
#endif // #if defined( _WORK )
continue;
}
InsertInventoryItem( pSession, j, pItem );
}
pSession->GetItem()->InitializePlayerCashItem(this);
return true;
}
bool CDnItemTask::InitializePlayerItem()
{
const TItem *pItemData;
CDnItem *pItem;
CDNUserSession *pSession;
for( DWORD i=0; i<GetUserCount(); i++ ) {
pSession = GetUserData(i);
for( int j=0; j<EQUIPMAX; j++ ) {
pItemData = pSession->GetItem()->GetEquip(j);
if( !pItemData || pItemData->nItemID == 0 ) continue;
pItem = CreateItem( pItemData );
if( !pItem ) {
_ASSERT(0);
continue;
}
InsertEquipItem( pSession, j, pItem );
}
for( int j=0; j<CASHEQUIPMAX; j++ ) {
pItemData = pSession->GetItem()->GetCashEquip(j);
if( !pItemData || pItemData->nItemID == 0 ) continue;
pItem = CreateItem( pItemData );
if( !pItem ) {
_ASSERT(0);
continue;
}
InsertCashEquipItem( pSession, j, pItem );
}
for( int j=0; j<GLYPHMAX; j++ ) {
pItemData = pSession->GetItem()->GetGlyph(j);
if( !pItemData || pItemData->nItemID == 0 ) continue;
pItem = CreateItem( pItemData );
if( !pItem ) {
_ASSERT(0);
continue;
}
InsertGlyphItem( pSession, j, pItem );
}
#if defined(PRE_ADD_TALISMAN_SYSTEM)
for( int j=0; j<TALISMAN_MAX; j++ ) {
pItemData = pSession->GetItem()->GetTalisman(j);
if( !pItemData || pItemData->nItemID == 0 ) continue;
pItem = CreateItem( pItemData );
if( !pItem ) {
_ASSERT(0);
continue;
}
InsertTalismanItem( pSession, j, pItem );
}
#endif
for( int j=0; j<INVENTORYMAX; j++ ) {
pItemData = pSession->GetItem()->GetInventory(j);
if( !pItemData || pItemData->nItemID == 0 )
continue;
pItem = CreateItem( pItemData );
if( !pItem ) {
_ASSERT(0);
continue;
}
InsertInventoryItem( pSession, j, pItem );
}
pSession->GetItem()->InitializePlayerCashItem(this);
}
return true;
}
int CDnItemTask::ScanItemFromID( DnActorHandle hActor, int nItemTableID, std::vector<CDnItem *> *pVecResult )
{
for( DWORD i=0; i<GetUserCount(); i++ ) {
if( GetUserData(i)->GetActorHandle() == hActor ) {
int nCount = 0;
CDNGameRoom::PartyStruct *pStruct = GetPartyData(i);
if( pStruct == NULL ) continue;
//CDNSession::PartyStruct *pStruct = GetPartyData(i);
for( DWORD j=0; j<INVENTORYMAX; j++ ) {
CDnItem *pItem = pStruct->pInventory[j];
if( pItem == NULL ) continue;
if( pItem->GetClassID() == nItemTableID ) {
if( pVecResult ) pVecResult->push_back( pItem );
nCount += pItem->GetOverlapCount();
}
}
return nCount;
}
}
return 0;
}
void CDnItemTask::RequestRebirthCoinUseAnyPlayer( CDNUserSession *pUser, CDNUserSession *pTarget )
{
// 부활가능한지 검사
if( !_bIsRebirth() )
return;
DnActorHandle hActor = pTarget->GetActorHandle();
if (pUser->GetRebirthCashCoin() > 0){
pUser->DelCashRebirthCoin(1);
// Note : 이벤토리에서 부활 코인이 남아 있는지 확인한다.
// 남아 있다면 코인을 하나 소모하고 부활 상태효과를 추가한다.
if( hActor )
{
hActor->CmdAddStateEffect( NULL, STATE_BLOW::BLOW_057, 5000, "Coin" );
}
pUser->GetEventSystem()->OnEvent( EventSystem::OnRebirthAny );
}
else
{
_ASSERT(0);
return;
}
if (GetRoom()->GetPartyData(pTarget)->nUsableRebirthCoin > 0){
GetRoom()->GetPartyData(pTarget)->nUsableRebirthCoin -= 1;
if (GetRoom()->GetPartyData(pTarget)->nUsableRebirthCoin <= 0) GetRoom()->GetPartyData(pTarget)->nUsableRebirthCoin = 0;
}
pUser->SendRebirthCoin(ERROR_NONE, GetPartyData(pUser)->nUsableRebirthCoin, _REBIRTH_REBIRTHEE, pTarget->GetSessionID());
pTarget->SendRebirthCoin(ERROR_NONE, GetPartyData(pTarget)->nUsableRebirthCoin, _REBIRTH_REBIRTHER, pUser->GetSessionID());
}
int CDnItemTask::FindInventoryItemFromItemType( CDNUserSession * pSession, eItemTypeEnum Type, std::vector<CDnItem *> &pVecResult )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( !pStruct ) return 0;
for( int i=0; i<INVENTORYMAX; i++ ) {
if( !pStruct->pInventory[i] ) continue;
if( pStruct->pInventory[i]->GetItemType() == Type )
pVecResult.push_back( pStruct->pInventory[i] );
}
return (int)pVecResult.size();
}
int CDnItemTask::FindCashInventoryItemFromItemType( CDNUserSession * pSession, eItemTypeEnum Type, std::vector<CDnItem *> &pVecResult )
{
CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession );
if( !pStruct ) return 0;
std::map<INT64, CDnItem*>::iterator iter;
for (iter = pStruct->pMapCashInventory.begin(); iter != pStruct->pMapCashInventory.end(); ++iter){
if (iter->second->GetItemType() == Type)
pVecResult.push_back( iter->second );
}
return (int)pVecResult.size();
}
int CDnItemTask::OnRecvItemModitemExpireDate( CDNUserSession *pSession, CSModItemExpireDate *pPacket, int nLen )
{
//현재 게임서버에서는 사용불가임(클라이언트에서 막혀있음. 확인 후 사용 가능해야 한다면 리턴문 삭제)
return ERROR_NONE;
if (sizeof(CSModItemExpireDate) != nLen)
return ERROR_INVALIDPACKET;
if( !pSession->GetActorHandle() )
return ERROR_NONE;
// Note 한기: 죽은 상태에선 아이템 사용 불가. 물약 같은 거 못 먹음.
if( pSession->GetActorHandle()->IsDie() )
return ERROR_NONE;
CDNUserItem *pItem = pSession->GetItem();
if(!pItem)
return ERROR_NONE;
const TItem *pExpendItem = pSession->GetItem()->GetCashInventory(pPacket->biExpireDateItemSerial);
bool bFlag = false; //사용 성공인지 실패인지 체크
if(pExpendItem)
{
TItemData *pExpendItemData = g_pDataManager->GetItemData(pExpendItem->nItemID);
if(pExpendItemData)
{
int nMin = 0;
//기간연장 아이템 타입에 따라 대상 아이템 가져오는 위치가 달라짐
switch(pExpendItemData->nType)
{
case ITEMTYPE_PET_EXPIRE:
{
const TVehicle *pPet = pItem->GetVehicleInventory(pPacket->biItemSerial);
if(pPet)
{
TItemData *pPetItemData = g_pDataManager->GetItemData( pPet->Vehicle[Pet::Slot::Body].nItemID );
if( pPetItemData && pPetItemData->nType == ITEMTYPE_PET )
{
nMin = pExpendItemData->nTypeParam[0] * 24 * 60;
bFlag = true;
}
}
}
break;
default:
break;
}
if(bFlag)
{
pItem->ModItemExpireDate(pPacket, nMin);
pItem->DeleteCashInventoryBySerial(pPacket->biExpireDateItemSerial,1,false); //기간연장아이템 제거함 위ModItemExpireDate() 함수 안에서 아이템 사용하는 쿼리도 실행됨.
}
}
}
return ERROR_NONE;
}
int CDnItemTask::OnRecvItemDeletePetSkill( CDNUserSession *pSession, CSPetSkillDelete *pPacket, int nLen )
{
if (sizeof(CSPetSkillDelete) != nLen)
return ERROR_INVALIDPACKET;
CDNUserItem *pItem = pSession->GetItem();
if(!pItem)
return ERROR_NONE;
int nRet = pItem->DelPetSkill(pPacket->cSlotNum);
pSession->SendPetSkillDelete(nRet, pPacket->cSlotNum);
return ERROR_NONE;
}