#include "stdafx.h" #include #include #include #include #include #include #include // Ŭ¶óÀÌ¾ðÆ®¿¡¼­µµ ¾²À̹ǷΠinclude¸¦ ¸í½ÃÇÑ´Ù. #include #include #include "SkillMgr.h" #include "GMMemory.h" #define DECODE_HEADER(Start_In, Length_In, PageVer_In, PageNum_In) CXORCrypt::GetInstance().DecodeHeader((Start_In),(Length_In),(PageVer_In),(PageNum_In)) #define ENCODE_HEADER(Start_In, Length_In, PageVer_In, PageNum_In) CXORCrypt::GetInstance().EncodeHeader((Start_In),(Length_In),(PageVer_In),(PageNum_In)) #define COMPRESS(In, In_len, Out, Out_len) CMiniLZO::Compress((In), (In_len), (Out), (Out_len)) #define DECOMPRESS(In, In_len, Out, Out_len) CMiniLZO::Decompress((In), (In_len), (Out), (Out_len)) CSkillMgr CSkillMgr::ms_this; const char* CSkillMgr::ms_szSkillScriptFileName = "./Script/Game/SkillScript.txt"; CSkillMgr::CSkillMgr() : m_ProtoTypeArray(NULL), m_nSkillNum(0), m_dwCRC32(0) { } CSkillMgr::~CSkillMgr() { ClearProtoType(); } void CSkillMgr::ClearProtoType(void) { if (NULL != m_ProtoTypeArray) { delete [] m_ProtoTypeArray; m_ProtoTypeArray = NULL; } } bool CSkillMgr::LoadSkillsFromFile(const char* szFileName) { using namespace Skill; // Àӽú¯¼öµé const int SKILL_ID_LEN = 32; const int HEADER_LINE_NUM = 1; char szBuffer[SKILL_ID_LEN]; unsigned char chTempValue; int nLineCount = 0; int nSkillCount = 0; CDelimitedFile DelimitedFile; // °´Ã¼ ¼Ò¸ê½Ã, ÀÚµ¿ Close. ProtoTypeArray tempProtoType; // ¸ÅÅ©·Î¿¡ ·Î±× ÄÚµå »ðÀÔÀ» ÀØÁö ¸» °Í. // ¸ÅÅ©·Î¿¡¼­ \µÚ¿¡ °ø¹éÀ̳ª ¹®ÀÚ »ðÀÔµÇÁö ¾Êµµ·Ï ÁÖÀÇÇÒ °Í. // ( 'À̽ºÄÉÀÌÇÁ ½ÃÄö½º°¡ À߸øµÇ¾ú½À´Ï´Ù' ¿¡·¯ ¹ß»ý ) #define READ_DATA(ColumnName, Argument) \ if (false == DelimitedFile.ReadData(ColumnName, Argument)) \ { \ ERRLOG2(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount + HEADER_LINE_NUM, #ColumnName); \ return false; \ } #define READ_STRING(ColumnName, Buffer, BufferSize) \ if (false == DelimitedFile.ReadString(ColumnName, Buffer, BufferSize)) \ {\ ERRLOG2(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount + HEADER_LINE_NUM, #ColumnName);\ return false;\ } #define READ_STRING_TO_TYPE_VALUE(saveType, saveValue, szColumn, TypeArray, nMaxType)\ saveValue = static_cast(ReadStringToTypeValue(DelimitedFile, szColumn, TypeArray, nMaxType));\ if (nMaxType == saveValue)\ {\ ERRLOG2(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount + HEADER_LINE_NUM, #szColumn); \ return false;\ } if (false == DelimitedFile.Open(szFileName ? szFileName : ms_szSkillScriptFileName, HEADER_LINE_NUM)) { ERRLOG1(g_Log, "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.", szFileName ? szFileName : ms_szSkillScriptFileName); return false; } std::vector ProtoTypeVector; while (DelimitedFile.ReadLine()) { ++nLineCount; READ_STRING("ID", szBuffer, SKILL_ID_LEN); tempProtoType.m_ProtoTypes[nSkillCount].m_usSkill_ID = Math::Convert::Atos(szBuffer); READ_STRING_TO_TYPE_VALUE(Skill::Type::SkillType, tempProtoType.m_ProtoTypes[nSkillCount].m_eSkillType, "Type", Type::SkillTypes, Type::MAX_SKILL_TYPE); READ_DATA("ClassSkill", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bIsClassSkill = chTempValue != 0; READ_STRING("Name[5]", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_szName, ProtoType::MAX_SKILL_NAME); READ_STRING_TO_TYPE_VALUE(Skill::UseLimit::Type, tempProtoType.m_ProtoTypes[nSkillCount].m_eUseLimit, "Limit", UseLimit::UseLimits, UseLimit::MAX_USE_LIMIT); READ_STRING_TO_TYPE_VALUE(unsigned char, tempProtoType.m_ProtoTypes[nSkillCount].m_StatusLimitType[0], "Stat[0]", StatusLimit::StatusLimits, StatusLimit::MAX_STATUS_LIMIT); READ_DATA("Value[0]", tempProtoType.m_ProtoTypes[nSkillCount].m_StatusLimitValue[0]); READ_STRING_TO_TYPE_VALUE(unsigned char, tempProtoType.m_ProtoTypes[nSkillCount].m_StatusLimitType[1], "Stat[1]", StatusLimit::StatusLimits, StatusLimit::MAX_STATUS_LIMIT); READ_DATA("Value[1]", tempProtoType.m_ProtoTypes[nSkillCount].m_StatusLimitValue[1]); READ_STRING_TO_TYPE_VALUE(Skill::Target::Type, tempProtoType.m_ProtoTypes[nSkillCount].m_eTargetType, "Target", Target::TargetTypes, Target::MAX_TARGET_TYPE); READ_DATA("mRange", tempProtoType.m_ProtoTypes[nSkillCount].m_fMinRange); READ_DATA("Range", tempProtoType.m_ProtoTypes[nSkillCount].m_fMaxRange); READ_DATA("Region", tempProtoType.m_ProtoTypes[nSkillCount].m_fEffectExtent); READ_DATA("StartMP", tempProtoType.m_ProtoTypes[nSkillCount].m_StartMP); READ_DATA("LevelMP", tempProtoType.m_ProtoTypes[nSkillCount].m_LevelMP); READ_DATA("LockAdd", tempProtoType.m_ProtoTypes[nSkillCount].m_LockMP); READ_DATA("Starttick", tempProtoType.m_ProtoTypes[nSkillCount].m_StartTick); READ_DATA("LevelTick", tempProtoType.m_ProtoTypes[nSkillCount].m_LevelTick); READ_STRING("CastingFlag", tempProtoType.m_ProtoTypes[nSkillCount].m_szCastingFileName, ProtoType::MAX_FILE_NAME); READ_STRING("EffectFlag", tempProtoType.m_ProtoTypes[nSkillCount].m_szEffectFileName, ProtoType::MAX_FILE_NAME); READ_STRING("HitFlag", tempProtoType.m_ProtoTypes[nSkillCount].m_szHitFileName, ProtoType::MAX_FILE_NAME); READ_DATA("CoolDownTime", tempProtoType.m_ProtoTypes[nSkillCount].m_dwCoolDownTime); READ_DATA("EndCoolDown", tempProtoType.m_ProtoTypes[nSkillCount].m_cEndCoolDown); READ_STRING("dds", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_szSpriteName, ProtoType::MAX_FILE_NAME); READ_DATA("MinX", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_nSpriteMinX); READ_DATA("MinY", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_nSpriteMinY); READ_DATA("MaxX", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_nSpriteMaxX); READ_DATA("MaxY", tempProtoType.m_ProtoTypes[nSkillCount].m_SpriteInfo.m_nSpriteMaxY); READ_DATA("Hit", tempProtoType.m_ProtoTypes[nSkillCount].m_cStrikeNum); READ_DATA("EndScript", tempProtoType.m_ProtoTypes[nSkillCount].m_cEndScript); READ_DATA("Protection", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bProtection = chTempValue != 0; READ_DATA("Interrupt", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bInterrupt = chTempValue != 0; READ_DATA("Counter", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bCounter = chTempValue != 0; READ_DATA("Gauge", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bGauge = chTempValue != 0; READ_STRING("Parent", szBuffer, SKILL_ID_LEN); tempProtoType.m_ProtoTypes[nSkillCount].m_usParentSkill = Math::Convert::Atos(szBuffer); READ_STRING("Child", szBuffer, SKILL_ID_LEN); tempProtoType.m_ProtoTypes[nSkillCount].m_usChildSkill = Math::Convert::Atos(szBuffer); READ_STRING("Text", tempProtoType.m_ProtoTypes[nSkillCount].m_szSkillDescribe, ProtoType::MAX_SKILL_DESCRIBE); if (tempProtoType.m_ProtoTypes[0].m_usSkill_ID != tempProtoType.m_ProtoTypes[nSkillCount].m_usSkill_ID) { ERRLOG2(g_Log, "½ºÅ³ ¼ýÀÚ°¡ ¸ÂÁö ¾Ê½À´Ï´Ù. Ŭ·¡½º ½ºÅ³À» Á¦¿ÜÇϰí´Â, °¢ ½ºÅ³Àº ¹Ýµå½Ã °°Àº ID°¡" " 5°³°¡ ¿¬¼ÓÇØ¼­ ³ª¿Í¾ß ÇÕ´Ï´Ù. ÇöÀç ½ºÅ³ ¹øÈ£´Â 0x%04x, °³¼ö´Â %dÀÔ´Ï´Ù.", tempProtoType.m_ProtoTypes[nSkillCount].m_usSkill_ID, nSkillCount); return false; } ++nSkillCount; if (MAX_SKILL_LOCKCOUNT == nSkillCount || tempProtoType.m_ProtoTypes[0].m_bIsClassSkill) { ProtoTypeVector.push_back(tempProtoType); for (int nIndex = 0; nIndex < nSkillCount; ++nIndex) { tempProtoType.m_ProtoTypes[nIndex].Initialize(); } nSkillCount = 0; } } std::sort(ProtoTypeVector.begin(), ProtoTypeVector.end()); for (std::vector::iterator itr = ProtoTypeVector.begin(); itr != ProtoTypeVector.end() - 1; ++itr) { if (itr->m_ProtoTypes[0].m_usSkill_ID == (itr+1)->m_ProtoTypes[0].m_usSkill_ID) { ERRLOG1(g_Log, "°ãÄ¡´Â ½ºÅ³ Á¾·ù ID°¡ ÀÖ½À´Ï´Ù. Á¾·ùID:0x%04x", itr->m_ProtoTypes[0].m_usSkill_ID); return false; } } m_nSkillNum = ProtoTypeVector.size(); m_ProtoTypeArray = new ProtoTypeArray[m_nSkillNum]; if (NULL == m_ProtoTypeArray) { ERRLOG0(g_Log, "¸Þ¸ð¸® ÇÒ´ç¿¡ ½ÇÆÐÇß½À´Ï´Ù."); return false; } std::copy(ProtoTypeVector.begin(), ProtoTypeVector.end(), m_ProtoTypeArray); if (false == CheckParentChildRule()) { ERRLOG0(g_Log, "½ºÅ³ ½ºÅ©¸³Æ®ÀÇ À߸øµÈ ºÎ¸ð/ÀÚ½Ä °ü°è¸¦ ¼öÁ¤ÇØÁÖ¼¼¿ä."); return false; } // ½ºÅ³ üũ¼¶À» ºôµåÇϰڼÒ. if(NO_ERROR != CCrc32Static::BufferCrc32(reinterpret_cast(m_ProtoTypeArray), sizeof(ProtoTypeArray) * m_nSkillNum, m_dwCRC32)) { ERRLOG0(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® üũ¼¶ ºôµå¿¡ ½ÇÆÐÇß½À´Ï´Ù."); return false; } return true; } bool CSkillMgr::LoadSkillsFromBinary(const char* szFileNameBinary) { HANDLE hFile = CreateFile((0 == szFileNameBinary) ? ms_szSkillScriptFileName : szFileNameBinary, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return false; } CEnsureCloseHandle hfile(hFile); unsigned long dwRead = 0; unsigned long dwFileHighSize = 0; unsigned long dwFileSize = GetFileSize(hFile, &dwFileHighSize); char* lpAllocated = new char[dwFileSize]; CEnsureDeleteArray allocated(lpAllocated); if (NULL == lpAllocated) { ERRLOG0(g_Log, "¸Þ¸ð¸®°¡ ºÎÁ·ÇÕ´Ï´Ù."); return false; } if (false == ReadFile(hFile, lpAllocated, dwFileSize, &dwRead, NULL)) { ERRLOG1(g_Log, "ÀÐ±â ½ÇÆÐ : %d¿¡·¯", GetLastError()); return false; } unsigned long dwHeaderSize = sizeof(unsigned long) + *reinterpret_cast(lpAllocated) + sizeof(unsigned long); unsigned long dwDecompressedSize = *reinterpret_cast(lpAllocated + dwHeaderSize - sizeof(unsigned long)); ClearProtoType(); m_nSkillNum = dwDecompressedSize/sizeof(ProtoTypeArray); m_ProtoTypeArray = new ProtoTypeArray[m_nSkillNum]; if (NULL == m_ProtoTypeArray) { ERRLOG0(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ³»¿ëÀ» ºÒ·¯¿Ã ¼ö ¾ø½À´Ï´Ù. ¸Þ¸ð¸®°¡ ºÎÁ·ÇÕ´Ï´Ù."); return false; } DECOMPRESS(lpAllocated + dwHeaderSize, dwFileSize - dwHeaderSize, reinterpret_cast(m_ProtoTypeArray), &dwDecompressedSize); DECODE_HEADER(reinterpret_cast(m_ProtoTypeArray), dwDecompressedSize, 3, 3); // ½ºÅ³ üũ¼¶À» ºôµåÇϰڼÒ. if(NO_ERROR != CCrc32Static::BufferCrc32(reinterpret_cast(m_ProtoTypeArray), sizeof(ProtoTypeArray) * m_nSkillNum, m_dwCRC32)) { ERRLOG0(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® üũ¼¶ ºôµå¿¡ ½ÇÆÐÇß½À´Ï´Ù."); return false; } return true; } bool CSkillMgr::SaveSkillsToBinary(const char* szFileNameBinary, const char* szTrashFile) { HANDLE hFile = CreateFile((0 == szFileNameBinary) ? ms_szSkillScriptFileName : szFileNameBinary, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return false; } CEnsureCloseHandle file(hFile); unsigned long dwSkillSize = static_cast(sizeof(ProtoTypeArray) * m_nSkillNum); unsigned long dwCompressSize = dwSkillSize; char* lpSkill_Info = new char[dwSkillSize]; char* lpCompressedInfo = new char[dwSkillSize]; if (NULL == lpSkill_Info || NULL == lpCompressedInfo) { ERRLOG0(g_Log, "¸Þ¸ð¸®°¡ ºÎÁ·ÇÕ´Ï´Ù."); return false; } CEnsureDeleteArray skill_info(lpSkill_Info); CEnsureDeleteArray compress_info(lpCompressedInfo); memcpy(lpSkill_Info, m_ProtoTypeArray, dwSkillSize); ENCODE_HEADER(lpSkill_Info, dwSkillSize, 3, 3); COMPRESS(lpSkill_Info, dwSkillSize, lpCompressedInfo, &dwCompressSize); unsigned long dwWritten = 0; // ¾²·¹±â(´õ¹Ì) ÀÚ·á HANDLE hTrashFile = CreateFile(szTrashFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hTrashFile == INVALID_HANDLE_VALUE) { ERRLOG1(g_Log, "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.", szTrashFile); return false; } CEnsureCloseHandle trashFile(hTrashFile); unsigned long dwRead = 0; unsigned long dwFileHighSize = 0; unsigned long dwFileSize = GetFileSize(hTrashFile, &dwFileHighSize); char* lpAllocated = new char[dwFileSize]; CEnsureDeleteArray allocated(lpAllocated); if (false == ReadFile(hTrashFile, lpAllocated, dwFileSize, &dwRead, NULL)) { ERRLOG0(g_Log, "¾²·¹±â ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù."); return false; } WriteFile(hFile, &dwFileSize, sizeof(unsigned long), &dwWritten, 0); WriteFile(hFile, lpAllocated, dwFileSize, &dwWritten, 0); // ¿Ã¹Ù¸¥ ÀÚ·á WriteFile(hFile, &dwSkillSize, sizeof(unsigned long), &dwWritten, 0); // ¿øº» µ¥ÀÌÅÍ Å©±â WriteFile(hFile, lpCompressedInfo, dwCompressSize, &dwWritten, 0); // ¾ÐÃàµÈ µ¥ÀÌÅÍ Å©±â return true; } const Skill::ProtoType* CSkillMgr::GetSkillProtoType(unsigned short usSkill_ID) { ProtoTypeArray* lpFirst = m_ProtoTypeArray; ProtoTypeArray* lpLast = m_ProtoTypeArray + m_nSkillNum; ProtoTypeArray* lpMid = NULL; size_t nCount = m_nSkillNum; size_t nCount2 = 0; for (; 0 < nCount; ) { nCount2 = nCount / 2; lpMid = lpFirst + nCount2; if (lpMid->m_ProtoTypes[0].m_usSkill_ID < usSkill_ID) { lpFirst = ++lpMid, nCount -= nCount2 + 1; } else { nCount = nCount2; } } return (lpFirst != lpLast && !(usSkill_ID < lpFirst->m_ProtoTypes[0].m_usSkill_ID)) ? lpFirst->m_ProtoTypes : NULL; } void CSkillMgr::GetClassSkill(unsigned char cClass, unsigned short *arySkillID, unsigned char *cSkillNum) { *cSkillNum = 0; for (size_t nIndex = 0; nIndex < m_nSkillNum; nIndex++) { Skill::ProtoType protoType = (m_ProtoTypeArray + nIndex)->m_ProtoTypes[0]; if (true == protoType.m_bIsClassSkill) { unsigned char cSkillClass = static_cast((((protoType.m_usSkill_ID - Skill::SKILL_MASK) & 0xFF00) >> 8) & 0x00FF); if (cClass == cSkillClass || CClass::GetPreviousJob(cClass) == cSkillClass) { arySkillID[*cSkillNum] = protoType.m_usSkill_ID; (*cSkillNum)++; } } } } unsigned char CSkillMgr::ReadStringToTypeValue(CDelimitedFile& DelimitedFile, const char* szColumn, const CTypeName* TypeArray, const unsigned char nMaxType) { char szReadData[MAX_PATH]; unsigned char nCount = 0; // µî±Þ ±¸ºÐ Àбâ. if (false == DelimitedFile.ReadString(szColumn, szReadData, MAX_PATH)) { ERRLOG0(g_Log, "µî±Þ ±¸ºÐ Àб⿡ ½ÇÆÐÇÏ¿´½À´Ï´Ù."); return nMaxType; // ½ÇÆÐ½Ã nMaxTypeÀ» ¸®ÅÏ. } for (nCount = 0; nCount < nMaxType; ++nCount) { if (0 == strcmp(szReadData, TypeArray[nCount].GetTypeName())) { break; } } if (nCount == nMaxType) { ERRLOG0(g_Log, "ÀоîµéÀÎ Á¤º¸°¡ ŸÀÔ ¹è¿­¿¡ Á¸ÀçÇÏÁö ¾Ê½À´Ï´Ù."); return nMaxType; } return TypeArray[nCount].GetTypeValue(); } bool CSkillMgr::CheckParentChildRule(void) { for (ProtoTypeArray* lpPointer = m_ProtoTypeArray; lpPointer != m_ProtoTypeArray + m_nSkillNum; ++lpPointer) { Skill::ProtoType ProtoType = lpPointer->m_ProtoTypes[0]; const Skill::ProtoType* lpParent = GetSkillProtoType(ProtoType.m_usParentSkill); const Skill::ProtoType* lpChild = GetSkillProtoType(ProtoType.m_usChildSkill); if (0 != ProtoType.m_usParentSkill && NULL == lpParent) { ERRLOG1(g_Log, "¾ÙÅÍ³ÊÆ¼ºê ½ºÅ³ ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ÀÌ ºÎ¸ð·Î ¼³Á¤µÇ¾ú½À´Ï´Ù. SkillID:0x%04x", ProtoType.m_usSkill_ID); return false; } if (0 != ProtoType.m_usChildSkill && NULL == lpChild) { ERRLOG1(g_Log, "¾ÙÅÍ³ÊÆ¼ºê ½ºÅ³ ¿À·ù : Á¸ÀçÇÏÁö ¾Ê´Â ½ºÅ³ÀÌ ÀÚ½ÄÀ¸·Î ¼³Á¤µÇ¾ú½À´Ï´Ù. SkillID:0x%04x", ProtoType.m_usSkill_ID); return false; } if (NULL == lpParent && NULL == lpChild) { continue; } switch (ProtoType.m_eSkillType) { case Skill::Type::PASSIVE: { if (0 != ProtoType.m_usChildSkill) { ERRLOG1(g_Log, "¾ÙÅÍ³ÊÆ¼ºê ½ºÅ³ ¿À·ù : ÆÐ½Ãºê ½ºÅ³ÀÌ ºÎ¸ð·Î ¼³Á¤µÇ¾ú½À´Ï´Ù. SkillID:0x%04x", ProtoType.m_usSkill_ID); return false; } } break; case Skill::Type::CHANT: { if (0 != ProtoType.m_usParentSkill) { ERRLOG1(g_Log, "¾ÙÅÍ³ÊÆ¼ºê ½ºÅ³ ¿À·ù : æƮ ½ºÅ³ÀÌ ÀÚ½ÄÀ¸·Î ¼³Á¤µÇ¾ú½À´Ï´Ù. SkillID:0x%04x", ProtoType.m_usSkill_ID); return false; } if (0 != ProtoType.m_usChildSkill) { if (Skill::Type::CHANT == lpChild->m_eSkillType) { ERRLOG1(g_Log, "¾ÙÅÍ³ÊÆ¼ºê ½ºÅ³ ¿À·ù : æƮ ½ºÅ³ÀÇ ÀÚ½ÄÀ¸·Î æƮ ½ºÅ³ÀÌ ¼³Á¤µÇ¾ú½À´Ï´Ù. SkillID:0x%04x", ProtoType.m_usSkill_ID); return false; } } } break; } } return true; } bool CSkillMgr::CheckData() { unsigned long dwCheckSum = 0; // ½ºÅ³ üũ¼¶À» ºôµåÇϰڼÒ. if(NO_ERROR != CCrc32Static::BufferCrc32(reinterpret_cast(m_ProtoTypeArray), sizeof(ProtoTypeArray) * m_nSkillNum, dwCheckSum)) { ERRLOG0(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® üũ¼¶ ºôµå¿¡ ½ÇÆÐÇß½À´Ï´Ù."); return false; } return (m_dwCRC32 == dwCheckSum); }