#include "stdafx.h" #include #include #include #include #include #include #include "SkillMgr.h" #include "../Utility/DelimitedFile.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) CMiniLZOCompress::Compress((In), (In_len), (Out), (Out_len)) #define DECOMPRESS(In, In_len, Out, Out_len) CMiniLZOCompress::Decompress((In), (In_len), (Out), (Out_len)) CSkillMgr CSkillMgr::ms_this; #ifdef _TEST_SERVER_ const char* CSkillMgr::ms_szSkillScriptFileName = "TestSkillScript.txt"; #else const char* CSkillMgr::ms_szSkillScriptFileName = "SkillScript.txt"; #endif CSkillMgr::CSkillMgr() : m_ProtoTypeArray(NULL) { } CSkillMgr::~CSkillMgr() { ClearProtoType(); } void CSkillMgr::ClearProtoType() { 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; 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(!DelimitedFile.ReadData(ColumnName, Argument)) \ { \ ERRLOG2(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount, #ColumnName); \ return false; \ } #define READ_STRING(ColumnName, Buffer, BufferSize) \ if(!DelimitedFile.ReadString(ColumnName, Buffer, BufferSize)) \ {\ ERRLOG2(g_Log, "½ºÅ³ ½ºÅ©¸³Æ® ÀÐ±â ½ÇÆÐ : %dÇà %sÄ÷³¿¡¼­ ¿¡·¯ ¹ß»ý!", nLineCount, #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, #szColumn); \ return false;\ } if (!DelimitedFile.Open(szFileName ? szFileName : ms_szSkillScriptFileName, 1 /* HeadLine */)) { 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::StrToHex16(szBuffer); READ_STRING_TO_TYPE_VALUE(Skill::Type::Type, 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("Range", tempProtoType.m_ProtoTypes[nSkillCount].m_EffectDistance); READ_DATA("Region", tempProtoType.m_ProtoTypes[nSkillCount].m_EffectExtent); READ_DATA("StartMP", tempProtoType.m_ProtoTypes[nSkillCount].m_StartMP); READ_DATA("LevelMP", tempProtoType.m_ProtoTypes[nSkillCount].m_LevelMP); 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_usCoolDownTime); 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("Gauge", chTempValue); tempProtoType.m_ProtoTypes[nSkillCount].m_bGauge = chTempValue != 0; READ_DATA("MinRange", tempProtoType.m_ProtoTypes[nSkillCount].m_cMinRange); READ_DATA("MaxRange", tempProtoType.m_ProtoTypes[nSkillCount].m_cMaxRange); if(tempProtoType.m_ProtoTypes[0].m_usSkill_ID != tempProtoType.m_ProtoTypes[nSkillCount].m_usSkill_ID) { ERRLOG2(g_Log, "½ºÅ³ ¼ýÀÚ°¡ ¸ÂÁö ¾Ê½À´Ï´Ù. Ŭ·¡½º ½ºÅ³À» Á¦¿ÜÇϰí´Â, °¢ ½ºÅ³Àº ¹Ýµå½Ã °°Àº ID°¡" " 5°³°¡ ¿¬¼ÓÇØ¼­ ³ª¿Í¾ß ÇÕ´Ï´Ù. ÇöÀç ½ºÅ³ ¹øÈ£´Â %d, °³¼ö´Â %dÀÔ´Ï´Ù.", tempProtoType.m_ProtoTypes[nSkillCount].m_usSkill_ID, nSkillCount); return false; } tempProtoType.m_ProtoTypes[nSkillCount].m_cSpell_LockCount = nSkillCount; ++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:%d", 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); return true; } 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 (!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(); } 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; } 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); DWORD dwRead = 0; DWORD dwFileHighSize = 0; DWORD dwFileSize = GetFileSize(hFile, &dwFileHighSize); char* lpAllocated = new char[dwFileSize]; CEnsureDeleteArray allocated(lpAllocated); if(NULL == lpAllocated) { ERRLOG0(g_Log, "¸Þ¸ð¸®°¡ ºÎÁ·ÇÕ´Ï´Ù."); return false; } if(!ReadFile(hFile, lpAllocated, dwFileSize, &dwRead, NULL)) { ERRLOG1(g_Log, "ÀÐ±â ½ÇÆÐ : %d¿¡·¯", GetLastError()); return false; } DWORD dwHeaderSize = sizeof(DWORD) + *reinterpret_cast(lpAllocated) + sizeof(DWORD); DWORD dwDecompressedSize = *reinterpret_cast(lpAllocated + dwHeaderSize - sizeof(DWORD)); 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, 0, 1); 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); DWORD dwSkillSize = static_cast(sizeof(ProtoTypeArray) * m_nSkillNum); DWORD 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, 0, 1); COMPRESS(lpSkill_Info, dwSkillSize, lpCompressedInfo, &dwCompressSize); 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]; CEnsureDeleteArray allocated(lpAllocated); if (!ReadFile(hTrashFile, lpAllocated, dwFileSize, &dwRead, NULL)) { ERRLOG0(g_Log, "¾²·¹±â ÆÄÀÏÀ» ÀÐÀ» ¼ö ¾ø½À´Ï´Ù."); return false; } WriteFile(hFile, &dwFileSize, sizeof(DWORD), &dwWritten, 0); WriteFile(hFile, lpAllocated, dwFileSize, &dwWritten, 0); // ¿Ã¹Ù¸¥ ÀÚ·á WriteFile(hFile, &dwSkillSize, sizeof(DWORD), &dwWritten, 0); WriteFile(hFile, lpCompressedInfo, dwCompressSize, &dwWritten, 0); return true; } /* #ifndef _RYL_GAME_CLIENT_ void CSkillMgr::ProcessSkillException(SKILL* pSkill, unsigned short cClass) { // ´ë°Å ¸¶½ºÅ͸®°¡ ·Î±×¿ë¿¡¼­ ¾î½Ø½Å¿ëÀ¸·Î ¹Ù²î¸é¼­ ±âÁ¸ÀÇ °ÍµéÀ» Áö¿ì´Â ·çƾ bool IsDaggerMastery = false; for (int nSkillIndex = 0; nSkillIndex < pSkill->wSlotNum; nSkillIndex++) { if (pSkill->SSlot[nSkillIndex].SKILLINFO.wSkill == 0x8202) { pSkill->wSkillNum -= (pSkill->SSlot[nSkillIndex].SKILLINFO.cLockCount * (SKILLSLOT::MAX_SKILL_LEVEL - 1) + pSkill->SSlot[nSkillIndex].SKILLINFO.cSkillLevel); IsDaggerMastery = true; continue; } if (true == IsDaggerMastery) { pSkill->SSlot[nSkillIndex-1] = pSkill->SSlot[nSkillIndex]; } } if (true == IsDaggerMastery) { pSkill->SSlot[nSkillIndex-1] = SKILLSLOT(); pSkill->wSlotNum--; } // ³ÝÀÌ ÄĹèÅÏÆ®¿ë¿¡¼­ ÅÛÇ÷¯¿Í ¾îÅÂÄ¿¿ëÀ¸·Î ¹Ù²î¸é¼­ ±âÁ¸ÀÇ °ÍµéÀ» Áö¿ì´Â ·çƾ bool IsNet = false; for (int nSkillIndex = 0; nSkillIndex < pSkill->wSlotNum; nSkillIndex++) { if (pSkill->SSlot[nSkillIndex].SKILLINFO.wSkill == 0x9101) { IsNet = true; continue; } if (true == IsNet) { pSkill->SSlot[nSkillIndex-1] = pSkill->SSlot[nSkillIndex]; } } if (true == IsNet) { pSkill->SSlot[nSkillIndex-1] = SKILLSLOT(); pSkill->wSlotNum--; } // Ŭ·¡½º ½ºÅ³ ³Ö¾îÁÖ±â unsigned short usClassSkillID = NULL; bool IsClassSkill = false; usClassSkillID = CClass::GetClassSkillID(static_cast(cClass)); if (NULL != usClassSkillID) { for (int nSkillIndex = 0; nSkillIndex < pSkill->wSlotNum; nSkillIndex++) { if (pSkill->SSlot[nSkillIndex].SKILLINFO.wSkill == usClassSkillID) { IsClassSkill = true; break; } } if (false == IsClassSkill) { pSkill->SSlot[pSkill->wSlotNum] = SKILLSLOT(usClassSkillID, 0, 1); pSkill->wSlotNum++; } } usClassSkillID = NULL; IsClassSkill = false; if (CClass::JOB_CHANGE_1ST == CClass::GetJobLevel(static_cast(cClass))) { usClassSkillID = CClass::GetClassSkillID(CClass::GetPreviousJob(static_cast(cClass))); if (NULL != usClassSkillID) { for (int nSkillIndex = 0; nSkillIndex < pSkill->wSlotNum; nSkillIndex++) { if (pSkill->SSlot[nSkillIndex].SKILLINFO.wSkill == usClassSkillID) { IsClassSkill = true; break; } } if (false == IsClassSkill) { pSkill->SSlot[pSkill->wSlotNum] = SKILLSLOT(usClassSkillID, 0, 1); pSkill->wSlotNum++; } } } // ½ºÅ³ °¹¼ö ÀçÁ¶Á¤ pSkill->wSkillNum = 0; for (int nSkillIndex = 0; nSkillIndex < pSkill->wSlotNum; nSkillIndex++) { Skill::LPProtoType lpProtoType = GetSkillProtoType(pSkill->SSlot[nSkillIndex].SKILLINFO.wSkill); if (NULL != lpProtoType) { if (false == lpProtoType->m_bIsClassSkill) { pSkill->wSkillNum += (pSkill->SSlot[nSkillIndex].SKILLINFO.cLockCount * (SKILLSLOT::MAX_SKILL_LEVEL - 1) + pSkill->SSlot[nSkillIndex].SKILLINFO.cSkillLevel); } } } } #endif */