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>
296 lines
8.8 KiB
C++
296 lines
8.8 KiB
C++
// CharacterInfoDlg.cpp : 구현 파일입니다.
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "PrintLog.h"
|
|
#include "GAMELOGAnalyzer.h"
|
|
#include "CharacterInfoDlg.h"
|
|
#include "ItemInfoSheet.h"
|
|
#include "InfoDlg.h"
|
|
|
|
#include <BaseLibrary/Utility/Math/Math.h>
|
|
|
|
#include "GlobalFunctions.h"
|
|
|
|
|
|
// CCharacterInfoDlg 대화 상자입니다.
|
|
|
|
IMPLEMENT_DYNAMIC(CCharacterInfoDlg, CDialog)
|
|
CCharacterInfoDlg::CCharacterInfoDlg(CWnd* pParent /*=NULL*/)
|
|
: CDialog(CCharacterInfoDlg::IDD, pParent)
|
|
, m_LastPosX(_T(""))
|
|
, m_LastPosY(_T(""))
|
|
, m_LastPosZ(_T(""))
|
|
, m_SavePosX(_T(""))
|
|
, m_SavePosY(_T(""))
|
|
, m_SavePosZ(_T(""))
|
|
{
|
|
}
|
|
|
|
CCharacterInfoDlg::~CCharacterInfoDlg()
|
|
{
|
|
}
|
|
|
|
void CCharacterInfoDlg::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
CDialog::DoDataExchange(pDX);
|
|
DDX_Control(pDX, IDC_CHARACTER_STATUS_LIST, m_CharacterStatus);
|
|
DDX_Text(pDX, IDC_LAST_POSX, m_LastPosX);
|
|
DDX_Text(pDX, IDC_LAST_POSY, m_LastPosY);
|
|
DDX_Text(pDX, IDC_LAST_POSZ, m_LastPosZ);
|
|
DDX_Text(pDX, IDC_SAVE_POSX, m_SavePosX);
|
|
DDX_Text(pDX, IDC_SAVE_POSY, m_SavePosY);
|
|
DDX_Text(pDX, IDC_SAVE_POSZ, m_SavePosZ);
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CCharacterInfoDlg, CDialog)
|
|
ON_WM_CLOSE()
|
|
ON_BN_CLICKED(IDC_EXPORT_BUTTON, OnBnClickedItemInfo)
|
|
ON_BN_CLICKED(IDC_SHOW_QUICKSLOT, OnBnClickedShowQuickslot)
|
|
ON_BN_CLICKED(IDC_SHOW_SKILLSLOT, OnBnClickedShowSkillslot)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
// CCharacterInfoDlg 메시지 처리기입니다.
|
|
|
|
void CCharacterInfoDlg::PostNcDestroy()
|
|
{
|
|
// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
|
|
|
|
CDialog::PostNcDestroy();
|
|
delete this;
|
|
}
|
|
|
|
void CCharacterInfoDlg::OnClose()
|
|
{
|
|
// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
|
|
|
|
CDialog::OnClose();
|
|
DestroyWindow();
|
|
}
|
|
|
|
bool CCharacterInfoDlg::Initialize(const GAMELOG::sLogBase* lpLogBase)
|
|
{
|
|
using namespace GAMELOG;
|
|
|
|
m_dwCID = lpLogBase->m_dwCID;
|
|
m_dwUID = lpLogBase->m_dwUID;
|
|
m_time = lpLogBase->m_time;
|
|
|
|
switch(lpLogBase->m_cCmd)
|
|
{
|
|
case CMD::CHAR_LOGIN:
|
|
case CMD::CHAR_LOGOUT:
|
|
case CMD::CHAR_DBUPDATE:
|
|
{
|
|
const sCharLoginOut* pCharLoginOut = static_cast<const sCharLoginOut*>(lpLogBase);
|
|
|
|
std::copy(&pCharLoginOut->m_usDataSize[0],
|
|
&pCharLoginOut->m_usDataSize[DBUpdateData::MAX_UPDATE_DB],
|
|
m_usUpdateInfo);
|
|
|
|
size_t nSize = std::accumulate(&m_usUpdateInfo[0], &m_usUpdateInfo[DBUpdateData::MAX_UPDATE_DB], 0);
|
|
memcpy(m_szCharacterInfo, reinterpret_cast<const char*>(&pCharLoginOut[1]), nSize);
|
|
|
|
m_usDepositSize = pCharLoginOut->m_usDepositData;
|
|
memcpy(m_szDepositData, reinterpret_cast<const char*>(&pCharLoginOut[1]) + nSize, m_usDepositSize);
|
|
|
|
m_dwDepositMoney = pCharLoginOut->m_dwDepositMoney;
|
|
|
|
} break;
|
|
|
|
default: return false;
|
|
}
|
|
|
|
StatusUpdate();
|
|
PositionUpdate();
|
|
|
|
UpdateData(FALSE);
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
void CCharacterInfoDlg::StatusUpdate()
|
|
{
|
|
m_CharacterStatus.DeleteAllItems();
|
|
|
|
CHAR_INFOST* pCharInfoSt = reinterpret_cast<CHAR_INFOST*>(m_szCharacterInfo
|
|
+ std::accumulate(&m_usUpdateInfo[0], &m_usUpdateInfo[DBUpdateData::STATUS_UPDATE], 0));
|
|
|
|
struct tm* pTm = localtime(&m_time);
|
|
|
|
char szNameCIDTime[MAX_PATH];
|
|
_snprintf(szNameCIDTime, MAX_PATH - 1, "[ UID: %10u ][ %4d/%02d/%02d %02d:%02d:%02d ]",
|
|
m_dwUID, pTm->tm_year + 1900, pTm->tm_mon + 1, pTm->tm_mday,
|
|
pTm->tm_hour, pTm->tm_min, pTm->tm_sec);
|
|
szNameCIDTime[MAX_PATH - 1] = 0;
|
|
|
|
SetWindowText(szNameCIDTime);
|
|
|
|
char szExp[64];
|
|
Math::Convert::Hex64ToStr(szExp, pCharInfoSt->Exp);
|
|
|
|
const int MAX_ROW = 22;
|
|
const int MAX_BUFFER = 32;
|
|
static const char szCharInfoField[MAX_ROW][MAX_BUFFER] =
|
|
{
|
|
"CID", "Name", "Sex", "Hair", "Face", "Race", "Class", "Fame", "Mileage", "Guild",
|
|
"Party", "Level", "Gold", "IP", "STR", "DEX", "CON", "INT", "WIS", "HP", "MP", "EXP"
|
|
};
|
|
|
|
std::string szMoney = GetMoneyString(pCharInfoSt->Gold);
|
|
|
|
CString nValue[MAX_ROW];
|
|
|
|
nValue[0].Format("%d", pCharInfoSt->CID); nValue[1].Format("%s", pCharInfoSt->Name);
|
|
nValue[2].Format("%d", pCharInfoSt->Sex); nValue[3].Format("%d", pCharInfoSt->Hair);
|
|
nValue[4].Format("%d", pCharInfoSt->Face); nValue[5].Format("%d", pCharInfoSt->Race);
|
|
nValue[6].Format("%d", pCharInfoSt->Class); nValue[7].Format("%d", pCharInfoSt->Fame);
|
|
nValue[8].Format("%d", pCharInfoSt->Mileage); nValue[9].Format("0x%08X", pCharInfoSt->GID);
|
|
nValue[10].Format("%d", pCharInfoSt->PID); nValue[11].Format("%d", pCharInfoSt->Level);
|
|
nValue[12].Format("%s", szMoney.c_str()); nValue[13].Format("%d", pCharInfoSt->IP);
|
|
nValue[14].Format("%d", pCharInfoSt->STR); nValue[15].Format("%d", pCharInfoSt->DEX);
|
|
nValue[16].Format("%d", pCharInfoSt->CON); nValue[17].Format("%d", pCharInfoSt->INT);
|
|
nValue[18].Format("%d", pCharInfoSt->WIS); nValue[19].Format("%d", pCharInfoSt->HP);
|
|
nValue[20].Format("%d", pCharInfoSt->MP); nValue[21].Format("0x%s", szExp);
|
|
|
|
for(int nCount = 0; nCount < MAX_ROW; ++nCount)
|
|
{
|
|
m_CharacterStatus.InsertItem(nCount, szCharInfoField[nCount]);
|
|
m_CharacterStatus.SetItemText(nCount, 1, nValue[nCount]);
|
|
}
|
|
}
|
|
|
|
void CCharacterInfoDlg::PositionUpdate()
|
|
{
|
|
CHAR_POS* pCharPos = reinterpret_cast<CHAR_POS*>(m_szCharacterInfo
|
|
+ std::accumulate(&m_usUpdateInfo[0], &m_usUpdateInfo[DBUpdateData::POSITION_UPDATE], 0));
|
|
|
|
if(sizeof(CHAR_POS) != m_usUpdateInfo[DBUpdateData::POSITION_UPDATE])
|
|
{
|
|
return;
|
|
}
|
|
|
|
m_LastPosX.Format("%f", pCharPos->LastPoint.fPointX);
|
|
m_LastPosY.Format("%f", pCharPos->LastPoint.fPointY);
|
|
m_LastPosZ.Format("%f", pCharPos->LastPoint.fPointZ);
|
|
m_SavePosX.Format("%f", pCharPos->SavePoint.fPointX);
|
|
m_SavePosY.Format("%f", pCharPos->SavePoint.fPointY);
|
|
m_SavePosZ.Format("%f", pCharPos->SavePoint.fPointZ);
|
|
}
|
|
|
|
|
|
void CCharacterInfoDlg::OnBnClickedItemInfo()
|
|
{
|
|
CItemInfoSheet sheet(GetMyINIString("STRING_FOR_LOCALIZE", "CHAR_ITEM_INFO"));
|
|
|
|
sheet.Initialize(m_szCharacterInfo, m_usUpdateInfo, m_szDepositData, m_usDepositSize, m_dwDepositMoney);
|
|
|
|
sheet.DoModal();
|
|
}
|
|
|
|
|
|
void CCharacterInfoDlg::OnBnClickedShowQuickslot()
|
|
{
|
|
CString title(GetMyINIString("STRING_FOR_LOCALIZE", "QUICK_SLOT_INFO"));
|
|
CString quickSlot;
|
|
|
|
QUICK* pCharQuickSlot = reinterpret_cast<QUICK*>(m_szCharacterInfo
|
|
+ std::accumulate(&m_usUpdateInfo[0], &m_usUpdateInfo[DBUpdateData::QUICKSLOT_UPDATE], 0));
|
|
|
|
if(sizeof(QUICK) != m_usUpdateInfo[DBUpdateData::QUICKSLOT_UPDATE])
|
|
{
|
|
MessageBox(GetMyINIString("STRING_FOR_LOCALIZE", "ERR_003"));
|
|
return;
|
|
}
|
|
|
|
for(int nIndex = 0; nIndex < QUICK::MAX_QUICK_NUM; ++nIndex)
|
|
{
|
|
quickSlot.AppendFormat("[ SLOT %2d ] ", nIndex);
|
|
|
|
if(0 == pCharQuickSlot->Slots[nIndex].wID)
|
|
{
|
|
quickSlot.AppendFormat("EMPTY SLOT");
|
|
}
|
|
else
|
|
{
|
|
switch(pCharQuickSlot->Slots[nIndex].nType)
|
|
{
|
|
case QUICKSLOT::NONE:
|
|
quickSlot.AppendFormat("Unknown Type: ");
|
|
break;
|
|
|
|
case QUICKSLOT::ITEM:
|
|
quickSlot.AppendFormat("SkillType ID: %d", pCharQuickSlot->Slots[nIndex].wID);
|
|
break;
|
|
|
|
case QUICKSLOT::SKILL:
|
|
quickSlot.AppendFormat("SkillType ID: 0x%04x LockCount: %d Level: %d",
|
|
pCharQuickSlot->Slots[nIndex].wID,
|
|
pCharQuickSlot->Slots[nIndex].nSkillLockCount,
|
|
pCharQuickSlot->Slots[nIndex].nSkillLevel);
|
|
};
|
|
}
|
|
|
|
quickSlot.AppendFormat("\r\n");
|
|
}
|
|
|
|
CInfoDlg quickInfoDlg(title, quickSlot);
|
|
quickInfoDlg.DoModal();
|
|
}
|
|
|
|
void CCharacterInfoDlg::OnBnClickedShowSkillslot()
|
|
{
|
|
CString title(GetMyINIString("STRING_FOR_LOCALIZE", "SKILL_SLOT_INFO"));
|
|
CString skillSlot;
|
|
|
|
SKILL* pCharSKILLSlot = reinterpret_cast<SKILL*>(m_szCharacterInfo
|
|
+ std::accumulate(&m_usUpdateInfo[0], &m_usUpdateInfo[DBUpdateData::SKILL_UPDATE], 0));
|
|
|
|
if(sizeof(SKILL) != m_usUpdateInfo[DBUpdateData::SKILL_UPDATE])
|
|
{
|
|
MessageBox(GetMyINIString("STRING_FOR_LOCALIZE", "ERR_004"));
|
|
return;
|
|
}
|
|
|
|
for(int nIndex = 0; nIndex < SKILL::MAX_SLOT_NUM; ++nIndex)
|
|
{
|
|
skillSlot.AppendFormat("[ SLOT %2d ] ", nIndex);
|
|
|
|
if(0 == pCharSKILLSlot->SSlot[nIndex].SKILLINFO.wSkill)
|
|
{
|
|
skillSlot.AppendFormat("EMPTY SLOT");
|
|
}
|
|
else
|
|
{
|
|
skillSlot.AppendFormat("SkillType ID: 0x%04x LockCount: %d Level: %d",
|
|
pCharSKILLSlot->SSlot[nIndex].SKILLINFO.wSkill,
|
|
pCharSKILLSlot->SSlot[nIndex].SKILLINFO.cLockCount,
|
|
pCharSKILLSlot->SSlot[nIndex].SKILLINFO.cSkillLevel);
|
|
}
|
|
|
|
skillSlot.AppendFormat("\r\n");
|
|
}
|
|
|
|
CInfoDlg skillInfoDlg(title, skillSlot);
|
|
skillInfoDlg.DoModal();
|
|
}
|
|
|
|
BOOL CCharacterInfoDlg::OnInitDialog()
|
|
{
|
|
CDialog::OnInitDialog();
|
|
|
|
m_CharacterStatus.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_FLATSB);
|
|
|
|
m_CharacterStatus.InsertColumn(0, GetMyINIString("STRING_FOR_LOCALIZE", "ITEM"), LVCFMT_LEFT, 50);
|
|
m_CharacterStatus.InsertColumn(1, GetMyINIString("STRING_FOR_LOCALIZE", "VALUE"), LVCFMT_LEFT, 140);
|
|
|
|
SetDlgItemText(IDC_CHARACTERINFO_GROUP, GetMyINIString("STRING_FOR_LOCALIZE", "CHAR_INFO"));
|
|
SetDlgItemText(IDC_EXPORT_BUTTON, GetMyINIString("STRING_FOR_LOCALIZE", "SHOW_ITEM_INFO"));
|
|
SetDlgItemText(IDC_SHOW_QUICKSLOT, GetMyINIString("STRING_FOR_LOCALIZE", "SHOW_QSLOT_INFO"));
|
|
SetDlgItemText(IDC_SHOW_SKILLSLOT, GetMyINIString("STRING_FOR_LOCALIZE", "SHOW_SKILLSLOT_INFO"));
|
|
|
|
return TRUE;
|
|
} |