#include "stdafx.h" #include #include #include #include #include #define ENCODEHEADER(Start_In, Length_In, PageNum_In, PageVer_In) CXORCrypt::GetInstance().EncodeHeader((Start_In), (Length_In), (PageNum_In), (PageVer_In)) #define DECODEHEADER(Start_In, Length_In, PageNum_In, PageVer_In) CXORCrypt::GetInstance().DecodeHeader((Start_In), (Length_In), (PageNum_In), (PageVer_In)) #define COMPRESS(In, In_len, Out, Out_len) CMiniLZOCompress::Compress((In), (In_len), (Out), (Out_len)) #define DECOMPRESS(In, In_len, Out, Out_len) CMiniLZOCompress::Decompress((In), (In_len), (Out), (Out_len)) #include #include #include "MonsterMgr.h" CMonsterMgr CMonsterMgr::ms_this; #ifdef _TEST_SERVER_ const char* CMonsterMgr::m_szMonsterScriptFileName = "TestMonsterProtoType.txt"; #else const char* CMonsterMgr::m_szMonsterScriptFileName = "MonsterProtoType.txt"; #endif CMonsterMgr::CMonsterMgr(void) : m_nMonsterNum(0), m_ProtoTypeArray(NULL) { } CMonsterMgr::~CMonsterMgr(void) { ClearProtoType(); } void CMonsterMgr::ClearProtoType() { if(NULL != m_ProtoTypeArray) { delete [] m_ProtoTypeArray; } } bool CMonsterMgr::LoadMonstersFromFile(const char* szFileName) { int nIndex = 0; int nLineCount = 0; char strTemp[MAX_PATH]; CDelimitedFile DelimitedFile; // °´Ã¼ ¼Ò¸ê½Ã, ÀÚµ¿ Close. std::vector monsterProtoTypeVector; monsterProtoTypeVector.reserve(1000); MonsterProtoType tempProtoType; // ¸ÅÅ©·Î¿¡ ·Î±× ÄÚµå »ðÀÔÀ» ÀØÁö ¸» °Í. // ¸ÅÅ©·Î¿¡¼­ \µÚ¿¡ °ø¹éÀ̳ª ¹®ÀÚ »ðÀÔµÇÁö ¾Êµµ·Ï ÁÖÀÇÇÒ °Í. // ( 'À̽ºÄÉÀÌÇÁ ½ÃÄö½º°¡ À߸øµÇ¾ú½À´Ï´Ù' ¿¡·¯ ¹ß»ý ) #define READ_DATA(ColumnName, Argument) \ if (!DelimitedFile.ReadData(Argument)) { \ ERRLOG2(g_Log, "¸ó½ºÅÍ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount, #ColumnName); \ return false; \ } #define READ_STRING(ColumnName, Buffer, BufferSize) \ if (!DelimitedFile.ReadString(Buffer, BufferSize)) { \ ERRLOG2(g_Log, "¸ó½ºÅÍ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount, #ColumnName); \ return false; \ } #define READ_DATA_ARRAY(ColumnName, Argument, ArgumentNum) \ for (nIndex=0; nIndex < ArgumentNum; ++nIndex) { \ READ_DATA(ColumnName, Argument[nIndex]); \ } #define READ_DATA_BOOL(ColumnName, Argument) \ if (!DelimitedFile.ReadString(strTemp, MAX_PATH)) { \ ERRLOG2(g_Log, "¸ó½ºÅÍ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount, #ColumnName); \ return false; \ } \ Argument = (!strcmp(strTemp, "O")) ? true : false; if (!DelimitedFile.Open(szFileName ? szFileName : m_szMonsterScriptFileName)) { ERRLOG1(g_Log, "%s ÆÄÀÏÀ» ¿­ ¼ö ¾ø½À´Ï´Ù.", szFileName ? szFileName : m_szMonsterScriptFileName); return false; } while (DelimitedFile.ReadLine()) { ++nLineCount; // ¼ø¼­°¡ ¹Ù²î¸é °ï¶õÇϴٴϱñ~!!! (¹ö·°!) READ_DATA("KID", tempProtoType.m_MonsterInfo.m_dwKID); READ_STRING("À̸§", tempProtoType.m_MonsterInfo.m_strName, MonsterInfo::MAX_NAME_LENGTH); READ_STRING("¸ðµ¨¸µ ÇüÅ Ç÷¡±×", tempProtoType.m_MonsterInfo.m_strModelingFlag, MonsterInfo::MAX_MODELING_FLAG_LENGTH); READ_STRING("½ºÅ³ÆÐÅÏ", strTemp, MAX_PATH); tempProtoType.m_MonsterInfo.m_nSkillPattern = MonsterInfo::GetMonsterPattern(strTemp); // ¸ð¼Ç Á¤º¸ tempProtoType.m_MonsterInfo.m_MonsterMotions[0].m_wAction = MonsterInfo::Z3D_CA_WALK; READ_DATA("°È±âÇÁ·¹ÀÓ", tempProtoType.m_MonsterInfo.m_MonsterMotions[0].m_dwFrame); READ_DATA("°È±â°Å¸®", tempProtoType.m_MonsterInfo.m_MonsterMotions[0].m_fVelocity); tempProtoType.m_MonsterInfo.m_MonsterMotions[0].m_fVelocity /= 100.0f; tempProtoType.m_MonsterInfo.m_MonsterMotions[1].m_wAction = MonsterInfo::Z3D_CA_RUN; READ_DATA("´Þ¸®±âÇÁ·¹ÀÓ", tempProtoType.m_MonsterInfo.m_MonsterMotions[1].m_dwFrame); READ_DATA("´Þ¸®±â°Å¸®", tempProtoType.m_MonsterInfo.m_MonsterMotions[1].m_fVelocity); tempProtoType.m_MonsterInfo.m_MonsterMotions[1].m_fVelocity /= 100.0f; tempProtoType.m_MonsterInfo.m_MonsterMotions[2].m_wAction = MonsterInfo::Z3D_CA_ATTACK; READ_DATA("°ø°ÝÇÁ·¹ÀÓ", tempProtoType.m_MonsterInfo.m_MonsterMotions[2].m_dwFrame); tempProtoType.m_MonsterInfo.m_MonsterMotions[3].m_wAction = MonsterInfo::Z3D_CA_CASTING; READ_DATA("½ºÅ³ÇÁ·¹ÀÓ", tempProtoType.m_MonsterInfo.m_MonsterMotions[3].m_dwFrame); READ_DATA_ARRAY("Ÿ°Ý¹Ú½º", tempProtoType.m_MonsterInfo.m_fHitBox, MonsterInfo::MAX_HITBOX_NUM); READ_DATA("°ø°Ý°Å¸®", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nAttackRange); READ_DATA("°ø°Ý°¢µµ", tempProtoType.m_MonsterInfo.m_fAttackAngle); // ±âº» Á¤º¸ READ_DATA("±âº» °æÇèÁ¡", tempProtoType.m_CreatureStatus.m_nExp); READ_DATA("·¹º§", tempProtoType.m_CreatureStatus.m_nLevel); READ_DATA("ÃÖ¼Òµ¥¹ÌÁö", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMinDamage); READ_DATA("ÃÖ´ëµ¥¹ÌÁö", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMaxDamage); READ_DATA("°ø°Ýº¸Á¤", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nOffenceRevision); READ_DATA("¹æ¾î·Â", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nDefence); READ_DATA("¹æ¾îº¸Á¤", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nDefenceRevision); READ_DATA("ºí·ÏÀ²", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nBlockingPercentage); READ_DATA("DRC", tempProtoType.m_CreatureStatus.m_StatusInfo.m_fDRC); READ_DATA("Å©¸®Æ¼ÄÃÈ®·ü", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nCriticalPercentage); READ_DATA("Å©¸®Æ¼ÄßÀÔ", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nCriticalType); READ_DATA("ÀúÇ×·Â", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMagicResistance); READ_DATA_ARRAY("°ø°Ý¼Ó¼º", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nWeaponAttributeLevel, StatusInfo::MAX_ATTRIBUTE_NUM); READ_DATA_ARRAY("¼Ó¼ºÀúÇ×", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nAttributeResistance, StatusInfo::MAX_ATTRIBUTE_NUM); READ_DATA("°ø°Ý¼Óµµ", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nAttackSpeed); READ_DATA("À̵¿¼Óµµ", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMoveSpeed); READ_DATA("HP Max", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMaxHP); READ_DATA("MP Max", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMaxMP); READ_DATA("HP ȸº¹·®", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nHPRegenAmount); READ_DATA("MP ȸº¹·®", tempProtoType.m_CreatureStatus.m_StatusInfo.m_nMPRegenAmount); // ±âŸ READ_DATA("»çÀÌÁî", tempProtoType.m_MonsterInfo.m_fSize); READ_DATA("½ºÅ³·¹º§", tempProtoType.m_MonsterInfo.m_nSkillLevel); READ_DATA_BOOL("½ºÅÚ½ºÅ¸ÀÔ¿©ºÎ", tempProtoType.m_MonsterInfo.m_bStealth); READ_DATA_BOOL("¼±Á¦°ø°Ý¿©ºÎ", tempProtoType.m_MonsterInfo.m_bFirstAttack); READ_DATA_BOOL("µµ¸Á¿©ºÎ", tempProtoType.m_MonsterInfo.m_bEscape); READ_DATA_BOOL("±Íȯ¿©ºÎ", tempProtoType.m_MonsterInfo.m_bReturnPosition); READ_DATA("¸®½ºÆùŸÀÓ", tempProtoType.m_MonsterInfo.m_dwRespawnTime); READ_DATA_ARRAY("¿À¸®Áö³¯¾ÆÀÌÅÛ", tempProtoType.m_MonsterInfo.m_AwardItem, MonsterInfo::MAX_ORIGINAL_ITEM_NUM); READ_DATA_ARRAY("¾ÆÀÌÅÛµå¶ø·ü", tempProtoType.m_MonsterInfo.m_nDropRate, MonsterInfo::MAX_AWARD_KIND); monsterProtoTypeVector.push_back(tempProtoType); } std::sort(monsterProtoTypeVector.begin(), monsterProtoTypeVector.end()); for(std::vector::iterator itr = monsterProtoTypeVector.begin(); itr != monsterProtoTypeVector.end() - 1; ++itr) { if(itr->m_MonsterInfo.m_dwKID == (itr+1)->m_MonsterInfo.m_dwKID) { ERRLOG1(g_Log, "°ãÄ¡´Â ¸ó½ºÅÍ Á¾·ù ID°¡ ÀÖ½À´Ï´Ù. Á¾·ùID:%d", itr->m_MonsterInfo.m_dwKID); return false; } }; m_nMonsterNum = monsterProtoTypeVector.size(); m_ProtoTypeArray = new MonsterProtoType[m_nMonsterNum]; if(NULL == m_ProtoTypeArray) { ERRLOG0(g_Log, "¸ó½ºÅÍ ½ºÅ©¸³Æ® ÃʱâÈ­ ½ÇÆÐ : ¸Þ¸ð¸® ºÎÁ·"); return false; } std::copy(monsterProtoTypeVector.begin(), monsterProtoTypeVector.end(), m_ProtoTypeArray); return true; } const CMonsterMgr::MonsterProtoType* CMonsterMgr::GetMonsterProtoType(DWORD dwKID) { MonsterProtoType* lpFirst = m_ProtoTypeArray; MonsterProtoType* lpLast = m_ProtoTypeArray + m_nMonsterNum; MonsterProtoType* lpMid = NULL; size_t nCount = m_nMonsterNum; size_t nCount2 = 0; for (; 0 < nCount; ) { nCount2 = nCount / 2; lpMid = lpFirst + nCount2; if(lpMid->m_MonsterInfo.m_dwKID < dwKID) { lpFirst = ++lpMid, nCount -= nCount2 + 1; } else { nCount = nCount2; } } return (lpFirst != lpLast && !(dwKID < lpFirst->m_MonsterInfo.m_dwKID)) ? lpFirst : NULL; } const CMonsterMgr::MonsterProtoType* CMonsterMgr::GetMonsterProtoType(char* szName) { for (size_t nIndex = 0; nIndex < m_nMonsterNum; nIndex++) { if (0 == strncmp(szName, m_ProtoTypeArray[nIndex].m_MonsterInfo.m_strName, MonsterInfo::MAX_NAME_LENGTH)) { return m_ProtoTypeArray + nIndex; } } return NULL; } bool CMonsterMgr::LoadMonstersFromBinary(const char* szFileNameBinary) { HANDLE hFile = CreateFile((0 == szFileNameBinary) ? m_szMonsterScriptFileName : szFileNameBinary, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return false; } CEnsureCloseHandle readFile(hFile); DWORD dwRead = 0; DWORD dwFileHighSize = 0; DWORD dwFileSize = GetFileSize(hFile, &dwFileHighSize); char* lpAllocated = new char[dwFileSize]; if(NULL == lpAllocated) { return false; } CEnsureDeleteArray allocated(lpAllocated); if(!ReadFile(hFile, lpAllocated, dwFileSize, &dwRead, NULL)) { return false; } MonsterProtoType* lpProtoType = 0; MonsterInfo* lpMonsterInfo = 0; CreatureStatus* lpCreatureStatus = 0; DWORD dwStructSize = 0; DWORD dwHeaderSize = sizeof(DWORD) + *reinterpret_cast(lpAllocated) + sizeof(DWORD); DWORD dwBufferSize = *reinterpret_cast(lpAllocated + dwHeaderSize - sizeof(DWORD)); char* lpBuffer = new char[dwBufferSize]; if(NULL == lpBuffer) { return false; } CEnsureDeleteArray buffer(lpBuffer); char* lpBufferStartPointer = lpBuffer; DECOMPRESS(lpAllocated + dwHeaderSize, dwFileSize - dwHeaderSize, lpBuffer, &dwBufferSize); DECODEHEADER(lpBuffer, dwBufferSize, 0, 3); m_nMonsterNum = dwBufferSize / sizeof(MonsterProtoType); m_ProtoTypeArray = new MonsterProtoType[m_nMonsterNum]; if(NULL == m_ProtoTypeArray) { return false; } for(size_t nIndex = 0; nIndex < m_nMonsterNum; ++nIndex) { lpMonsterInfo = reinterpret_cast(lpBuffer); lpCreatureStatus = reinterpret_cast(lpBuffer + sizeof(MonsterInfo)); m_ProtoTypeArray[nIndex].m_MonsterInfo = MonsterInfo(*lpMonsterInfo); dwBufferSize -= sizeof(MonsterInfo); lpBuffer += sizeof(MonsterInfo); m_ProtoTypeArray[nIndex].m_CreatureStatus = CreatureStatus(*lpCreatureStatus); dwBufferSize -= sizeof(CreatureStatus); lpBuffer += sizeof(CreatureStatus); } return true; } bool CMonsterMgr::SaveMonstersToBinary(const char* szFileNameBinary, const char* szTrashFile) { if(0 == m_ProtoTypeArray) { return false; } HANDLE hFile = CreateFile((0 == szFileNameBinary) ? m_szMonsterScriptFileName : szFileNameBinary, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return false; } CEnsureCloseHandle writeFile(hFile); const size_t MAX_SCRIPT_FILE_SIZE = m_nMonsterNum * sizeof(MonsterProtoType); char *pInputBuffer = new char[MAX_SCRIPT_FILE_SIZE]; char *pOutputBuffer = new char[MAX_SCRIPT_FILE_SIZE]; CEnsureDeleteArray input(pInputBuffer); CEnsureDeleteArray output(pOutputBuffer); if (0 == pInputBuffer || 0 == pOutputBuffer) { return false; } char *InputStartPointer = pInputBuffer; char *OutputStartPointer = pOutputBuffer; DWORD dwInputBufferSize = 0; DWORD dwOutputBufferSize = 0; for(size_t nCount = 0; nCount < m_nMonsterNum; ++nCount) { memcpy(pInputBuffer, &m_ProtoTypeArray[nCount].m_MonsterInfo, sizeof(MonsterInfo)); dwInputBufferSize += sizeof(MonsterInfo); pInputBuffer += sizeof(MonsterInfo); memcpy(pInputBuffer, &m_ProtoTypeArray[nCount].m_CreatureStatus, sizeof(CreatureStatus)); dwInputBufferSize += sizeof(CreatureStatus); pInputBuffer += sizeof(CreatureStatus); } ENCODEHEADER(InputStartPointer, dwInputBufferSize, 0, 3); COMPRESS(InputStartPointer, dwInputBufferSize, pOutputBuffer, &dwOutputBufferSize); DWORD dwWritten = 0; // ¾²·¹±â(´õ¹Ì) ÀÚ·á HANDLE hTrashFile = CreateFile(szTrashFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hTrashFile == INVALID_HANDLE_VALUE) { return false; } CEnsureCloseHandle trashFile(hTrashFile); DWORD dwRead = 0; DWORD dwFileHighSize = 0; DWORD dwFileSize = GetFileSize(hTrashFile, &dwFileHighSize); char* lpAllocated = new char[dwFileSize]; if(NULL == lpAllocated) { return false; } CEnsureDeleteArray allocated(lpAllocated); if (!ReadFile(hTrashFile, lpAllocated, dwFileSize, &dwRead, NULL)) { return false; } // ¾²·¹±â(´õ¹Ì) ÀÚ·á WriteFile(hFile, &dwFileSize, sizeof(DWORD), &dwWritten, 0); WriteFile(hFile, lpAllocated, dwFileSize, &dwWritten, 0); // ¿Ã¹Ù¸¥ ÀÚ·á WriteFile(hFile, &dwInputBufferSize, sizeof(DWORD), &dwWritten, 0); WriteFile(hFile, pOutputBuffer, dwOutputBufferSize, &dwWritten, 0); return true; }