Files
Sun1602/Server/GameServer/PacketHandler/Handler_AG_ITEM.cpp
T
2022-10-26 12:25:11 +08:00

307 lines
9.5 KiB
C++

#include "StdAfx.h"
#include "Handler_AG_ITEM.h"
#include <PacketStruct_AG.h>
#include "Player.h"
#include "./Status/StatusManager.h"
#include "ItemManager.h"
#include "GameServerEx.h"
//--------------------------------------------------------------------------------------------------
// changes, f100819.1L
const nsPacket::PacketHandlerInfo Handler_AG_ITEM::GetPacketHandlerNodes()
{
#define HANDLER_NODE_INFO(c, p, phase) { MAKEWORD(c, p), phase, Handler_AG_ITEM::On##p }
#define HANDLER_NODE_INFO_EOR() { 0, static_cast<ePHASE_SHIFT>(0), NULL }
static const nsPacket::PacketHandlerNode handlers_static_[] =
{
HANDLER_NODE_INFO(AG_ITEM, AG_ITEM_PORTAL_ACK, PHASE_SERVICE),
HANDLER_NODE_INFO(AG_ITEM, AG_ITEM_UNLOCK_CMD, PHASE_SERVICE),
HANDLER_NODE_INFO(AG_ITEM, AG_ITEM_DECREASE_UNLOCK_CMD, PHASE_SERVICE),
HANDLER_NODE_INFO(AG_ITEM, AG_ITEM_USE_DECREE_ITEM_SYN, PHASE_SERVICE),
#ifdef _NA_20101011_HEIM_LOTTO_CASH_TICKET
HANDLER_NODE_INFO(AG_ITEM, AG_ITEM_USE_HEIM_LOTTO_TICKET_ACK, PHASE_SERVICE),
#endif
HANDLER_NODE_INFO_EOR() // end of records
};
//
BOOST_STATIC_ASSERT(_countof(handlers_static_) >= 1);
nsPacket::PacketHandlerInfo return_value = { handlers_static_, _countof(handlers_static_) - 1 };
//
return return_value;
};
//--------------------------------------------------------------------------------------------------
Handler_AG_ITEM_IMPL( AG_ITEM_PORTAL_ACK )
{
__TOUCHED((pServerSession, pMsg, wSize));
MSG_AG_ITEM_PORTAL_ACK *pRecvMsg = (MSG_AG_ITEM_PORTAL_ACK*)pMsg;
Player *pPlayer = PlayerManager::Instance()->FindPlayerByUserKey( pRecvMsg->m_dwKey );
if( !pPlayer ) return;
//{__NA001164_20081024_CHAR_WAY_POINT_ITEM
//웨이포인트 리스트를 통한 이동 후처리.
ItemManager* pItemManager = pPlayer->GetItemManager();
if( !pItemManager ) return;
ASSERT(pRecvMsg->m_ItemCode);
if (pRecvMsg->m_ItemCode == 0)
return;
SCSlotContainer * pContainer = (SCSlotContainer *)pItemManager->GetItemSlotContainer( SI_INVENTORY );
SCItemSlot & rItemSlot = (SCItemSlot &)pContainer->GetSlot( pRecvMsg->m_PortalPos );
POSTYPE item_position = INVALID_POSTYPE_VALUE;
if (rItemSlot.GetItemCode() == pRecvMsg->m_ItemCode)
{
item_position = pRecvMsg->m_PortalPos;
}
else
{
const SCSlotContainer::SLOT_LINEAR_LIST& slot_list = pContainer->GetSlotList();
uint count = slot_list.size();
for (uint i = 0 ; i < count ; ++i)
{
SCItemSlot& temp_slot = (SCItemSlot&)pContainer->GetSlot(i);
if (pRecvMsg->m_ItemCode == temp_slot.GetItemCode())
{
item_position = temp_slot.GetPos();
break;
}
}
}
if (item_position == INVALID_POSTYPE_VALUE)
return;
SCItemSlot& item_slot = (SCItemSlot&)pContainer->GetSlot(item_position);
if (item_slot.IsWayPointItem())
return;
if (item_slot.GetItemInfo()->m_wType != eITEMTYPE_PORTAL)
return;
// 복수의 돌 아이템을 삭제한다.
RC::eITEM_RESULT rcResult = pPlayer->GetItemManager()->Delete( SI_INVENTORY, pRecvMsg->m_PortalPos, 1, ITEM_DELETE_ITEM_PORTAL );
if( rcResult != RC::RC_ITEM_SUCCESS )
{
SUNLOG( eCRITICAL_LOG, "[AG_ITEM_PORTAL_ACK] Cannot Delete PortalItem! ErrorCode[%d]", rcResult );
return;
}
}
Handler_AG_ITEM_IMPL( AG_ITEM_UNLOCK_CMD )
{
__TOUCHED((pServerSession, pMsg, wSize));
MSG_AG_ITEM_UNLOCK_CMD *pRecvMsg = (MSG_AG_ITEM_UNLOCK_CMD*)pMsg;
Player *pPlayer = PlayerManager::Instance()->FindPlayerByUserKey( pRecvMsg->m_dwKey );
if( !pPlayer ) return;
ItemManager* pItemManager = pPlayer->GetItemManager();
if( !pItemManager ) return;
SCSlotContainer * pContainer = (SCSlotContainer *)pItemManager->GetItemSlotContainer( pRecvMsg->m_ItemIndex );
if( !pItemManager->ValidState() )
return;
//if( !pItemManager->ValidPos( pRecvMsg->m_ItemIndex, pRecvMsg->m_ItemPos ) )
// return;
SCItemSlot & rItemSlot = (SCItemSlot &)pContainer->GetSlot( pRecvMsg->m_ItemPos );
if( !rItemSlot.GetItemInfo() )
return;
rItemSlot.SetLock(FALSE);
// (f100528.2L) prevent a locked state after an instance dungeon moving transaction failed
// if a item operation is fails, a post action is failed, too.
// referenced by f100514.3L
switch (pRecvMsg->post_action_)
{
case pRecvMsg->eAction_MoveFailed:
{
StatusManager* status_manager = pPlayer->GetStatusManager();
status_manager->ChangeInterState(eCHAR_STATE_ZONE_TRANSACTION, false);
};
break;
}
}
Handler_AG_ITEM_IMPL( AG_ITEM_DECREASE_UNLOCK_CMD )
{
__TOUCHED((pServerSession, pMsg, wSize));
MSG_AG_ITEM_DECREASE_UNLOCK_CMD *pRecvMsg = (MSG_AG_ITEM_DECREASE_UNLOCK_CMD*)pMsg;
Player *pPlayer = PlayerManager::Instance()->FindPlayerByUserKey( pRecvMsg->m_dwKey );
if( !pPlayer ) return;
ItemManager* pItemManager = pPlayer->GetItemManager();
if( !pItemManager ) return;
SCSlotContainer * pContainer = (SCSlotContainer *)pItemManager->GetItemSlotContainer( pRecvMsg->m_ItemIndex );
SCItemSlot & rItemSlot = (SCItemSlot &)pContainer->GetSlot( pRecvMsg->m_ItemPos );
if( !rItemSlot.GetItemInfo() )
return;
rItemSlot.SetLock(FALSE);
if( !pItemManager->ValidState() )
return;
if( !pItemManager->ValidPos( pRecvMsg->m_ItemIndex, pRecvMsg->m_ItemPos ) )
return;
GAMELOG->LogItem( ITEM_USE, pPlayer, &rItemSlot );
pItemManager->Lose( pContainer, pRecvMsg->m_ItemPos, 1);
WORD wCoolTimeType = rItemSlot.GetItemInfo()->m_wCoolTimeType;
pPlayer->ResetUseItem( wCoolTimeType );
}
Handler_AG_ITEM_IMPL( AG_ITEM_USE_DECREE_ITEM_SYN )
{
__TOUCHED((pServerSession, pMsg, wSize));
MSG_AG_ITEM_USE_DECREE_ITEM_SYN* pRecvMsg = (MSG_AG_ITEM_USE_DECREE_ITEM_SYN *)pMsg;
Player* pPlayer = PlayerManager::Instance()->FindPlayerByUserKey(pRecvMsg->m_dwKey);
if(!pPlayer) return;
if(!pPlayer->GetField() ) return;
ItemManager* pItemManager = pPlayer->GetItemManager();
if(!pItemManager) return;
SCSlotContainer* pContainer = (SCSlotContainer *)pItemManager->GetItemSlotContainer(SI_INVENTORY);
if(!pContainer) return;
for(int pos = 0; pos < MAX_INVENTORY_SLOT_NUM; pos++)
{
if( pContainer->IsEmpty(pos) )
continue;
SCItemSlot &rItemSlot = (SCItemSlot &)pContainer->GetSlot(pos);
if( rItemSlot.GetSerial() != 0 )
{
const BASE_ITEMINFO* const pInfo = rItemSlot.GetItemInfo();
if(!pInfo) break;
if(pInfo->m_wType == eITEMTYPE_CHAT_SHOUT_CONSUME)
{
if(!pItemManager->ValidState()) return;
if(!pItemManager->ValidPos(SI_INVENTORY, pos)) return;
//__CN_1299_WASTE_ITEM_LEVEL_LIMITE_CHECK
RC::eITEM_RESULT rcResult = pPlayer->CanUseItem( rItemSlot.GetItemInfo() );
if( rcResult != RC::RC_ITEM_SUCCESS )
{
MSG_AG_ITEM_USE_DECREE_ITEM_NAK msgNAK;
msgNAK.m_dwKey = pPlayer->GetUserGuid();
msgNAK.m_byErrorCode = rcResult;
g_pGameServer->SendToServer(AGENT_SERVER, &msgNAK, sizeof(msgNAK));
return;
}
pItemManager->Lose(pContainer, pos, 1);
MSG_CG_ITEM_USE_ACK ackMsg;
ackMsg.m_atIndex = static_cast<BYTE>(SI_INVENTORY);
ackMsg.m_atPos = pos;
pPlayer->SendPacket( &ackMsg, sizeof( ackMsg ) );
MSG_AG_ITEM_USE_DECREE_ITEM_ACK msgACK;
msgACK.m_dwKey = pPlayer->GetUserGuid();
g_pGameServer->SendToServer(AGENT_SERVER, &msgACK, sizeof(msgACK));
return;
}
}
continue;
}
//여기까지 오면 해당 아이템이 없는거다.
MSG_AG_ITEM_USE_DECREE_ITEM_NAK msgNAK;
msgNAK.m_dwKey = pPlayer->GetUserGuid();
msgNAK.m_byErrorCode = RC::RC_ITEM_NOT_EXIST;
g_pGameServer->SendToServer(AGENT_SERVER, &msgNAK, sizeof(msgNAK));
}
#ifdef _NA_20101011_HEIM_LOTTO_CASH_TICKET
// 하임행운 캐시 응모권 사용 응답
Handler_AG_ITEM_IMPL( AG_ITEM_USE_HEIM_LOTTO_TICKET_ACK )
{
__TOUCHED((pServerSession, pMsg, wSize));
const MSG_AG_ITEM_USE_HEIM_LOTTO_TICKET_ACK* msg = \
static_cast<const MSG_AG_ITEM_USE_HEIM_LOTTO_TICKET_ACK*>(pMsg);
Player* player = PlayerManager::Instance()->FindPlayerByCharKey(msg->char_guid);
if (player == NULL || player->GetField() == NULL) {
return;
}
if (msg->result_code != RC::RC_ITEM_SUCCESS)
{
MSG_CG_ITEM_USE_NAK nak;
nak.m_ErrorCode = (BYTE)msg->result_code;
player->SendPacket(&nak, (WORD)sizeof(nak));
// 실패의 경우에도 유효한 아이템의 unlock을 위해 일단 진행
}
ItemManager* item_manager = player->GetItemManager();
if (item_manager == NULL) {
return;
}
SCSlotContainer* container = (SCSlotContainer*)item_manager->GetItemSlotContainer(msg->index);
if (container == NULL) {
return;
}
SCItemSlot& item_slot = (SCItemSlot&)container->GetSlot(msg->pos);
if (item_slot.GetSerial() == 0) {
return;
}
const BASE_ITEMINFO* item_info = item_slot.GetItemInfo();
if (item_info == NULL) {
return;
}
item_slot.SetLock(FALSE);
// 실패의 경우에는 여기서 리턴
if (msg->result_code != RC::RC_ITEM_SUCCESS) {
return;
}
// 성공의 경우에는 먼저 아이템 사용 로그부터 남긴다
GAMELOG->LogItem(ITEM_USE, player, &item_slot);
// 소모성 아이템 삭제
if (item_info->m_wType == eITEMTYPE_HEIM_LOTTO_TICKET)
{
if(item_slot.GetNum() <= 1) {
container->DeleteSlot(msg->pos, NULL);
}
else {
container->UpdateSlot(msg->pos, -1);
}
}
player->ResetUseItem(item_info->m_wCoolTimeType);
MSG_CG_ITEM_USE_ACK ack;
ack.m_atIndex = msg->index;
ack.m_atPos = msg->pos;
player->SendPacket(&ack, (WORD)sizeof(ack));
}
#endif // _NA_20101011_HEIM_LOTTO_CASH_TICKET