Files
Client/Server/ToolProject/ItemRebalanceConverter/ItemRebalanceConverter.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

1859 lines
83 KiB
C++

// ItemRebalanceConverter.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#define _WIN32_WINNT 0x0500
#include "stdafx.h"
#include "OldItemStructure.h"
#include <objbase.h>
#include <Log/ServerLog.h>
#include <atldbcli.h>
#define INITGUID
#define DBINITCONSTANTS
#include <sqloledb.h>
#include <fstream>
#include <iostream>
#include <numeric>
#include <iomanip>
#include <ctime>
#include <Item/ItemMgr.h>
#include <Skill/SkillStructure.h>
#include <Network/Packet/PacketStruct/ServerInfo.h>
#include <Utility/Setup/ServerSetup.h>
#include "OldItemMgr.h"
#define COPY_AND_ADVANCE_DST(dst, src, size) memcpy((dst), (src), (size)); (dst) += (size)
#define COPY_AND_ADVANCE_SRC(dst, src, size) memcpy((dst), (src), (size)); (src) += (size)
class COMInitialize
{
public:
static COMInitialize& GetInstance();
private:
COMInitialize();
~COMInitialize();
};
COMInitialize& COMInitialize::GetInstance()
{
static COMInitialize initialize;
return initialize;
}
COMInitialize::COMInitialize()
{
CoInitializeEx(NULL, COINIT_MULTITHREADED);
}
COMInitialize::~COMInitialize()
{
CoUninitialize();
}
class CUserItemDataGet
{
public:
int m_nCID;
BYTE m_Equip[sizeof(EQUIP)];
BYTE m_Inven[sizeof(INVEN)];
BYTE m_Extra[sizeof(EXTRA)];
BYTE m_Exchange[sizeof(EXCHANGE)];
DBLENGTH m_EquipLength;
DBLENGTH m_InvenLength;
DBLENGTH m_ExtraLength;
DBLENGTH m_ExchangeLength;
void Init()
{
m_nCID = 0;
m_EquipLength = m_InvenLength = m_ExtraLength = m_ExchangeLength = 0;
memset(m_Equip, 0, sizeof(EQUIP));
memset(m_Inven, 0, sizeof(INVEN));
memset(m_Extra, 0, sizeof(EXTRA));
memset(m_Exchange, 0, sizeof(EXCHANGE));
}
};
class CUserItemDataSet
{
public:
int m_nCID;
BYTE m_Equip[sizeof(EQUIP)];
BYTE m_Inven[sizeof(INVEN)];
BYTE m_Extra[sizeof(EXTRA)];
DBLENGTH m_EquipLength;
DBLENGTH m_InvenLength;
DBLENGTH m_ExtraLength;
void Init()
{
m_nCID = 0;
m_EquipLength = m_InvenLength = m_ExtraLength = 0;
memset(m_Equip, 0, sizeof(EQUIP));
memset(m_Inven, 0, sizeof(INVEN));
memset(m_Extra, 0, sizeof(EXTRA));
}
};
class CUserItemDataSetEx
{
public:
int m_nCID;
BYTE m_Exchange[sizeof(EXCHANGE)];
DBLENGTH m_ExchangeLength;
void Init()
{
m_nCID = 0;
m_ExchangeLength = 0;
memset(m_Exchange, 0, sizeof(EXCHANGE));
}
};
class CStoreItemData
{
public:
DBLENGTH m_StoreLength;
int m_nUID;
BYTE m_Store[sizeof(STORE)];
void Init()
{
m_StoreLength = 0;
m_nUID = 0;
memset(m_Store, 0, sizeof(STORE));
}
};
class CGetUserItemData : public CUserItemDataGet
{
public:
typedef CCommand< CAccessor< CGetUserItemData >, CRowset, CMultipleResults > Command;
BEGIN_COLUMN_MAP(CGetUserItemData)
COLUMN_ENTRY(1, m_nCID)
COLUMN_ENTRY_LENGTH(2, m_Equip, m_EquipLength)
COLUMN_ENTRY_LENGTH(3, m_Inven, m_InvenLength)
COLUMN_ENTRY_LENGTH(4, m_Extra, m_ExtraLength)
END_COLUMN_MAP()
};
class CGetUserItemDataEx : public CUserItemDataGet
{
public:
typedef CCommand< CAccessor< CGetUserItemDataEx >, CRowset, CMultipleResults > Command;
BEGIN_COLUMN_MAP(CGetUserItemDataEx)
COLUMN_ENTRY(1, m_nCID)
COLUMN_ENTRY_LENGTH(2, m_Exchange, m_ExchangeLength)
END_COLUMN_MAP()
};
class CSetUserItemData : public CUserItemDataSet
{
public:
typedef CCommand< CAccessor< CSetUserItemData >, CNoRowset> Command;
BEGIN_PARAM_MAP(CSetUserItemData)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY_LENGTH(1, m_Equip, m_EquipLength)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY_LENGTH(2, m_Inven, m_InvenLength)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY_LENGTH(3, m_Extra, m_ExtraLength)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY(4, m_nCID)
END_PARAM_MAP()
};
class CSetUserItemDataEx : public CUserItemDataSetEx
{
public:
typedef CCommand< CAccessor< CSetUserItemDataEx >, CNoRowset > Command;
BEGIN_PARAM_MAP(CSetUserItemDataEx)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY_LENGTH(1, m_Exchange, m_ExchangeLength);
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY(2, m_nCID)
END_PARAM_MAP()
};
class CGetStoreItemData : public CStoreItemData
{
public:
typedef CCommand< CAccessor< CGetStoreItemData >, CRowset, CMultipleResults > Command;
BEGIN_COLUMN_MAP(CGetStoreItemData)
COLUMN_ENTRY(1, m_nUID)
COLUMN_ENTRY_LENGTH(2, m_Store, m_StoreLength)
END_COLUMN_MAP()
};
class CSetStoreItemData : public CStoreItemData
{
public:
typedef CCommand< CAccessor< CSetStoreItemData >, CNoRowset > Command;
BEGIN_PARAM_MAP(CSetStoreItemData)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY_LENGTH(1, m_Store, m_StoreLength)
SET_PARAM_TYPE(DBPARAMIO_INPUT)
COLUMN_ENTRY(2, m_nUID)
END_PARAM_MAP()
};
void PrintUsage()
{
printf("Usage : ItemRebalanceConverter DBServerAddr DBName DBAccount DBPassword ServerGroupNum convertCharDelHistory(1/0) writeDB(1/0)");
}
int ParseItemData(unsigned long dwUID, unsigned long dwCID,
char* szItemData, unsigned long dwSize,
char* szOutData, unsigned long& dwOutDataSize);
bool CreateAdjustedItem(unsigned long dwUID,
unsigned long dwCID,
OldItem::ItemData* lpItemData,
OldItem::EquipmentInfo* lpEquipmentInfo,
unsigned char* lpSocketInfo,
OldItem::ItemAttribute* lpAttribute,
char* szOutData,
unsigned long& dwRemainBufferSize_InOut);
Item::Grade::GradeInfo GetGradeInfo(short* wNewAttribute, const int nMaxAttributeNum,
const Item::ItemInfo& newItemInfo);
const char* GetGradeString(Item::EquipType::Grade grade);
#define ERROR_HRESULT_RETURN(ErrorMessage, hr, retVal) \
if(FAILED(hr)) { printf(ErrorMessage" : hr(0x%08x)", (hr)); return (retVal); }
int ProcessCharItem(ATL::CSession& readSession, ATL::CSession& writeSession,
bool bProcessDelHistory, bool bWriteDB);
int ProcessCharItemEx(ATL::CSession& readSession, ATL::CSession& writeSession,
bool bProcessDelHistory, bool bWriteDB);
int ProcessStore(ATL::CSession& readSession, ATL::CSession& writeSession,
int nStoreNum, bool bWriteDB);
bool RewriteItemUID(ATL::CSession& writeSession, int nServerGroupNum);
const int SHOW_NUM_PER_PROCESS = 1000;
int g_GradeNum[Item::EquipType::MAX_GRADE] = { 0, };
unsigned __int64 g_UID = 0;
const int MAX_SERVERZONE = 20;
unsigned __int64 g_MaxUID[MAX_SERVERZONE] = { 0, };
CServerLog g_ItemLog("ItemLog.log");
int _tmain(int argc, _TCHAR* argv[])
{
COMInitialize::GetInstance();
if(argc != 8)
{
PrintUsage();
return -1;
}
// 아이템 스크립트 읽기
if(!Item::CItemMgr::GetInstance().LoadItemProtoType("./NewItemScript.txt"))
{
printf("NewItemScript load failed.");
return -1;
}
// 아이템 스크립트 읽기
if(!OldItem::CItemMgr::GetInstance().LoadItemProtoType("./OldItemScript.txt"))
{
printf("OldItemScript load failed.");
return -1;
}
int nServerGroupNum = atoi(argv[5]);
bool bWriteDB = (0 == strcmp("1", argv[7]));
DETLOG0(g_Log, "DBQuery and convert start!");
printf("DBQuery and convert start!\n");
// DB Property 설정.
ATL::CDBPropSet dsPropSet[2];
dsPropSet[0].SetGUID(DBPROPSET_DBINIT);
dsPropSet[0].AddProperty(DBPROP_INIT_DATASOURCE, argv[1]);
dsPropSet[0].AddProperty(DBPROP_INIT_CATALOG, argv[2]);
dsPropSet[0].AddProperty(DBPROP_AUTH_USERID, argv[3]);
dsPropSet[0].AddProperty(DBPROP_AUTH_PASSWORD, argv[4]);
dsPropSet[1].SetGUID(DBPROPSET_ROWSET);
dsPropSet[1].AddProperty(DBPROP_UPDATABILITY, long(VARIANT_TRUE));
// 데이터베이스 오픈
ATL::CDataSource dataSource;
HRESULT hr = dataSource.Open(CLSID_SQLOLEDB, dsPropSet, 2);
ERROR_HRESULT_RETURN("DataSource1 open failed", hr, -1);
// 데이터베이스 읽기 세션 열기
ATL::CSession readSession;
hr = readSession.Open(dataSource);
ERROR_HRESULT_RETURN("readSession open failed", hr, -1);
// 데이터베이스 쓰기 세션 열기
ATL::CSession writeSession;
hr = writeSession.Open(dataSource);
ERROR_HRESULT_RETURN("writeSession open failed", hr, -1);
#define LOG_CONVERT(str) DETLOG0(g_Log, (str)); printf(str "\n");
#define LOG_CONVERT1(str, arg1) DETLOG1(g_Log, (str), (arg1)); printf(str "\n", (arg1));
#define LOG_CONVERT2(str, arg1, arg2) DETLOG2(g_Log, (str), (arg1), (arg2)); printf(str "\n", (arg1), (arg2));
LOG_CONVERT("Convert CharItem Start.");
ProcessCharItem(readSession, writeSession, false, bWriteDB);
LOG_CONVERT("Convert CharItemEx Start.");
ProcessCharItemEx(readSession, writeSession, false, bWriteDB);
LOG_CONVERT("Convert Store1 Start.");
ProcessStore(readSession, writeSession, 1, bWriteDB);
LOG_CONVERT("Convert Store2 Start.");
ProcessStore(readSession, writeSession, 2, bWriteDB);
if(0 == strcmp("1", argv[6]))
{
LOG_CONVERT("Convert CharDelHistory..CharItem Start.");
ProcessCharItem(readSession, writeSession, true, bWriteDB);
LOG_CONVERT("Convert CharDelHistory..CharItemEx Start.");
ProcessCharItemEx(readSession, writeSession, true, bWriteDB);
}
LOG_CONVERT1("Grade AAA : %10u", g_GradeNum[Item::EquipType::AAA_GRADE]);
LOG_CONVERT1("Grade AA : %10u", g_GradeNum[Item::EquipType::AA_GRADE]);
LOG_CONVERT1("Grade A : %10u", g_GradeNum[Item::EquipType::A_GRADE]);
LOG_CONVERT1("Grade B : %10u", g_GradeNum[Item::EquipType::B_GRADE]);
LOG_CONVERT1("Grade C : %10u", g_GradeNum[Item::EquipType::C_GRADE]);
LOG_CONVERT1("Grade D : %10u", g_GradeNum[Item::EquipType::D_GRADE]);
LOG_CONVERT1("Grade F : %10u", g_GradeNum[Item::EquipType::F_GRADE]);
for(int nCount = 0; nCount < MAX_SERVERZONE; ++nCount)
{
if(0 != g_MaxUID[nCount])
{
LOG_CONVERT2("ServerGroup : %d / Max Old UID : 0x%016I64X", nCount, g_MaxUID[nCount]);
}
}
RewriteItemUID(writeSession, nServerGroupNum);
LOG_CONVERT1("Max New UID : %I64u", g_UID);
LOG_CONVERT("Convert Complete");
return 0;
}
bool RewriteItemUID(ATL::CSession& writeSession, int nServerGroupNum)
{
// 아이템 시리얼 전부 지우고, 재기록하기.
CCommand<> DelCmd;
HRESULT hr = DelCmd.Open(writeSession, "Delete from ItemUID");
ERROR_HRESULT_RETURN("readSession open failed", hr, false);
SERVER_ID serverID;
serverID.sID.Type = CServerSetup::AuthServer;
serverID.sID.Group = nServerGroupNum;
serverID.sID.Channel = 0;
serverID.sID.ID = 0;
const int MAX_QUERY_LEN = 512;
char szQuery[MAX_QUERY_LEN];
_snprintf(szQuery, MAX_QUERY_LEN - 1, "Insert into ItemUID values (0x%08x, 0x%0I64x)",
serverID.dwID, g_UID);
hr = DelCmd.Open(writeSession, szQuery);
ERROR_HRESULT_RETURN("readSession open failed", hr, false);
return true;
}
int ParseItemData(unsigned long dwUID, unsigned long dwCID,
char* szItemData, unsigned long dwSize,
char* szOutData, unsigned long& dwOutDataSize)
{
char* szItemDataPos = szItemData;
char* szItemDataEnd = szItemData + dwSize;
char* szOutDataPos = szOutData;
char* szOutDataEnd = szOutData + dwOutDataSize;
for(; szItemDataPos < szItemDataEnd && szOutDataPos < szOutDataEnd;
szItemDataPos += reinterpret_cast<OldItem::ItemData*>(szItemDataPos)->m_cItemSize)
{
OldItem::ItemData* lpItemData = reinterpret_cast<OldItem::ItemData*>(szItemDataPos);
if(sizeof(OldItem::ItemData) + sizeof(OldItem::EquipmentInfo) <= lpItemData->m_cItemSize)
{
// 뒤에 추가 정보가 있으므로 장비다. 옵션을 수정한 후 복사해 준다.
OldItem::EquipmentInfo* lpEquipmentInfo = reinterpret_cast<OldItem::EquipmentInfo*>(
szItemDataPos + sizeof(OldItem::ItemData));
unsigned char* lpSocketInfo = reinterpret_cast<unsigned char*>(lpEquipmentInfo + 1);
OldItem::ItemAttribute* lpAttribute = reinterpret_cast<OldItem::ItemAttribute*>(
lpSocketInfo + lpEquipmentInfo->m_cSocketNum);
unsigned long dwDataSize = static_cast<unsigned long>(szOutDataEnd - szOutDataPos);
if(0 == lpEquipmentInfo->m_cReserved)
{
if(CreateAdjustedItem(dwUID, dwCID, lpItemData, lpEquipmentInfo,
lpSocketInfo, lpAttribute, szOutDataPos, dwDataSize))
{
szOutDataPos += dwDataSize;
}
else
{
// 뭔가 길이가 이상한 아이템이다.
DETLOG5(g_Log, "Item recreation failed.\tUID:%10u\tCID:%10u\tItemUID:0x%016I64X\tPrototypeID:%5u\tItemSize:%3u\t",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, lpItemData->m_cItemSize);
}
}
else
{
// 이미 리밸런싱된 아이템이다.
DETLOG5(g_Log, "이미 리밸런싱된 아이템입니다\tUID:%10u\tCID:%10u\tItemUID:0x%016I64X\tPrototypeID:%5u\tItemSize:%3u\t",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, lpItemData->m_cItemSize);
memcpy(szOutDataPos, lpItemData, lpItemData->m_cItemSize);
szOutDataPos += lpItemData->m_cItemSize;
}
}
else if(lpItemData->m_cItemSize == sizeof(OldItem::ItemData))
{
// 장비가 아닌 잡템이다. 그냥 복사해 준다.
memcpy(szOutDataPos, lpItemData, lpItemData->m_cItemSize);
szOutDataPos += lpItemData->m_cItemSize;
}
else
{
DETLOG5(g_Log, "Item length is invalid. UID:%10u/CID:%10u/ItemUID:0x%016I64X/PrototypeID:%5u/ItemSize:%3u",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_usProtoTypeID, lpItemData->m_cItemSize);
}
}
dwOutDataSize = static_cast<unsigned long>(szOutDataPos - szOutData);
return 0;
}
bool CreateAdjustedItem(unsigned long dwUID,
unsigned long dwCID,
OldItem::ItemData* lpItemData,
OldItem::EquipmentInfo* lpEquipmentInfo,
unsigned char* lpSocketInfo,
OldItem::ItemAttribute* lpAttribute,
char* szOutData,
unsigned long& dwRemainBufferSize_InOut)
{
const int MAX_ATTR_NUM = 7;
const OldItem::ItemInfo* lpOldItemInfo =
OldItem::CItemMgr::GetInstance().GetItemInfo(lpItemData->m_usProtoTypeID);
const Item::ItemInfo* lpNewItemInfo =
Item::CItemMgr::GetInstance().GetItemInfo(lpItemData->m_usProtoTypeID);
if(0 == lpNewItemInfo || 0 == lpOldItemInfo)
{
DETLOG3(g_Log, "Script has not this item.\tUID:%10u\tCID:%10u\tPrototypeID:%5u\t",
dwUID, dwCID, lpItemData->m_usProtoTypeID);
return false;
}
if(sizeof(OldItem::ItemData) + sizeof(OldItem::EquipmentInfo) +
sizeof(OldItem::ItemAttribute) * MAX_ATTR_NUM < dwRemainBufferSize_InOut)
{
char* szOutDataPos = szOutData;
unsigned char cItemType = lpOldItemInfo->m_DetailData.m_cItemType;
unsigned short wDropOption = lpNewItemInfo->m_DetailData.m_wDropOption;
unsigned char cMaxDurablility = lpEquipmentInfo->m_cDiffMaxDurability + lpOldItemInfo->m_DetailData.m_cDefaultDurabilityOrStack;
if(150 < cMaxDurablility)
{
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
int nTotalLength = _snprintf(szBuffer, MAX_BUFFER - 1,
"Item durability is invalid.\tUID:%10u\tCID:%10u\tItemUID:0x%016I64X\tItemSize:%3u\tPrototypeID:%5u\tItemType:%20s\tDurability:%d\t",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_cItemSize, lpItemData->m_usProtoTypeID,
OldItem::CItemType::GetInstance().GetItemTypeName()[cItemType].GetTypeName(),
cMaxDurablility);
DETLOG0(g_Log, szBuffer);
cMaxDurablility = 150;
}
lpEquipmentInfo->m_cDiffMaxDurability =
cMaxDurablility - lpOldItemInfo->m_DetailData.m_cDefaultDurabilityOrStack;
// 일단 기본 데이터 부분은 그냥 복사한다.
memcpy(szOutDataPos, lpItemData, sizeof(OldItem::ItemData));
unsigned __int64 nNewItemSerial = ++g_UID;
INFLOG4(g_ItemLog, "UID:%10u / CID:%10u / OldItemSerial:0x%0I64X / NewItemSerial:0x%0I64X / 아이템 시리얼 변경",
dwUID, dwCID, reinterpret_cast<Item::ItemData*>(szOutDataPos)->m_dwUID, nNewItemSerial);
reinterpret_cast<Item::ItemData*>(szOutDataPos)->m_dwUID = nNewItemSerial;
szOutDataPos += sizeof(OldItem::ItemData);
int nIndex = static_cast<int>(lpItemData->m_dwUID >> 56);
if(nIndex < MAX_SERVERZONE)
{
if(g_MaxUID[nIndex] < lpItemData->m_dwUID)
{
g_MaxUID[nIndex] = lpItemData->m_dwUID;
}
}
else
{
ERRLOG3(g_Log, "Invalid ItemUID : 0x%0I64X / UID:%10d / CID :%10d",
lpItemData->m_dwUID, dwUID, dwCID);
}
lpEquipmentInfo->m_cReserved = 0;
COPY_AND_ADVANCE_DST(szOutDataPos, lpEquipmentInfo, sizeof(OldItem::EquipmentInfo));
// 이제 소켓 부분을 복사할 차례이다.
if(0 < lpEquipmentInfo->m_cSocketNum)
{
// 소켓이 있으면 소켓을 복사.
COPY_AND_ADVANCE_DST(szOutDataPos, lpSocketInfo,
sizeof(unsigned char) * lpEquipmentInfo->m_cSocketNum);
}
// 이제 아이템 속성을 지대로 복사할 차례인데..
// 1. 아이템 속성값을 배열에 담는다.
// 2. 업그레이드 속성값을 적용한다.
// 3. Gem속성값을 적용한다.
// 4. 아이템 타입별로, 위에서부터 죽 흝으면서 적용할 속성값만 걸러서, 값을 계산한 후 복사한다.
short wAttributeValue[OldItem::Attribute::MAX_ATTRIBUTE_NUM];
short wNewAttributeValue[Item::Attribute::MAX_ATTRIBUTE_NUM];
std::fill_n(wAttributeValue, unsigned short(OldItem::Attribute::MAX_ATTRIBUTE_NUM), 0);
std::fill_n(wNewAttributeValue, unsigned short(Item::Attribute::MAX_ATTRIBUTE_NUM), 0);
// 아이템 속성값 배열에 담기.
OldItem::ItemAttribute* lpAttributePos = lpAttribute;
OldItem::ItemAttribute* lpAttributeEnd = lpAttribute + lpEquipmentInfo->m_cAttributeNum;
for(; lpAttributePos != lpAttributeEnd; ++lpAttributePos)
{
if(0 != lpAttributePos->m_cType && lpAttributePos->m_cType < OldItem::Attribute::MAX_ATTRIBUTE_NUM)
{
wAttributeValue[lpAttributePos->m_cType] += lpAttributePos->m_usValue;
}
}
// 업그레이드 속성값 얻어와서 더하기.
if(0 < lpEquipmentInfo->m_cDiffMaterialType)
{
OldItem::ItemAttribute attrUpgrade[OldItem::EquipmentInfo::MAX_UPGRADE_ATTRIBUTE];
memset(&attrUpgrade, 0, sizeof(OldItem::ItemAttribute) * OldItem::EquipmentInfo::MAX_UPGRADE_ATTRIBUTE);
OldItem::CItemType::GetUpgradeItemAttribute(static_cast<OldItem::ItemType::Type>(cItemType),
attrUpgrade, lpEquipmentInfo->m_cDiffMaterialType, OldItem::EquipmentInfo::MAX_UPGRADE_ATTRIBUTE);
lpAttributePos = attrUpgrade;
lpAttributeEnd = attrUpgrade + OldItem::EquipmentInfo::MAX_UPGRADE_ATTRIBUTE;
for(; lpAttributePos != lpAttributeEnd; ++lpAttributePos)
{
if(0 != lpAttributePos->m_cType && lpAttributePos->m_cType < OldItem::Attribute::MAX_ATTRIBUTE_NUM)
{
wAttributeValue[lpAttributePos->m_cType] += lpAttributePos->m_usValue;
}
}
}
// 소켓 속성값 얻어와서 더하기.
if(0 < lpEquipmentInfo->m_cSocketNum)
{
OldItem::ItemAttribute attrGems[OldItem::EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM];
memset(&attrGems, 0, sizeof(OldItem::ItemAttribute) * OldItem::EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM);
OldItem::CItemType::GetInstallGemAttribute(lpSocketInfo, attrGems,
static_cast<OldItem::ItemType::Type>(cItemType), lpEquipmentInfo->m_cSocketNum,
OldItem::EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM);
lpAttributePos = attrGems;
lpAttributeEnd = attrGems + OldItem::EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM;
for(; lpAttributePos != lpAttributeEnd; ++lpAttributePos)
{
if(0 != lpAttributePos->m_cType && lpAttributePos->m_cType < OldItem::Attribute::MAX_ATTRIBUTE_NUM)
{
wAttributeValue[lpAttributePos->m_cType] += lpAttributePos->m_usValue;
}
}
}
#define CHECK_ATTR(nOverflowIndex, MaxValue, Value, nIndex) \
if((MaxValue) < (Value[nIndex])) { (Value[nIndex]) = (MaxValue); (nOverflowIndex) = (nIndex); }
bool bInvalidMaxValue = false;
bool bInvalidUnknownAttr = false;
int nOverflowIndex = OldItem::Attribute::MAX_ATTRIBUTE_NUM;
short wInvalidAttribute[OldItem::Attribute::MAX_ATTRIBUTE_NUM];
std::copy(wAttributeValue, wAttributeValue + OldItem::Attribute::MAX_ATTRIBUTE_NUM, wInvalidAttribute);
short wOldAttributeValue[OldItem::Attribute::MAX_ATTRIBUTE_NUM];
std::copy(wAttributeValue, wAttributeValue + OldItem::Attribute::MAX_ATTRIBUTE_NUM, wOldAttributeValue);
// 이제, 아이템 타입별로 골라서 복사할 차례가 왔다.
switch(lpNewItemInfo->m_DetailData.m_cItemType)
{
case Item::ItemType::CON_ARMOUR:
case Item::ItemType::CON_BODY:
/*
구항목 신항목 계산식 구항목 최대값.
방어력 방어력 구 방어력 * 2.6 72
방어보정 회피 구 방어보정 * 0.7 58
HP Max HP Max 구 HP Max * 0.6 54
MP Max HP 회복 구 MP Max * 1.2 69
저항력 마법저항 구 저항력 * 0.32 + 구 블록 * 0.32 30
블록 11
*/
CHECK_ATTR(nOverflowIndex, 72, wAttributeValue, OldItem::Attribute::DEFENCE);
CHECK_ATTR(nOverflowIndex, 58, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 54, wAttributeValue, OldItem::Attribute::MAX_HP);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MAX_MP);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 11, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
wNewAttributeValue[Item::Attribute::ARMOR] = static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE] * 2.6f);
wNewAttributeValue[Item::Attribute::EVADE] = static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE_REVISION] * 0.7f);
wNewAttributeValue[Item::Attribute::MAX_HP] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_HP] * 0.6f);
wNewAttributeValue[Item::Attribute::HP_REGEN] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_MP] * 1.2f);
wNewAttributeValue[Item::Attribute::MAGIC_RESIST] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.32f +
wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 0.32f);
wInvalidAttribute[OldItem::Attribute::DEFENCE] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_HP] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_MP] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
break;
case Item::ItemType::DEX_ARMOUR:
case Item::ItemType::DEX_BODY:
/*
구항목 신항목 계산식 구항목 최대값.
방어력 방어력 구 방어력 * 2.6 72
방어보정 회피 구 방어보정 * 0.7 58
HP Max HP Max 구 HP Max * 0.6 54
MP Max HP 회복 구 MP Max * 1.2 69
저항력 마법저항 구 저항력 * 0.32 + 구 블록 * 0.32 30
블록 11
*/
CHECK_ATTR(nOverflowIndex, 72, wAttributeValue, OldItem::Attribute::DEFENCE);
CHECK_ATTR(nOverflowIndex, 58, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 54, wAttributeValue, OldItem::Attribute::MAX_HP);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MAX_MP);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 11, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
wNewAttributeValue[Item::Attribute::ARMOR] = static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE] * 2.6f);
wNewAttributeValue[Item::Attribute::EVADE] = static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE_REVISION] * 0.7f);
wNewAttributeValue[Item::Attribute::MAX_HP] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_HP] * 0.6f);
wNewAttributeValue[Item::Attribute::HP_REGEN] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_MP] * 1.2f);
wNewAttributeValue[Item::Attribute::MAGIC_RESIST] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.32f +
wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 0.32f);
wInvalidAttribute[OldItem::Attribute::DEFENCE] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_HP] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_MP] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
break;
case Item::ItemType::CON_HELM:
case Item::ItemType::CON_HEAD:
case Item::ItemType::DEX_HELM:
case Item::ItemType::DEX_HEAD:
/*
구항목 신항목 변경규칙 구항목 최대값
방어력 DropOption * 0.9 0
회피 DropOption * 0.225 0
HP 회복 HP Max 구 HP Max * 0.6 39
MP 회복 HP 회복 구 MP Max * 1.2 39
저항력 마법저항 구 저항력 * 0.5 22
*/
CHECK_ATTR(nOverflowIndex, 39, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 39, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 22, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
wNewAttributeValue[Item::Attribute::ARMOR] = static_cast<short>(wDropOption * 0.9);
wNewAttributeValue[Item::Attribute::EVADE] = static_cast<short>(wDropOption * 0.225);
wNewAttributeValue[Item::Attribute::MAX_HP] = static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6);
wNewAttributeValue[Item::Attribute::HP_REGEN] = static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2);
wNewAttributeValue[Item::Attribute::MAGIC_RESIST] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.5);
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
break;
case Item::ItemType::DAGGER:
case Item::ItemType::OPP_TALON:
/*
구항목 신항목 변경규칙 구항목 최대값
mDmg mDmg 구 mDmg * 2.2 43
MDmg MDmg 구 MDmg * 1.6 64
공격보정 명중 구 공격보정 * 3.8 43
HP 회복 MPMax 구 HP 회복 * 0.6 30
MP 회복 MP회복 구 MP 회복 * 1.2 30
블록 블록 구 블록 * 1.2 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 2.2f);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.6f);
wNewAttributeValue[Item::Attribute::HIT_RATE] = static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 3.8f);
wNewAttributeValue[Item::Attribute::MAX_MP] = static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f);
wNewAttributeValue[Item::Attribute::MP_REGEN] = static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f);
wNewAttributeValue[Item::Attribute::BLOCK] = static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.2f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::SKILL_A_KNIFE:
/*
구항목 신항목 변경규칙 구항목 최대값
mDmg mDmg 구 mDmg * 2.2 43
MDmg MDmg 구 MDmg * 1.6 64
공격보정 명중 구 공격보정 * 1.9 + 구 방어보정 * 1.9 43
방어보정 43
HP 회복 MPMax 구 HP 회복 * 0.6 69
MP 회복 MP회복 구 MP 회복 * 1.2 69
저항력 블록 구 저항력 * 0.2 + 구 블록 * 1 8
블록 블록 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 8, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 2.2f);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.6f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 1.9f +
wAttributeValue[OldItem::Attribute::DEFENCE_REVISION] * 1.9f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f);
wNewAttributeValue[Item::Attribute::BLOCK] =
static_cast<short>(
wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.2f +
wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.0f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::ONEHANDED_SWORD:
case Item::ItemType::ONEHANDED_AXE:
case Item::ItemType::ONEHANDED_BLUNT:
case Item::ItemType::COM_BLUNT:
case Item::ItemType::COM_SWORD:
case Item::ItemType::OPP_HAMMER:
case Item::ItemType::OPP_AXE:
case Item::ItemType::OPP_SLUSHER:
/*
구항목 신항목 계산식 구항목최대값
mDmg mDmg 구 mDmg * 3.2 43
MDmg MDmg 구 MDmg * 1.8 64
공격보정 명중 구 공격보정 * 3.8 43
HP 회복 MPMax 구 HP 회복 * 0.6 + DropOption * 0.15 30
MP 회복 MP회복 구 MP 회복 * 1.2 + DropOption * 0.15 30
블록 블록 구 블록 * 1.2 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 3.2);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.8f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 3.8f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::BLOCK] = static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.2f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::BOW:
case Item::ItemType::CROSSBOW:
/*
구항목 신항목 계산식 구항목최대값
mDmg mDmg 구 mDmg * 3.2 43
MDmg MDmg 구 MDmg * 1.8 64
공격보정 명중 구 공격보정 * 3.8 43
HP 회복 MPMax 구 HP 회복 * 0.6 + DropOption * 0.15 30
MP 회복 MP회복 구 MP 회복 * 1.2 + DropOption * 0.15 30
블록 블록 구 블록 * 1.2 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 3.2f);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.8f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 3.8f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::BLOCK] = static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.2f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::SKILL_A_ATTACK:
/*
구항목 신항목 계산식 구항목최대값
mDmg mDmg 구 mDmg * 3.2 43
MDmg MDmg 구 MDmg * 1.8 64
공격보정 명중 구 공격보정 * 1.9 + 구 방어보정 * 1.9 43
방어보정 43
HP 회복 MPMax 구 HP 회복 * 0.6 69
MP 회복 MP회복 구 MP 회복 * 1.2 69
블록 블록 구 저항력 * 0.2 + 구 블록 * 1 10
저항력 30
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 3.2f);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.8f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 1.9f +
wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 1.9f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f);
wNewAttributeValue[Item::Attribute::BLOCK] =
static_cast<short>(
wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.2f +
wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::SKILL_A_GUN:
/*
구항목 신항목 계산식 구항목최대값
mDmg mDmg 구 mDmg * 3.2 43
MDmg MDmg 구 MDmg * 1.8 64
공격보정 명중 구 공격보정 * 1.9 + 구 방어보정 * 1.9 43
방어보정 43
HP 회복 MPMax 구 HP 회복 * 0.6 69
MP 회복 MP회복 구 MP 회복 * 1.2 69
블록 블록 구 저항력 * 0.2 + 구 블록 * 1 10
저항력 30
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 3.2f);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 1.8f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 1.9f +
wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 1.9f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f);
wNewAttributeValue[Item::Attribute::BLOCK] =
static_cast<short>(
wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.2f +
wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::TWOHANDED_SWORD:
case Item::ItemType::TWOHANDED_AXE:
case Item::ItemType::TWOHANDED_BLUNT:
/*
구항목 신항목 계산식 구항목최대값
mDmg mDmg 구 mDmg * 2.8 43
MDmg MDmg 구 MDmg * 3.0 64
공격보정 명중 구 공격보정 * 3.8 43
HP 회복 MPMax 구 HP 회복 * 0.6 + DropOption * 0.15 30
MP 회복 MP회복 구 MP 회복 * 1.2 + DropOption * 0.15 30
블록 블록 구 블록 * 1.2 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MIN_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 2.8);
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] = static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 3.0);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 3.8f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f + wDropOption * 0.15f);
wNewAttributeValue[Item::Attribute::BLOCK] = static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.2f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
case Item::ItemType::STAFF:
case Item::ItemType::OPP_SYTHE:
/*
구항목 신항목 계산식 구항목최대값
mDmg 마법력 구 mDmg * 8 43
MDmg MDmg 구 MDmg * 3.0 64
공격보정 명중 구 공격보정 * 3.8 43
HP 회복 MPMax 구 HP 회복 * 0.6 + DropOption * 0.3 45
MP 회복 MP회복 구 MP 회복 * 1.2 + DropOption * 0.3 45
블록 블록 구 블록 * 1.2 10
크리티컬 크리티컬 구 크리티컬 * 1 20
*/
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::MIN_DAMAGE);
CHECK_ATTR(nOverflowIndex, 64, wAttributeValue, OldItem::Attribute::MAX_DAMAGE);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::OFFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 45, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 45, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 10, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 20, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MAGIC_POWER] = wAttributeValue[OldItem::Attribute::MIN_DAMAGE] * 8;
wNewAttributeValue[Item::Attribute::MAX_DAMAGE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MAX_DAMAGE] * 3.0f);
wNewAttributeValue[Item::Attribute::HIT_RATE] =
static_cast<short>(wAttributeValue[OldItem::Attribute::OFFENCE_REVISION] * 3.8f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.6f + wDropOption * 0.3f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 1.2f + wDropOption * 0.3f);
wNewAttributeValue[Item::Attribute::BLOCK] = static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.2f);
wNewAttributeValue[Item::Attribute::CRITICAL] = wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 1;
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::OFFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
// 무쉬!
wInvalidAttribute[OldItem::Attribute::MAX_MP] = 0;
break;
case Item::ItemType::SHIELD:
case Item::ItemType::SKILL_A_GUARD:
/*
구항목 신항목 계산식 구항목최대값
방어력 HPMax 구 방어력 * 0.1 22
HP 회복 HP회복 구 HP 회복 * 0.1 69
방어보정 MPMax 구 방어보정 * 0.1 43
MP 회복 MP회복 구 MP 회복 * 0.1 69
블록 블록 구 블록 * 1 + 구 마법 저항 * 0.2 + 구 크리티컬 * 0.2 36
저항력 30
크리티컬 15
*/
CHECK_ATTR(nOverflowIndex, 22, wAttributeValue, OldItem::Attribute::DEFENCE);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::HP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 43, wAttributeValue, OldItem::Attribute::DEFENCE_REVISION);
CHECK_ATTR(nOverflowIndex, 69, wAttributeValue, OldItem::Attribute::MP_REGEN_AMOUNT);
CHECK_ATTR(nOverflowIndex, 36, wAttributeValue, OldItem::Attribute::BLOCKING_PERCENTAGE);
CHECK_ATTR(nOverflowIndex, 30, wAttributeValue, OldItem::Attribute::MAGIC_RESISTANCE);
CHECK_ATTR(nOverflowIndex, 22, wAttributeValue, OldItem::Attribute::CRITICAL_PERCENTAGE);
wNewAttributeValue[Item::Attribute::MAX_HP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE] * 0.1f);
wNewAttributeValue[Item::Attribute::HP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::HP_REGEN_AMOUNT] * 0.1f);
wNewAttributeValue[Item::Attribute::MAX_MP] =
static_cast<short>(wAttributeValue[OldItem::Attribute::DEFENCE_REVISION] * 0.1f);
wNewAttributeValue[Item::Attribute::MP_REGEN] =
static_cast<short>(wAttributeValue[OldItem::Attribute::MP_REGEN_AMOUNT] * 0.1f);
wNewAttributeValue[Item::Attribute::BLOCK] =
static_cast<short>(wAttributeValue[OldItem::Attribute::BLOCKING_PERCENTAGE] * 1.0f +
wAttributeValue[OldItem::Attribute::MAGIC_RESISTANCE] * 0.2f +
wAttributeValue[OldItem::Attribute::CRITICAL_PERCENTAGE] * 0.2f);
// 무쉬!
wInvalidAttribute[OldItem::Attribute::MIN_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAX_DAMAGE] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE] = 0;
wInvalidAttribute[OldItem::Attribute::DEFENCE_REVISION] = 0;
wInvalidAttribute[OldItem::Attribute::HP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::MP_REGEN_AMOUNT] = 0;
wInvalidAttribute[OldItem::Attribute::BLOCKING_PERCENTAGE] = 0;
wInvalidAttribute[OldItem::Attribute::MAGIC_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::CRITICAL_PERCENTAGE] = 0;
break;
}
// wNewAttributeValue를 0이 아닌 항목만 골라서 szOutDataPos에 저장한다.
short* lpNewAttributeValuePos = wNewAttributeValue;
short* lpNewAttributeValueEnd = wNewAttributeValue + Item::Attribute::MAX_ATTRIBUTE_NUM;
for(int nAttrPos = 0; lpNewAttributeValuePos != lpNewAttributeValueEnd; ++lpNewAttributeValuePos, ++nAttrPos)
{
if(*lpNewAttributeValuePos < 0)
{
*lpNewAttributeValuePos = 0;
}
else if(0 < *lpNewAttributeValuePos)
{
Item::ItemAttribute itemAttribute;
itemAttribute.m_cType = nAttrPos;
itemAttribute.m_usValue = *lpNewAttributeValuePos;
COPY_AND_ADVANCE_DST(szOutDataPos, &itemAttribute, sizeof(Item::ItemAttribute));
}
}
wInvalidAttribute[OldItem::Attribute::ATTACK_RANGE] = 0;
wInvalidAttribute[OldItem::Attribute::FIRE_ATTACK] = 0;
wInvalidAttribute[OldItem::Attribute::LIGHTNING_ATTACK] = 0;
wInvalidAttribute[OldItem::Attribute::COLD_ATTACK] = 0;
wInvalidAttribute[OldItem::Attribute::DRAIN_ATTACK] = 0;
wInvalidAttribute[OldItem::Attribute::POISON_ATTACK] = 0;
wInvalidAttribute[OldItem::Attribute::FIRE_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::LIGHTNING_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::COLD_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::DRAIN_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::POISON_RESISTANCE] = 0;
wInvalidAttribute[OldItem::Attribute::ADD_STR] = 0;
wInvalidAttribute[OldItem::Attribute::ADD_DEX] = 0;
wInvalidAttribute[OldItem::Attribute::ADD_CON] = 0;
wInvalidAttribute[OldItem::Attribute::ADD_INT] = 0;
wInvalidAttribute[OldItem::Attribute::ADD_WIS] = 0;
if(nOverflowIndex == OldItem::Attribute::MAX_ATTRIBUTE_NUM)
{
for(nOverflowIndex = 0; nOverflowIndex < OldItem::Attribute::MAX_ATTRIBUTE_NUM; ++nOverflowIndex)
{
if(0 != wInvalidAttribute[nOverflowIndex])
{
break;
}
}
}
Item::Grade::GradeInfo gradeInfo = GetGradeInfo(wNewAttributeValue,
Item::Attribute::MAX_ATTRIBUTE_NUM, *lpNewItemInfo);
++g_GradeNum[gradeInfo.m_eItemGrade];
if(gradeInfo.m_eItemGrade <= Item::EquipType::B_GRADE)
{
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
int nTotalLength = _snprintf(szBuffer, MAX_BUFFER - 1,
"ItemGrade is %s.\tUID:%10u\tCID:%10u\tItemUID:0x%016I64X\tItemSize:%3u\tPrototypeID:%5u\t"
"\tItemName:%20s\t%d\tItemType:%20s\t",
GetGradeString(gradeInfo.m_eItemGrade), dwUID, dwCID,
lpItemData->m_dwUID, lpItemData->m_cItemSize, lpItemData->m_usProtoTypeID,
lpNewItemInfo->m_SpriteData.m_szName,
lpNewItemInfo->m_UseLimit.m_wLimitValue,
lpNewItemInfo->m_StringData.m_szTypeName);
short* lpAttributeValuePos = wNewAttributeValue;
short* lpAttributeValueEnd = wNewAttributeValue + Item::Attribute::MAX_ATTRIBUTE_NUM;
Item::EquipType::Grade* lpGradePos = gradeInfo.m_aryAttributeGrade;
Item::EquipType::Grade* lpGradeEnd = gradeInfo.m_aryAttributeGrade +
Item::Attribute::MAX_ATTRIBUTE_NUM;
for(int nCount = 0;
lpAttributeValuePos != lpAttributeValueEnd; ++lpAttributeValuePos, ++lpGradePos, ++nCount)
{
if(*lpGradePos == gradeInfo.m_eItemGrade)
{
int nLength = _snprintf(szBuffer + nTotalLength,
MAX_BUFFER - nTotalLength -1, "%s:%3d(%s)\t",
Item::Attribute::Attributes[nCount].GetTypeName(),
(*lpAttributeValuePos), GetGradeString(*lpGradePos));
if(0 < nLength)
{
nTotalLength += nLength;
}
}
}
DETLOG0(g_Log, szBuffer);
}
if(nOverflowIndex != OldItem::Attribute::MAX_ATTRIBUTE_NUM)
{
const int MAX_BUFFER = 1024;
char szBuffer[MAX_BUFFER];
int nTotalLength = _snprintf(szBuffer, MAX_BUFFER - 1,
"Item attribute is invalid.\tUID:%10u\tCID:%10u\tItemUID:0x%016I64X\tItemSize:%3u\tPrototypeID:%5u\tItemType:%20s\tInvalidAttr:%s\t",
dwUID, dwCID, lpItemData->m_dwUID, lpItemData->m_cItemSize, lpItemData->m_usProtoTypeID,
OldItem::CItemType::GetInstance().GetItemTypeName()[cItemType].GetTypeName(),
OldItem::Attribute::Attributes[nOverflowIndex].GetTypeName());
short* lpAttributeValuePos = wOldAttributeValue;
short* lpAttributeValueEnd = wOldAttributeValue + OldItem::Attribute::MAX_ATTRIBUTE_NUM;
for(; lpAttributeValuePos != lpAttributeValueEnd; ++lpAttributeValuePos)
{
int nLength = _snprintf(szBuffer + nTotalLength, MAX_BUFFER - nTotalLength -1, "%3d\t", *lpAttributeValuePos);
if(0 < nLength)
{
nTotalLength += nLength;
}
}
DETLOG0(g_Log, szBuffer);
}
dwRemainBufferSize_InOut = static_cast<unsigned long>(szOutDataPos - szOutData);
reinterpret_cast<OldItem::ItemData*>(szOutData)->m_cItemSize = static_cast<unsigned char>(dwRemainBufferSize_InOut);
}
else
{
DETLOG3(g_Log, "Not enough datasize : UID:%10u/CID:%10u/current(%u)", dwUID, dwCID, dwRemainBufferSize_InOut);
return false;
}
return true;
}
int ProcessCharItem(ATL::CSession& readSession, ATL::CSession& writeSession, bool bProcessDelHistory, bool bWriteDB)
{
// 데이터베이스 커맨드 생성 - 아이템 읽기. 장비, 인벤토리, 기타, 교환창
CGetUserItemData::Command getCharItemCommand;
CSetUserItemData::Command setCharItemCommand;
int nCount = 0;
HRESULT hr = setCharItemCommand.Create(writeSession, bProcessDelHistory ?
L"UPDATE CharDelHistory..DelCharItem SET Equip=?, Inventory=?, Extra=? WHERE UID=?" :
L"UPDATE CharItem SET Equip=?, Inventory=?, Extra=? WHERE UID=?", DBGUID_SQL);
ERROR_HRESULT_RETURN("Create setCharItemCommand failed.", hr, -1);
hr = setCharItemCommand.Prepare();
ERROR_HRESULT_RETURN("Prepare setCharItemCommand failed.", hr, -1);
hr = getCharItemCommand.Open(readSession, bProcessDelHistory ?
L"Select UID, Equip, Inventory, Extra from CharDelHistory..DelCharItem" :
L"Select UID, Equip, Inventory, Extra from CharItem");
ERROR_HRESULT_RETURN("Get Equip, Inventory, Extra failed", hr, -1);
getCharItemCommand.Init();
setCharItemCommand.Init();
// 장비, 인벤, Extra, 교환창 컨버팅.
while (S_OK == getCharItemCommand.MoveNext())
{
// 데이터 세팅
setCharItemCommand.m_nCID = getCharItemCommand.m_nCID;
setCharItemCommand.m_EquipLength = getCharItemCommand.m_EquipLength;
setCharItemCommand.m_InvenLength = getCharItemCommand.m_InvenLength;
setCharItemCommand.m_ExtraLength = getCharItemCommand.m_ExtraLength;
// -----------------------------------------------------------------------
// 장비 세팅 및 컨버팅
EQUIP* lpGetEquip = reinterpret_cast<EQUIP*>(getCharItemCommand.m_Equip);
EQUIP* lpSetEquip = reinterpret_cast<EQUIP*>(setCharItemCommand.m_Equip);
if(sizeof(unsigned long) <= lpGetEquip->dwSize) { lpGetEquip->dwSize -= sizeof(unsigned long); }
lpSetEquip->dwSize = EQUIP::MAX_EQUIP_SIZE;
ParseItemData(0, getCharItemCommand.m_nCID, lpGetEquip->Data, lpGetEquip->dwSize,
lpSetEquip->Data, lpSetEquip->dwSize);
lpSetEquip->dwSize += sizeof(unsigned long);
// -----------------------------------------------------------------------
// 인벤토리 세팅 및 컨버팅
INVEN* lpGetInven = reinterpret_cast<INVEN*>(getCharItemCommand.m_Inven);
INVEN* lpSetInven = reinterpret_cast<INVEN*>(setCharItemCommand.m_Inven);
if(sizeof(unsigned long) <= lpGetInven->dwSize) { lpGetInven->dwSize -= sizeof(unsigned long); }
lpSetInven->dwSize = INVEN::MAX_INVEN_SIZE;
ParseItemData(0, getCharItemCommand.m_nCID, lpGetInven->Data, lpGetInven->dwSize,
lpSetInven->Data, lpSetInven->dwSize);
lpSetInven->dwSize += sizeof(unsigned long);
// -----------------------------------------------------------------------
// Extra 세팅 및 컨버팅
EXTRA* lpGetExtra = reinterpret_cast<EXTRA*>(getCharItemCommand.m_Extra);
EXTRA* lpSetExtra = reinterpret_cast<EXTRA*>(setCharItemCommand.m_Extra);
if(sizeof(unsigned long) <= lpGetExtra->dwSize) { lpGetExtra->dwSize -= sizeof(unsigned long); }
lpSetExtra->dwSize = EXTRA::MAX_EXTRA_SIZE;
ParseItemData(0, getCharItemCommand.m_nCID, lpGetExtra->Data, lpGetExtra->dwSize,
lpSetExtra->Data, lpSetExtra->dwSize);
lpSetExtra->dwSize += sizeof(unsigned long);
// -----------------------------------------------------------------------
// 데이터 업데이트 및 데이터 초기화
if (0 != memcmp(lpGetEquip, lpSetEquip, sizeof(EQUIP)) ||
0 != memcmp(lpGetInven, lpSetInven, sizeof(INVEN)) ||
0 != memcmp(lpGetExtra, lpSetExtra, sizeof(EXTRA)))
{
// 업데이트
if(bWriteDB)
{
hr = setCharItemCommand.Open();
if(FAILED(hr))
{
ERRLOG2(g_Log, "CharItem : CID:%10u write failed(hr:0x%08x)", getCharItemCommand.m_nCID, hr);
}
}
}
// 초기화
getCharItemCommand.Init();
setCharItemCommand.Init();
if(0 == (++nCount % SHOW_NUM_PER_PROCESS))
{
printf("%d\n", nCount);
}
}
return 0;
}
int ProcessCharItemEx(ATL::CSession& readSession, ATL::CSession& writeSession, bool bProcessDelHistory, bool bWriteDB)
{
CGetUserItemDataEx::Command getCharItemExCommand;
CSetUserItemDataEx::Command setCharItemExCommand;
int nCount = 0;
HRESULT hr = setCharItemExCommand.Create(writeSession, bProcessDelHistory ?
L"UPDATE CharDelHistory..DelCharItemEx SET Exchange=? WHERE UID=?" :
L"UPDATE CharItemEx SET Exchange=? WHERE UID=?", DBGUID_SQL);
ERROR_HRESULT_RETURN("Create setCharItemExCommand failed.", hr, -1);
hr = setCharItemExCommand.Prepare();
ERROR_HRESULT_RETURN("Prepare setCharItemCommandEx failed.", hr, -1);
hr = getCharItemExCommand.Open(readSession, bProcessDelHistory ?
L"Select UID, Exchange from CharDelHistory..DelCharItemEx" : L"Select UID, Exchange from CharItemEx");
ERROR_HRESULT_RETURN("Get Equip, Inventory, Extra failed", hr, -1);
getCharItemExCommand.Init();
setCharItemExCommand.Init();
while(S_OK == getCharItemExCommand.MoveNext())
{
setCharItemExCommand.m_nCID = getCharItemExCommand.m_nCID;
setCharItemExCommand.m_ExchangeLength = getCharItemExCommand.m_ExchangeLength;
// -----------------------------------------------------------------------
// Exchage 세팅 및 컨버팅
EXCHANGE* lpGetExchange = reinterpret_cast<EXCHANGE*>(getCharItemExCommand.m_Exchange);
EXCHANGE* lpSetExchange = reinterpret_cast<EXCHANGE*>(setCharItemExCommand.m_Exchange);
if(sizeof(unsigned long) <= lpGetExchange->dwSize) { lpGetExchange->dwSize -= sizeof(unsigned long); }
lpSetExchange->dwSize = EXCHANGE::MAX_EXCHANGE_SIZE;
ParseItemData(0, getCharItemExCommand.m_nCID, lpGetExchange->Data, lpGetExchange->dwSize,
lpSetExchange->Data, lpSetExchange->dwSize);
lpSetExchange->dwSize += sizeof(unsigned long);
if(0 != memcmp(lpGetExchange, lpSetExchange, sizeof(EXCHANGE)))
{
// 업데이트
if(bWriteDB)
{
hr = setCharItemExCommand.Open();
if(FAILED(hr))
{
ERRLOG2(g_Log, "CharItemEx : CID:%10u write failed(hr:0x%08x)", getCharItemExCommand.m_nCID, hr);
}
}
}
getCharItemExCommand.Init();
setCharItemExCommand.Init();
if(0 == (++nCount % SHOW_NUM_PER_PROCESS))
{
printf("%d\n", nCount);
}
}
return 0;
}
int ProcessStore(ATL::CSession& readSession, ATL::CSession& writeSession, int nStoreNum, bool bWriteDB)
{
CGetStoreItemData::Command getStoreItemData;
CSetStoreItemData::Command setStoreItemData;
// 데이터베이스 커맨드 생성 - 아이템 기록.
LPCWSTR szUpdateQuery = 0;
LPCWSTR szSelectQuery = 0;
switch (nStoreNum)
{
case 1:
szUpdateQuery = L"UPDATE ItemStore1 SET Store=? WHERE UID=?";
szSelectQuery = L"SELECT UID, Store from ItemStore1";
break;
case 2:
szUpdateQuery = L"UPDATE ItemStore2 SET Store=? WHERE UID=?";
szSelectQuery = L"SELECT UID, Store from ItemStore2";
break;
}
if(0 == szUpdateQuery || 0 == szSelectQuery)
{
return -1;
}
int nCount = 0;
HRESULT hr = setStoreItemData.Create(writeSession, szUpdateQuery, DBGUID_SQL);
ERROR_HRESULT_RETURN("Create setStoreItemData failed.", hr, -1);
hr = setStoreItemData.Prepare();
ERROR_HRESULT_RETURN("Prepare setStoreItemData failed.", hr, -1);
// 창고 컨버팅
hr = getStoreItemData.Open(readSession, szSelectQuery);
ERROR_HRESULT_RETURN("Get Store1, Store2 failed", hr, -1);
getStoreItemData.Init();
setStoreItemData.Init();
while(S_OK == getStoreItemData.MoveNext())
{
setStoreItemData.m_nUID = getStoreItemData.m_nUID;
setStoreItemData.m_StoreLength = getStoreItemData.m_StoreLength;
// 창고 컨버팅
STORE* lpGetStore = reinterpret_cast<STORE*>(getStoreItemData.m_Store);
STORE* lpSetStore = reinterpret_cast<STORE*>(setStoreItemData.m_Store);
if(sizeof(unsigned long) <= lpGetStore->dwSize) { lpGetStore->dwSize -= sizeof(unsigned long); }
lpSetStore->dwSize = STORE::MAX_STORE_SIZE;
ParseItemData(0, getStoreItemData.m_nUID, lpGetStore->Data, lpGetStore->dwSize,
lpSetStore->Data, lpSetStore->dwSize);
lpSetStore->dwSize += sizeof(unsigned long);
if(0 != memcmp(lpGetStore, lpSetStore, sizeof(STORE)))
{
// 업데이트
if(bWriteDB)
{
hr = setStoreItemData.Open();
if(FAILED(hr))
{
ERRLOG2(g_Log, "Store : UID:%10u write failed(hr:0x%08x)", getStoreItemData.m_nUID, hr);
}
}
}
getStoreItemData.Init();
setStoreItemData.Init();
if(0 == (++nCount % SHOW_NUM_PER_PROCESS))
{
printf("%d\n", nCount);
}
}
return 0;
}
Item::Grade::GradeInfo GetGradeInfo(short* wNewAttribute, const int nMaxAttributeNum,
const Item::ItemInfo& newItemInfo)
{
using namespace Item;
// -------------------------------------------------------------------------------------------------
// 가치 그레이드 테이블
static const float aryArmorValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 0, 0, 1.8f, 0, 0.45f, 0.9f, 1.8f, 0, 0, 0, 0, 0, 0, 0.18f }, // Grade AAA
{ 0, 0, 0, 1.5f, 0, 0.375f, 0.75f, 1.5f, 0, 0, 0, 0, 0, 0, 0.15f }, // Grade AA
{ 0, 0, 0, 1.2f, 0, 0.3f, 0.6f, 1.2f, 0, 0, 0, 0, 0, 0, 0.12f }, // Grade A
{ 0, 0, 0, 0.9f, 0, 0.225f, 0.45f, 0.9f, 0, 0, 0, 0, 0, 0, 0.09f }, // Grade B
{ 0, 0, 0, 0.6f, 0, 0.15f, 0.3f, 0.6f, 0, 0, 0, 0, 0, 0, 0.06f }, // Grade C
{ 0, 0, 0, 0.3f, 0, 0.075f, 0.15f, 0.3f, 0, 0, 0, 0, 0, 0, 0.03f }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryDaggerValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 0.9f, 1.26f, 0, 1.8f, 0, 0, 0, 0.9f, 1.8f, 0.36f, 0.36f, 0, 0, 0 }, // Grade AAA
{ 0, 0.75f, 1.05f, 0, 1.5f, 0, 0, 0, 0.75f, 1.5f, 0.3f, 0.3f, 0, 0, 0 }, // Grade AA
{ 0, 0.6f, 0.84f, 0, 1.2f, 0, 0, 0, 0.6f, 1.2f, 0.24f, 0.24f, 0, 0, 0 }, // Grade A
{ 0, 0.45f, 0.63f, 0, 0.9f, 0, 0, 0, 0.45f, 0.9f, 0.18f, 0.18f, 0, 0, 0 }, // Grade B
{ 0, 0.3f, 0.42f, 0, 0.6f, 0, 0, 0, 0.3f, 0.6f, 0.12f, 0.12f, 0, 0, 0 }, // Grade C
{ 0, 0.15f, 0.21f, 0, 0.3f, 0, 0, 0, 0.15f, 0.3f, 0.06f, 0.06f, 0, 0, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryOneHandedWeaponValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 1.08f, 1.44f, 0, 1.8f, 0, 0, 0, 0.9f, 1.8f, 0.36f, 0.36f, 0, 0, 0 }, // Grade AAA
{ 0, 0.9f, 1.2f, 0, 1.5f, 0, 0, 0, 0.75f, 1.5f, 0.3f, 0.3f, 0, 0, 0 }, // Grade AA
{ 0, 0.72f, 0.96f, 0, 1.2f, 0, 0, 0, 0.6f, 1.2f, 0.24f, 0.24f, 0, 0, 0 }, // Grade A
{ 0, 0.54f, 0.72f, 0, 0.9f, 0, 0, 0, 0.45f, 0.9f, 0.18f, 0.18f, 0, 0, 0 }, // Grade B
{ 0, 0.36f, 0.48f, 0, 0.6f, 0, 0, 0, 0.3f, 0.6f, 0.12f, 0.12f, 0, 0, 0 }, // Grade C
{ 0, 0.18f, 0.24f, 0, 0.3f, 0, 0, 0, 0.15f, 0.3f, 0.06f, 0.06f, 0, 0, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryLongRangeWeaponValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 1.08f, 1.44f, 0, 1.8f, 0, 0, 0, 0.9f, 1.8f, 0.36f, 0.36f, 0, 0, 0 }, // Grade AAA
{ 0, 0.9f, 1.2f, 0, 1.5f, 0, 0, 0, 0.75f, 1.5f, 0.3f, 0.3f, 0, 0, 0 }, // Grade AA
{ 0, 0.72f, 0.96f, 0, 1.2f, 0, 0, 0, 0.6f, 1.2f, 0.24f, 0.24f, 0, 0, 0 }, // Grade A
{ 0, 0.54f, 0.72f, 0, 0.9f, 0, 0, 0, 0.45f, 0.9f, 0.18f, 0.18f, 0, 0, 0 }, // Grade B
{ 0, 0.36f, 0.48f, 0, 0.6f, 0, 0, 0, 0.3f, 0.6f, 0.12f, 0.12f, 0, 0, 0 }, // Grade C
{ 0, 0.18f, 0.24f, 0, 0.3f, 0, 0, 0, 0.15f, 0.3f, 0.06f, 0.06f, 0, 0, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryTwoHandedWeaponValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 1.08f, 1.8f, 0, 1.8f, 0, 0, 0, 0.9f, 1.8f, 0.36f, 0.36f, 0, 0, 0 }, // Grade AAA
{ 0, 0.9f, 1.5f, 0, 1.5f, 0, 0, 0, 0.75f, 1.5f, 0.3f, 0.3f, 0, 0, 0 }, // Grade AA
{ 0, 0.72f, 1.2f, 0, 1.2f, 0, 0, 0, 0.6f, 1.2f, 0.24f, 0.24f, 0, 0, 0 }, // Grade A
{ 0, 0.54f, 0.9f, 0, 0.9f, 0, 0, 0, 0.45f, 0.9f, 0.18f, 0.18f, 0, 0, 0 }, // Grade B
{ 0, 0.36f, 0.6f, 0, 0.6f, 0, 0, 0, 0.3f, 0.6f, 0.12f, 0.12f, 0, 0, 0 }, // Grade C
{ 0, 0.18f, 0.3f, 0, 0.3f, 0, 0, 0, 0.15f, 0.3f, 0.06f, 0.06f, 0, 0, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryStaffValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 0, 1.8f, 0, 1.8f, 0, 0, 0, 1.8f, 3.6f, 0.36f, 0.36f, 0, 1.8f, 0 }, // Grade AAA
{ 0, 0, 1.5f, 0, 1.5f, 0, 0, 0, 1.5f, 3.0f, 0.3f, 0.3f, 0, 1.5f, 0 }, // Grade AA
{ 0, 0, 1.2f, 0, 1.2f, 0, 0, 0, 1.2f, 2.4f, 0.24f, 0.24f, 0, 1.2f, 0 }, // Grade A
{ 0, 0, 0.9f, 0, 0.9f, 0, 0, 0, 0.9f, 1.8f, 0.18f, 0.18f, 0, 0.9f, 0 }, // Grade B
{ 0, 0, 0.6f, 0, 0.6f, 0, 0, 0, 0.6f, 1.2f, 0.12f, 0.12f, 0, 0.6f, 0 }, // Grade C
{ 0, 0, 0.3f, 0, 0.3f, 0, 0, 0, 0.3f, 0.6f, 0.06f, 0.06f, 0, 0.3f, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
static const float aryShieldValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = {
// MinDam. MaxDam. Armor HitRate Evade MaxHP HPRegen MaxMP MPRegen Cri. Block Speed M.Power M.Res.
{ 0, 0, 0, 0, 0, 0, 0.45f, 0.9f, 0.45f, 0.9f, 0, 0.36f, 0, 0, 0 }, // Grade AAA
{ 0, 0, 0, 0, 0, 0, 0.375f, 0.75f, 0.375f, 0.75f, 0, 0.3f, 0, 0, 0 }, // Grade AA
{ 0, 0, 0, 0, 0, 0, 0.3f, 0.6f, 0.3f, 0.6f, 0, 0.24f, 0, 0, 0 }, // Grade A
{ 0, 0, 0, 0, 0, 0, 0.225f, 0.45f, 0.225f, 0.45f, 0, 0.18f, 0, 0, 0 }, // Grade B
{ 0, 0, 0, 0, 0, 0, 0.15f, 0.3f, 0.15f, 0.3f, 0, 0.12f, 0, 0, 0 }, // Grade C
{ 0, 0, 0, 0, 0, 0, 0.075f, 0.15f, 0.075f, 0.15f, 0, 0.06f, 0, 0, 0 }, // Grade D
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Grade F
};
// -------------------------------------------------------------------------------------------------
if (0 == newItemInfo.m_DetailData.m_wDropOption)
{
return Item::Grade::GradeInfo();
}
float aryUsingValueGradeTable[EquipType::MAX_GRADE][Attribute::MAX_ATTRIBUTE_NUM] = { 0, };
switch (newItemInfo.m_DetailData.m_cItemType)
{
case ItemType::CON_ARMOUR: case ItemType::DEX_ARMOUR:
case ItemType::CON_HELM: case ItemType::DEX_HELM:
case ItemType::CON_BODY: case ItemType::DEX_BODY:
case ItemType::CON_HEAD: case ItemType::DEX_HEAD:
memcpy(aryUsingValueGradeTable, aryArmorValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::DAGGER:
case ItemType::OPP_TALON:
case ItemType::SKILL_A_KNIFE:
memcpy(aryUsingValueGradeTable, aryDaggerValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::ONEHANDED_SWORD:
case ItemType::ONEHANDED_AXE:
case ItemType::ONEHANDED_BLUNT:
case ItemType::COM_BLUNT:
case ItemType::COM_SWORD:
case ItemType::OPP_HAMMER:
case ItemType::OPP_SLUSHER:
case ItemType::SKILL_A_ATTACK:
memcpy(aryUsingValueGradeTable, aryOneHandedWeaponValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::BOW:
case ItemType::CROSSBOW:
case ItemType::SKILL_A_GUN:
memcpy(aryUsingValueGradeTable, aryLongRangeWeaponValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::TWOHANDED_SWORD:
case ItemType::TWOHANDED_AXE:
case ItemType::TWOHANDED_BLUNT:
memcpy(aryUsingValueGradeTable, aryTwoHandedWeaponValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::STAFF:
case ItemType::OPP_SYTHE:
memcpy(aryUsingValueGradeTable, aryStaffValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
case ItemType::SHIELD:
case ItemType::SKILL_A_GUARD:
memcpy(aryUsingValueGradeTable, aryShieldValueGradeTable,
sizeof(float) * EquipType::MAX_GRADE * Attribute::MAX_ATTRIBUTE_NUM);
break;
default:
return Item::Grade::GradeInfo();
}
// 아이템의 그레이드 정보를 초기화
Item::Grade::GradeInfo resultGradeInfo = Item::Grade::GradeInfo();
for (unsigned char cAttributeIndex = 0; cAttributeIndex < Attribute::MAX_ATTRIBUTE_NUM; ++cAttributeIndex)
{
// 속성값이 B 그레이드를 넘으면, B그레이드 값으로 고정한다.
short wMaxAttribute = static_cast<short>(
aryUsingValueGradeTable[EquipType::A_GRADE][cAttributeIndex] *
static_cast<float>(newItemInfo.m_DetailData.m_wDropOption));
if(wMaxAttribute < wNewAttribute[cAttributeIndex])
{
wNewAttribute[cAttributeIndex] = wMaxAttribute;
}
const float fGradeFactor = wNewAttribute[cAttributeIndex] /
static_cast<float>(newItemInfo.m_DetailData.m_wDropOption);
// D 그레이드를 초과하면 F 그레이드가 된다.
for (unsigned char cGradeIndex = 0; cGradeIndex <= EquipType::D_GRADE; ++cGradeIndex)
{
if (0 != aryUsingValueGradeTable[cGradeIndex][cAttributeIndex] &&
fGradeFactor > aryUsingValueGradeTable[cGradeIndex][cAttributeIndex])
{
resultGradeInfo.m_aryAttributeGrade[cAttributeIndex] =
static_cast<EquipType::Grade>(cGradeIndex);
if (resultGradeInfo.m_eItemGrade > resultGradeInfo.m_aryAttributeGrade[cAttributeIndex])
{
resultGradeInfo.m_eItemGrade = resultGradeInfo.m_aryAttributeGrade[cAttributeIndex];
resultGradeInfo.m_cPlus = 0;
}
else
{
if (resultGradeInfo.m_eItemGrade == resultGradeInfo.m_aryAttributeGrade[cAttributeIndex])
{
++resultGradeInfo.m_cPlus;
}
}
break;
}
}
}
return resultGradeInfo;
}
const char* GetGradeString(Item::EquipType::Grade grade)
{
switch(grade)
{
case Item::EquipType::AAA_GRADE: return "AAA";
case Item::EquipType::AA_GRADE: return "AA";
case Item::EquipType::A_GRADE: return "A";
case Item::EquipType::B_GRADE: return "B";
case Item::EquipType::C_GRADE: return "C";
case Item::EquipType::D_GRADE: return "D";
case Item::EquipType::F_GRADE: return "F";
}
return "Unknown";
}