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>
390 lines
12 KiB
C++
390 lines
12 KiB
C++
#define NOMINMAX
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include <Item/Item.h>
|
|
#include "BroadcastCharacterData.h"
|
|
|
|
#include <utility>
|
|
#include "GMMemory.h"
|
|
|
|
|
|
namespace Broadcast2nd
|
|
{
|
|
|
|
const unsigned char CNetworkEquipGrade::TransferNetworkEquipGrade(Item::CItem* lpItem)
|
|
{
|
|
Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem);
|
|
if (NULL != lpEquip)
|
|
{
|
|
Item::Grade::GradeInfo gradeInfo = lpEquip->GetItemGrade();
|
|
|
|
// A 그레이드부터 이펙트를 표기한다.
|
|
if (Item::EquipType::B_GRADE > gradeInfo.m_eItemGrade)
|
|
{
|
|
return (Item::EquipType::B_GRADE - gradeInfo.m_eItemGrade);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
CAggresiveCreatureData::CAggresiveCreatureData()
|
|
: m_dwCID(0), m_usHP(0), m_dwDataFlag(0), m_dwLastUpdatedPulse(0)
|
|
{
|
|
|
|
|
|
}
|
|
|
|
CAggresiveCreatureData::~CAggresiveCreatureData()
|
|
{
|
|
|
|
}
|
|
|
|
void CAggresiveCreatureData::SetEnchantInfo(const EnchantInfo& enchantInfo)
|
|
{
|
|
std::copy(enchantInfo.m_dwStatusFlag,
|
|
enchantInfo.m_dwStatusFlag + EnchantInfo::MAX_ARRAY, m_EnchantInfo.m_dwStatusFlag);
|
|
}
|
|
|
|
void CAggresiveCreatureData::ClearData()
|
|
{
|
|
m_dwCID = 0;
|
|
m_usHP = 0;
|
|
m_dwDataFlag = 0;
|
|
m_dwLastUpdatedPulse = 0;
|
|
|
|
m_NetworkPos.Initialize(0, 0, 0, 0, 0);
|
|
m_EnchantInfo.ClearFlag();
|
|
}
|
|
|
|
CCharacterData::CCharacterData()
|
|
{
|
|
memset(m_szName, 0, sizeof(char) * MAX_NAME);
|
|
memset(m_szStallName, 0, sizeof(char) * StallNode::MAX_STALL_NAME);
|
|
memset(m_dwDoubleEquipsID, 0, sizeof(unsigned long) * HALF_EQUIP_POS);
|
|
|
|
memset(&m_CommunityInfo, 0, sizeof(CommunityInfo));
|
|
memset(&m_StatusInfo, 0, sizeof(bcStatusInfo));
|
|
memset(&m_NetworkEquipGrade, 0, sizeof(CNetworkEquipGrade));
|
|
memset(&m_WarFlagInfo, 0, sizeof(WarFlagInfo));
|
|
|
|
memset(&m_cRealmPoint, 0, sizeof(unsigned char));
|
|
}
|
|
|
|
CCharacterData::~CCharacterData()
|
|
{
|
|
|
|
}
|
|
|
|
void CCharacterData::ClearData()
|
|
{
|
|
CAggresiveCreatureData::ClearData();
|
|
|
|
memset(m_szName, 0, sizeof(char) * MAX_NAME);
|
|
memset(m_szStallName, 0, sizeof(char) * StallNode::MAX_STALL_NAME);
|
|
memset(m_dwDoubleEquipsID, 0, sizeof(unsigned long) * HALF_EQUIP_POS);
|
|
|
|
memset(&m_CommunityInfo, 0, sizeof(CommunityInfo));
|
|
memset(&m_StatusInfo, 0, sizeof(bcStatusInfo));
|
|
memset(&m_NetworkEquipGrade, 0, sizeof(CNetworkEquipGrade));
|
|
memset(&m_WarFlagInfo, 0, sizeof(WarFlagInfo));
|
|
memset(&m_cRealmPoint, 0, sizeof(unsigned char));
|
|
}
|
|
|
|
void CCharacterData::GetEquipmentsID(unsigned short* lpEquipmentsID_Out, unsigned char nIDNum) const
|
|
{
|
|
unsigned short* dupEquipsID = (unsigned short*)m_dwDoubleEquipsID;
|
|
std::copy(dupEquipsID, dupEquipsID +
|
|
std::min(nIDNum, unsigned char(Item::EquipmentPos::MAX_EQUPMENT_POS)), lpEquipmentsID_Out);
|
|
}
|
|
|
|
void CCharacterData::SetEquipmentsID(unsigned short* lpEquipmentsID_In, const unsigned char nIDNum)
|
|
{
|
|
std::copy(lpEquipmentsID_In, lpEquipmentsID_In +
|
|
std::min(nIDNum, unsigned char(Item::EquipmentPos::MAX_EQUPMENT_POS)), reinterpret_cast<unsigned short*>(m_dwDoubleEquipsID));
|
|
}
|
|
|
|
void Broadcast2nd::CCharacterData::SetEquipmentsID(unsigned long dwEquipmentsID_In, const unsigned char nIDIndex)
|
|
{
|
|
if (nIDIndex < HALF_EQUIP_POS)
|
|
{
|
|
m_dwDoubleEquipsID[nIDIndex] = dwEquipmentsID_In;
|
|
}
|
|
}
|
|
|
|
void CCharacterData::SetName(const char* szName, const size_t nNameLen)
|
|
{
|
|
memcpy(m_szName, szName, std::min(size_t(MAX_NAME), nNameLen));
|
|
}
|
|
|
|
void CCharacterData::SetStallName(const char* szStallName, const size_t nStallNameLen)
|
|
{
|
|
memcpy(m_szStallName, szStallName, std::min(size_t(StallNode::MAX_STALL_NAME), nStallNameLen));
|
|
}
|
|
|
|
bool CCharacterData::UpdateData(unsigned long dwCID, unsigned long dwCurrentPulse,
|
|
const char* szData, int& nBufferSize_InOut)
|
|
{
|
|
// 데이터 순서는 다음과 같다.
|
|
// UpdateFlag(4byte)
|
|
// 장비들(16개 * 2byte = 32byte)
|
|
// 이름(16byte)
|
|
// 노점상 이름(32byte)
|
|
// 주소 정보 (public addr/private addr 12byte)
|
|
// 커뮤니티 정보 ( 길드ID / 파티ID / 용병 / 명성 / 마일리지 )
|
|
// 몸 정보 ( 4byte )
|
|
// 레벨 및
|
|
// Total 138 Bytes
|
|
|
|
unsigned long dwUpdateFlag = 0;
|
|
|
|
const char* szDataPos = szData;
|
|
const int nBufferSize = nBufferSize_InOut;
|
|
if (nBufferSize < sizeof(unsigned long))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
COPY_AND_ADVANCE_SRC(&dwUpdateFlag, szDataPos, sizeof(unsigned long));
|
|
|
|
// 읽어온 UpdateFlag로, 필요한 데이터의 양을 추산한다. 데이터 양이 부족하면 에러를 뱉는다.
|
|
int nEstimateBufferSize = EstimateBufferSize(dwUpdateFlag);
|
|
|
|
if (nBufferSize < nEstimateBufferSize )
|
|
{
|
|
// 버퍼 크기가 추산한 길이보다 작은 경우는 실패
|
|
return false;
|
|
}
|
|
|
|
// 데이터 복사. 순서 바뀌면 죽는다!!.
|
|
m_dwCID = dwCID;
|
|
|
|
if (0 != dwCurrentPulse)
|
|
{
|
|
// Pulse가 0으로 오면 CellLogin이다. Pulse를 업데이트하지 않는다.
|
|
m_dwLastUpdatedPulse = dwCurrentPulse;
|
|
}
|
|
|
|
int nCount = 0;
|
|
|
|
for (; nCount < HALF_EQUIP_POS; ++nCount)
|
|
{
|
|
if (dwUpdateFlag & (1 << nCount))
|
|
{
|
|
COPY_AND_ADVANCE_SRC(m_dwDoubleEquipsID + nCount, szDataPos, sizeof(unsigned long));
|
|
}
|
|
}
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_CHAR_NAME) { COPY_AND_ADVANCE_SRC(m_szName, szDataPos, sizeof(unsigned char) * MAX_NAME); }
|
|
if (dwUpdateFlag & CHAR_DELTA_STALL_NAME) { COPY_AND_ADVANCE_SRC(m_szStallName, szDataPos, sizeof(unsigned char) * StallNode::MAX_STALL_NAME); }
|
|
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwGuild_ID, szDataPos, sizeof(unsigned long)); }
|
|
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_cTacticsFlag, szDataPos, sizeof(unsigned char)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_PARTY_ID) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwParty_ID, szDataPos, sizeof(unsigned long)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_FAME) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwFame, szDataPos, sizeof(unsigned long)); }
|
|
if (dwUpdateFlag & CHAR_DELTA_FAME) { COPY_AND_ADVANCE_SRC(&m_CommunityInfo.m_dwMileage, szDataPos, sizeof(unsigned long)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_BODYINFO) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_dwBodyInfo, szDataPos, sizeof(unsigned long)); }
|
|
if (dwUpdateFlag & CHAR_DELTA_CLASS) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_cClass, szDataPos, sizeof(unsigned char)); }
|
|
if (dwUpdateFlag & CHAR_DELTA_LEVEL) { COPY_AND_ADVANCE_SRC(&m_StatusInfo.m_cLevel, szDataPos, sizeof(unsigned char)); }
|
|
|
|
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
|
|
{
|
|
if (dwUpdateFlag & (CHAR_DELTA_ENCHANT_INFO << nCount))
|
|
{
|
|
COPY_AND_ADVANCE_SRC(m_EnchantInfo.m_dwStatusFlag + nCount, szDataPos, sizeof(unsigned long));
|
|
}
|
|
}
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_NETWORK_POS) { COPY_AND_ADVANCE_SRC(&m_NetworkPos, szDataPos, sizeof(CNetworkPos));}
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_HP) { COPY_AND_ADVANCE_SRC(&m_usHP, szDataPos, sizeof(unsigned short)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_EQUIP_GRADE) { COPY_AND_ADVANCE_SRC(&m_NetworkEquipGrade, szDataPos, sizeof(CNetworkEquipGrade)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_WAR_FLAG) { COPY_AND_ADVANCE_SRC(&m_WarFlagInfo, szDataPos, sizeof(WarFlagInfo)); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_REALM_POINT) { COPY_AND_ADVANCE_SRC(&m_cRealmPoint, szDataPos, sizeof(unsigned char)); }
|
|
|
|
nBufferSize_InOut = static_cast<int>(szDataPos - szData);
|
|
|
|
if (0 != dwUpdateFlag)
|
|
{
|
|
// 변경된 데이터가 있는지 살피고, 변경되었다면 데이터 변경 비트를 세팅한다.
|
|
SetDataFlag(CHARDATA_CHANGED);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
int CCharacterData::EstimateBufferSize(unsigned long dwUpdateFlag)
|
|
{
|
|
// CID와 UpdateFlag의 길이만큼 더한다.
|
|
int nEstimateBufferSize = 0;
|
|
int nCount = 0;
|
|
|
|
for (; nCount < Broadcast2nd::CCharacterData::HALF_EQUIP_POS; ++nCount)
|
|
{
|
|
if (dwUpdateFlag & (1 << nCount))
|
|
{
|
|
nEstimateBufferSize += sizeof(unsigned long);
|
|
}
|
|
}
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_CHAR_NAME) { nEstimateBufferSize += sizeof(unsigned char) * MAX_NAME; }
|
|
if (dwUpdateFlag & CHAR_DELTA_STALL_NAME) { nEstimateBufferSize += sizeof(unsigned char) * StallNode::MAX_STALL_NAME; }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { nEstimateBufferSize += sizeof(unsigned long); }
|
|
if (dwUpdateFlag & CHAR_DELTA_GUILD_ID) { nEstimateBufferSize += sizeof(unsigned char); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_PARTY_ID) { nEstimateBufferSize += sizeof(unsigned long); }
|
|
if (dwUpdateFlag & CHAR_DELTA_FAME) { nEstimateBufferSize += sizeof(unsigned long) * 2; }
|
|
if (dwUpdateFlag & CHAR_DELTA_BODYINFO) { nEstimateBufferSize += sizeof(unsigned long); }
|
|
if (dwUpdateFlag & CHAR_DELTA_CLASS) { nEstimateBufferSize += sizeof(unsigned char); }
|
|
if (dwUpdateFlag & CHAR_DELTA_LEVEL) { nEstimateBufferSize += sizeof(unsigned char); }
|
|
|
|
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
|
|
{
|
|
if (dwUpdateFlag & (CHAR_DELTA_ENCHANT_INFO << nCount))
|
|
{
|
|
nEstimateBufferSize += sizeof(unsigned long);
|
|
}
|
|
}
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_NETWORK_POS) { nEstimateBufferSize += sizeof(CNetworkPos); }
|
|
if (dwUpdateFlag & CHAR_DELTA_HP) { nEstimateBufferSize += sizeof(unsigned short); }
|
|
if (dwUpdateFlag & CHAR_DELTA_EQUIP_GRADE) { nEstimateBufferSize += sizeof(CNetworkEquipGrade); }
|
|
if (dwUpdateFlag & CHAR_DELTA_WAR_FLAG) { nEstimateBufferSize += sizeof(WarFlagInfo); }
|
|
|
|
if (dwUpdateFlag & CHAR_DELTA_REALM_POINT) { nEstimateBufferSize += sizeof(unsigned char); }
|
|
|
|
return nEstimateBufferSize;
|
|
}
|
|
|
|
void CMonsterData::ClearData()
|
|
{
|
|
CAggresiveCreatureData::ClearData();
|
|
m_dwMasterCID = 0;
|
|
}
|
|
|
|
|
|
CMonsterData::CMonsterData()
|
|
: m_dwMasterCID(0)
|
|
{
|
|
|
|
}
|
|
|
|
CMonsterData::~CMonsterData()
|
|
{
|
|
|
|
}
|
|
|
|
bool CMonsterData::UpdateData(unsigned long dwCID, unsigned long dwCurrentPulse,
|
|
const char* szData, int& nBufferSize_InOut)
|
|
{
|
|
const char* szDataPos = szData;
|
|
const int nBufferSize = nBufferSize_InOut;
|
|
if (nBufferSize < sizeof(unsigned char))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
unsigned char cUpdateFlag =
|
|
*reinterpret_cast<const unsigned char*>(szDataPos);
|
|
|
|
++szDataPos;
|
|
|
|
// 읽어온 UpdateFlag로, 필요한 데이터의 양을 추산한다. 데이터 양이 부족하면 에러를 뱉는다.
|
|
int nEstimateBufferSize = EstimateBufferSize(cUpdateFlag);
|
|
if (nBufferSize < nEstimateBufferSize)
|
|
{
|
|
// 버퍼 크기가 추산한 길이보다 작은 경우는 실패
|
|
return false;
|
|
}
|
|
|
|
// 데이터 복사. 순서 바뀌면 죽는다!!.
|
|
m_dwCID = dwCID;
|
|
|
|
if (0 != dwCurrentPulse)
|
|
{
|
|
// Pulse가 0으로 오면 CellLogin이다. Pulse를 업데이트하지 않는다.
|
|
m_dwLastUpdatedPulse = dwCurrentPulse;
|
|
}
|
|
|
|
for (int nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
|
|
{
|
|
if (cUpdateFlag & (MON_DELTA_ENCHANT_INFO << nCount))
|
|
{
|
|
COPY_AND_ADVANCE_SRC(
|
|
m_EnchantInfo.m_dwStatusFlag + nCount,
|
|
szDataPos, sizeof(unsigned long));
|
|
}
|
|
}
|
|
|
|
const CNetworkPos oldNetPos = m_NetworkPos;
|
|
|
|
if (cUpdateFlag & MON_DELTA_NETWORK_POS) { COPY_AND_ADVANCE_SRC(&m_NetworkPos, szDataPos, sizeof(CNetworkPos)); }
|
|
if (cUpdateFlag & MON_DELTA_HP) { COPY_AND_ADVANCE_SRC(&m_usHP, szDataPos, sizeof(unsigned short)); }
|
|
if (cUpdateFlag & MON_DELTA_MASTERCID) { COPY_AND_ADVANCE_SRC(&m_dwMasterCID, szDataPos, sizeof(unsigned long)); }
|
|
|
|
/*
|
|
// TODO : REMOVE HERE
|
|
if (49 < oldNetPos.GetSquaredRange(CNetworkPos(0, 0, 0)) &&
|
|
49 < oldNetPos.GetSquaredRange(m_NetworkPos))
|
|
{
|
|
const int MAX_BUFFER = 256;
|
|
char szBuffer[MAX_BUFFER];
|
|
|
|
if (0 < _snprintf(szBuffer, MAX_BUFFER - 1,
|
|
"PktBroadcast2nd : CID:0x%08x : 순간이동하나?.. %f거리를 눈앞에서 이동했다!"
|
|
"/CurrentPulse:%d (%f,%f,%f)->(%f,%f,%f)\n",
|
|
m_dwCID, oldNetPos.GetSquaredRange(m_NetworkPos), dwCurrentPulse,
|
|
oldNetPos.GetXPos(), oldNetPos.GetYPos(), oldNetPos.GetZPos(),
|
|
m_NetworkPos.GetXPos(), m_NetworkPos.GetYPos(), m_NetworkPos.GetZPos()))
|
|
{
|
|
szBuffer[MAX_BUFFER - 1] = 0;
|
|
OutputDebugString(szBuffer);
|
|
}
|
|
}
|
|
*/
|
|
|
|
nBufferSize_InOut = static_cast<int>(szDataPos - szData);
|
|
|
|
if (0 != cUpdateFlag)
|
|
{
|
|
// 변경된 데이터가 있는지 살피고, 변경되었다면 데이터 변경 비트를 세팅한다.
|
|
SetDataFlag(CHARDATA_CHANGED);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int CMonsterData::EstimateBufferSize(unsigned char cUpdateFlag)
|
|
{
|
|
// CID와 UpdateFlag의 길이만큼 더한다.
|
|
int nEstimateBufferSize = 0;
|
|
int nCount = 0;
|
|
|
|
for (nCount = 0; nCount < EnchantInfo::MAX_ARRAY; ++nCount)
|
|
{
|
|
if (cUpdateFlag & (MON_DELTA_ENCHANT_INFO << nCount))
|
|
{
|
|
nEstimateBufferSize += sizeof(unsigned long);
|
|
}
|
|
}
|
|
|
|
if (cUpdateFlag & MON_DELTA_NETWORK_POS) { nEstimateBufferSize += sizeof(CNetworkPos); }
|
|
if (cUpdateFlag & MON_DELTA_HP) { nEstimateBufferSize += sizeof(unsigned short); }
|
|
if (cUpdateFlag & MON_DELTA_MASTERCID) { nEstimateBufferSize += sizeof(unsigned long); }
|
|
|
|
return nEstimateBufferSize;
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|