#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( 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(pData), nLen ); case eItem::CS_ITEM_COMPOUND_REQ: return OnrecvItemCompoundReq( pSession, reinterpret_cast(pData), nLen ); case eItem::CS_ITEM_COMPOUND_CANCEL_REQ: return OnRecvItemCompoundCancelReq( pSession, reinterpret_cast(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 rebirthItems; ScanItemFromID(pSession->GetActorHandle(), nItemID, &rebirthItems); if (rebirthItems.empty()) return false; std::vector::iterator iter = rebirthItems.begin(); std::vector::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::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(BackupInfo.nHPPercent)); } if( BackupInfo.nSPPercent < 100 ) { strParam.append("/"); strParam.append(boost::lexical_cast(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::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(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(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; inCount; ++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(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; iGetActorHandle() ) continue; CDnPlayerActor *pPlayer = static_cast(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; iGetState() == 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(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::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::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::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::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::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::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; jGetItem()->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; jGetItem()->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; jGetItem()->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; jGetItem()->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; jGetItem()->GetInventory( j ); if( !pItemData || pItemData->nItemID == 0 ) continue; pItem = CreateItem( pItemData ); if( !pItem ) { #if defined( _WORK ) const_cast(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; iGetItem()->GetEquip(j); if( !pItemData || pItemData->nItemID == 0 ) continue; pItem = CreateItem( pItemData ); if( !pItem ) { _ASSERT(0); continue; } InsertEquipItem( pSession, j, pItem ); } for( int j=0; jGetItem()->GetCashEquip(j); if( !pItemData || pItemData->nItemID == 0 ) continue; pItem = CreateItem( pItemData ); if( !pItem ) { _ASSERT(0); continue; } InsertCashEquipItem( pSession, j, pItem ); } for( int j=0; jGetItem()->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; jGetItem()->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; jGetItem()->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 *pVecResult ) { for( DWORD i=0; iGetActorHandle() == hActor ) { int nCount = 0; CDNGameRoom::PartyStruct *pStruct = GetPartyData(i); if( pStruct == NULL ) continue; //CDNSession::PartyStruct *pStruct = GetPartyData(i); for( DWORD j=0; jpInventory[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 &pVecResult ) { CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession ); if( !pStruct ) return 0; for( int i=0; ipInventory[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 &pVecResult ) { CDNGameRoom::PartyStruct *pStruct = GetPartyData( pSession ); if( !pStruct ) return 0; std::map::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; }