Files
Client/Server/ToolProject/SkillRebalanceConverter/SkillRebalanceConverter.cpp
LGram16 dd97ddec92 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>
2025-11-29 20:17:20 +09:00

1384 lines
47 KiB
C++

// SkillRebalanceConverter.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#pragma warning(disable:4800)
#include <winsock2.h>
#include <windows.h>
#include <DB/DBComponent.h>
#include <DB/GameDBComponent.h>
#include <map>
#include <boost/pool/pool_alloc.hpp>
#include <Item/ItemMgr.h>
#include <Item/Item.h>
#include <Item/ItemContainer.h>
#include <Item/ItemFactory.h>
#include <Item/ItemStructure.h>
#include <Skill/SkillMgr.h>
#include <Log/ServerLog.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Utility/Setup/ServerSetup.h>
#include "ItemSerialMgr.h"
#include "3DArrayChecker.h"
#pragma pack(1)
struct SkillData
{
unsigned long m_dwCID;
SKILL m_skill;
};
struct CharData
{
unsigned long m_dwCID;
INVEN m_Inventory;
EXTRA m_Extra;
EXCHANGE m_Exchange;
};
struct StoreData
{
unsigned long m_dwUID;
STORE m_store1;
STORE m_store2;
};
#pragma pack()
struct SkillBookData
{
enum { MAX_SKILL_LOCKCOUNT = 5 };
unsigned long m_dwSkillBookNum[MAX_SKILL_LOCKCOUNT];
};
typedef std::map<unsigned long, SkillBookData, std::less<unsigned long>,
boost::fast_pool_allocator<std::pair<unsigned long, SkillBookData> > > SkillBookMap;
/*
typedef std::map<unsigned long, SkillBookData> SkillBookMap;
*/
bool ProcessCharData(CDBComponent& readDB, CDBComponent& writeDB,
SkillBookMap& skillBookMap, bool bDelCharHistory, bool bWriteDB);
bool ProcessStoreData(CDBComponent& readDB, CDBComponent& writeDB,
SkillBookMap& skillBookMap, bool bWriteDB);
bool ReadSkillData(CDBComponent& readDB, SkillBookMap& cidSkillBookMap, bool bReadDelCharHistory);
bool RemoveSkills(unsigned long dwKey, const char* szContainerName, SkillBookMap& skillBookMap,
const char* szInputData, unsigned long dwInputDataSize,
char* szResultData, unsigned long& dwResultDataSize);
unsigned long InsertSkillBookTicket(unsigned long dwKey, const char* szContainerName,
C3DArrayChecker& arrayChecker, SkillBookMap& skillBookMap,
char* szData, unsigned long& dwDataSize_InOut, unsigned long dwMaxDataSize);
bool InsertToTempInven(CDBComponent& readDB, unsigned long dwCID, SkillBookMap& cidBookMap);
bool InsertToCharDelTempInven(CDBComponent& writeDB, unsigned long dwCID, SkillBookMap& cidBookMap);
void WriteSkillClear(CDBComponent& writeDB, bool bDelCharHistory);
void WriteBackCharacterData(CDBComponent& writeDB, CharData& originalData, CharData& newData);
void WriteBackStoreData(CDBComponent& writeDB, StoreData& originalData, StoreData& newData);
void WriteBackCharDelHistoryData(CDBComponent& writeDB, CharData& originalData, CharData& newData);
void AddCharGold(CDBComponent& writeDB, unsigned long dwGold, unsigned long dwCID, bool bCharDelHistory);
void AddStoreGold(CDBComponent& writeDB, unsigned long dwGold, unsigned long dwUID);
namespace DBComponent
{
namespace GameDB
{
bool UpdateDelHistoryInven(CDBComponent& DBComponent, unsigned long CharID_In, LPINVEN lpInven_In);
bool UpdateDelHistoryExtra(CDBComponent& DBComponent, unsigned long CharID_In, LPEXTRA lpExtra_In);
bool UpdateDelHistoryExchange(CDBComponent& DBComponent, unsigned long CharID_In, LPEXCHANGE lpExchange_In);
}
}
void PrintUsage()
{
printf("Usage : SkillRebalanceConverter DBServerName DBName DBAccount DBPassword "
"ServerGroup(GroupNum) ConvertDelHistroy(0/1) DBWrite(0/1)\n");
}
CServerLog g_GoldLog("GoldLog.log");
int _tmain(int argc, _TCHAR* argv[])
{
if(argc != 8)
{
PrintUsage();
return -1;
}
int nGroupNum = atoi(argv[5]);
bool bConvertDelHistory = (0 == strcmp("1", argv[6]));
bool bWriteDB = (0 == strcmp("1", argv[7]));
CDBComponent readDB;
if(!readDB.Connect(argv[1], argv[2], argv[3], argv[4]))
{
printf("Open readDB failed\n");
return -1;
}
CDBComponent writeDB;
if(!writeDB.Connect(argv[1], argv[2], argv[3], argv[4]))
{
printf("Open writeDB failed\n");
return -1;
}
if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./NewItemScript.txt"))
{
printf("ItemScript load failed\n");
return -1;
}
if(!CSkillMgr::GetInstance().LoadSkillsFromFile("./NewSkillScript.txt"))
{
printf("SkillScript load failed\n");
return -1;
}
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::AdminToolServer;
serverID.sID.Group = nGroupNum;
serverID.sID.Channel = 1;
serverID.sID.ID = SERVER_ID::ADMIN_TOOL_ZONE;
CItemSerialMgr itemSerialMgr;
if(!itemSerialMgr.LoadItemSerial(readDB, serverID.dwID))
{
printf("AdminTool serial setting failed\n");
return -1;
}
Item::CItemFactory::GetInstance().SetItemUID(itemSerialMgr.GetItemSerial());
/*
1. 기존 스킬을 읽어 카운팅하고 리셋한다
4단계/3단계/2단계/1단계 개수 카운팅
2. 기존 스킬북을 읽어서 Container에 Serialize한 후 iterator 로 돌면서 제거한다
4단계/3단계/2단계/1단계 개수 카운팅
3. 빈공간을 검색해서, 3/4단계 스킬에 대해서 보상 아이템을 넣어준다
4. 빈공간이 없으면 임시 인벤토리에 넣어 준다.
5. 다시 Serialize해서 DB에 저장한다.
6. 1/2단계 스킬북에 대한 보상 금액을 DB에 갱신한다.
*/
SkillBookMap m_cidBookMap;
SkillBookMap m_uidBookMap;
/*
SkillBookData data;
memset(&data, 0, sizeof(SkillBookData));
data.m_dwSkillBookNum[2] = 10;
data.m_dwSkillBookNum[3] = 10;
m_cidBookMap.insert(std::make_pair(277715, data));
InsertToTempInven(writeDB, 277715, m_cidBookMap);
*/
// 제거 성공했으면, 인벤토리에 스킬북 교환권을 넣어준다.
if(bConvertDelHistory)
{
printf("Convert CharDelHistory\n");
INFLOG0(g_Log, "Convert CharDelHistory");
if(!ReadSkillData(readDB, m_cidBookMap, true))
{
printf("Skill data read failed\n");
return -1;
}
if(!ProcessCharData(readDB, writeDB, m_cidBookMap, true, bWriteDB))
{
printf("CharDelHistory : Character data convert failed\n");
return -1;
}
SkillBookMap::iterator pos = m_cidBookMap.begin();
SkillBookMap::iterator end = m_cidBookMap.end();
for(; pos != end; ++pos)
{
unsigned long dwCID = pos->first;
SkillBookData& skillBookData = pos->second;
ERRLOG5(g_Log, "CID:%10u / 0:%u / 1:%u / 2:%u / 3:%u / CharDelHistory : 다음 스킬을 캐릭터에 지급하지 못했습니다",
dwCID, skillBookData.m_dwSkillBookNum[0], skillBookData.m_dwSkillBookNum[1],
skillBookData.m_dwSkillBookNum[2], skillBookData.m_dwSkillBookNum[3]);
}
m_cidBookMap.clear();
WriteSkillClear(writeDB, true);
}
printf("Read SkillData\n");
INFLOG0(g_Log, "Read SkillData");
if(!ReadSkillData(readDB, m_cidBookMap, false))
{
printf("Skill data read failed\n");
return -1;
}
printf("Convert CharData\n");
INFLOG0(g_Log, "Convert CharData");
if(!ProcessCharData(readDB, writeDB, m_cidBookMap, false, bWriteDB))
{
printf("Character data convert failed\n");
return -1;
}
printf("Convert StoreData\n");
INFLOG0(g_Log, "Convert Store");
if(!ProcessStoreData(readDB, writeDB, m_uidBookMap, bWriteDB))
{
printf("Store data convert failed\n");
return -1;
}
SkillBookMap::iterator pos = m_cidBookMap.begin();
SkillBookMap::iterator end = m_cidBookMap.end();
for(; pos != end; ++pos)
{
unsigned long dwCID = pos->first;
SkillBookData& skillBookData = pos->second;
ERRLOG5(g_Log, "CID:%10u / 0:%u / 1:%u / 2:%u / 3:%u / 다음 스킬을 캐릭터에 지급하지 못했습니다",
dwCID, skillBookData.m_dwSkillBookNum[0], skillBookData.m_dwSkillBookNum[1],
skillBookData.m_dwSkillBookNum[2], skillBookData.m_dwSkillBookNum[3]);
}
m_cidBookMap.clear();
pos = m_uidBookMap.begin();
end = m_uidBookMap.end();
for(; pos != end; ++pos)
{
unsigned long dwUID = pos->first;
SkillBookData& skillBookData = pos->second;
ERRLOG5(g_Log, "UID:%10u / 0:%u / 1:%u / 2:%u / 3:%u / 다음 스킬을 창고에 지급하지 못했습니다",
dwUID, skillBookData.m_dwSkillBookNum[0], skillBookData.m_dwSkillBookNum[1],
skillBookData.m_dwSkillBookNum[2], skillBookData.m_dwSkillBookNum[3]);
}
m_uidBookMap.clear();
printf("Clear Skill\n");
INFLOG0(g_Log, "Clear Skill");
if(bWriteDB)
{
// 스킬을 초기화한다.
WriteSkillClear(writeDB, false);
printf("Clear Skill Complete\n");
INFLOG0(g_Log, "Clear Skill Complete");
// 아이템 시리얼을 저장한다.
itemSerialMgr.SetItemSerial(Item::CItemFactory::GetInstance().GetItemUID());
if(!itemSerialMgr.SaveItemSerial(writeDB, serverID.dwID))
{
printf("AdminTool serial save failed\n");
}
}
printf("Convert Complete\n");
INFLOG0(g_Log, "Convent Complete");
return 0;
}
bool ProcessCharData(CDBComponent& readDB, CDBComponent& writeDB, SkillBookMap& skillBookMap,
bool bDelCharHistory, bool bWriteDB)
{
const char* szQuery = bDelCharHistory ?
"Select UID, Inventory, Extra from CharDelHistory..DelCharItem" :
"Select a.UID, a.Inventory, a.Extra, b.Exchange from CharItem a join CharItemEX b on a.UID = b.UID";
const int MAX_CHAR_DATA = 1024;
CharData* lpCharData = new CharData[MAX_CHAR_DATA];
if(0 == lpCharData)
{
printf("Memory allocation failed : CharData\n");
return false;
}
memset(lpCharData, 0, sizeof(CharData) * MAX_CHAR_DATA);
// 캐릭터 인벤 뒤져서 스킬북 제거하고, 카운팅하기.
if(!readDB.ExecuteQuery(szQuery))
{
printf("DBQuery failed : %s : %s\n", szQuery, readDB.GetErrorString());
return false;
}
int nCount = 0;
int nGetRowNum = 0;
while(readDB.GetData((void**)lpCharData, sizeof(CharData), MAX_CHAR_DATA, &nGetRowNum))
{
if(0 == nGetRowNum)
{
break;
}
CharData* lpCharDataPos = lpCharData;
CharData* lpCharDataEnd = lpCharData + nGetRowNum;
for(; lpCharDataPos != lpCharDataEnd; ++lpCharDataPos, ++nCount)
{
unsigned long dwCID = lpCharDataPos->m_dwCID;
CharData resultData;
memset(&resultData, 0, sizeof(CharData));
resultData.m_dwCID = dwCID;
// 인벤토리에서 제거
if(sizeof(unsigned long) <= lpCharDataPos->m_Inventory.dwSize)
{
lpCharDataPos->m_Inventory.dwSize -= sizeof(unsigned long);
}
resultData.m_Inventory.dwSize = INVEN::MAX_INVEN_SIZE;
RemoveSkills(dwCID, "Inventory", skillBookMap,
lpCharDataPos->m_Inventory.Data, lpCharDataPos->m_Inventory.dwSize,
resultData.m_Inventory.Data, resultData.m_Inventory.dwSize);
// 교환창에서 제거
if(sizeof(unsigned long) <= lpCharDataPos->m_Exchange.dwSize)
{
lpCharDataPos->m_Exchange.dwSize -= sizeof(unsigned long);
}
resultData.m_Exchange.dwSize = EXCHANGE::MAX_EXCHANGE_SIZE;
RemoveSkills(dwCID, "Exchange", skillBookMap,
lpCharDataPos->m_Exchange.Data, lpCharDataPos->m_Exchange.dwSize,
resultData.m_Exchange.Data, resultData.m_Exchange.dwSize);
// Extra에서 제거
if(sizeof(unsigned long) <= lpCharDataPos->m_Extra.dwSize)
{
lpCharDataPos->m_Extra.dwSize -= sizeof(unsigned long);
}
resultData.m_Extra.dwSize = EXTRA::MAX_EXTRA_SIZE;
RemoveSkills(dwCID, "Extra", skillBookMap,
lpCharDataPos->m_Extra.Data, lpCharDataPos->m_Extra.dwSize,
resultData.m_Extra.Data, resultData.m_Extra.dwSize);
// 제거 성공했으면, 인벤토리에 스킬북 교환권을 넣어준다.
C3DItemArrayChecker<6, 6, 3> invenArrayChecker(TakeType::TS_INVEN);
unsigned long dwGold =
InsertSkillBookTicket(dwCID, "Inventory", invenArrayChecker, skillBookMap,
resultData.m_Inventory.Data, resultData.m_Inventory.dwSize, INVEN::MAX_INVEN_SIZE);
// 제거 성공했으면, 다시 DB에 기록
if(bWriteDB)
{
if(0 < dwGold)
{
AddCharGold(writeDB, dwGold, dwCID, bDelCharHistory);
}
// 캐릭터 데이터 DB에 기록
if(bDelCharHistory)
{
InsertToCharDelTempInven(writeDB, dwCID, skillBookMap);
WriteBackCharDelHistoryData(writeDB, *lpCharDataPos, resultData);
}
else
{
// 임시 인벤토리에 데이터 삽입.
InsertToTempInven(writeDB, dwCID, skillBookMap);
WriteBackCharacterData(writeDB, *lpCharDataPos, resultData);
}
}
if(0 == (nCount % 1000))
{
printf(".");
}
}
memset(lpCharData, 0, sizeof(CharData) * MAX_CHAR_DATA);
}
printf("\n");
delete [] lpCharData;
return true;
}
bool ProcessStoreData(CDBComponent& readDB, CDBComponent& writeDB, SkillBookMap& skillBookMap, bool bWriteDB)
{
if(!readDB.ExecuteQuery(
"Select a.UID, a.Store, b.Store from ItemStore1 a join ItemStore2 b on a.UID = b.UID"))
{
printf("Store query failed : %s\n", readDB.GetErrorString());
return false;
}
const int MAX_STORE_DATA_NUM = 1024;
StoreData* lpStoreData = new StoreData[MAX_STORE_DATA_NUM];
if(0 == lpStoreData)
{
printf("Store memory allocation failed\n");
return false;
}
int nCount = 0;
int nGetRowNum = 0;
while(readDB.GetData((void**)lpStoreData, sizeof(StoreData), MAX_STORE_DATA_NUM, &nGetRowNum))
{
if(0 == nGetRowNum)
{
break;
}
StoreData* lpStoreDataPos = lpStoreData;
StoreData* lpStoreDataEnd = lpStoreData + nGetRowNum;
for(; lpStoreDataPos != lpStoreDataEnd; ++lpStoreDataPos, ++nCount)
{
unsigned long dwUID = lpStoreDataPos->m_dwUID;
StoreData resultData;
memset(&resultData, 0, sizeof(StoreData));
if(sizeof(unsigned long) <= lpStoreDataPos->m_store1.dwSize) { lpStoreDataPos->m_store1.dwSize -= sizeof(unsigned long); }
if(sizeof(unsigned long) <= lpStoreDataPos->m_store2.dwSize) { lpStoreDataPos->m_store2.dwSize -= sizeof(unsigned long); }
resultData.m_store1.dwSize = STORE::MAX_STORE_SIZE;
resultData.m_store2.dwSize = STORE::MAX_STORE_SIZE;
// 창고 1 스킬북 읽어서 제거
RemoveSkills(dwUID, "Store1", skillBookMap,
lpStoreDataPos->m_store1.Data, lpStoreDataPos->m_store1.dwSize,
resultData.m_store1.Data, resultData.m_store1.dwSize);
// 창고 2 스킬북 읽어서 제거
RemoveSkills(dwUID, "Store2", skillBookMap,
lpStoreDataPos->m_store2.Data, lpStoreDataPos->m_store2.dwSize,
resultData.m_store2.Data, resultData.m_store2.dwSize);
// 제거 성공했으면, 창고에 스킬북 교환권을 넣어준다.
C3DItemArrayChecker<8, 12, 4> storeArrayChecker(TakeType::TS_DEPOSIT);
unsigned long dwStoreGold =
InsertSkillBookTicket(dwUID, "store1", storeArrayChecker, skillBookMap,
resultData.m_store1.Data, resultData.m_store1.dwSize, STORE::MAX_STORE_SIZE);
// 창고 1/2탭에 아이템이 꽉차서 못넣은 경우가 생길 수 있다. 이때는 창고 3/4탭에 넣는다.
InsertSkillBookTicket(dwUID, "store2", storeArrayChecker, skillBookMap,
resultData.m_store2.Data, resultData.m_store2.dwSize, STORE::MAX_STORE_SIZE);
// 제거 성공했으면, 다시 DB에 기록
if(bWriteDB)
{
if(0 < dwStoreGold)
{
AddStoreGold(writeDB, dwStoreGold, dwUID);
}
// 창고 데이터 DB에 기록
WriteBackStoreData(writeDB, *lpStoreDataPos, resultData);
}
if(0 == (nCount % 1000))
{
printf(".");
}
}
memset(lpStoreData, 0, sizeof(StoreData) * MAX_STORE_DATA_NUM);
}
printf("\n");
delete [] lpStoreData;
return true;
}
bool RemoveSkills(unsigned long dwKey, const char* szContainerName,
SkillBookMap& skillBookMap,
const char* szInputData, unsigned long dwInputDataSize,
char* szResultData, unsigned long& dwResultDataSize)
{
if(dwResultDataSize < dwInputDataSize)
{
ERRLOG4(g_Log, "Key:%10u / ResultData:%10u / InputData:%10u / %s : ResultBuffer is too small",
dwKey, dwResultDataSize, dwInputDataSize, szContainerName);
return false;
}
const char* szPos = szInputData;
const char* szEnd = szInputData + dwInputDataSize;
char* szResultPos = szResultData;
for(; szPos < szEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szPos);
const Item::ItemInfo* lpItemInfo =
Item::CItemMgr::GetInstance().GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 == lpItemInfo)
{
ERRLOG4(g_Log, "Key:%10u / Serial:0x%016I64X / ProtoType:%6d / %s : Script has not this item",
dwKey, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, szContainerName);
}
else if(Item::ItemType::SKILLBOOK == lpItemInfo->m_DetailData.m_cItemType)
{
// 교환권 배열에 카운팅하고, 아이템을 복사하지 않는다.
SkillBookMap::iterator pos = skillBookMap.find(dwKey);
SkillBookMap::iterator end = skillBookMap.end();
if(pos != end)
{
pos->second.m_dwSkillBookNum[lpItemInfo->m_UseItemInfo.m_usSkill_LockCount] +=
lpItemData->m_cNumOrDurability;
}
else
{
SkillBookData bookData;
memset(&bookData, 0, sizeof(SkillBookData));
bookData.m_dwSkillBookNum[lpItemInfo->m_UseItemInfo.m_usSkill_LockCount] +=
lpItemData->m_cNumOrDurability;
skillBookMap.insert(std::make_pair(dwKey, bookData));
}
}
else
{
// 그냥 아이템을 복사한다.
memcpy(szResultPos, lpItemData, lpItemData->m_cItemSize);
szResultPos += lpItemData->m_cItemSize;
}
szPos += lpItemData->m_cItemSize;
}
dwResultDataSize = static_cast<unsigned long>(szResultPos - szResultData);
return true;
}
unsigned long InsertSkillBookTicket(unsigned long dwKey, const char* szContainerName, C3DArrayChecker& arrayChecker,
SkillBookMap& skillBookMap,
char* szData, unsigned long& dwDataSize_InOut, unsigned long dwMaxDataSize)
{
unsigned long dwGold = 0;
if(dwMaxDataSize < dwDataSize_InOut + sizeof(Item::ItemData) * 2)
{
ERRLOG2(g_Log, "Key:%10u / %s : give skillbook failed - data overflow", dwKey, szContainerName);
return 0;
}
SkillBookMap::iterator pos = skillBookMap.find(dwKey);
SkillBookMap::iterator end = skillBookMap.end();
if(pos != end)
{
SkillBookData& bookData = pos->second;
dwGold = bookData.m_dwSkillBookNum[0] * 1000 + bookData.m_dwSkillBookNum[1] * 10000;
bookData.m_dwSkillBookNum[0] = 0;
bookData.m_dwSkillBookNum[1] = 0;
unsigned long dw3rdBookNum = bookData.m_dwSkillBookNum[2];
unsigned long dw4thBookNum = bookData.m_dwSkillBookNum[3];
if(0 < dw3rdBookNum || 0 < dw4thBookNum)
{
const char* szDataPos = szData;
const char* szDataEnd = szData + dwDataSize_InOut;
for(; szDataPos < szDataEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szDataPos);
const Item::ItemInfo* lpItemInfo =
Item::CItemMgr::GetInstance().GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 != lpItemInfo)
{
arrayChecker.Set(lpItemData->m_ItemPos,
lpItemInfo->m_DetailData.m_cXSize, lpItemInfo->m_DetailData.m_cYSize);
}
else
{
ERRLOG4(g_Log, "Key:%10u / Serial:0x%016I64X / ProtoType:%6d / %s : Script has not this item",
dwKey, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, szContainerName);
}
szDataPos += lpItemData->m_cItemSize;
}
if(0 < dw3rdBookNum)
{
Item::ItemData thirdSkillBook;
memset(&thirdSkillBook, 0, sizeof(Item::ItemData));
thirdSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
thirdSkillBook.m_usProtoTypeID = 3401;
thirdSkillBook.m_cItemSize = sizeof(Item::ItemData);
thirdSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw3rdBookNum);
if(arrayChecker.FindEmptyPos(thirdSkillBook.m_ItemPos, 1, 1))
{
Item::CItemFactory::GetInstance().SetItemUID(thirdSkillBook.m_dwUID);
memcpy(szData + dwDataSize_InOut, &thirdSkillBook, sizeof(Item::ItemData));
dwDataSize_InOut += sizeof(Item::ItemData);
arrayChecker.Set(thirdSkillBook.m_ItemPos, 1, 1);
bookData.m_dwSkillBookNum[2] = 0;
}
else
{
DETLOG3(g_Log, "Key:%10u / 3rdBookNum:%10u / %s : 빈 공간이 없어서 3단계 스킬북 교환권을 임시 인벤에 넣습니다.",
dwKey, dw3rdBookNum, szContainerName);
}
}
if(0 < dw4thBookNum)
{
Item::ItemData forthSkillBook;
memset(&forthSkillBook, 0, sizeof(Item::ItemData));
forthSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
forthSkillBook.m_usProtoTypeID = 3402;
forthSkillBook.m_cItemSize = sizeof(Item::ItemData);
forthSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw4thBookNum);
if(arrayChecker.FindEmptyPos(forthSkillBook.m_ItemPos, 1, 1))
{
Item::CItemFactory::GetInstance().SetItemUID(forthSkillBook.m_dwUID);
memcpy(szData + dwDataSize_InOut, &forthSkillBook, sizeof(Item::ItemData));
dwDataSize_InOut += sizeof(Item::ItemData);
arrayChecker.Set(forthSkillBook.m_ItemPos, 1, 1);
bookData.m_dwSkillBookNum[3] = 0;
}
else
{
DETLOG3(g_Log, "Key:%10u / 4thBookNum:%10u / %s : 빈 공간이 없어서 4단계 스킬북 교환권을 임시 인벤에 넣습니다.",
dwKey, dw4thBookNum, szContainerName);
}
}
}
if(0 == bookData.m_dwSkillBookNum[0] && 0 == bookData.m_dwSkillBookNum[1] &&
0 == bookData.m_dwSkillBookNum[2] && 0 == bookData.m_dwSkillBookNum[3])
{
// 제대로 다 지급했으면 맵에서 지운다.
skillBookMap.erase(pos);
}
}
return dwGold;
}
bool InsertToTempInven(CDBComponent& writeDB, unsigned long dwCID, SkillBookMap& cidBookMap)
{
SkillBookMap::iterator pos = cidBookMap.find(dwCID);
SkillBookMap::iterator end = cidBookMap.end();
if(pos != end)
{
// 아직 스킬북 지급이 끝나지 않았다. 임시 인벤에 넣어준다.
SkillBookData& bookData = pos->second;
unsigned long dw3rdBookNum = bookData.m_dwSkillBookNum[2];
unsigned long dw4thBookNum = bookData.m_dwSkillBookNum[3];
TEMPINVEN tempInven;
memset(&tempInven, 0, sizeof(TEMPINVEN));
if(!DBComponent::GameDB::GetTempInven(writeDB, dwCID, &tempInven))
{
printf("Read temp inventory faild : CID:%10u / %s\n", dwCID, writeDB.GetErrorString());
ERRLOG2(g_Log, "CID:%10u / Read temp inventory failed : %s", dwCID, writeDB.GetErrorString());
return false;
}
const char* szDataPos = tempInven.Data;
const char* szDataEnd = tempInven.Data + tempInven.dwSize;
int nCount = 0;
for(; szDataPos < szDataEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szDataPos);
szDataPos += lpItemData->m_cItemSize;
++nCount;
}
if(0 < dw3rdBookNum)
{
Item::ItemData thirdSkillBook;
memset(&thirdSkillBook, 0, sizeof(Item::ItemData));
thirdSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
thirdSkillBook.m_usProtoTypeID = 3401;
thirdSkillBook.m_cItemSize = sizeof(Item::ItemData);
thirdSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw3rdBookNum);
thirdSkillBook.m_ItemPos = Item::ItemPos(TakeType::TS_TEMPINVEN, nCount);
++nCount;
if(tempInven.dwSize + sizeof(Item::ItemData) < TEMPINVEN::MAX_TEMPINVEN_SIZE)
{
Item::CItemFactory::GetInstance().SetItemUID(thirdSkillBook.m_dwUID);
memcpy(tempInven.Data + tempInven.dwSize, &thirdSkillBook, sizeof(Item::ItemData));
tempInven.dwSize += sizeof(Item::ItemData);
DETLOG2(g_Log, "CID:%10u / 3rdBookNum:%10u / 3단계 스킬북 교환권을 임시 인벤에 넣습니다.", dwCID, dw3rdBookNum);
}
else
{
ERRLOG2(g_Log, "CID:%10u / Num:%d / Insert 3rdBook to tempinven failed - not enough space", dwCID, dw3rdBookNum);
}
}
if(0 < dw4thBookNum)
{
Item::ItemData forthSkillBook;
memset(&forthSkillBook, 0, sizeof(Item::ItemData));
forthSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
forthSkillBook.m_usProtoTypeID = 3402;
forthSkillBook.m_cItemSize = sizeof(Item::ItemData);
forthSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw4thBookNum);
forthSkillBook.m_ItemPos = Item::ItemPos(TakeType::TS_TEMPINVEN, nCount);
++nCount;
if(tempInven.dwSize + sizeof(Item::ItemData) < TEMPINVEN::MAX_TEMPINVEN_SIZE)
{
Item::CItemFactory::GetInstance().SetItemUID(forthSkillBook.m_dwUID);
memcpy(tempInven.Data + tempInven.dwSize, &forthSkillBook, sizeof(Item::ItemData));
tempInven.dwSize += sizeof(Item::ItemData);
DETLOG2(g_Log, "CID:%10u / 4thBookNum:%10u / 4단계 스킬북 교환권을 임시 인벤에 넣습니다.", dwCID, dw4thBookNum);
}
else
{
ERRLOG2(g_Log, "CID:%10u / Num:%d / Insert 3rdBook to tempinven failed - not enough space",
dwCID, dw3rdBookNum);
}
}
if(!DBComponent::GameDB::UpdateTempInven(writeDB, dwCID, &tempInven))
{
printf("Write temp inventory faild : CID:%10u / %s\n", dwCID, writeDB.GetErrorString());
ERRLOG2(g_Log, "CID:%10u / Write temp inventory failed : %s", dwCID, writeDB.GetErrorString());
return false;
}
cidBookMap.erase(pos);
}
return true;
}
bool InsertToCharDelTempInven(CDBComponent& writeDB, unsigned long dwCID, SkillBookMap& cidBookMap)
{
SkillBookMap::iterator pos = cidBookMap.find(dwCID);
SkillBookMap::iterator end = cidBookMap.end();
if(pos != end)
{
// 아직 스킬북 지급이 끝나지 않았다. 임시 인벤에 넣어준다.
SkillBookData& bookData = pos->second;
unsigned long dw3rdBookNum = bookData.m_dwSkillBookNum[2];
unsigned long dw4thBookNum = bookData.m_dwSkillBookNum[3];
TEMPINVEN tempInven;
memset(&tempInven, 0, sizeof(TEMPINVEN));
_snprintf(writeDB.GetQueryBuffer(), CDBComponent::MAX_QUERY_LENGTH,
"SELECT TempInven FROM CharDelHistory..DelCharItemEx WHERE UID = %d", dwCID);
if(!writeDB.ExecuteQueryGetData(writeDB.GetQueryBuffer(), &tempInven))
{
printf("Read temp inventory faild : CID:%10u / %s\n", dwCID, writeDB.GetErrorString());
ERRLOG2(g_Log, "CID:%10u / Read temp inventory failed : %s", dwCID, writeDB.GetErrorString());
return false;
}
if(sizeof(unsigned long) <= tempInven.dwSize)
{
tempInven.dwSize -= sizeof(unsigned long);
}
const char* szDataPos = tempInven.Data;
const char* szDataEnd = tempInven.Data + tempInven.dwSize;
int nCount = 0;
for(; szDataPos < szDataEnd; )
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szDataPos);
szDataPos += lpItemData->m_cItemSize;
++nCount;
}
if(0 < dw3rdBookNum)
{
Item::ItemData thirdSkillBook;
memset(&thirdSkillBook, 0, sizeof(Item::ItemData));
thirdSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
thirdSkillBook.m_usProtoTypeID = 3401;
thirdSkillBook.m_cItemSize = sizeof(Item::ItemData);
thirdSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw3rdBookNum);
thirdSkillBook.m_ItemPos = Item::ItemPos(TakeType::TS_TEMPINVEN, nCount);
++nCount;
if(tempInven.dwSize + sizeof(Item::ItemData) < TEMPINVEN::MAX_TEMPINVEN_SIZE)
{
Item::CItemFactory::GetInstance().SetItemUID(thirdSkillBook.m_dwUID);
memcpy(tempInven.Data + tempInven.dwSize, &thirdSkillBook, sizeof(Item::ItemData));
tempInven.dwSize += sizeof(Item::ItemData);
DETLOG2(g_Log, "CID:%10u / 3rdBookNum:%10u / 3단계 스킬북 교환권을 임시 인벤에 넣습니다.", dwCID, dw3rdBookNum);
}
else
{
ERRLOG2(g_Log, "CID:%10u / Num:%d / Insert 3rdBook to tempinven failed - not enough space", dwCID, dw3rdBookNum);
}
}
if(0 < dw4thBookNum)
{
Item::ItemData forthSkillBook;
memset(&forthSkillBook, 0, sizeof(Item::ItemData));
forthSkillBook.m_dwUID = Item::CItemFactory::GetInstance().GetItemUID() + 1;
forthSkillBook.m_usProtoTypeID = 3402;
forthSkillBook.m_cItemSize = sizeof(Item::ItemData);
forthSkillBook.m_cNumOrDurability = static_cast<unsigned char>(dw4thBookNum);
forthSkillBook.m_ItemPos = Item::ItemPos(TakeType::TS_TEMPINVEN, nCount);
++nCount;
if(tempInven.dwSize + sizeof(Item::ItemData) < TEMPINVEN::MAX_TEMPINVEN_SIZE)
{
Item::CItemFactory::GetInstance().SetItemUID(forthSkillBook.m_dwUID);
memcpy(tempInven.Data + tempInven.dwSize, &forthSkillBook, sizeof(Item::ItemData));
tempInven.dwSize += sizeof(Item::ItemData);
DETLOG2(g_Log, "CID:%10u / 4thBookNum:%10u / 4단계 스킬북 교환권을 임시 인벤에 넣습니다.", dwCID, dw4thBookNum);
}
else
{
ERRLOG2(g_Log, "CID:%10u / Num:%d / Insert 3rdBook to tempinven failed - not enough space",
dwCID, dw3rdBookNum);
}
}
_snprintf(writeDB.GetQueryBuffer(), CDBComponent::MAX_QUERY_LENGTH,
"SELECT TempInven FROM CharDelHistory..DelCharItemEx WHERE UID = %d", dwCID);
tempInven.dwSize += sizeof(unsigned long);
if (!writeDB.ExecuteQuery(writeDB.GetQueryBuffer(), OleDB::Rowset_Update) ||
!writeDB.SetBinaryData(1, (OleDB::LPSET_BINARY)&tempInven))
{
printf("Write temp inventory faild : CID:%10u / %s\n", dwCID, writeDB.GetErrorString());
ERRLOG2(g_Log, "CID:%10u / Write temp inventory failed : %s", dwCID, writeDB.GetErrorString());
return false;
}
cidBookMap.erase(pos);
}
return true;
}
bool ReadSkillData(CDBComponent& readDB, SkillBookMap& cidSkillBookMap, bool bReadCharDelHistory)
{
const int MAX_SKILL_DATA = 1024;
SkillData* lpSkillData = new SkillData[MAX_SKILL_DATA];
if(0 == lpSkillData)
{
printf("ReadSkillData : Memory allocation failed\n");
return false;
}
const char* szQuery = bReadCharDelHistory ?
"select UID, Skill From CharDelHistory..DelCharSkill" :
"select UID, SKill From CharSkill";
if(!readDB.ExecuteQuery(szQuery))
{
printf("ReadSkillData : Query failed : %s : %s\n", szQuery, readDB.GetErrorString());
return false;
}
int nCount = 0;
int nGetRowNum = 0;
memset(lpSkillData, 0, sizeof(SkillData) * MAX_SKILL_DATA);
while(readDB.GetData((void**)lpSkillData, sizeof(SkillData), MAX_SKILL_DATA, &nGetRowNum))
{
if(0 == nGetRowNum)
{
break;
}
SkillData* lpSkillPos = lpSkillData;
SkillData* lpSkillEnd = lpSkillData + nGetRowNum;
for(; lpSkillPos != lpSkillEnd; ++lpSkillPos, ++nCount)
{
unsigned long dwCID = lpSkillPos->m_dwCID;
SKILL& skill = lpSkillPos->m_skill;
SkillBookData bookData;
memset(&bookData, 0, sizeof(SkillBookData));
for(int nSkillCount = 0; nSkillCount < skill.wSlotNum; ++nSkillCount)
{
SKILLSLOT& skillSlot = skill.SSlot[nSkillCount];
if(skillSlot.SKILLINFO.cLockCount < CSkillMgr::MAX_SKILL_LOCKCOUNT &&
skillSlot.SKILLINFO.cSkillLevel <= CSkillMgr::MAX_SKILL_LEVEL &&
0 != CSkillMgr::GetInstance().GetSkillProtoType(skillSlot.SKILLINFO.wSkill))
{
// 스킬의 종류에 관계 없이 지급
for(int nLockCount = 0; nLockCount < skillSlot.SKILLINFO.cLockCount; ++nLockCount)
{
bookData.m_dwSkillBookNum[nLockCount] += CSkillMgr::MAX_SKILL_LEVEL;
}
bookData.m_dwSkillBookNum[skillSlot.SKILLINFO.cLockCount] +=
skillSlot.SKILLINFO.cSkillLevel;
}
else
{
ERRLOG4(g_Log, "CID:%10u / Skill_ID:0x%04X / LockCount:%6d / Level:%6d / 알 수 없는 스킬입니다",
dwCID, skillSlot.SKILLINFO.wSkill, skillSlot.SKILLINFO.cLockCount, skillSlot.SKILLINFO.cSkillLevel);
}
}
cidSkillBookMap.insert(std::make_pair(dwCID, bookData));
if(0 == (nCount % 1000))
{
printf(".");
}
}
memset(lpSkillData, 0, sizeof(SkillData) * MAX_SKILL_DATA);
}
printf("\n");
delete [] lpSkillData;
return true;
}
// 변경된 점을 DB에 기록한다.
void WriteBackCharacterData(CDBComponent& writeDB, CharData& originalData, CharData& newData)
{
unsigned long dwCID = originalData.m_dwCID;
// 인벤토리 기록
if((newData.m_Inventory.dwSize != originalData.m_Inventory.dwSize ||
0 != memcmp(newData.m_Inventory.Data, originalData.m_Inventory.Data, newData.m_Inventory.dwSize)) &&
!DBComponent::GameDB::UpdateInven(writeDB, dwCID, &newData.m_Inventory))
{
ERRLOG1(g_Log, "CID:%10u / 인벤토리 기록에 실패했습니다.", dwCID);
}
// 교환창 기록
if((newData.m_Exchange.dwSize != originalData.m_Exchange.dwSize ||
0 != memcmp(newData.m_Exchange.Data, originalData.m_Exchange.Data, newData.m_Exchange.dwSize)) &&
!DBComponent::GameDB::UpdateExchange(writeDB, dwCID, &newData.m_Exchange))
{
ERRLOG1(g_Log, "CID:%10u / Exchange 기록에 실패했습니다.", dwCID);
}
// Extra 기록
if((newData.m_Extra.dwSize != originalData.m_Extra.dwSize ||
0 != memcmp(newData.m_Extra.Data, originalData.m_Extra.Data, newData.m_Extra.dwSize)) &&
!DBComponent::GameDB::UpdateExtra(writeDB, dwCID, &newData.m_Extra))
{
ERRLOG1(g_Log, "CID:%10u / Extra 기록에 실패했습니다.", dwCID);
}
}
void WriteBackCharDelHistoryData(CDBComponent& writeDB, CharData& originalData, CharData& newData)
{
unsigned long dwCID = originalData.m_dwCID;
// 인벤토리 기록
if((newData.m_Inventory.dwSize != originalData.m_Inventory.dwSize ||
0 != memcmp(newData.m_Inventory.Data, originalData.m_Inventory.Data, newData.m_Inventory.dwSize)) &&
!DBComponent::GameDB::UpdateDelHistoryInven(writeDB, dwCID, &newData.m_Inventory))
{
ERRLOG1(g_Log, "CID:%10u / DelHistory 인벤토리 기록에 실패했습니다.", dwCID);
}
// 교환창 기록
if((newData.m_Exchange.dwSize != originalData.m_Exchange.dwSize ||
0 != memcmp(newData.m_Exchange.Data, originalData.m_Exchange.Data, newData.m_Exchange.dwSize)) &&
!DBComponent::GameDB::UpdateDelHistoryExchange(writeDB, dwCID, &newData.m_Exchange))
{
ERRLOG1(g_Log, "CID:%10u / DelHistory Exchange 기록에 실패했습니다.", dwCID);
}
// Extra 기록
if((newData.m_Extra.dwSize != originalData.m_Extra.dwSize ||
0 != memcmp(newData.m_Extra.Data, originalData.m_Extra.Data, newData.m_Extra.dwSize)) &&
!DBComponent::GameDB::UpdateDelHistoryExtra(writeDB, dwCID, &newData.m_Extra))
{
ERRLOG1(g_Log, "CID:%10u / DelHistory Extra 기록에 실패했습니다.", dwCID);
}
}
void WriteBackStoreData(CDBComponent& writeDB, StoreData& originalData, StoreData& newData)
{
unsigned long dwUID = originalData.m_dwUID;
if((newData.m_store1.dwSize != originalData.m_store1.dwSize ||
0 != memcmp(newData.m_store1.Data, originalData.m_store1.Data, newData.m_store1.dwSize)) &&
!DBComponent::GameDB::UpdateItemStore1(writeDB, dwUID, &newData.m_store1))
{
ERRLOG1(g_Log, "UID:%10u / 창고 1 기록에 실패했습니다.", dwUID);
}
if((newData.m_store2.dwSize != originalData.m_store2.dwSize ||
0 != memcmp(newData.m_store2.Data, originalData.m_store2.Data, newData.m_store2.dwSize)) &&
!DBComponent::GameDB::UpdateItemStore2(writeDB, dwUID, &newData.m_store2))
{
ERRLOG1(g_Log, "UID:%10u / 창고 2 기록에 실패했습니다.", dwUID);
}
}
void WriteSkillClear(CDBComponent& writeDB, bool bDelCharHistory)
{
const int MAX_QUERY = 4;
const char* szQuery[MAX_QUERY] =
{
"Update CharSkill_1 set Skill = NULL",
"Update CharSkill_2 set Skill = NULL",
"Update CharSkill_3 set Skill = NULL",
"Update CharSkill_4 set Skill = NULL"
};
const char* szQuickSlotQuery = "Update CharItem set Quick = NULL";
if(bDelCharHistory)
{
szQuery[0] = "Update CharDelHistory..DelCharSkill_1 set Skill = NULL";
szQuery[1] = "Update CharDelHistory..DelCharSkill_2 set Skill = NULL";
szQuery[2] = "Update CharDelHistory..DelCharSkill_3 set Skill = NULL";
szQuery[3] = "Update CharDelHistory..DelCharSkill_4 set Skill = NULL";
szQuickSlotQuery = "Update CharDelHistory..DelCharItem set Quick = NULL";
}
for(int nCount = 0; nCount < MAX_QUERY; ++nCount)
{
if(!writeDB.ExecuteQuery(szQuery[nCount]))
{
printf("Query failed : %s : %s\n", szQuery[nCount], writeDB.GetErrorString());
ERRLOG2(g_Log, "Query failed : %s : %s\n", szQuery[nCount], writeDB.GetErrorString());
break;
}
}
if(!writeDB.ExecuteQuery(szQuickSlotQuery))
{
printf("Query failed : %s : %s\n", szQuickSlotQuery, writeDB.GetErrorString());
ERRLOG2(g_Log, "Query failed : %s : %s\n", szQuickSlotQuery, writeDB.GetErrorString());
}
}
void AddCharGold(CDBComponent& writeDB, unsigned long dwGold, unsigned long dwCID, bool bCharDelHistory)
{
unsigned long dwOldGold = 0;
unsigned long dwNewGold = 0;
if(bCharDelHistory)
{
unsigned long dwIndex = (dwCID % 4) + 1;
const int MAX_QUERY_LEN = 1024;
char szGetQuery[MAX_QUERY_LEN];
char szUpdateQuery[MAX_QUERY_LEN];
_snprintf(szGetQuery, MAX_QUERY_LEN, "select Gold from CharDelHistory..DelCharInfo_%u where UID = %d",
dwIndex, dwCID);
if(!writeDB.ExecuteQueryGetData(szGetQuery, &dwOldGold))
{
ERRLOG2(g_Log, "CID:%10u / Gold:%10u / CharDelHistory : 돈을 넣어주기 위해 캐릭터 데이터 읽어오기 실패", dwCID, dwGold);
}
else
{
if(dwOldGold < ULONG_MAX - dwGold)
{
dwNewGold = dwOldGold + dwGold;
}
else
{
dwNewGold = ULONG_MAX;
}
_snprintf(szUpdateQuery, MAX_QUERY_LEN, "UPDATE CharDelHistory..DelCharInfo_%u SET Gold = %d where UID = %d",
dwIndex, dwNewGold, dwCID);
if(!writeDB.ExecuteQuery(szUpdateQuery))
{
dwNewGold = 0;
ERRLOG2(g_Log, "CID:%10u / Gold:%10u / 돈을 넣어주기 위해 캐릭터 데이터 저장하기 실패", dwCID, dwGold);
}
}
}
else
{
const int MAX_EQUIP_VIEW = 15;
CHAR_INFOST charInfoST;
unsigned short usEquipView[MAX_EQUIP_VIEW];
memset(&charInfoST, 0, sizeof(CHAR_INFOST));
memset(usEquipView, 0, sizeof(unsigned short) * MAX_EQUIP_VIEW);
if(!DBComponent::GameDB::GetCharInfo(writeDB, dwCID,
&charInfoST, usEquipView, MAX_EQUIP_VIEW))
{
ERRLOG2(g_Log, "CID:%10u / Gold:%10u / 돈을 넣어주기 위해 캐릭터 데이터 읽어오기 실패", dwCID, dwGold);
}
else
{
dwOldGold = charInfoST.Gold;
if(charInfoST.Gold < ULONG_MAX - dwGold)
{
charInfoST.Gold += dwGold;
}
else
{
charInfoST.Gold = ULONG_MAX;
}
if(!DBComponent::GameDB::UpdateCharInfo(writeDB, dwCID,
&charInfoST, usEquipView, MAX_EQUIP_VIEW))
{
ERRLOG2(g_Log, "CID:%10u / Gold:%10u / 돈을 넣어주기 위해 캐릭터 데이터 저장하기 실패", dwCID, dwGold);
}
else
{
dwNewGold = charInfoST.Gold;
}
}
}
if(0 != dwNewGold && 0 != dwGold)
{
DETLOG4(g_GoldLog, "CID:%10u / OldGold:%10u / NewGold:%10u / GetGold:%10u / 캐릭터에 돈을 지급했습니다.",
dwCID, dwOldGold, dwNewGold, dwGold);
}
}
void AddStoreGold(CDBComponent& writeDB, unsigned long dwGold, unsigned long dwUID)
{
STORE_INFO storeInfo;
memset(&storeInfo, 0, sizeof(STORE_INFO));
unsigned long dwOldGold = 0;
unsigned long dwNewGold = 0;
if(!DBComponent::GameDB::GetItemStoreInfo(writeDB, dwUID, &storeInfo))
{
ERRLOG2(g_Log, "UID:%10u / Gold:%10u / 돈 더하기 실패 : 창고 정보 읽기 실패", dwUID, dwGold);
}
else
{
dwOldGold = storeInfo.Gold;
if(storeInfo.Gold < ULONG_MAX - dwGold)
{
storeInfo.Gold += dwGold;
}
else
{
storeInfo.Gold = ULONG_MAX;
}
if(!DBComponent::GameDB::SetItemStoreInfo(writeDB, dwUID, &storeInfo))
{
ERRLOG2(g_Log, "UID:%10u / Gold:%10u / 돈 더히기 실패 : 창고 정보 저장 실패", dwUID, dwGold);
}
else
{
dwNewGold = storeInfo.Gold;
}
}
if(0 != dwNewGold && 0 != dwGold)
{
DETLOG4(g_GoldLog, "UID:%10u / OldGold:%10u / NewGold:%10u / GetGold:%10u / 창고에 돈을 지급했습니다.",
dwUID, dwOldGold, dwNewGold, dwGold);
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateInven [ public ]
// - 인벤 업데이트
//
// Parameter :
// 1st : 캐릭터 아이디[In]
// 2st : 인벤 데이터[Out]
//
// Return :
// 생성 성공 시 true, 실패시 false
//
///////////////////////////////////////////////////////////////////////////////////////////////
bool DBComponent::GameDB::UpdateDelHistoryInven(CDBComponent& DBComponent, unsigned long CharID_In, LPINVEN lpInven_In)
{
_snprintf(DBComponent.GetQueryBuffer(), CDBComponent::MAX_QUERY_LENGTH,
"SELECT Inventory FROM CharDelHistory..DelCharItem WHERE UID = %d", CharID_In );
lpInven_In->dwSize += sizeof(unsigned long);
if (DBComponent.ExecuteQuery(DBComponent.GetQueryBuffer(), OleDB::Rowset_Update)) {
if (DBComponent.SetBinaryData(1, (OleDB::LPSET_BINARY)lpInven_In)) {
lpInven_In->dwSize -= sizeof(unsigned long);
return true;
}
}
SERLOG3(g_Log, "CID:%10u %s %s", CharID_In, DBComponent.GetErrorString(), DBComponent.GetQueryBuffer());
lpInven_In->dwSize -= sizeof(unsigned long);
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateExtra [ public ]
// - 인벤 퀵 슬롯
//
// Parameter :
// 1st : 캐릭터 아이디[In]
// 2st : 퀵[Out]
//
// Return :
// 생성 성공 시 true, 실패시 false
//
///////////////////////////////////////////////////////////////////////////////////////////////
bool DBComponent::GameDB::UpdateDelHistoryExtra(CDBComponent& DBComponent, unsigned long CharID_In, LPEXTRA lpExtra_In)
{
_snprintf(DBComponent.GetQueryBuffer(), CDBComponent::MAX_QUERY_LENGTH,
"SELECT Extra FROM CharDelHistory..DelCharItem WHERE UID = %d", CharID_In );
lpExtra_In->dwSize += sizeof(unsigned long);
if (DBComponent.ExecuteQuery(DBComponent.GetQueryBuffer(), OleDB::Rowset_Update)) {
if (DBComponent.SetBinaryData(1, (OleDB::LPSET_BINARY)lpExtra_In)) {
lpExtra_In->dwSize -= sizeof(unsigned long);
return true;
}
}
ERRLOG3(g_Log, "CID:%10u %s %s", CharID_In, DBComponent.GetErrorString(), DBComponent.GetQueryBuffer());
lpExtra_In->dwSize -= sizeof(unsigned long);
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////
//
// UpdateExchange [ public ]
// - 교환 업데이트
//
// Parameter :
// 1st : 캐릭터 아이디[In]
// 2st : 교환[In]
//
// Return :
// 생성 성공 시 true, 실패시 false
//
///////////////////////////////////////////////////////////////////////////////////////////////
bool DBComponent::GameDB::UpdateDelHistoryExchange(CDBComponent& DBComponent, unsigned long CharID_In, LPEXCHANGE lpExchange_In)
{
_snprintf(DBComponent.GetQueryBuffer(), CDBComponent::MAX_QUERY_LENGTH,
"SELECT Exchange FROM CharDelHistory..DelCharItemEx WHERE UID = %d", CharID_In );
lpExchange_In->dwSize += sizeof(unsigned long);
if (DBComponent.ExecuteQuery(DBComponent.GetQueryBuffer(), OleDB::Rowset_Update)) {
if (DBComponent.SetBinaryData(1, (OleDB::LPSET_BINARY)lpExchange_In)) {
lpExchange_In->dwSize -= sizeof(unsigned long);
return true;
}
}
ERRLOG3(g_Log, "CID:%10u %s %s", CharID_In, DBComponent.GetErrorString(), DBComponent.GetQueryBuffer());
lpExchange_In->dwSize -= sizeof(unsigned long);
return false;
}