Files
Client/Server/DBProcess/RebalanceOverItem/RebalanceOverItem.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

1678 lines
53 KiB
C++

// RebalanceOverItem.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include "stdafx.h"
#include "RebalanceOverItem.h"
#include "RebalanceQuery.h"
#define LOG_CONVERT0(str) { SERLOG0(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)); }
#define LOG_CONVERT3(str, arg1, arg2, arg3) { ERRLOG3(g_Log, (str), (arg1), (arg2), (arg3)); printf(str "\n", (arg1), (arg2), (arg3))); }
#define LOG_CONVERT4(str, arg1, arg2, arg3, arg4) { ERRLOG4(g_Log, (str), (arg1), (arg2), (arg3), (arg4)); printf(str "\n", (arg1), (arg2), (arg3), (arg4)); }
// 보상 관련 계산 수식
#define CALC_REWARDSTONE(value) ((value) * 10)
#define CALC_REWARDGOLD(value, arg1) ((value) / 8.0f * (arg1))
//CServerLog g_ItemLog("Remain-CSV_");
//CServerLog g_CalcLog("Reward-Calc_");
//CServerLog g_RewardLog("Reward-Result_");
//CServerLog g_Rebalance("Rebalance");
//CServerLog g_UIDCID("UIDCID");
CServerLog g_ItemList("OverItemList");
using namespace Item;
class CDBRebalanceOverItem :
public IDBCharInfoProcess,
public IDBCharItemProcess,
public IDBCharItemExProcess,
public IDBStoreProcess
{
public:
CDBRebalanceOverItem(ATL::CSession& session, Item::CItemMgr& ItemMgr, CDBItemSerialMgr& dbItemSerialMgr)
: m_Session(session), m_ItemMgr(ItemMgr), m_DBItemSerialMgr(dbItemSerialMgr), m_nOverItem(0) { }
~CDBRebalanceOverItem() { }
void SetUnified(const char* szFlag) { m_bUnified = (atoi(szFlag) != 0); }
bool GetUnified() { return m_bUnified; }
void SetSimulate(const char* szFlag) { m_bSimulated = (atoi(szFlag) != 0); }
bool GetSimulate() { return m_bSimulated; }
HRESULT SetTarget();
void StampRemainLog();
void PrintItemOptionList();
enum ProcessResult
{
FAILED = 0,
SUCCESS = 1,
SKIPPED = 2
};
private:
enum RewardItem
{
RHATARIUM = 2005,
RHATARIUM_COUPON = 10591,
GOLD_COUPON = 10592
};
enum Ratio
{
COUPONTORHATARIUM = 10,
COUPONTOGOLD = 100000000
};
enum MaxLimit
{
MAX_NAME = 1024,
MAX_ITEMSTACK = 200
};
typedef struct _CharInfo
{
unsigned long dwUID;
char szName[MAX_NAME];
} sCharInfo, *lpCharInfo;
typedef std::map<unsigned long, unsigned long> StoneRewardMap;
typedef std::map<unsigned long, unsigned __int64> GoldRewardMap;
typedef std::map<unsigned long, sCharInfo> CIDUIDMAP;
ATL::CSession& m_Session;
StoneRewardMap m_StoneMap;
GoldRewardMap m_GoldMap;
CIDUIDMAP m_CIDUIDMap;
Item::CItemMgr& m_ItemMgr;
CDBItemSerialMgr& m_DBItemSerialMgr;
bool m_bUnified;
bool m_bSimulated;
unsigned int m_nOverItem;
private:
virtual ConvertResult operator() (RylDBCommand::CCharData& charData_inOut);
virtual ConvertResult operator() (RylDBCommand::CCharItem& charItem_InOut);
virtual ConvertResult operator() (RylDBCommand::CCharItemEx& charItemEx_InOut);
virtual ConvertResult operator() (RylDBCommand::CUnifiedStore1& unifiedStore1_InOut);
virtual ConvertResult operator() (RylDBCommand::CUnifiedStore2& unifiedStore2_InOut);
ProcessResult SetTargetAndCalcReward(unsigned long dwUID, unsigned long dwCID,
const char* szOriginalData, unsigned long dwOriginalSize);
void ReserveItemPos(RebalanceLib::CItemChecker& itemChecker, const char* szOriginalData, unsigned long dwOriginalSize);
bool RewardStone(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut);
bool RewardGold(unsigned long dwKey, const char* szPosition, unsigned long& dwGold_InOut);
bool RewardGoldCoupon(unsigned long dwKey, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut);
bool RewardGoldAndCoupon(unsigned long dwKey, unsigned long& dwGold_InOut, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut);
void PrintItemOption(Item::CEquipment* lpEquipment, short* lpAttribute, unsigned long dwKey);
bool TransferReward();
void CalcReward(const Item::CItemType::ArrayType eEquipType, Item::CEquipment* lpEquipment, short* lpAttrFactor, short* lpAttrValue,
unsigned long& dwStone, unsigned __int64& dwGold, unsigned long dwKey);
void AddReward(unsigned long dwUIDCID, unsigned long dwStone, unsigned __int64 dwGold);
float CalcAttribute(Item::CEquipment* lpEquipment, Item::Attribute::Type eAttributeType, unsigned long dwKey, short attrFactor, short attrValue);
void GetAttrString(Item::Attribute::Type eAttributeType, char* lpString);
bool IsExistCID(const unsigned long dwCID);
bool IsExistUID(const unsigned long dwUID);
unsigned long GetUIDByCID(const unsigned long dwCID);
bool GetCharNameByCID(const unsigned long dwCID, char* szCharName);
};
void PrintUsage()
{
printf("usage : RebalanceOverItem.exe DBAddress DBName DBAccount DBPassword ServerGroupNum(0~9) FlagUnified(0/1) FlagSimulate(0/1)\n");
}
int _tmain(int argc, _TCHAR* argv[])
{
bool bError = FALSE;
if(8 != argc)
{
PrintUsage();
return -1;
}
if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./ItemScript.txt"))
{
LOG_CONVERT0("ItemScript.txt load failed\n");
return -1;
}
CoInitialize(0);
g_SessionLog.Disable(0xFFFFFFFF);
HRESULT hr = S_OK;
ATL::CDataSource ds;
ATL::CSession session;
CDBItemSerialMgr dbItemSerialMgr;
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::AuthServer;
serverID.sID.Group = static_cast<char>(atoi(argv[5]));
serverID.sID.Channel = 0;
serverID.sID.ID = 0;
// 데이터베이스 오픈
if(FAILED(hr = CRylDBProcess::ConnectDB(ds, argv[1], argv[2], argv[3], argv[4])))
{
LOG_CONVERT1("Connect DB failed : hr:0x%08X", hr);
}
else if(FAILED(hr = session.Open(ds)))
{
LOG_CONVERT1("Open session failed : hr:0x%08X", hr);
}
else if(FAILED(hr = dbItemSerialMgr.ClearAllSerialDB(session)))
{
LOG_CONVERT1("Clear itemSerial failed : hr:0x%08X", hr);
}
else if(FAILED(hr = dbItemSerialMgr.LoadItemSerialDB(session, serverID.dwID)))
{
LOG_CONVERT1("Insert itemSerial failed : hr:0x%08X", hr);
}
else if (FAILED(hr = session.StartTransaction()))
{
LOG_CONVERT1("Start transaction failed : hr:0x%08x", hr);
}
else
{
try
{
CRylDBProcess dbProcess(session);
CConsoleCounter consoleCounter(100);
CDBRebalanceOverItem processItem(session, Item::CItemMgr::GetInstance(), dbItemSerialMgr);
processItem.SetUnified(argv[6]);
processItem.SetSimulate(argv[7]);
processItem.SetTarget();
processItem.PrintItemOptionList();
LOG_CONVERT0("Start Reward");
const int MAX_QUERY_BUFFER = 1024;
char szQueryBuffer[MAX_QUERY_BUFFER];
int nServerType;
if(processItem.GetUnified())
{
nServerType = 23;
}
else
{
nServerType = 22;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER, QUERYZ::Char,
"CharItemEx",
"Char1 as CID", nServerType,
"Char2 as CID", nServerType,
"Char3 as CID", nServerType,
"Char4 as CID", nServerType,
"Char5 as CID", nServerType,
"A.CID = B.CID"
);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = '\0';
SERLOG0(g_Log, "StartCharItemEx");
if (FAILED(hr = dbProcess.CharItemEx(processItem, consoleCounter, szQueryBuffer)))
{
LOG_CONVERT1("CharItemEx process failed : hr:0x%08x", hr);
bError = TRUE;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER, QUERYZ::Char,
"CharItem",
"Char1 as CID", nServerType,
"Char2 as CID", nServerType,
"Char3 as CID", nServerType,
"Char4 as CID", nServerType,
"Char5 as CID", nServerType,
"A.CID = B.CID"
);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = '\0';
SERLOG0(g_Log, "StartCharItem");
if (FAILED(hr = dbProcess.CharItem(processItem, consoleCounter, szQueryBuffer)))
{
LOG_CONVERT1("Add Reward(Inven Stone/Gold) process failed : hr:0x%08x", hr);
bError = TRUE;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER, QUERYZ::Char,
"CharInfo",
"Char1 as CID", nServerType,
"Char2 as CID", nServerType,
"Char3 as CID", nServerType,
"Char4 as CID", nServerType,
"Char5 as CID", nServerType,
"A.CID = B.CID"
);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = '\0';
SERLOG0(g_Log, "StartCharInfo");
if (FAILED(hr = dbProcess.CharInfo(processItem, consoleCounter, szQueryBuffer)))
{
LOG_CONVERT1("Add Reward(CharacterInfo Gold) process failed : hr:0x%08x", hr);
bError = TRUE;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER, QUERYZ::Store,
"TblUnifiedItemStore2",
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"A.UID = B.UID"
);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = '\0';
SERLOG0(g_Log, "StartStore2");
if (FAILED(hr = dbProcess.UnifiedStore2(processItem, consoleCounter, szQueryBuffer)))
{
LOG_CONVERT1("Add Reward(UnfiedStore1 Stone) process failed : hr:0x%08x", hr);
bError = TRUE;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER, QUERYZ::Store,
"TblUnifiedItemStore1",
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"UID", nServerType,
"A.UID = B.UID"
);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = '\0';
SERLOG0(g_Log, "StartStore1");
if (FAILED(hr = dbProcess.UnifiedStore1(processItem, consoleCounter, szQueryBuffer)))
{
LOG_CONVERT1("Add Reward(UnfiedStore1 Stone/Gold) process failed : hr:0x%08x", hr);
bError = TRUE;
}
// 보상되지 않은 내역 로그 추출
processItem.StampRemainLog();
}
catch(...)
{
bError = TRUE;
LOG_CONVERT0("Exception occured! rollback transaction now!");
if(FAILED(hr = session.Abort()))
{
LOG_CONVERT1("Rollback transaction failed! : hr:0x%08x", hr);
}
else
{
SERLOG1(g_Log, "Rollback transaction succeeded! : hr:0x%08x", hr);
}
}
SERLOG0(g_Log, "Commit transaction now!");
if(FAILED(hr = session.Commit()))
{
LOG_CONVERT1("Commit transaction failed! : hr:0x%08x", hr);
}
else
{
SERLOG1(g_Log, "Commit transaction succeeded! : hr:0x%08x", hr);
}
}
session.Close();
ds.Close();
CoUninitialize();
if(true == bError)
{
LOG_CONVERT0("Rebalance incomplete!!");
return -1;
}
else
{
LOG_CONVERT0("Rebalance Complete");
return 0;
}
}
void CDBRebalanceOverItem::StampRemainLog()
{
unsigned long dwUIDCID = 0, dwStone = 0;
unsigned __int64 dwGold = 0;
unsigned int nCntStone = 0, nCntGold = 0;
size_t nMapStone = m_StoneMap.size(), nMapGold = m_GoldMap.size();
StoneRewardMap::iterator stone_pos = m_StoneMap.begin();
StoneRewardMap::iterator stone_end = m_StoneMap.end();
//SERLOG0(g_ItemLog, "보상되지 않은 값들입니다. CSV 형태로 찍히니 엑셀로 보는게 편할듯.");
//SERLOG2(g_ItemLog, "%-20s: %u개 발견.", "오버 아이템", m_nOverItem);
//SERLOG3(g_ItemLog, "%-20s: 제련석 %u건, 골드 %u건", "잔여 보상 데이터", nMapStone, nMapGold);
//ERRLOG0(g_ItemLog, "\tdwKey\tStone\tGold\t\t\t\t");
for(; stone_pos != stone_end; ++stone_pos)
{
dwUIDCID = stone_pos->first;
dwStone = stone_pos->second;
dwGold = 0;
++nCntStone;
GoldRewardMap::iterator itr = m_GoldMap.find(dwUIDCID);
if (m_GoldMap.end() != itr)
{
dwGold = itr->second;
++nCntGold;
m_GoldMap.erase(itr);
}
//ERRLOG3(g_ItemLog, "\t%u\t%u\t%u\t\t\t\t", dwUIDCID, dwStone, dwGold);
}
GoldRewardMap::iterator gold_pos = m_GoldMap.begin();
GoldRewardMap::iterator gold_end = m_GoldMap.end();
for(; gold_pos != gold_end; ++gold_pos)
{
dwUIDCID = gold_pos->first;
dwStone = 0;
dwGold = gold_pos->second;
++nCntGold;
/*ERRLOG3(g_ItemLog, "\t%u\t%u\t%u\t\t\t\t", dwUIDCID, dwStone, dwGold);*/
}
/*SERLOG4(g_ItemLog, "Checksum. nCntStone(%u)/nMapStone(%u) nCntGold(%u)/nMapGold(%u)", nCntStone, nMapStone, nCntGold, nMapGold);*/
}
ConvertResult CDBRebalanceOverItem::operator() (RylDBCommand::CCharItem& charItem_InOut)
{
unsigned long dwCID = charItem_InOut.GetCID();
ProcessResult nResult[3] = { FAILED };
const EQUIP& equip_In = charItem_InOut.GetEquip();
const INVEN& inven_In = charItem_InOut.GetInven();
const EXTRA& extra_In = charItem_InOut.GetExtra();
if(FAILED == (nResult[0] = SetTargetAndCalcReward(0, dwCID,
equip_In.Data, equip_In.dwSize)))
{
LOG_CONVERT1("CID:%10u / Equip convert failed", dwCID);
return CONVERT_FAILED;
}
else if(FAILED == (nResult[1] = SetTargetAndCalcReward(0, dwCID,
extra_In.Data, extra_In.dwSize)))
{
LOG_CONVERT1("CID:%10u / Extra convert failed", dwCID);
return CONVERT_FAILED;
}
else if(FAILED == (nResult[2] = SetTargetAndCalcReward(0, dwCID,
inven_In.Data, inven_In.dwSize)))
{
LOG_CONVERT1("CID:%10u / Inventory convert failed", dwCID);
return CONVERT_FAILED;
}
//EQUIP equip_Out;
//INVEN inven_Out;
//EXTRA extra_Out;
//memset(&equip_Out, 0, sizeof(EQUIP));
//memset(&inven_Out, 0, sizeof(INVEN));
//memset(&extra_Out, 0, sizeof(EXTRA));
//equip_Out.dwSize = EQUIP::MAX_EQUIP_SIZE;
//inven_Out.dwSize = INVEN::MAX_INVEN_SIZE;
//extra_Out.dwSize = EXTRA::MAX_EXTRA_SIZE;
//memcpy(&equip_Out, &equip_In, sizeof(EQUIP));
//memcpy(&inven_Out, &inven_In, sizeof(INVEN));
//memcpy(&extra_Out, &extra_In, sizeof(EXTRA));
//RebalanceLib::CItemArrayChecker<
// ContainerConstant::INVENTORY_WIDTH,
// ContainerConstant::INVENTORY_HEIGHT,
// ContainerConstant::MAX_INVENTORY_TAB> invenChecker(TakeType::TS_INVEN);
//invenChecker.FillTab(3);
//ReserveItemPos(invenChecker, inven_In.Data, inven_In.dwSize);
//if(!RewardGoldCoupon(dwCID, invenChecker, "[INVEN]", inven_Out.Data, INVEN::MAX_INVEN_SIZE, inven_Out.dwSize) && 0 != inven_Out.dwSize)
//{
// LOG_CONVERT1("CID:%10u / Gold reward failed", dwCID);
// return CONVERT_FAILED;
//}
//else if(!RewardStone(0, dwCID, invenChecker, "[INVEN]", inven_Out.Data, INVEN::MAX_INVEN_SIZE, inven_Out.dwSize) && 0 != inven_Out.dwSize)
//{
// LOG_CONVERT1("CID:%10u / Stone reward failed", dwCID);
// return CONVERT_FAILED;
//}
/*if(false == GetSimulate())
{
charItem_InOut.SetInven(inven_Out);
return CONVERT_SUCCEEDED;
}
else
{
return CONVERT_DO_NOT_WRITE;
}*/
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CDBRebalanceOverItem::operator() (RylDBCommand::CCharData& charData_InOut)
{
//unsigned long dwCID = charData_InOut.GetCID();
//unsigned long dwGold = charData_InOut.GetGold();
//SERLOG1(g_Log, "CharInfo Start : %u", dwCID);
//// 보상 전용 프로세스이므로 보상 처리 상황이 아니면 실행해서는 안된다.
//if(!RewardGold(dwCID, "[CHARINFO]", dwGold))
//{
// LOG_CONVERT1("CID:%10u / Gold reward failed", dwCID);
// return CONVERT_FAILED;
//}
//else
//{
// if(false == GetSimulate())
// {
// charData_InOut.SetGold(dwGold);
// return CONVERT_SUCCEEDED;
// }
// else
// {
// return CONVERT_DO_NOT_WRITE;
// }
//}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CDBRebalanceOverItem::operator() (RylDBCommand::CCharItemEx& charItemEx_InOut)
{
unsigned long dwCID = charItemEx_InOut.GetCID();
ProcessResult nResult[2] = { FAILED };
const EXCHANGE& exchange_In = charItemEx_InOut.GetExchange();
const TEMPINVEN& tempInven_In = charItemEx_InOut.GetTempInven();
if(FAILED == (nResult[0] = SetTargetAndCalcReward(0, dwCID,
exchange_In.Data, exchange_In.dwSize)))
{
LOG_CONVERT1("CID:%10u / Exchange convert failed", dwCID);
return CONVERT_FAILED;
}
else if(FAILED == (nResult[1] = SetTargetAndCalcReward(0, dwCID,
tempInven_In.Data, tempInven_In.dwSize)))
{
LOG_CONVERT1("CID:%10u / TempInven convert failed", dwCID);
return CONVERT_FAILED;
}
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CDBRebalanceOverItem::operator() (RylDBCommand::CUnifiedStore1& unifiedStore1_InOut)
{
unsigned long dwUID = unifiedStore1_InOut.GetUID();
ProcessResult nResult = FAILED;
if(GetUnified() && 23 != unifiedStore1_InOut.GetOldServerGroupID())
{
return CONVERT_DO_NOT_WRITE;
}
const STORE& store_In = unifiedStore1_InOut.GetStore();
if(FAILED == (nResult = SetTargetAndCalcReward(dwUID, 0,
store_In.Data, store_In.dwSize)))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / Store convert failed",
dwUID, unifiedStore1_InOut.GetOldServerGroupID());
return CONVERT_FAILED;
}
/*STORE store_Out;
memset(&store_Out, 0, sizeof(STORE));
store_Out.dwSize = STORE::MAX_STORE_SIZE;
memcpy(&store_Out, &store_In, sizeof(STORE));
unsigned long dwGold = unifiedStore1_InOut.GetGold();
RebalanceLib::CItemArrayChecker<
ContainerConstant::DEPOSIT_WIDTH,
ContainerConstant::DEPOSIT_HEIGHT,
ContainerConstant::MAX_DEPOSIT_TAB> storeChecker(TakeType::TS_DEPOSIT);
storeChecker.FillTab(2);
storeChecker.FillTab(3);
ReserveItemPos(storeChecker, store_In.Data, store_In.dwSize);
if(!RewardGoldAndCoupon(dwUID, dwGold, storeChecker, "[UNIFIED_STORE1]", store_Out.Data, STORE::MAX_STORE_SIZE, store_Out.dwSize))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / Gold reward failed",
dwUID, unifiedStore1_InOut.GetOldServerGroupID());
}
else if(!RewardStone(dwUID, 0, storeChecker, "[UNIFIED_STORE1]", store_Out.Data, STORE::MAX_STORE_SIZE, store_Out.dwSize))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / Stone reward failed",
dwUID, unifiedStore1_InOut.GetOldServerGroupID());
}*/
/*if(false == GetSimulate())
{
unifiedStore1_InOut.SetGold(dwGold);
unifiedStore1_InOut.SetStore(store_Out);
return CONVERT_SUCCEEDED;
}
else
{
return CONVERT_DO_NOT_WRITE;
}*/
return CONVERT_DO_NOT_WRITE;
}
ConvertResult CDBRebalanceOverItem::operator() (RylDBCommand::CUnifiedStore2& unifiedStore2_InOut)
{
TransferReward();
unsigned long dwUID = unifiedStore2_InOut.GetUID();
ProcessResult nResult = FAILED;
if(GetUnified() && 23 != unifiedStore2_InOut.GetOldServerGroupID())
{
return CONVERT_DO_NOT_WRITE;
}
const STORE& store_In = unifiedStore2_InOut.GetStore();
if(FAILED == (nResult = SetTargetAndCalcReward(dwUID, 0,
store_In.Data, store_In.dwSize)))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / Store convert failed",
dwUID, unifiedStore2_InOut.GetOldServerGroupID());
return CONVERT_FAILED;
}
/*STORE store_Out;
memset(&store_Out, 0, sizeof(STORE));
store_Out.dwSize = STORE::MAX_STORE_SIZE;
memcpy(&store_Out, &store_In, sizeof(STORE));
RebalanceLib::CItemArrayChecker<
ContainerConstant::DEPOSIT_WIDTH,
ContainerConstant::DEPOSIT_HEIGHT,
ContainerConstant::MAX_DEPOSIT_TAB> storeChecker(TakeType::TS_DEPOSIT);
storeChecker.FillTab(0);
storeChecker.FillTab(1);
ReserveItemPos(storeChecker, store_In.Data, store_In.dwSize);
if(!RewardGoldCoupon(dwUID, storeChecker, "[UNIFIED_STORE2]", store_Out.Data, STORE::MAX_STORE_SIZE, store_Out.dwSize))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / GoldCoupon reward failed",
dwUID, unifiedStore2_InOut.GetOldServerGroupID());
}
else if(!RewardStone(dwUID, 0, storeChecker, "[UNIFIED_STORE2]", store_Out.Data, STORE::MAX_STORE_SIZE, store_Out.dwSize))
{
LOG_CONVERT2("UID:%10u / OldServerGroupID:%d / Stone reward failed",
dwUID, unifiedStore2_InOut.GetOldServerGroupID());
}*/
//if(false == GetSimulate())
//{
// unifiedStore2_InOut.SetStore(store_Out);
// return CONVERT_SUCCEEDED;
//}
//else
//{
// return CONVERT_DO_NOT_WRITE;
//}
return CONVERT_DO_NOT_WRITE;
}
CDBRebalanceOverItem::ProcessResult CDBRebalanceOverItem::SetTargetAndCalcReward(unsigned long dwUID, unsigned long dwCID,
const char* szOriginalData, unsigned long dwOriginalSize)
{
const char* szPos = szOriginalData;
const char* szEnd = szOriginalData + dwOriginalSize;
bool bConvert = FALSE;
char szString[20] = {0};
Item::CEquipment* lpEquipment = NULL;
Item::Grade::GradeInfo convertedGrade;
if(0 != dwUID || 0 != dwCID)
{
unsigned long dwKey = (0 !=dwUID) ? dwUID : dwCID;
/*SERLOG1(g_UIDCID, "dwKey : %10u", dwKey);*/
for(; szPos < szEnd;)
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szPos);
const Item::ItemInfo* lpItemInfo = m_ItemMgr.GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 == lpItemInfo)
{
LOG_CONVERT4("UID:%10u / CID:%10u / Serial:0x%016I64X / ProtoType:%6d / Script has not this item",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
return SKIPPED;
}
else if(0 != (lpItemInfo->m_DetailData.m_dwFlags & Item::DetailData::EQUIP) &&
sizeof(Item::ItemData) + sizeof(Item::EquipmentInfo) <= lpItemData->m_cItemSize)
{
// 장비인 경우 아이템 컨버팅을 한다.
// 아래에 해당하는 아이템은 컨버트 하지 않는다.
switch(lpItemInfo->m_DetailData.m_cItemType)
{
case Item::ItemType::SHIRT:
case Item::ItemType::TUNIC:
case Item::ItemType::CON_HELM:
case Item::ItemType::CON_GLOVE:
case Item::ItemType::CON_BOOTS:
case Item::ItemType::DEX_HELM:
case Item::ItemType::DEX_GLOVE:
case Item::ItemType::DEX_BOOTS:
case Item::ItemType::CON_HEAD:
case Item::ItemType::CON_PELVIS:
case Item::ItemType::CON_PROTECT_A:
case Item::ItemType::DEX_HEAD:
case Item::ItemType::DEX_PELVIS:
case Item::ItemType::DEX_PROTECT_A:
case Item::ItemType::NECKLACE:
case Item::ItemType::RING:
case Item::ItemType::RUNE:
bConvert = FALSE;
break;
default:
bConvert = TRUE;
break;
}
lpEquipment = static_cast<Item::CEquipment*>(Item::CItemFactory::GetInstance().CreateTempItem(*lpItemInfo));
if(NULL == lpEquipment)
{
LOG_CONVERT4("UID:%10u / CID:%10u / Serial:0x%016I64X / ProtoType:%6d / Class allocation failed",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
return FAILED;
}
else
{
short AttrFactor[ Item::Attribute::MAX_ATTRIBUTE_NUM ] = {0};
short AttrValue[ Item::Attribute::MAX_ATTRIBUTE_NUM ] = {0};
const Item::CItemType::ArrayType eEquipType =
Item::CItemType::GetEquipType(lpItemInfo->m_DetailData.m_dwFlags);
lpEquipment->GetLimitValue(AttrValue);
lpEquipment->SetUID(lpItemData->m_dwUID);
size_t DataSize_InOut = 0;
DataSize_InOut = sizeof(Item::ItemData);
if(false == lpEquipment->SerializeIn(reinterpret_cast<const char*>(lpItemData), DataSize_InOut))
{
LOG_CONVERT4("UID:%10u / CID:%10u / Serial:0x%016I64X / ProtoType:%6d / Serializein failed",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
return FAILED;
}
else
{
Item::Grade::GradeInfo itemGrade = lpEquipment->GetItemGrade();
if(Item::EquipType::S_GRADE == itemGrade.m_eItemGrade && true == bConvert)
{
++m_nOverItem;
lpEquipment->GetSubRuneAttribute(AttrFactor);
// 아이템 옵션 로그 출력
PrintItemOption(lpEquipment, AttrFactor, dwKey);
//// 보상 값 계산
//unsigned long dwStone = 0;
//unsigned __int64 dwGold = 0;
//CalcReward(eEquipType, lpEquipment, AttrFactor, AttrValue, dwStone, dwGold, dwKey);
// 보상 내용 저장
/*AddReward(dwKey, dwStone, dwGold);*/
}
}
}
if(NULL != lpEquipment)
{
Item::CItemFactory::GetInstance().DeleteItem(lpEquipment);
lpEquipment = NULL;
}
}
szPos += lpItemData->m_cItemSize;
}
}
return SUCCESS;
}
void CDBRebalanceOverItem::ReserveItemPos(RebalanceLib::CItemChecker& itemChecker, const char* szOriginalData, unsigned long dwOriginalSize)
{
const char* szPos = szOriginalData;
const char* szEnd = szOriginalData + dwOriginalSize;
for(; szPos < szEnd;)
{
const Item::ItemData* lpItemData = reinterpret_cast<const Item::ItemData*>(szPos);
const Item::ItemInfo* lpItemInfo = m_ItemMgr.GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 == lpItemInfo)
{
ERRLOG2(g_Log, "Serial:0x%016I64X / ProtoType:%6d / Script has not this item",
lpItemData->m_dwUID, lpItemData->m_usProtoTypeID);
}
else
{
itemChecker.Set(lpItemData->m_ItemPos,
lpItemInfo->m_DetailData.m_cXSize, lpItemInfo->m_DetailData.m_cYSize);
}
szPos += lpItemData->m_cItemSize;
}
}
bool CDBRebalanceOverItem::TransferReward()
{
unsigned long dwCID, dwUID;
StoneRewardMap::iterator stone_itr_UID;
GoldRewardMap::iterator gold_itr_UID;
StoneRewardMap::iterator stone_itr_Temp;
GoldRewardMap::iterator gold_itr_Temp;
for (StoneRewardMap::iterator itr = m_StoneMap.begin(); itr != m_StoneMap.end(); ++itr)
{
if (IsExistCID(itr->first))
{
dwCID = itr->first;
dwUID = GetUIDByCID(dwCID);
if (0 != dwUID)
{
stone_itr_UID = m_StoneMap.find(dwUID);
if(m_StoneMap.end() == stone_itr_UID)
{
m_StoneMap.insert(std::make_pair(dwUID, itr->second));
}
else
{
stone_itr_UID->second += itr->second;
}
itr->second = 0;
stone_itr_Temp = itr;
itr++;
m_StoneMap.erase(stone_itr_Temp);
}
else
{
/*ERRLOG4(g_RewardLog, "StoneTransfer Fail CID : %10u, itr_CID : 0x%10x / UID : %10u, itr_UID : 0x%10x",
dwCID, itr, dwUID, stone_itr_UID);*/
return false;
}
}
}
for (GoldRewardMap::iterator itr = m_GoldMap.begin(); itr != m_GoldMap.end(); ++itr)
{
if (IsExistCID(itr->first))
{
dwCID = itr->first;
dwUID = GetUIDByCID(dwCID);
if (0 != dwUID)
{
gold_itr_UID = m_GoldMap.find(dwUID);
if(m_GoldMap.end() == gold_itr_UID)
{
if(_UI64_MAX >= itr->second)
{
m_GoldMap.insert(std::make_pair(dwUID, itr->second));
}
else
{
m_GoldMap.insert(std::make_pair(dwUID, _UI64_MAX));
}
}
else
{
if(_UI64_MAX >= gold_itr_UID->second + itr->second)
{
gold_itr_UID->second += itr->second;
}
else
{
gold_itr_UID->second = _UI64_MAX;
}
}
itr->second = 0;
gold_itr_Temp = itr;
itr++;
m_GoldMap.erase(gold_itr_Temp);
}
else
{
/*ERRLOG4(g_RewardLog, "GoldTransfer Fail CID : %10u, itr_CID : 0x%10x / UID : %10u, itr_UID : 0x%10x",
dwCID, itr, dwUID, gold_itr_UID);*/
return false;
}
}
}
return true;
}
bool CDBRebalanceOverItem::RewardStone(unsigned long dwUID, unsigned long dwCID, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut)
{
unsigned long dwKey = (0 !=dwUID) ? dwUID : dwCID;
unsigned long dwReward = 0, dwStone = 0;
StoneRewardMap::iterator pos = m_StoneMap.find(dwKey);
Item::ItemPos itemPos;
char* szDataPos = szData_InOut + dwDataSize_InOut;
const char* szDataEnd = szData_InOut + dwMaxDataSize;
if(pos != m_StoneMap.end())
{
dwStone = pos->second;
while(0 < dwStone &&
szDataPos + sizeof(Item::ItemData) < szDataEnd &&
itemChecker.FindEmptyPos(itemPos, 1, 1))
{
Item::ItemData Rhatarium;
memset(&Rhatarium, 0, sizeof(Item::ItemData));
unsigned long dwAmountStone = 0;
unsigned long dwAmountResult = 0;
if (COUPONTORHATARIUM <= dwStone)
{
dwAmountStone = (dwStone / COUPONTORHATARIUM) * COUPONTORHATARIUM;
if(MAX_ITEMSTACK * COUPONTORHATARIUM <= dwAmountStone)
{
dwAmountStone = MAX_ITEMSTACK * COUPONTORHATARIUM;
}
dwStone -= dwAmountStone;
dwReward += dwAmountStone;
dwAmountResult = dwAmountStone / COUPONTORHATARIUM;
Rhatarium.m_usProtoTypeID = RHATARIUM_COUPON;
}
else
{
dwAmountStone = dwStone;
dwStone -= dwAmountStone;
dwReward += dwAmountStone;
dwAmountResult = dwAmountStone;
Rhatarium.m_usProtoTypeID = RHATARIUM;
}
Rhatarium.m_dwUID = m_DBItemSerialMgr.GetNewItemSerial();
Rhatarium.m_ItemPos = itemPos;
Rhatarium.m_cNumOrDurability = static_cast<unsigned char>(dwAmountResult);
Rhatarium.m_cItemSize = sizeof(Item::ItemData);
memcpy(szDataPos, &Rhatarium, sizeof(Item::ItemData));
szDataPos += sizeof(Item::ItemData);
dwDataSize_InOut += static_cast<unsigned long>(sizeof(Item::ItemData));
itemChecker.Set(itemPos, 1, 1);
if(Rhatarium.m_usProtoTypeID == RHATARIUM)
{
/*SERLOG6(g_RewardLog, "[Key - %8u] %s Reward Stone [ItemUID:0x%016I64X / ItemQuantity:%10u ItemPos:(%d:0x%03X)]",
dwKey, szPosition, Rhatarium.m_dwUID, dwAmountResult, Rhatarium.m_ItemPos.m_cPos, Rhatarium.m_ItemPos.m_cIndex);*/
}
else if(Rhatarium.m_usProtoTypeID == RHATARIUM_COUPON)
{
/*SERLOG6(g_RewardLog, "[Key - %8u] %s Reward StoneCoupon [ItemUID:0x%016I64X / ItemQuantity:%10u ItemPos:(%d:0x%03X)]",
dwKey, szPosition, Rhatarium.m_dwUID, dwAmountResult, Rhatarium.m_ItemPos.m_cPos, Rhatarium.m_ItemPos.m_cIndex);*/
}
}
dwDataSize_InOut = static_cast<unsigned long>(szDataPos - szData_InOut);
if(0 == dwStone)
{
pos->second = dwStone;
m_StoneMap.erase(pos);
/*SERLOG2(g_RewardLog, "[Key - %8u] ----Success : Reward %10u Stone", dwKey, dwReward);*/
return true;
}
else
{
/*ERRLOG4(g_RewardLog, "[Key - %8u] -----Failed : Reward %10u Stone overflow(%10u), Remain Stone(%10u)",
dwKey, pos->second, dwReward, dwStone);*/
pos->second = dwStone;
return false;
}
}
else
{
return true;
}
}
bool CDBRebalanceOverItem::RewardGold(unsigned long dwKey, const char* szPosition, unsigned long& dwGold_InOut)
{
GoldRewardMap::iterator pos = m_GoldMap.find(dwKey);
unsigned __int64 dwReward = 0, dwGold = 0;
if(pos != m_GoldMap.end())
{
dwGold = pos->second;
unsigned long dwAmountGold = static_cast<unsigned long>(dwGold % COUPONTOGOLD);
if(ULONG_MAX - dwGold_InOut >= dwAmountGold)
{
dwGold_InOut += dwAmountGold;
dwGold -= static_cast<unsigned __int64>(dwAmountGold);
pos->second = dwGold;
//SERLOG2(g_RewardLog, "[Key - %8u] ----Success : Reward %10u Gold", dwKey, dwAmountGold);
if(dwGold == 0)
{
m_GoldMap.erase(pos);
}
return true;
}
else
{
/*ERRLOG3(g_RewardLog, "[Key - %8u] -----Failed : Reward %16I64u Gold overflow(%10u)", dwKey, pos->second, dwAmountGold);*/
return false;
}
}
else
{
return true;
}
}
bool CDBRebalanceOverItem::RewardGoldCoupon(unsigned long dwKey, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut)
{
unsigned __int64 dwReward = 0, dwGold= 0;
GoldRewardMap::iterator pos = m_GoldMap.find(dwKey);
Item::ItemPos itemPos;
char* szDataPos = szData_InOut + dwDataSize_InOut;
const char* szDataEnd = szData_InOut + dwMaxDataSize;
Item::ItemData GoldCoupon;
if(pos != m_GoldMap.end())
{
dwGold = pos->second;
unsigned long dwAmountCoupon = 0;
while(COUPONTOGOLD <= dwGold && szDataPos + sizeof(Item::ItemData) < szDataEnd && itemChecker.FindEmptyPos(itemPos, 1, 1))
{
memset(&GoldCoupon, 0, sizeof(Item::ItemData));
GoldCoupon.m_usProtoTypeID = GOLD_COUPON;
GoldCoupon.m_dwUID = m_DBItemSerialMgr.GetNewItemSerial();
GoldCoupon.m_ItemPos = itemPos;
GoldCoupon.m_cNumOrDurability = static_cast<unsigned char>(1);
GoldCoupon.m_cItemSize = sizeof(Item::ItemData);
memcpy(szDataPos, &GoldCoupon, sizeof(Item::ItemData));
szDataPos += sizeof(Item::ItemData);
dwDataSize_InOut += static_cast<unsigned long>(sizeof(Item::ItemData));
itemChecker.Set(itemPos, 1, 1);
dwGold -= COUPONTOGOLD;
dwReward += COUPONTOGOLD;
++dwAmountCoupon;
}
/*SERLOG6(g_RewardLog, "[Key - %8u] %s Reward GoldCoupon [ItemUID:0x%016I64X / ItemQuantity:%10u ItemPos:(%d:0x%03X)]",
dwKey, szPosition, GoldCoupon.m_dwUID, dwAmountCoupon, GoldCoupon.m_ItemPos.m_cPos, GoldCoupon.m_ItemPos.m_cIndex);*/
dwDataSize_InOut = static_cast<unsigned long>(szDataPos - szData_InOut);
if(COUPONTOGOLD > dwGold)
{
pos->second = dwGold;
if(dwReward/COUPONTOGOLD)
{
/*SERLOG2(g_RewardLog, "[Key - %8u] ----Success : Reward %16I64u Gold", dwKey, dwReward);*/
}
if(0 == dwGold)
{
m_GoldMap.erase(pos);
}
return true;
}
else
{
/*ERRLOG4(g_RewardLog, "[Key - %8u] -----Failed : Reward %16I64u GoldCoupon overflow(%16I64u), Remain Gold(%16I64u)",
dwKey, pos->second/COUPONTOGOLD, dwReward/COUPONTOGOLD, dwGold);*/
pos->second = dwGold;
return false;
}
}
else
{
return true;
}
}
bool CDBRebalanceOverItem::RewardGoldAndCoupon(unsigned long dwKey, unsigned long& dwGold_InOut, RebalanceLib::CItemChecker& itemChecker,
const char* szPosition, char* szData_InOut, const unsigned long dwMaxDataSize, unsigned long& dwDataSize_InOut)
{
if(RewardGold(dwKey, szPosition, dwGold_InOut) &&
RewardGoldCoupon(dwKey, itemChecker, szPosition, szData_InOut, dwMaxDataSize, dwDataSize_InOut))
{
return true;
}
else
{
return false;
}
}
void CDBRebalanceOverItem::AddReward(unsigned long dwKey, unsigned long dwStone, unsigned __int64 dwGold)
{
StoneRewardMap::iterator stone_pos = m_StoneMap.find(dwKey);
GoldRewardMap::iterator gold_pos = m_GoldMap.find(dwKey);
bool bPrint = false;
if(0 < dwStone)
{
if(m_StoneMap.end() == stone_pos)
{
m_StoneMap.insert(std::make_pair(dwKey, CALC_REWARDSTONE(dwStone)));
bPrint = false;
}
else
{
stone_pos->second += CALC_REWARDSTONE(dwStone);
bPrint = true;
}
if(0 < dwGold)
{
dwGold = static_cast<unsigned __int64>(CALC_REWARDGOLD(dwGold, dwStone));
if(m_GoldMap.end() == gold_pos)
{
if(_UI64_MAX >= dwGold)
{
m_GoldMap.insert(std::make_pair(dwKey, dwGold));
bPrint = false;
}
else
{
m_GoldMap.insert(std::make_pair(dwKey, _UI64_MAX));
dwGold = _UI64_MAX;
bPrint = false;
}
}
else
{
if(_UI64_MAX >= dwGold + gold_pos->second)
{
gold_pos->second += dwGold;
bPrint = (bPrint & true);
}
else
{
gold_pos->second = _UI64_MAX;
dwGold = _UI64_MAX;
bPrint = (bPrint & true);
}
}
}
}
/*SERLOG3(g_CalcLog, "[Key - %8u] -- Reward Stone %5u / Gold %16I64u",
dwKey, CALC_REWARDSTONE(dwStone), dwGold);*/
if(true == bPrint)
{
/*SERLOG3(g_CalcLog, "[Key - %8u] -- Total Reward Stone %5u / Gold %16I64u",
dwKey, stone_pos->second, gold_pos->second);*/
}
}
void CDBRebalanceOverItem::CalcReward(const Item::CItemType::ArrayType eEquipType, Item::CEquipment* lpEquipment, short* lpAttrFactor, short* lpAttrValue,
unsigned long& dwStone, unsigned __int64& dwGold, unsigned long dwKey)
{
float fTempFactor = 0;
float fTempFactor2 = 0;
long dwTempStone = 0;
dwStone = 0;
dwGold = 0;
/*SERLOG5(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] -- %s(%s)",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, lpEquipment->GetItemInfo().m_SpriteData.m_szName, lpEquipment->GetItemInfo().m_StringData.m_szTypeName);*/
// 제련석 계산
switch(eEquipType)
{
case Item::CItemType::DAGGER_TYPE:
case Item::CItemType::ONEHANDED_TYPE:
case Item::CItemType::LONGRANGE_TYPE:
case Item::CItemType::TWOHANDED_TYPE:
case Item::CItemType::STAFF_TYPE:
// 무기류, 스태프/사이드류 공통 #1 : 크리티컬 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::CRITICAL, dwKey, lpAttrFactor[Item::Attribute::Type::CRITICAL], lpAttrValue[Item::Attribute::Type::CRITICAL]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Critical : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 무기류, 스태프/사이드류 공통 #2 : 명중률 / 12
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::HIT_RATE, dwKey, lpAttrFactor[Item::Attribute::Type::HIT_RATE], lpAttrValue[Item::Attribute::Type::HIT_RATE]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 12.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Hitrate : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
switch(eEquipType)
{
case Item::CItemType::DAGGER_TYPE:
case Item::CItemType::ONEHANDED_TYPE:
case Item::CItemType::LONGRANGE_TYPE:
case Item::CItemType::TWOHANDED_TYPE:
// 무기류 공통 #1 : MP회복 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MP_REGEN, dwKey, lpAttrFactor[Item::Attribute::Type::MP_REGEN], lpAttrValue[Item::Attribute::Type::MP_REGEN]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
//SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MPRegen : Reward Stone %5u",
// dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);
// 무기류 공통 #2 : 최대MP / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_MP, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_MP], lpAttrValue[Item::Attribute::Type::MAX_MP]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MaxMP : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
fTempFactor = std::max(CalcAttribute(lpEquipment, Item::Attribute::Type::MIN_DAMAGE, dwKey, lpAttrFactor[Item::Attribute::Type::MIN_DAMAGE], lpAttrValue[Item::Attribute::Type::MIN_DAMAGE]),
CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_DAMAGE, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_DAMAGE], lpAttrValue[Item::Attribute::Type::MAX_DAMAGE]));
switch(eEquipType)
{
case Item::CItemType::DAGGER_TYPE:
// 단검류 추가 : MAX(최소 데미지, 최대 데미지) / 3
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
break;
case Item::CItemType::ONEHANDED_TYPE:
case Item::CItemType::LONGRANGE_TYPE:
// 한손무기류, 장거리무기류 추가 : MAX(최소 데미지, 최대 데미지) / 6
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 6.0f)), 0UL);
break;
case Item::CItemType::TWOHANDED_TYPE:
// 양손무기류 추가 : MAX(최소 데미지, 최대 데미지) / 9
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 9.0f)), 0UL);
break;
}
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Damage : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
break;
case Item::CItemType::STAFF_TYPE:
// 스태프, 사이드류 추가 #1 : 마법력 / 15 or 최대 데미지 / 9
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAGIC_POWER, dwKey, lpAttrFactor[Item::Attribute::Type::MAGIC_POWER], lpAttrValue[Item::Attribute::Type::MAGIC_POWER]);
fTempFactor2 = CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_DAMAGE, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_DAMAGE], lpAttrValue[Item::Attribute::Type::MAX_DAMAGE]);
if (fTempFactor > fTempFactor2)
{
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 15.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MagicPower : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
}
else
{
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor2 / 9.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Max_Damage : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
}
// 스태프, 사이드류 추가 #2 : MP회복 / 6
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MP_REGEN, dwKey, lpAttrFactor[Item::Attribute::Type::MP_REGEN], lpAttrValue[Item::Attribute::Type::MP_REGEN]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 6.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MPRegen : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 스태프, 사이드류 추가 #3 : 최대MP / 6
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_MP, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_MP], lpAttrValue[Item::Attribute::Type::MAX_MP]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 6.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MaxMP : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
break;
}
break;
case Item::CItemType::ARMOUR_TYPE:
case Item::CItemType::SHIELD_TYPE:
// 방어구류 방패와가드암 공통 : 최대HP / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_HP, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_HP], lpAttrValue[Item::Attribute::Type::MAX_HP]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MaxHP : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 방어구류 방패와가드암 공통 : HP회복 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::HP_REGEN, dwKey, lpAttrFactor[Item::Attribute::Type::HP_REGEN], lpAttrValue[Item::Attribute::Type::HP_REGEN]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] HPRegen : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
switch(eEquipType)
{
case Item::CItemType::ARMOUR_TYPE:
// 방어구류 추가 #1 : 회피 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::EVADE, dwKey, lpAttrFactor[Item::Attribute::Type::EVADE], lpAttrValue[Item::Attribute::Type::EVADE]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Evade : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 방어구류 추가 #2 : 마법저항 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAGIC_RESIST, dwKey, lpAttrFactor[Item::Attribute::Type::MAGIC_RESIST], lpAttrValue[Item::Attribute::Type::MAGIC_RESIST]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MagicResist : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 방어구류 추가 #3 : 방어력 / 6
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::ARMOR, dwKey, lpAttrFactor[Item::Attribute::Type::ARMOR], lpAttrValue[Item::Attribute::Type::ARMOR]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 6.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Armor : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
break;
case Item::CItemType::SHIELD_TYPE:
// 방패와가드암류 추가 #1 : 최대MP / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MAX_MP, dwKey, lpAttrFactor[Item::Attribute::Type::MAX_MP], lpAttrValue[Item::Attribute::Type::MAX_MP]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MaxMP : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 방패와가드암류 추가 #2 : MP회복 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::MP_REGEN, dwKey, lpAttrFactor[Item::Attribute::Type::MP_REGEN], lpAttrValue[Item::Attribute::Type::MP_REGEN]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] MPRegen : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
// 방패와가드암류 추가 #3 : 블록 / 3
fTempFactor = CalcAttribute(lpEquipment, Item::Attribute::Type::BLOCK, dwKey, lpAttrFactor[Item::Attribute::Type::BLOCK], lpAttrValue[Item::Attribute::Type::BLOCK]);
dwTempStone = std::max(static_cast<unsigned long>(ceil(fTempFactor / 3.0f)), 0UL);
dwTempStone = std::max(dwTempStone, 0L);
dwStone += dwTempStone;
/*SERLOG4(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] Block : Reward Stone %5u",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, dwTempStone);*/
break;
}
}
// 골드 계산
lpEquipment->Repair();
dwGold = lpEquipment->GetBuyPrice();
}
float CDBRebalanceOverItem::CalcAttribute(Item::CEquipment* lpEquipment, Item::Attribute::Type eAttributeType, unsigned long dwKey, short attrFactor, short attrValue)
{
float fTempFactor = static_cast<float>(attrFactor - attrValue);
char szString[20] = {0};
GetAttrString(eAttributeType, szString);
/*SERLOG7(g_CalcLog, "[Key - %8u / UID - 0x%016I64X(%5u)] %-15s : %u - %u = %f",
dwKey, lpEquipment->GetUID(), lpEquipment->GetItemInfo().m_usProtoTypeID, szString, attrFactor, attrValue, fTempFactor);*/
return fTempFactor;
}
void CDBRebalanceOverItem::GetAttrString(Item::Attribute::Type eAttributeType, char* lpString)
{
const char MAX_STRING = 20;
switch(eAttributeType)
{
case Item::Attribute::MIN_DAMAGE: _snprintf(lpString, MAX_STRING, "MinDamage"); break;
case Item::Attribute::MAX_DAMAGE: _snprintf(lpString, MAX_STRING, "MaxDamage"); break;
case Item::Attribute::ARMOR: _snprintf(lpString, MAX_STRING, "Armor"); break;
case Item::Attribute::HIT_RATE: _snprintf(lpString, MAX_STRING, "HitRate"); break;
case Item::Attribute::EVADE: _snprintf(lpString, MAX_STRING, "Evade"); break;
case Item::Attribute::MAX_HP: _snprintf(lpString, MAX_STRING, "MaxHP"); break;
case Item::Attribute::HP_REGEN: _snprintf(lpString, MAX_STRING, "HPRegen"); break;
case Item::Attribute::MAX_MP: _snprintf(lpString, MAX_STRING, "MaxMP"); break;
case Item::Attribute::MP_REGEN: _snprintf(lpString, MAX_STRING, "MPRegen"); break;
case Item::Attribute::CRITICAL: _snprintf(lpString, MAX_STRING, "Critical"); break;
case Item::Attribute::BLOCK: _snprintf(lpString, MAX_STRING, "Block"); break;
case Item::Attribute::SPEED: _snprintf(lpString, MAX_STRING, "Speed"); break;
case Item::Attribute::MAGIC_POWER: _snprintf(lpString, MAX_STRING, "MagicPower"); break;
case Item::Attribute::MAGIC_RESIST: _snprintf(lpString, MAX_STRING, "MagicResist"); break;
case Item::Attribute::RUNE: _snprintf(lpString, MAX_STRING, "Rune"); break;
case Item::Attribute::FROST: _snprintf(lpString, MAX_STRING, "Frost"); break;
case Item::Attribute::FIRE: _snprintf(lpString, MAX_STRING, "Fire"); break;
case Item::Attribute::ELECTRO: _snprintf(lpString, MAX_STRING, "Electro"); break;
case Item::Attribute::DARKNESS: _snprintf(lpString, MAX_STRING, "Darkness"); break;
default: _snprintf(lpString, MAX_STRING, "Unknown"); break;
}
}
HRESULT CDBRebalanceOverItem::SetTarget()
{
const int MAX_QUERY_BUFFER = 1024;
char szQueryBuffer[MAX_QUERY_BUFFER];
int nServerType;
sCharInfo itemCharInfo = {0};
if(GetUnified())
{
nServerType = 23;
}
else
{
nServerType = 22;
}
_snprintf(szQueryBuffer, MAX_QUERY_BUFFER,
"SELECT A.CID, B.UID, CAST(A.Name AS CHAR(1024)) FROM CharInfo A "
"INNER JOIN (SELECT UID, Char1 as CID FROM UserInfo WHERE OldServerGroupID = %d AND Char1 > 0 UNION ALL "
"SELECT UID, Char2 as CID FROM UserInfo WHERE OldServerGroupID = %d AND Char2 > 0 UNION ALL "
"SELECT UID, Char3 as CID FROM UserInfo WHERE OldServerGroupID = %d AND Char3 > 0 UNION ALL "
"SELECT UID, Char4 as CID FROM UserInfo WHERE OldServerGroupID = %d AND Char4 > 0 UNION ALL "
"SELECT UID, Char5 as CID FROM UserInfo WHERE OldServerGroupID = %d AND Char5 > 0 ) B "
"ON A.CID = B.CID",
nServerType, nServerType, nServerType, nServerType, nServerType);
szQueryBuffer[MAX_QUERY_BUFFER - 1] = 0;
HRESULT hr = S_OK;
ATL::CCommand<ATL::CDynamicAccessor,
ATL::CBulkRowset, ATL::CMultipleResults> getCIDUID;
getCIDUID.SetRows(1000000);
if (FAILED(hr = getCIDUID.Open(m_Session, szQueryBuffer)))
{
LOG_CONVERT1("Get Target from UserInfo failed : hr:0x%08x", hr);
}
else
{
int nCount = 0;
DWORD nCID = 0;
hr = getCIDUID.MoveFirst( );
while (SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET)
{
memset(&itemCharInfo, 0, sizeof(sCharInfo));
getCIDUID.GetValue(1, &nCID);
getCIDUID.GetValue(2, &(itemCharInfo.dwUID));
/*getCIDUID.GetValue(3, itemCharInfo.szName);*/
m_CIDUIDMap.insert(CIDUIDMAP::value_type(nCID, itemCharInfo));
hr = getCIDUID.MoveNext();
if (0 == (++nCount % 1000)) { printf("Read UID,CID info : %d\n", nCount); }
}
printf("Read UID,CID info success : %d\n", nCount);
}
return hr;
}
bool CDBRebalanceOverItem::IsExistCID(const unsigned long dwCID)
{
CIDUIDMAP::iterator itr = m_CIDUIDMap.find(dwCID);
if (itr == m_CIDUIDMap.end())
{
return false;
}
else
{
return true;
}
}
bool CDBRebalanceOverItem::IsExistUID(const unsigned long dwUID)
{
for (CIDUIDMAP::iterator itr = m_CIDUIDMap.begin(); itr != m_CIDUIDMap.end(); ++itr)
{
sCharInfo itemCharInfo = itr->second;
if(dwUID == itemCharInfo.dwUID)
{
return true;
}
}
return false;
}
unsigned long CDBRebalanceOverItem::GetUIDByCID(const unsigned long dwCID)
{
for (CIDUIDMAP::iterator itr = m_CIDUIDMap.begin(); itr != m_CIDUIDMap.end(); ++itr)
{
if(dwCID == itr->first)
{
sCharInfo itemCharInfo = itr->second;
return itemCharInfo.dwUID;
}
}
return 0;
}
bool CDBRebalanceOverItem::GetCharNameByCID(const unsigned long dwCID, char* szCharName)
{
for (CIDUIDMAP::iterator itr = m_CIDUIDMap.begin(); itr != m_CIDUIDMap.end(); ++itr)
{
if(dwCID == itr->first)
{
sCharInfo itemCharInfo = itr->second;
szCharName = itemCharInfo.szName;
return true;
}
}
return false;
}
void CDBRebalanceOverItem::PrintItemOptionList()
{
char szMessage[1024] = {0}, szAttribute[64] = {0};
int nPrintNum = 0;
nPrintNum = sprintf(szMessage, "\t\tItemUID\tdwUID\tdwCID\tPrototypeID\tItemName\tTypeName\t");
for(int i = Item::Attribute::MIN_DAMAGE; i < Item::Attribute::MP_REGEN + 1; i++)
{
ZeroMemory(szAttribute, sizeof(char) * 64);
GetAttrString(static_cast<Item::Attribute::Type>(i), szAttribute);
nPrintNum += sprintf(szMessage + nPrintNum, "%s\t", szAttribute);
}
for(i = Item::Attribute::MAGIC_POWER; i < Item::Attribute::MAGIC_RESIST + 1; i++)
{
ZeroMemory(szAttribute, sizeof(char) * 64);
GetAttrString(static_cast<Item::Attribute::Type>(i), szAttribute);
nPrintNum += sprintf(szMessage + nPrintNum, "%s\t", szAttribute);
}
for(i = Item::Attribute::CRITICAL; i < Item::Attribute::SPEED + 1; i++)
{
ZeroMemory(szAttribute, sizeof(char) * 64);
GetAttrString(static_cast<Item::Attribute::Type>(i), szAttribute);
nPrintNum += sprintf(szMessage + nPrintNum, "%s\t", szAttribute);
}
SERLOG0(g_ItemList, szMessage);
}
void CDBRebalanceOverItem::PrintItemOption(Item::CEquipment* lpEquipment, short* lpAttribute, unsigned long dwKey)
{
if(NULL == lpAttribute || NULL == lpEquipment)
{
return;
}
else
{
char szMessage[2048] = {0};
char* szCharName = 0;
int nPrintNum = 0;
unsigned long dwUID = 0;
unsigned long dwCID = 0;
if(IsExistCID(dwKey))
{
dwCID = dwKey;
dwUID = GetUIDByCID(dwCID);
if(!GetCharNameByCID(dwCID, szCharName))
{
ERRLOG1(g_ItemList, "CID(%u) is not converted to CharName", dwKey);
}
}
else if(IsExistUID(dwKey))
{
dwUID = dwKey;
}
else
{
ERRLOG1(g_ItemList, "dwKey(%u) is not exist in UID & CIDMAP", dwKey);
}
nPrintNum += sprintf(szMessage, "\t\t0x%016I64X\t%u\t%u\t%u\t%s\t%s\t",
lpEquipment->GetUID(), dwUID, dwCID, lpEquipment->GetPrototypeID(),
lpEquipment->GetItemInfo().m_SpriteData.m_szName, lpEquipment->GetItemTypeName());
for(int i = Item::Attribute::MIN_DAMAGE; i < Item::Attribute::MP_REGEN + 1; i++)
{
nPrintNum += sprintf(szMessage + nPrintNum, "%u\t", lpAttribute[i]);
}
for(i = Item::Attribute::MAGIC_POWER; i < Item::Attribute::MAGIC_RESIST + 1; i++)
{
nPrintNum += sprintf(szMessage + nPrintNum, "%u\t", lpAttribute[i]);
}
for(i = Item::Attribute::CRITICAL; i < Item::Attribute::SPEED + 1; i++)
{
nPrintNum += sprintf(szMessage + nPrintNum, "%u\t", lpAttribute[i]);
}
SERLOG0(g_ItemList, szMessage);
}
}