Move git root from Client/ to src/ to track all source code: - Client: Game client source (moved to Client/Client/) - Server: Game server source - GameTools: Development tools - CryptoSource: Encryption utilities - database: Database scripts - Script: Game scripts - rylCoder_16.02.2008_src: Legacy coder tools - GMFont, Game: Additional resources 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
292 lines
9.1 KiB
C++
292 lines
9.1 KiB
C++
|
|
#include "stdafx.h"
|
|
|
|
#include <Creature/CreatureManager.h>
|
|
#include <Creature/Character/Character.h>
|
|
#include <Creature/Character/ExpTable.h>
|
|
#include <Creature/Character/CharRespawnMgr.h>
|
|
|
|
#include <Map/FieldMap/VirtualArea/VirtualArea.h>
|
|
#include <Map/FieldMap/VirtualArea/VirtualAreaMgr.h>
|
|
|
|
#include <Network/Dispatch/ParseUtils.h>
|
|
#include <Network/Dispatch/Chat/ChatDispatch.h>
|
|
|
|
#include <Network/Packet/PacketStruct/ServerInfo.h>
|
|
#include <Network/Packet/PacketStruct/CharStatusPacket.h>
|
|
#include <Network/Packet/PacketStruct/CharItemPacket.h>
|
|
#include <Network/Packet/PacketStruct/CharItemPacketStruct.h>
|
|
#include <Network/Packet/PacketStruct/CharCommunityPacket.h>
|
|
#include <Network/Packet/PacketStruct/CharConfigPacket.h>
|
|
#include <Network/Packet/PacketStruct/RankingPacket.h>
|
|
|
|
#include <Network/Dispatch/GameClient/SendCharAttack.h>
|
|
|
|
#include <Utility/Setup/ServerSetup.h>
|
|
#include <Ranking/RankingMgr.h>
|
|
|
|
#include "GameClientDispatch.h"
|
|
#include "SendCharEtc.h"
|
|
#include "ParseCharEtc.h"
|
|
|
|
|
|
// 캐릭터 자살
|
|
bool GameClientParsePacket::ParseCharSuicide(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktSC), GameClientDispatch);
|
|
|
|
PktSC* lpPktSC = static_cast<PktSC*>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwCharID = lpPktSC->m_dwCharID;
|
|
Position Pos = Position::Position();
|
|
|
|
lpCharacter->Dead(NULL);
|
|
if (0 != lpCharacter->GetMapIndex())
|
|
{
|
|
VirtualArea::CVirtualArea* lpVirtualArea = VirtualArea::CVirtualAreaMgr::GetInstance().GetVirtualArea( lpCharacter->GetMapIndex() );
|
|
if (NULL != lpVirtualArea)
|
|
{
|
|
Pos = lpVirtualArea->GetRespawnPosition(lpCharacter->GetRace(), 0);
|
|
}
|
|
}
|
|
|
|
lpCharacter->Respawn(CCharRespawnMgr::RST_TOWN, Pos);
|
|
lpCharacter->SaveToDBData();
|
|
|
|
if (0 != lpCharacter->GetPID())
|
|
{
|
|
// 파티원 리스폰을 알린다.
|
|
GameClientSendPacket::SendCharDeadToParty(lpCharacter, 0, PktDeadInfo::RESPAWN);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// 캐릭터 바인드 포지션
|
|
bool GameClientParsePacket::ParseCharBindPosition(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktBP), GameClientDispatch);
|
|
|
|
PktBP* lpPktBP = static_cast<PktBP*>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwNPCID = lpPktBP->m_dwNPCID;
|
|
unsigned char cCmd = lpPktBP->m_cCmd;
|
|
POS &Pos = lpPktBP->m_Pos;
|
|
char cZone = lpPktBP->m_cZone;
|
|
|
|
Position DestPos = Pos;
|
|
|
|
switch (cCmd)
|
|
{
|
|
case PktBP::BP_SAVE_POSITION: // 새 위치 저장
|
|
lpCharacter->BindPositionToNPC(dwNPCID);
|
|
break;
|
|
|
|
case PktBP::BP_WARP: // 워프
|
|
DETLOG5(g_Log, "CID:0x%08x 워프 명령을 사용하였습니다. NewPos : %.1f, %.1f, %.1f, Zone : %d",
|
|
lpCharacter->GetCID(), Pos.fPointX, Pos.fPointY, Pos.fPointZ, cZone);
|
|
lpCharacter->MoveTo(DestPos, false);
|
|
break;
|
|
}
|
|
|
|
return GameClientSendPacket::SendCharBindPosition(*lpCharacter,
|
|
dwNPCID, cCmd, Pos, cZone, 0);
|
|
}
|
|
|
|
// 캐릭터 퀵 슬롯 이동
|
|
bool GameClientParsePacket::ParseCharQuickSlotMove(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktQSM), GameClientDispatch);
|
|
|
|
PktQSM* lpPktQSM = static_cast<PktQSM*>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
TakeType takeType = lpPktQSM->m_TakeType;
|
|
unsigned short usSkillID = lpPktQSM->m_usSkillID;
|
|
unsigned char cLockCount = lpPktQSM->m_cLockCount;
|
|
unsigned char cSkillLevel = lpPktQSM->m_cSkillLevel;
|
|
|
|
unsigned short usError = 0;
|
|
|
|
if (false == lpCharacter->MoveQuickSlot(takeType, usSkillID, cLockCount, cSkillLevel))
|
|
{
|
|
usError = PktQSM::FAIL_MOVE;
|
|
}
|
|
|
|
return GameClientSendPacket::SendCharQuickSlotMove(
|
|
GameClientDispatch.GetSendStream(), takeType, usSkillID, usError);
|
|
}
|
|
|
|
|
|
// 캐릭터 옵션 조정
|
|
bool GameClientParsePacket::ParseCharControlOption(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktCOp), GameClientDispatch);
|
|
|
|
PktCOp* lpPktCOp = static_cast<PktCOp*>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwCharID = lpPktCOp->m_dwCharID;
|
|
RejectOption Reject = lpPktCOp->m_RejectOption;
|
|
|
|
unsigned short usError = 0;
|
|
|
|
// 거부 옵션 조정
|
|
if (false == lpCharacter->ControlOption(Reject, false))
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 캐릭터 거부 옵션 조정 실패.", dwCharID);
|
|
return false;
|
|
}
|
|
|
|
return GameClientSendPacket::SendCharControlOption(GameClientDispatch.GetSendStream(), dwCharID, Reject);
|
|
}
|
|
|
|
|
|
// 인증 판넬에 대한 승인
|
|
bool GameClientParsePacket::ParseCharAuthorizePanel(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktAP), GameClientDispatch);
|
|
|
|
PktAP* lpPktAP = static_cast<PktAP *>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwAffectedID = lpPktAP->m_dwAffectedID;
|
|
unsigned long dwCasterID = lpPktAP->m_dwCasterID;
|
|
unsigned char cCmd = lpPktAP->m_cCmd;
|
|
|
|
switch (cCmd)
|
|
{
|
|
case PktAP::AP_RESURRECTION:
|
|
{
|
|
if (0 == lpCharacter->GetStatus().m_nNowHP)
|
|
{
|
|
if (SERVER_ID::ZONE3 == CServerSetup::GetInstance().GetServerZone())
|
|
{
|
|
CCreatureManager::GetInstance().PopRespawnQueue(lpCharacter);
|
|
}
|
|
|
|
if (false == lpCharacter->Respawn(CCharRespawnMgr::RST_RESURRECTION, lpCharacter->GetCurrentPos()))
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 캐릭터 레저렉션 (전송) 실패.", dwAffectedID);
|
|
}
|
|
|
|
if (0 != lpCharacter->GetPID())
|
|
{
|
|
// 파티원에게 리스폰을 알린다.
|
|
GameClientSendPacket::SendCharDeadToParty(lpCharacter,
|
|
CCreatureManager::GetInstance().GetCharacter(dwCasterID), PktDeadInfo::RESURRECT);
|
|
}
|
|
}
|
|
} break;
|
|
|
|
case PktAP::AP_RECALL:
|
|
{
|
|
CCharacter* lpCaster = CCreatureManager::GetInstance().GetCharacter(dwCasterID);
|
|
if (NULL == lpCaster)
|
|
{
|
|
ERRLOG1(g_Log, "CID:0x%08x 리콜에 실패했습니다.", dwCasterID);
|
|
break;
|
|
}
|
|
|
|
const Position& Pos = lpCaster->GetCastingPos();
|
|
lpCharacter->MoveTo(Pos, false);
|
|
|
|
// edith 2009.03.07 리콜 높이 조절
|
|
POS DestPos;
|
|
DestPos.fPointX = Pos.m_fPointX;
|
|
DestPos.fPointY = Pos.m_fPointY+0.3f;
|
|
DestPos.fPointZ = Pos.m_fPointZ;
|
|
|
|
return GameClientSendPacket::SendCharBindPosition(*lpCharacter,
|
|
dwCasterID, PktBP::BP_RECALL, DestPos, CServerSetup::GetInstance().GetServerZone(), 0);
|
|
|
|
} break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
// 캐릭터 명성(공헌도) 정보 요청
|
|
bool GameClientParsePacket::ParseCharFameInfo(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktFI), GameClientDispatch);
|
|
|
|
PktFI* lpPktFI = static_cast<PktFI *>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwCharID = lpPktFI->m_dwCharID;
|
|
|
|
return GameClientSendPacket::SendCharFameInfo(GameClientDispatch.GetSendStream(),
|
|
lpCharacter, "", "", 0, 0, PktFIAck::FAME_INFO, PktBase::NO_SERVER_ERR);
|
|
}
|
|
|
|
|
|
// 랭킹 정보
|
|
bool GameClientParsePacket::ParseCharRankingInfo(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktRankingInfo), GameClientDispatch);
|
|
|
|
PktRankingInfo* lpRankingInfo = static_cast<PktRankingInfo *>(lpPktBase);
|
|
CCharacter* lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
unsigned long dwCharID = lpRankingInfo->m_dwCharID;
|
|
unsigned char cClass = lpRankingInfo->m_cClass;
|
|
unsigned char cPage = lpRankingInfo->m_cPage;
|
|
|
|
return CRankingMgr::GetInstance().SendRankingInfo(dwCharID, cClass, cPage);
|
|
}
|
|
|
|
bool GameClientParsePacket::ParseCastObjectInfo(CGameClientDispatch& GameClientDispatch, PktBase* lpPktBase)
|
|
{
|
|
CHECK_FIXED_PACKETSIZE(lpPktBase, sizeof(PktCOInfo), GameClientDispatch);
|
|
|
|
PktCOInfo* lpPktCOInfo = static_cast<PktCOInfo*>(lpPktBase);
|
|
CCharacter*lpCharacter = GameClientDispatch.GetCharacter();
|
|
|
|
CHECK_CHARACTER_PTR(lpCharacter, GameClientDispatch, lpPktBase->GetCmd());
|
|
|
|
if(lpCharacter->GetCID() == lpPktCOInfo->m_dwSenderID)
|
|
{
|
|
// 전송자 ID가 나인 경우에만 전송.
|
|
CCell* lpCell = lpCharacter->GetCellPos().m_lpCell;
|
|
|
|
if(0 != lpCell)
|
|
{
|
|
lpCell->SendCastObjectInfo(lpPktCOInfo->m_dwSenderID,
|
|
lpPktCOInfo->m_dwReceiverID, lpPktCOInfo->m_sCastObject);
|
|
}
|
|
}
|
|
else if (lpCharacter->IsRideArms() && lpCharacter->GetRideArmsCID() == lpPktCOInfo->m_dwSenderID)
|
|
{
|
|
// 전송자 ID가 내가 타고 있는 병기인 경우에만 전송.
|
|
CCell* lpCell = lpCharacter->GetCellPos().m_lpCell;
|
|
|
|
if(0 != lpCell)
|
|
{
|
|
lpCell->SendCastObjectInfo(lpPktCOInfo->m_dwSenderID,
|
|
lpPktCOInfo->m_dwReceiverID, lpPktCOInfo->m_sCastObject);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|