#include "stdafx.h"
// 클라이언트에서도 쓰이므로 include를 명시한다.
#include <algorithm>
#include <Log/ServerLog.h>
#include <Utility/Math/Math.h>
#include <Creature/Character/CharacterClass.h>
#include <Item/ItemMgr.h>
#include <Item/ItemFactory.h>
#ifdef _RYL_GAME_CLIENT_
#include "RYLNetworkData.h"
#endif
#ifndef _RYL_GAME_CLIENT_
#include <Utility/Setup/ServerSetup.h>
#endif
#include "Item.h"
#include "GMMemory.h"
using namespace Item;
static ItemInfo NullProtoType;
CItem::CItem()
: m_ItemInfo(NullProtoType)
{
m_ItemData.m_dwUID = 0;
m_ItemData.m_usProtoTypeID = 0;
m_ItemData.m_ItemPos.m_cPos = 0;
m_ItemData.m_ItemPos.m_cIndex = 0;
m_ItemData.m_cItemSize = sizeof(ItemData);
m_ItemData.m_cNumOrDurability = 0;
m_cMaxNumOrDurability = 0;
m_dwStallPrice = 0;
m_dwPrice = 0;
}
CItem::CItem(const ItemInfo& itemInfo)
: m_ItemInfo(itemInfo)
{
m_ItemData.m_dwUID = 0;
m_ItemData.m_usProtoTypeID = itemInfo.m_usProtoTypeID;
m_ItemData.m_ItemPos.m_cPos = 0;
m_ItemData.m_ItemPos.m_cIndex = 0;
m_ItemData.m_cItemSize = sizeof(ItemData);
m_ItemData.m_cNumOrDurability = m_ItemInfo.m_DetailData.m_cDefaultDurabilityOrStack;
m_cMaxNumOrDurability = m_ItemInfo.m_DetailData.m_cMaxDurabilityOrStack;
m_dwStallPrice = 0;
m_dwPrice = m_ItemInfo.m_DetailData.m_dwPrice;
}
CItem::~CItem()
{
}
bool CItem::SerializeOut(char* lpSerializeItem_Out, size_t& nBufferLength_InOut)
{
if (nBufferLength_InOut >= sizeof(ItemData))
{
m_ItemData.m_cItemSize = sizeof(ItemData);
nBufferLength_InOut = sizeof(ItemData);
*reinterpret_cast<ItemData*>(lpSerializeItem_Out) = m_ItemData;
return true;
}
nBufferLength_InOut = 0;
return false;
}
bool CItem::SerializeIn(const char* lpSerializeItem_In, size_t& nBufferLength_InOut)
{
const ItemData& itemData = *reinterpret_cast<const ItemData*>(lpSerializeItem_In);
if (sizeof(ItemData) <= nBufferLength_InOut)
{
nBufferLength_InOut = itemData.m_cItemSize;
if (itemData.m_usProtoTypeID == m_ItemInfo.m_usProtoTypeID)
{
m_ItemData = itemData;
m_itemPos_Real = m_ItemData.m_ItemPos;
return true;
}
}
ERRLOG4(g_Log, "SerializeIn에 실패했습니다. 아이템을 제거합니다. ItemDataSize:%d, nBufferLength_InOut:%d, "
"itemData.m_usProtoTypeID:%d, m_ItemInfo.m_usProtoTypeID:%d",
sizeof(ItemData), sizeof(nBufferLength_InOut), itemData.m_usProtoTypeID, m_ItemInfo.m_usProtoTypeID);
return false;
}
unsigned long CItem::GetBuyPrice(void) const
{
// edith 판매가격
if (0 != m_dwStallPrice)
{
return m_dwStallPrice;
}
if (true == m_ItemInfo.m_DetailData.m_bOptionPrice)
{
// 장비의 구매, 판매, 수리, 제련 가격의 경우 옵션과 내구도에 따라 계산된 가격을 소숫점 이하 올림합니다.
return static_cast<unsigned long>((m_dwPrice *
(100 - (m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) * 0.25f) / 100.0f) + 1);
}
return m_dwPrice;
}
unsigned long CItem::GetSellPrice(void) const
{
if (0 != m_dwStallPrice)
{
return m_dwStallPrice;
}
if (Item::ItemType::GEM_SELL == static_cast<Item::ItemType::Type>(m_ItemInfo.m_DetailData.m_cItemType))
{
return static_cast<unsigned long>(m_dwPrice);
}
unsigned long Price = static_cast<unsigned long>(m_dwPrice / 3.0f);
if (true == m_ItemInfo.m_DetailData.m_bOptionPrice)
{
Price = static_cast<unsigned long>((m_dwPrice * (100 - (m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) * 0.25f) / 100.0f) / 3);
}
if(Price == 0)
Price = 1;
return Price;
/*
if (true == m_ItemInfo.m_DetailData.m_bOptionPrice)
{
return static_cast<unsigned long>(((m_dwPrice *
(100 - (m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) * 0.25f) / 100.0f) / 3) + 1);
}
return static_cast<unsigned long>(m_dwPrice / 3.0f);
*/
}
unsigned long CItem::GetRepairPrice(void) const
{
return static_cast<unsigned long>((m_dwPrice *
((m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) * 0.25f) / 200.0f) + 1);
}
unsigned long CItem::GetUpgradePrice(void) const
{
return static_cast<unsigned long>((m_dwPrice * 0.3f) + 1);
// return static_cast<unsigned long>(((m_dwPrice *
// (100 - (m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) * 0.25f) / 100.0f) / 2) + 1);
}
unsigned long CItem::GetGraftPrice(void) const
{
return static_cast<unsigned long>((m_dwPrice * 0.3f) + 1);
// return static_cast<unsigned long>((m_dwPrice * (100 * 0.25f) / 100.0f) + 1);
}
CEquipment::CEquipment(const ItemInfo& itemInfo)
: CItem(itemInfo), m_cUpgradeLevel(0), m_cSocketNum(0), m_cSeasonRecord(0), m_cCoreLevel(0)
{
if (1 == m_ItemInfo.m_DetailData.m_cXSize && 1 == m_ItemInfo.m_DetailData.m_cYSize)
{
m_cMaxSocket = EquipmentInfo::MAX_MINSIZE_SOCKET_NUM;
m_cMaxAttribute = EquipmentInfo::MAX_MINSIZE_ATTRIBUTE_NUM;
}
else
{
m_cMaxSocket = EquipmentInfo::MAX_SOCKET_NUM;
m_cMaxAttribute = EquipmentInfo::MAX_ATTRIBUTE_NUM;
}
m_cMaxSocket = (itemInfo.m_DetailData.m_cMaxSocketNum < m_cMaxSocket) ?
itemInfo.m_DetailData.m_cMaxSocketNum : m_cMaxSocket;
m_ItemData.m_cItemSize += sizeof(EquipmentInfo);
std::fill_n(m_cSocket, int(EquipmentInfo::MAX_SOCKET_NUM), 0);
std::fill_n(m_usRuneSocket, int(EquipmentInfo::MAX_RUNE_SOCKET_NUM), 0);
InitializeAttribute();
}
CEquipment::~CEquipment()
{
}
bool CEquipment::SerializeOut(char* lpSerializeItem_Out, size_t& nBufferLength_InOut)
{
// edith 2009.09.16 소켓 개수 수정
const size_t nMaxItemSize = sizeof(ItemData) + sizeof(EquipmentInfo) +
EquipmentInfo::MAX_SOCKET_NUM * sizeof(unsigned char) +
Item::EquipmentInfo::MAX_ATTRIBUTE_NUM * sizeof(ItemAttribute);
float fGradeInfo = 0;
const CItemType::ArrayType eEquipType = CItemType::GetEquipType(m_ItemInfo.m_DetailData.m_dwFlags);
if (nMaxItemSize <= nBufferLength_InOut)
{
unsigned int nIndex = 0, nSocketIndex = 0, nAttributeNum = 0;
// 기본 정보 복사
ItemData& itemData = *reinterpret_cast<ItemData*>(lpSerializeItem_Out);
itemData = m_ItemData;
EquipmentInfo& equipmentInfo = *reinterpret_cast<EquipmentInfo*>(lpSerializeItem_Out + sizeof(ItemData));
char* lpSocketInfo = lpSerializeItem_Out + sizeof(ItemData) + sizeof(EquipmentInfo);
// 아이템 소켓 정보 복사
for(nIndex = 0, nSocketIndex = 0;
nIndex < EquipmentInfo::MAX_SOCKET_NUM && nSocketIndex < m_cMaxSocket; ++nIndex)
{
if (0 != m_cSocket[nIndex])
{
lpSocketInfo[nSocketIndex] = m_cSocket[nIndex];
++nSocketIndex;
}
}
// 속성값에서 소켓, 업그레이드에 의한 값을 제거
ApplyGemAttribute(REMOVE);
ApplyUpgradeAttribute(REMOVE);
ApplyRuneAttribute(REMOVE);
// 아이템 속성 정보 복사
ItemAttribute* lpAttribute = reinterpret_cast<ItemAttribute*>(
lpSocketInfo + (nSocketIndex * sizeof(unsigned char)));
for(nIndex = 0, nAttributeNum = 0;
nIndex < Item::Attribute::MAX_DB_ATTRIBUTE_NUM && nAttributeNum < m_cMaxAttribute; ++nIndex)
{
// 현재 속성값 - 상점값(스크립트)
short usDiffAttribute = m_wAttribute[nIndex] - m_ItemInfo.m_EquipAttribute.m_usAttributeValue[nIndex];
// edith 2008.07.16 사용하지 않는 능력치는 제한하기
fGradeInfo = Grade::GetGradeValue(eEquipType, Grade::VALUE_GRADE, EquipType::S_GRADE, static_cast<Attribute::Type>(nIndex));
if(fGradeInfo == 0.0f)
usDiffAttribute = 0;
if (0 != usDiffAttribute)
{
lpAttribute->m_cType = nIndex;
lpAttribute->m_usValue = usDiffAttribute;
++nAttributeNum;
++lpAttribute;
}
}
/*
for(unsigned char cIndex = 0; cIndex < 2; cIndex++)
{
unsigned short usRune = GetRuneSocket(cIndex);
if(usRune)
{
lpAttribute->m_cType = Attribute::RUNE;
lpAttribute->m_usValue = usRune-EtcItemID::RUNE_START_ID;
++nAttributeNum;
++lpAttribute;
}
}
*/
// 속성값에서 소켓, 업그레이드에 의한 값을 추가
Ap