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,582 @@
// QuestRemove.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
/*
스크립트 구조
클래스타입 계정국적타입 커맨드 퀘스트ID
클래스타입은 다음이 있다
ALL : 모든 클래스
HUMAN_1ST : 휴먼 기본 (파이터, 로그, 메이지, 어콜라이트)
HUMAN_2ND : 휴먼 상위 (디펜더, 워리어, 어쌔신, 아처, 소서러, 인챈터, 프리스트, 클레릭)
AKHAN_1ST : 아칸 기본 (컴배턴트, 오피세이터)
AKHAN_2ND : 아칸 상위 (템플러, 어태커, 거너, 룬오프, 라이프오프, 쉐도우오프)
FIGHTER : 휴먼 전사
ROGUE : 휴먼 로그
MAGE : 휴먼 메이지
ACOLYTE : 휴먼 어콜라이트
DEFENDER : 휴먼 디펜더
WARRIOR : 휴먼 워리어
ASSASSIN : 휴먼 어쌔신
ARCHER : 휴먼 아처
SORCERER : 휴먼 소서러
ENCHANTER : 휴먼 인챈터
PRIEST : 휴먼 프리스트
CLERIC : 휴먼 클레릭
COMBATANT : 아칸 컴배턴트
OFFICIATOR : 아칸 오피세이터
TEMPLAR : 아칸 템플러
ATTACKER : 아칸 어태커
GUNNER : 아칸 거너
RUNEOFF : 아칸 룬오프
LIFEOFF : 아칸 라이프오프
SHADOWOFF : 아칸 쉐도우오프
계정국적타입은 다음이 있다
ALL : 모든 국적
KA : 카르테란트
ME : 메르카디아
AP : 신의 해적단
커맨드는 다음이 있다
REMOVE_ALL : 수행중인 퀘스트, 수행 완료 퀘스트 둘 다
REMOVE_CURRENT : 수행중인 퀘스트 삭제
REMOVE_HISTORY : 수행완료 퀘스트 삭제
퀘스트ID 는 10진수 혹은 0x로 시작하는 16진수이다.
주석은 C스타일의 주석 // 만 지원한다
*/
#pragma warning(disable:4800)
#include "stdafx.h"
#include <list>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <RylDBLibrary/RylDBLibrary.h>
#include <RylDBLibrary/RylDBCharCommand.h>
#include <Network/Packet/PacketStruct/CharQuestPacket.h>
#include <Log/ServerLog.h>
#include <boost/pool/pool_alloc.hpp>
#include <Creature/CreatureStructure.h>
#include <Creature/Character/CharacterClass.h>
// Quest Script Command
enum QSCommand
{
NOTHING,
REMOVE_ALL,
REMOVE_CURRENT,
REMOVE_HISTORY
};
struct QuestData
{
std::bitset<CClass::MAX_CLASS> m_Class; // 동작을 수행할 클래스
Creature::Nation m_Nation; // 동작을 수행할 계정국적 (MAX_NATION == 국적에 관계없이 수행)
QSCommand m_Command; // 해당 퀘스트에 수행할 동작
unsigned short m_QuestID; // 퀘스트 ID
std::set<unsigned long, std::less<unsigned long>,
boost::fast_pool_allocator<unsigned long> > m_DstCharID; // 작업할 캐릭터ID
};
struct QuestTarget
{
unsigned long CID;
DBSTATUSENUM CIDStatus;
BEGIN_ACCESSOR_MAP(QuestTarget, 1)
BEGIN_ACCESSOR(0, true)
COLUMN_ENTRY_STATUS(1, CID, CIDStatus)
END_ACCESSOR()
END_ACCESSOR_MAP()
};
class CProcessQuest : public IDBCharQuestProcess
{
public:
bool LoadScript(const char* szScriptName);
HRESULT SetTargets(ATL::CSession& dbSession);
private:
typedef std::list<QuestData> QuestDataList;
virtual ConvertResult operator()(RylDBCommand::CCharQuest& charQuest_InOut);
QSCommand IsProcessQuest(unsigned long dwCID, unsigned short usQuestID);
QuestDataList m_ProcessQuestData;
};
void PrintUsage()
{
printf("usage : QuestRemove.exe DBAddress DBName DBAccount DBPassword QuestRemoveScriptName \n");
}
int _tmain(int argc, _TCHAR* argv[])
{
if(6 != argc)
{
PrintUsage();
return -1;
}
const char* szProcessQuestScript = argv[5];
CProcessQuest processQuest;
if(FAILED(processQuest.LoadScript(szProcessQuestScript)))
{
printf("%s 스크립트 로드 실패", szProcessQuestScript);
return -1;
}
CoInitialize(0);
HRESULT hr = S_OK;
ATL::CDataSource dataSource;
ATL::CSession Session;
#define LOG_CONVERT0(str) { ERRLOG0(g_Log, (str)); printf(str "\n"); }
#define LOG_CONVERT1(str, arg1) { ERRLOG1(g_Log, (str), (arg1)); printf(str "\n", (arg1)); }
#define LOG_CONVERT2(str, arg1, arg2) { ERRLOG2(g_Log, (str), (arg1), (arg2)); printf(str "\n", (arg1), (arg2)); }
if(FAILED(hr = CRylDBProcess::ConnectDB(dataSource, argv[1], argv[2], argv[3], argv[4])))
{
LOG_CONVERT1("Connect DB failed : hr:0x%08X", hr);
}
else if(FAILED(hr = Session.Open(dataSource)))
{
LOG_CONVERT1("Open session failed : hr:0x%08X", hr);
}
else if(FAILED(hr = processQuest.SetTargets(Session)))
{
LOG_CONVERT1("Target setting failed : hr:0x%08X", hr);
}
else
{
CRylDBProcess rylDBProcess(Session);
CConsoleCounter consoleCounter(1000);
if (!rylDBProcess.CharQuest(processQuest, consoleCounter))
{
LOG_CONVERT1("CharQuest process failed : hr:0x%08X", hr);
}
}
INFLOG0(g_Log, "Remove Complete");
Session.Close();
dataSource.Close();
CoUninitialize();
return 0;
}
bool CProcessQuest::LoadScript(const char* szScriptName)
{
bool bResult = true;
FILE* lpFile = fopen(szScriptName, "rt");
if (0 != lpFile)
{
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
const char* szDelimiter = "\r\n\t: ";
int nLine = 0;
const char* szComment = "//";
size_t nCommentLen = strlen(szComment);
const char* szHexHeader = "0X";
size_t nHexHeaderLen = strlen(szHexHeader);
char* szStopPtr = 0;
int nBase = 10;
while(fgets(szBuffer, MAX_BUFFER - 1, lpFile))
{
++nLine;
char* szClass = strtok(szBuffer, szDelimiter);
char* szNation = strtok(0, szDelimiter);
char* szCommand = strtok(0, szDelimiter);
char* szQuestID = strtok(0, szDelimiter);
if (0 != szClass && 0 != szNation && 0 != szCommand && 0 != szQuestID &&
0 != strncmp(szClass, szComment, nCommentLen))
{
strupr(szClass);
strupr(szNation);
strupr(szCommand);
strupr(szQuestID);
QuestData questData;
questData.m_Class.reset();
// 클래스 이름 파싱
if (0 == strcmp(szClass, "ALL"))
{
questData.m_Class.set();
}
else if (0 == strcmp(szClass, "HUMAN_1ST"))
{
questData.m_Class.set(CClass::Fighter);
questData.m_Class.set(CClass::Rogue);
questData.m_Class.set(CClass::Mage);
questData.m_Class.set(CClass::Acolyte);
}
else if (0 == strcmp(szClass, "HUMAN_2ND"))
{
questData.m_Class.set(CClass::Defender);
questData.m_Class.set(CClass::Warrior);
questData.m_Class.set(CClass::Assassin);
questData.m_Class.set(CClass::Archer);
questData.m_Class.set(CClass::Sorcerer);
questData.m_Class.set(CClass::Enchanter);
questData.m_Class.set(CClass::Priest);
questData.m_Class.set(CClass::Cleric);
}
else if (0 == strcmp(szClass, "AKHAN_1ST"))
{
questData.m_Class.set(CClass::Combatant);
questData.m_Class.set(CClass::Officiator);
}
else if (0 == strcmp(szClass, "AKHAN_2ND"))
{
questData.m_Class.set(CClass::Templar);
questData.m_Class.set(CClass::Attacker);
questData.m_Class.set(CClass::Gunner);
questData.m_Class.set(CClass::RuneOff);
questData.m_Class.set(CClass::LifeOff);
questData.m_Class.set(CClass::ShadowOff);
}
else if (0 == strcmp(szClass, "FIGHTER")) { questData.m_Class.set(CClass::Fighter); }
else if (0 == strcmp(szClass, "ROGUE")) { questData.m_Class.set(CClass::Rogue); }
else if (0 == strcmp(szClass, "MAGE")) { questData.m_Class.set(CClass::Mage); }
else if (0 == strcmp(szClass, "ACOLYTE")) { questData.m_Class.set(CClass::Acolyte); }
else if (0 == strcmp(szClass, "DEFENDER")) { questData.m_Class.set(CClass::Defender); }
else if (0 == strcmp(szClass, "WARRIOR")) { questData.m_Class.set(CClass::Warrior); }
else if (0 == strcmp(szClass, "ASSASSIN")) { questData.m_Class.set(CClass::Assassin); }
else if (0 == strcmp(szClass, "ARCHER")) { questData.m_Class.set(CClass::Archer); }
else if (0 == strcmp(szClass, "SORCERER")) { questData.m_Class.set(CClass::Sorcerer); }
else if (0 == strcmp(szClass, "ENCHANTER")) { questData.m_Class.set(CClass::Enchanter); }
else if (0 == strcmp(szClass, "PRIEST")) { questData.m_Class.set(CClass::Priest); }
else if (0 == strcmp(szClass, "CLERIC")) { questData.m_Class.set(CClass::Cleric); }
else if (0 == strcmp(szClass, "COMBATANT")) { questData.m_Class.set(CClass::Combatant); }
else if (0 == strcmp(szClass, "OFFICIATOR")) { questData.m_Class.set(CClass::Officiator); }
else if (0 == strcmp(szClass, "TEMPLAR")) { questData.m_Class.set(CClass::Templar); }
else if (0 == strcmp(szClass, "ATTACKER")) { questData.m_Class.set(CClass::Attacker); }
else if (0 == strcmp(szClass, "GUNNER")) { questData.m_Class.set(CClass::Gunner); }
else if (0 == strcmp(szClass, "RUNEOFF")) { questData.m_Class.set(CClass::RuneOff); }
else if (0 == strcmp(szClass, "LIFEOFF")) { questData.m_Class.set(CClass::LifeOff); }
else if (0 == strcmp(szClass, "SHADOWOFF")) { questData.m_Class.set(CClass::ShadowOff); }
else
{
// 파싱 불가.
printf("클래스가 잘못된 라인이 있습니다 : %s:%d", szClass, nLine);
bResult = false; break;
}
// 국적 파싱
if (0 == strcmp(szNation, "ALL")) { questData.m_Nation = Creature::MAX_NATION;}
else if (0 == strcmp(szNation, "KA")) { questData.m_Nation = Creature::KARTERANT; }
else if (0 == strcmp(szNation, "ME")) { questData.m_Nation = Creature::MERKADIA; }
else if (0 == strcmp(szNation, "AP")) { questData.m_Nation = Creature::ALMIGHTY_PIRATE; }
else
{
// 파싱 불가
LOG_CONVERT2("국적이 잘못된 라인이 있습니다 : %s:%d", szNation, nLine);
bResult = false; break;
}
// 커맨드 파싱
if (0 == strcmp(szCommand, "REMOVE_ALL")) { questData.m_Command = REMOVE_ALL; }
else if (0 == strcmp(szCommand, "REMOVE_CURRENT")) { questData.m_Command = REMOVE_CURRENT; }
else if (0 == strcmp(szCommand, "REMOVE_HISTORY")) { questData.m_Command = REMOVE_HISTORY; }
else
{
// 파싱 불가
LOG_CONVERT2("커맨드가 잘못된 라인이 있습니다 : %s:%d", szCommand, nLine);
bResult = false; break;
}
// 퀘스트ID 파싱
nBase = (0 == strncmp(szQuestID, szHexHeader, nHexHeaderLen)) ? 16 : 10;
questData.m_QuestID =
static_cast<unsigned short>(strtoul(szQuestID, &szStopPtr, nBase));
if (0 != questData.m_QuestID)
{
m_ProcessQuestData.push_back(questData);
}
else
{
LOG_CONVERT2("퀘스트ID 가 잘못된 라인이 있습니다 : %s:%d", szQuestID, nLine);
bResult = false; break;
}
}
}
fclose(lpFile);
}
else
{
LOG_CONVERT1("파일 열기에 실패했습니다 : %s", szScriptName);
bResult = false;
}
return bResult;
}
HRESULT CProcessQuest::SetTargets(ATL::CSession& dbSession)
{
/*
클래스가 ALL인 경우 - WHERE문을 날린다
국가가 ALL인 경우 - 2~6라인을 날린다
SELECT A.CID FROM CharInfo A
JOIN (SELECT Char1 as CID FROM UserInfo WHERE Nation = 1 AND Char1 > 0 UNION ALL
SELECT Char2 as CID FROM UserInfo WHERE Nation = 1 AND Char2 > 0 UNION ALL
SELECT Char3 as CID FROM UserInfo WHERE Nation = 1 AND Char3 > 0 UNION ALL
SELECT Char4 as CID FROM UserInfo WHERE Nation = 1 AND Char4 > 0 UNION ALL
SELECT Char5 as CID FROM UserInfo WHERE Nation = 1 AND Char5 > 0 ) B ON A.CID = B.CID
WHERE A.Class = 1
*/
const int MAX_QUERY_BUFFER = 512;
char szQueryBuffer[MAX_QUERY_BUFFER];
size_t nTotalTargetNum = 0;
QuestDataList::iterator pos = m_ProcessQuestData.begin();
QuestDataList::iterator end = m_ProcessQuestData.end();
for (; pos != end; ++pos)
{
QuestData& questData = *pos;
std::string targetQuery;
targetQuery.reserve(MAX_QUERY_BUFFER * 2);
targetQuery.assign("SELECT A.CID FROM CharInfo A ");
if (questData.m_Nation != Creature::MAX_NATION)
{
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER,
"JOIN (SELECT Char1 as CID FROM UserInfo WHERE Nation = %d AND Char1 > 0 UNION ALL"
"SELECT Char2 as CID FROM UserInfo WHERE Nation = %d AND Char2 > 0 UNION ALL"
"SELECT Char3 as CID FROM UserInfo WHERE Nation = %d AND Char3 > 0 UNION ALL"
"SELECT Char4 as CID FROM UserInfo WHERE Nation = %d AND Char4 > 0 UNION ALL"
"SELECT Char5 as CID FROM UserInfo WHERE Nation = %d AND Char5 > 0 ) B ON A.CID = B.CID",
questData.m_Nation, questData.m_Nation, questData.m_Nation,
questData.m_Nation, questData.m_Nation);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = 0;
targetQuery.append(szQueryBuffer);
}
if (questData.m_Class.any())
{
targetQuery.append("WHERE A.Class in (");
for (int nCount = 0; nCount < CClass::MAX_CLASS; ++nCount)
{
if (questData.m_Class.test(nCount))
{
targetQuery.append(itoa(nCount, szQueryBuffer, 10));
targetQuery.append(", ");
}
}
size_t position = targetQuery.find_last_of(",");
if (position != std::string::npos)
{
targetQuery[position] = ')';
}
}
CCommand<CAccessor<QuestTarget>, CBulkRowset, CMultipleResults> targetCIDs;
HRESULT hr = S_OK;
targetCIDs.SetRows(100000);
if (FAILED(hr = targetCIDs.Open(dbSession, targetQuery.c_str())))
{
LOG_CONVERT2("타겟 얻어오기 실패 : hr:0x08X / targetQuery:%s", hr, targetQuery.c_str);
return hr;
}
else
{
while(S_OK == (hr = targetCIDs.MoveNext()))
{
if (0 != targetCIDs.CID)
{
questData.m_DstCharID.insert(targetCIDs.CID);
targetCIDs.CID = 0;
}
}
RULLOG0(g_Log, targetQuery.c_str());
printf("QuestID:0x%04X - 타겟 얻어오기 성공(%u명)\n",
questData.m_QuestID, questData.m_DstCharID.size());
nTotalTargetNum += questData.m_DstCharID.size();
}
}
printf("총 타겟 수(%u명)\n", nTotalTargetNum);
return S_OK;
}
QSCommand CProcessQuest::IsProcessQuest(unsigned long dwCID, unsigned short usQuestID)
{
QuestDataList::iterator pos = m_ProcessQuestData.begin();
QuestDataList::iterator end = m_ProcessQuestData.end();
for (; pos != end; ++pos)
{
QuestData& questData = *pos;
if (questData.m_QuestID == usQuestID &&
questData.m_DstCharID.end() != questData.m_DstCharID.find(dwCID))
{
// 해당 퀘스트/대상자가 존재한다.
return questData.m_Command;
}
}
return NOTHING;
}
ConvertResult CProcessQuest::operator()(RylDBCommand::CCharQuest& charQuest_InOut)
{
unsigned long dwCID = charQuest_InOut.GetCID();
unsigned long dwTotalChangedCount = 0;
const QUEST& quest_In = charQuest_InOut.GetQuest();
const HISTORY history_In = charQuest_InOut.GetHistory();
if (0 < quest_In.dwSize)
{
unsigned long dwChangedCount = 0;
QUEST quest_Out;
memset(&quest_Out, 0, sizeof(QUEST));
const PktQuestDB::ExecutingQuest* lpExecutingQuestPos =
reinterpret_cast<const PktQuestDB::ExecutingQuest*>(quest_In.Data);
const PktQuestDB::ExecutingQuest* lpExecutingQuestEnd =
reinterpret_cast<const PktQuestDB::ExecutingQuest*>(quest_In.Data + quest_In.dwSize);
PktQuestDB::ExecutingQuest* lpDst = reinterpret_cast<PktQuestDB::ExecutingQuest*>(quest_Out.Data);
for(; lpExecutingQuestPos < lpExecutingQuestEnd; ++lpExecutingQuestPos)
{
QSCommand command = IsProcessQuest(dwCID, lpExecutingQuestPos->m_wQuestID);
if (REMOVE_ALL == command || REMOVE_CURRENT == command)
{
++dwChangedCount;
INFLOG2(g_Log, "CID:%10u / QuestID:0x%04X / 진행중인 퀘스트를 제거했습니다",
dwCID, lpExecutingQuestPos->m_wQuestID);
}
else
{
// 목록에 없는 경우에만 복사한다.
*lpDst = *lpExecutingQuestPos;
++lpDst;
}
}
if (0 < dwChangedCount)
{
quest_Out.dwSize = static_cast<unsigned long>(
reinterpret_cast<char*>(lpDst) - quest_Out.Data);
charQuest_InOut.SetQuest(quest_Out);
dwTotalChangedCount += dwChangedCount;
}
}
if (0 < history_In.dwSize)
{
unsigned long dwChangedCount = 0;
HISTORY history_Out;
memset(&history_Out, 0, sizeof(HISTORY));
const unsigned short* lpHistoryPos = reinterpret_cast<const unsigned short*>(history_In.Data);
const unsigned short* lpHistoryEnd = reinterpret_cast<const unsigned short*>(history_In.Data + history_In.dwSize);
unsigned short* lpDst = reinterpret_cast<unsigned short*>(history_Out.Data);
for(; lpHistoryPos < lpHistoryEnd; ++lpHistoryPos)
{
QSCommand command = IsProcessQuest(dwCID, *lpHistoryPos);
if (REMOVE_ALL == command || REMOVE_HISTORY == command)
{
++dwChangedCount;
INFLOG2(g_Log, "CID:%10u / QuestID:0x%04X / 수행 완료된 퀘스트를 제거했습니다",
dwCID, *lpHistoryPos);
}
else
{
// 목록에 없는 경우에만 복사한다.
*lpDst = *lpHistoryPos;
++lpDst;
}
}
if (0 < dwChangedCount)
{
history_Out.dwSize = static_cast<unsigned long>(
reinterpret_cast<char*>(lpDst) - history_Out.Data);
charQuest_InOut.SetHistory(history_Out);
dwTotalChangedCount += dwChangedCount;
}
}
return (0 < dwTotalChangedCount) ? CONVERT_SUCCEEDED : CONVERT_DO_NOT_WRITE;
}

