Restructure repository to include all source folders

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>
This commit is contained in:
2025-11-29 20:17:20 +09:00
parent 5d3cd64a25
commit dd97ddec92
11602 changed files with 1446576 additions and 0 deletions

View File

@@ -0,0 +1,487 @@
#include "stdafx.h"
#include <Log/ServerLog.h>
#include <Utility/Math/Math.h>
#include <Utility/Compress/MiniLZO/MiniLZOWrapper.h>
#include <Utility/Resource/EnsureCleanup.h>
#include <Network/XORCrypt/XORCrypt.h>
#include <algorithm>
#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<saveType>(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<ProtoTypeArray> 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<ProtoTypeArray>::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<char> 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<DWORD*>(lpAllocated) + sizeof(DWORD);
DWORD dwDecompressedSize = *reinterpret_cast<DWORD*>(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<char*>(m_ProtoTypeArray), &dwDecompressedSize);
DECODE_HEADER(reinterpret_cast<char*>(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<DWORD>(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<char> skill_info(lpSkill_Info);
CEnsureDeleteArray<char> 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<char> 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<unsigned char>(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<unsigned char>(cClass)))
{
usClassSkillID = CClass::GetClassSkillID(CClass::GetPreviousJob(static_cast<unsigned char>(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
*/

View File

@@ -0,0 +1,70 @@
#ifndef _SKILL_MGR_H_
#define _SKILL_MGR_H_
#define g_SkillMgr CSkillMgr::GetInstance()
#include <limits>
#include <Pattern/Singleton.h>
#include "SkillStructure.h"
// 전방 참조
class CDelimitedFile;
class CSkillMgr : public CSingleton<CSkillMgr>
{
public:
enum _Const
{
MAX_SKILL_LOCKCOUNT = 5, // 스킬의 최대 개수 (이 개수만큼 ProtoType이 존재한다)
MAX_SKILL_LEVEL = 7, // 스킬 레벨의 한계
PARTY_SPELL = 0x80, // 파티 주문의 비트
MAX_SKILL_PER_STATUS = 16, // 챈트와 인챈트의 가짓수
NORMAL_SKILL = -1,
MULTI_TARGET_SKILL = 1 // 타겟 타입 (범위 마법의 경우 한번만 MP를 소모한다)
};
unsigned int GetRange(unsigned short usSkill_ID);
bool LoadSkillsFromFile(const char* szFileName = 0);
bool LoadSkillsFromBinary(const char* szFileNameBinary = 0);
bool SaveSkillsToBinary(const char* szFileNameBinary = 0, const char* szTrashFile = 0);
void ClearProtoType();
const Skill::ProtoType* GetSkillProtoType(unsigned short usSkill_ID);
/*
// 기타 메소드
#ifndef _RYL_GAME_CLIENT_
void ProcessSkillException(SKILL* pSkill, unsigned short cClass);
#endif
*/
~CSkillMgr();
private:
CSkillMgr();
struct ProtoTypeArray
{
Skill::ProtoType m_ProtoTypes[MAX_SKILL_LOCKCOUNT];
inline bool operator < (ProtoTypeArray& rhs)
{ return m_ProtoTypes[0].m_usSkill_ID < rhs.m_ProtoTypes[0].m_usSkill_ID; }
};
static const char* ms_szSkillScriptFileName;
static CSkillMgr ms_this;
ProtoTypeArray* m_ProtoTypeArray;
size_t m_nSkillNum;
// 문자열과 비교해서, 알맞은 타입 값을 리턴한다. 실패시 nMaxType을 리턴한다.
unsigned char ReadStringToTypeValue(CDelimitedFile& DelimitedFile, const char* szColumn,
const CTypeName* TypeArray, const unsigned char nMaxType);
};
#endif

View File

@@ -0,0 +1,86 @@
#include "stdafx.h"
#include <algorithm>
#include "SkillStructure.h"
const CTypeName Skill::Type::SkillTypes[MAX_SKILL_TYPE] =
{
CTypeName(Skill::Type::NONE, "NONE"),
CTypeName(Skill::Type::PASSIVE, "PASSIVE"),
CTypeName(Skill::Type::INSTANCE, "INSTANCE"),
CTypeName(Skill::Type::CAST, "CAST"),
CTypeName(Skill::Type::CHANT, "CHANT"),
CTypeName(Skill::Type::ENCHANT, "ENCHANT")
};
const CTypeName Skill::UseLimit::UseLimits[MAX_USE_LIMIT] =
{
CTypeName(Skill::UseLimit::NONE, "NONE"),
CTypeName(Skill::UseLimit::FOR_FIGHTER, "FORFIGHTER"),
CTypeName(Skill::UseLimit::WITH_SHIELD, "WITHSHIELD"),
CTypeName(Skill::UseLimit::FOR_FIGHTER_TWOHANDED, "FORFIGHTERTWOHAND"),
CTypeName(Skill::UseLimit::FOR_ALL_ONEHAND, "FORALLONEHAND"),
CTypeName(Skill::UseLimit::WITH_DAGGER, "WITHDAGGER"),
CTypeName(Skill::UseLimit::WITH_THROWING_DAGGER, "WITHTHROWINGDAGGER"),
CTypeName(Skill::UseLimit::RANGED, "RANGED"),
CTypeName(Skill::UseLimit::LEFT_ARM, "LEFTARM"),
CTypeName(Skill::UseLimit::GUARD_ARM, "GUARDARM"),
CTypeName(Skill::UseLimit::WITH_WEAPON, "WITHWEAPON"),
CTypeName(Skill::UseLimit::ATTACK_ARM, "ATTACKARM"),
CTypeName(Skill::UseLimit::GUN_ARM, "GUNARM"),
CTypeName(Skill::UseLimit::KNIFE_ARM, "KNIFEARM"),
CTypeName(Skill::UseLimit::WITH_CLOW, "WITHCLOW")
};
const CTypeName Skill::StatusLimit::StatusLimits[MAX_STATUS_LIMIT] =
{
CTypeName(Skill::StatusLimit::NONE, "NONE"),
CTypeName(Skill::StatusLimit::STR, "STR"),
CTypeName(Skill::StatusLimit::DEX, "DEX"),
CTypeName(Skill::StatusLimit::CON, "CON"),
CTypeName(Skill::StatusLimit::INT, "INT"),
CTypeName(Skill::StatusLimit::WIS, "WIS")
};
const CTypeName Skill::Target::TargetTypes[MAX_TARGET_TYPE] =
{
CTypeName(Skill::Target::NONE, "NONE"),
CTypeName(Skill::Target::MELEE, "MELEE"),
CTypeName(Skill::Target::FRIEND, "FRIEND"),
CTypeName(Skill::Target::ENEMY, "ENEMY"),
CTypeName(Skill::Target::DEAD_FRIEND, "FRDEAD"),
CTypeName(Skill::Target::DEAD_ENEMY, "ENDEAD"),
CTypeName(Skill::Target::FRIEND_OBJECT, "FROBJ"),
CTypeName(Skill::Target::ENEMY_OBJECT, "ENOBJ"),
CTypeName(Skill::Target::PARTY, "PARTY"),
CTypeName(Skill::Target::FRIEND_EXCEPT_SELF, "FREXME"),
CTypeName(Skill::Target::LINE_ENEMY, "ENLINE")
};
Skill::ProtoType::ProtoType() { Initialize(); }
void Skill::ProtoType::Initialize()
{
m_eSkillType = Type::NONE;
m_eUseLimit = UseLimit::NONE;
m_eTargetType = Target::NONE;
m_EffectDistance = m_EffectExtent = 0.0f;
m_bInterrupt = m_bProtection = m_bGauge = m_bIsClassSkill = false;
m_cStrikeNum = m_cSpell_LockCount = m_cEndScript = m_cEndCoolDown = m_cMinRange = m_cMaxRange = 0;
m_usSkill_ID = m_StartMP = m_LevelMP = m_StartTick = m_LevelTick = m_usCoolDownTime = 0;
m_SpriteInfo.Initialize();
std::fill_n(&m_StatusLimitType[0], int(MAX_LIMIT_NUM), 0);
std::fill_n(&m_StatusLimitValue[0], int(MAX_LIMIT_NUM), 0);
std::fill_n(&m_szEffectFileName[0], int(MAX_FILE_NAME), 0);
std::fill_n(&m_szHitFileName[0], int(MAX_FILE_NAME), 0);
std::fill_n(&m_szCastingFileName[0], int(MAX_FILE_NAME), 0);
}

View File

@@ -0,0 +1,162 @@
#ifndef _SKILL_STRUCTURE_H_
#define _SKILL_STRUCTURE_H_
#pragma once
#include "../Utility/TypeArray.h"
#include "../Item/ItemStructure.h"
#pragma pack(8)
namespace Skill
{
enum { SkillMask = 0x8000 };
namespace Type
{
enum Type
{
NONE = 0,
PASSIVE = 1,
INSTANCE = 2,
CAST = 3,
CHANT = 4,
ENCHANT = 5,
MAX_SKILL_TYPE = 6
};
extern const CTypeName SkillTypes[MAX_SKILL_TYPE];
};
namespace UseLimit
{
enum Type
{
NONE = 0,
// 인간
FOR_FIGHTER = 1, // 스탶 대거 맨손 활 석궁 사용불가
WITH_SHIELD = 2, // 방패착용 : 방패가 없으면 사용할 수 없다.
FOR_FIGHTER_TWOHANDED = 3, // 양손무기착용(스탶제외) : 양손무기 착용시에만 사용이 가능하다. 스태프일 경우에는 사용이 불가능하다.
FOR_ALL_ONEHAND = 4, // 한손무기착용 : 양손무기나 맨손으로는 사용이 불가능하다. 대거 제외
WITH_DAGGER = 5, // 대거착용 : 대거 착용시에만 사용이 가능하다.
WITH_THROWING_DAGGER = 6, // 쓰로잉대거소모 : 인벤토리에 쓰로잉 대거가 남아있을 때에만 사용이 가능하다. (손에 장착되어 있을 필요는 없다.)
RANGED = 7, // 활/석궁장착,화살소모 : 활이나 석궁이 장착되어 있고 인벤토리에 화살이 남아있을 때에만 사용이 가능하다.
// 아칸
LEFT_ARM = 8, // 왼팔장착 : 왼팔을 장착하고 있어야지만 사용이 가능하다.
GUARD_ARM = 9, // 가드암장착 : 방어용의 암을 장착하고 있어야지만 사용이 가능하다.
WITH_WEAPON = 10, // 무기장착 : 오른손이 맨손일 때에는 사용이 불가능하다.
ATTACK_ARM = 11, // 어택암장착 : 공격용의 암을 장착하고 있어야지만 사용이 가능하다.
GUN_ARM = 12, // 건암장착 탄약소모 : 장거리용의 암을 장착하고 탄약을 가지고 있어야지만 사용이 가능하다.
KNIFE_ARM = 13, // 나이프암장착 : 나이프형의 암을 장착하고 있어야지만 사용이 가능하다.
WITH_CLOW = 14, // 클로우장착 : 클로우 착용시에만 사용이 가능하다.
MAX_USE_LIMIT = 15
};
extern const CTypeName UseLimits[MAX_USE_LIMIT];
};
namespace StatusLimit // 아이템 제한
{
enum Type
{
NONE = 0, // 제한 없음
STR = 1, // STR이 일정 이상 필요
DEX = 2, // DEX가 일정 이상 필요
CON = 3, // CON이 일정 이상 필요
INT = 4, // INT가 일정 이상 필요
WIS = 5, // WIS가 일정 이상 필요
MAX_STATUS_LIMIT = 6
};
extern const CTypeName StatusLimits[MAX_STATUS_LIMIT];
};
namespace Target
{
enum Type
{
NONE = 0,
MELEE = 1,
FRIEND = 2,
ENEMY = 3,
DEAD_FRIEND = 4,
DEAD_ENEMY = 5,
FRIEND_OBJECT = 6,
ENEMY_OBJECT = 7,
PARTY = 8,
FRIEND_EXCEPT_SELF = 9,
LINE_ENEMY = 10,
MAX_TARGET_TYPE = 11
};
extern const CTypeName TargetTypes[MAX_TARGET_TYPE];
};
struct ProtoType
{
enum { MAX_LIMIT_NUM = 2, MAX_FILE_NAME = 32, MAX_SKILL_NAME = 32 };
//-----------------------------------
char m_szEffectFileName[MAX_FILE_NAME];
char m_szHitFileName[MAX_FILE_NAME];
char m_szCastingFileName[MAX_FILE_NAME];
Item::SpriteData m_SpriteInfo;
//-----------------------------------
Type::Type m_eSkillType; // See Namespace Type
Target::Type m_eTargetType; // See Namespace Target
UseLimit::Type m_eUseLimit; // See Namespace UseLimit
unsigned char m_StatusLimitType[MAX_LIMIT_NUM];
char m_StatusLimitValue[MAX_LIMIT_NUM];
//-----------------------------------
unsigned short m_usSkill_ID;
unsigned short m_StartMP;
unsigned short m_LevelMP;
unsigned short m_StartTick;
//-----------------------------------
unsigned short m_LevelTick;
unsigned short m_usCoolDownTime;
//-----------------------------------
float m_EffectDistance;
float m_EffectExtent;
//-----------------------------------
bool m_bProtection;
bool m_bGauge;
bool m_bIsClassSkill;
bool m_bInterrupt;
unsigned char m_cEndScript;
unsigned char m_cEndCoolDown;
unsigned char m_cMinRange;
unsigned char m_cMaxRange;
//-----------------------------------
unsigned char m_cStrikeNum;
unsigned char m_cSpell_LockCount;
unsigned char m_cPadding[6];
//-----------------------------------
ProtoType();
void Initialize();
};
}
#pragma pack()
#endif