View File

@@ -0,0 +1,161 @@
<?xml version="1.0" encoding="ks_c_5601-1987"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="7.10"
Name="QuestRemove"
ProjectGUID="{329845C7-E869-42A8-B581-E37F837BEBBA}"
SccProjectName="SAK"
SccAuxPath="SAK"
SccLocalPath="SAK"
SccProvider="SAK"
Keyword="Win32Proj">
<Platforms>
<Platform
Name="Win32"/>
</Platforms>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfATL="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="../;../../RylServerProject;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/QuestRemove.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/RemoveQuest.pdb"
SubSystem="1"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="../Executable/$(ConfigurationName)"
IntermediateDirectory="../Intermediate/$(ProjectName)/$(ConfigurationName)"
ConfigurationType="1"
UseOfATL="1"
CharacterSet="2">
<Tool
Name="VCCLCompilerTool"
AdditionalIncludeDirectories="../;../../RylServerProject;../../RylServerProject/BaseLibrary;../../RylServerProject/RylServerLibrary;../../RylServerProject/RylGameLibrary"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="0"
UsePrecompiledHeader="2"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/QuestRemove.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"/>
<Tool
Name="VCMIDLTool"/>
<Tool
Name="VCPostBuildEventTool"/>
<Tool
Name="VCPreBuildEventTool"/>
<Tool
Name="VCPreLinkEventTool"/>
<Tool
Name="VCResourceCompilerTool"/>
<Tool
Name="VCWebServiceProxyGeneratorTool"/>
<Tool
Name="VCXMLDataGeneratorTool"/>
<Tool
Name="VCWebDeploymentTool"/>
<Tool
Name="VCManagedWrapperGeneratorTool"/>
<Tool
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="소스 파일"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
<File
RelativePath=".\QuestRemove.cpp">
</File>
<File
RelativePath=".\stdafx.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
UsePrecompiledHeader="1"/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="헤더 파일"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
<File
RelativePath=".\stdafx.h">
</File>
</Filter>
<Filter
Name="리소스 파일"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
</Filter>
<File
RelativePath=".\ReadMe.txt">
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -0,0 +1,32 @@
========================================================================
콘솔 응용 프로그램 : RemoveQuest 프로젝트 개요
========================================================================
응용 프로그램 마법사에서 이 RemoveQuest 응용 프로그램을 만들었습니다.
이 파일에는 RemoveQuest 응용 프로그램을 구성하는 각각의 파일에
들어 있는 요약 설명이 포함되어 있습니다.
RemoveQuest.vcproj
응용 프로그램 마법사를 사용하여 생성한 VC++ 프로젝트의 기본 프로젝트 파일입니다.
해당 파일을 생성한 Visual C++의 버전 정보를 비롯하여
응용 프로그램 마법사에서 선택한 플랫폼, 구성 및
프로젝트 기능에 대한 정보가 들어 있습니다.
RemoveQuest.cpp
기본 응용 프로그램 소스 파일입니다.
/////////////////////////////////////////////////////////////////////////////
기타 표준 파일:
StdAfx.h 및 StdAfx.cpp는
RemoveQuest.pch라는 이름의 PCH(미리 컴파일된 헤더) 파일과
StdAfx.obj라는 이름의 미리 컴파일된 형식 파일을 빌드하는 데 사용됩니다.
/////////////////////////////////////////////////////////////////////////////
기타 참고:
응용 프로그램 마법사에서 사용하는 "TODO:" 주석은 사용자가 추가하거나 사용자 지정해야 하는
소스 코드 부분을 나타냅니다.
/////////////////////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,8 @@
// stdafx.cpp : 표준 포함 파일만 들어 있는 소스 파일입니다.
// RemoveQuest.pch는 미리 컴파일된 헤더가 됩니다.
// stdafx.obj에는 미리 컴파일된 형식 정보가 포함됩니다.
#include "stdafx.h"
// TODO: 필요한 추가 헤더는
// 이 파일이 아닌 STDAFX.H에서 참조합니다.

View File

@@ -0,0 +1,15 @@
// stdafx.h : 자주 사용하지만 자주 변경되지는 않는
// 표준 시스템 포함 파일 및 프로젝트 관련 포함 파일이
// 들어 있는 포함 파일입니다.
//
#pragma once
#include <iostream>
#include <tchar.h>
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 일부 CString 생성자는 명시적으로 선언됩니다.
#include <atlbase.h>
// TODO: 프로그램에 필요한 추가 헤더는 여기에서 참조합니다.