Files
Client/Server/RylServerProject/RylGameLibrary/Item/ItemFactory.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

373 lines
14 KiB
C++

#include "stdafx.h"
#include "Item.h"
#include "ItemMgr.h"
#include "ItemFactory.h"
#include "ItemConstants.h" //--//
namespace Item
{
CItemOwnerInfo::CItemOwnerInfo(const char* szName, unsigned long dwUID, unsigned long dwCID)
: m_dwUID(dwUID), m_dwCID(dwCID)
{
strncpy(m_szName, szName, MAX_NAME);
m_szName[MAX_NAME - 1] = 0;
}
CItemFactory& CItemFactory::GetInstance()
{
static CItemFactory itemFactory;
return itemFactory;
}
CItemFactory::CItemFactory()
: m_nCurrentUID(0LL)
{
}
CItemFactory::~CItemFactory()
{
}
CItem* CItemFactory::CreateItem(const ItemInfo& itemInfo)
{
CItem* lpItem = CreateTempItem(itemInfo);
if(0 != lpItem)
{
lpItem->SetUID(GetNewItemUID());
}
return lpItem;
}
// Desc : 아이템 시리얼이 0인 임시 아이템을 생성한다.
CItem* CItemFactory::CreateTempItem(const ItemInfo& itemInfo)
{
unsigned long dwFlags = itemInfo.m_DetailData.m_dwFlags;
CItem* lpItem = 0;
if(DetailData::EQUIP == (dwFlags & DetailData::EQUIP))
{
lpItem = new CEquipment(itemInfo);
//--// start..
if (0 == itemInfo.m_DetailData.m_wDropOption)
{
Item::CEquipment* lpEquip = Item::CEquipment::DowncastToEquipment(lpItem);
if (NULL != lpEquip)
{
lpEquip->m_GradeInfo.m_eItemGrade = static_cast<EquipType::Grade>(itemInfo.m_DetailData.m_cGrade);
// edith 2008.02.10 임시아이템도 밸런스패치된걸로 처리한다. 원래는 없었다.
// lpEquip->SetNewEquip();
}
}
//--// end..
}
else if(DetailData::USE_ITEM == (dwFlags & DetailData::USE_ITEM))
{
lpItem = new CUseItem(itemInfo);
}
else
{
lpItem = new CItem(itemInfo);
}
return lpItem;
}
CItem* CItemFactory::CreateItem(unsigned short usProtoTypeID)
{
const ItemInfo* lpItemInfo = CItemMgr::GetInstance().GetItemInfo(usProtoTypeID);
if(0 != lpItemInfo)
{
return CreateItem(*lpItemInfo);
}
ERRLOG1(g_Log, "ProtoTypeID:%u / 아이템 생성 실패 : 스크립트에 없는 종류ID입니다", usProtoTypeID);
return 0;
}
CItem* CItemFactory::CreateItem(const char* lpSerializedItem_In, size_t& nParseLength_InOut)
{
const ItemData* lpItemData = reinterpret_cast<const ItemData*>(lpSerializedItem_In);
const ItemInfo* lpItemInfo = 0;
if (0 != lpItemData &&
0 != (lpItemInfo = CItemMgr::GetInstance().GetItemInfo(lpItemData->m_usProtoTypeID)))
{
// serialize시 itemUID가 들어가므로, itemUID가 생성된 아이템을 만들 필요는 없다.
CItem* lpItem = CreateTempItem(*lpItemInfo);
if (0 != lpItem &&
!lpItem->SerializeIn(lpSerializedItem_In, nParseLength_InOut))
{
DELETE_ITEM(lpItem);
}
return lpItem;
}
return 0;
}
void CItemFactory::DeleteItem(Item::CItem* lpDeleteItem)
{
// 여기서 전역 맵에서 데이터 삭제;;
RemoveItemMap(lpDeleteItem->GetUID());
delete lpDeleteItem;
}
CItemOwnerInfo* CItemFactory::AddItemMap(unsigned __int64 dwItemUID, const CItemOwnerInfo& itemOwnerInfo)
{
CItemOwnerInfo* lpOwnerInfo = 0;
ItemSerialMap::iterator pos = m_ItemSerialMap.lower_bound(dwItemUID);
if(pos == m_ItemSerialMap.end() || m_ItemSerialMap.comp(dwItemUID, pos->first))
{
m_ItemSerialMap.insert(pos, ItemSerialMap::value_type(dwItemUID, itemOwnerInfo));
}
else
{
// 이미 맵에 데이터가 있다. 소유자 정보를 리턴한다.
lpOwnerInfo = &pos->second;
}
return lpOwnerInfo;
}
void CItemFactory::RemoveItemMap(unsigned __int64 dwItemUID)
{
m_ItemSerialMap.erase(dwItemUID);
}
void CItemFactory::ClearItemMap()
{
m_ItemSerialMap.clear();
}
Item::CItem* CreateItemFromGiveInfo(CItemMgr& itemMgr, CItemFactory& itemFactory,
GiveItemInfo& giveItemInfo, Item::ItemPos itemPos)
{
char szItemData[Item::MAX_ITEM_SIZE];
unsigned long dwDataSize = Item::MAX_ITEM_SIZE;
unsigned __int64 dwItemUID = itemFactory.GetNewItemUID();
if (CreateItemDataFromGiveInfo(itemMgr, giveItemInfo,
szItemData, dwDataSize, dwItemUID, itemPos))
{
size_t data_size = dwDataSize;
return itemFactory.CreateItem(szItemData, data_size);
}
return NULL;
}
inline void AddAttrFromGiveInfo(short wNewAttribute[Item::Attribute::MAX_ATTRIBUTE_NUM],
GiveItemInfo& giveItemInfo,
Item::CItemType::ArrayType eArrayType,
unsigned short wDropOption,
Item::Attribute::Type eAttrType,
GiveItemInfo::GiveItemType eGiveItemType)
{
if(giveItemInfo.m_cAttribute[eGiveItemType] < Item::EquipType::MAX_GRADE)
{
unsigned short usMinValue = static_cast<short>(wDropOption *
Item::Grade::GetGradeValue(eArrayType, Item::Grade::VALUE_GRADE,
static_cast<Item::EquipType::Grade>(giveItemInfo.m_cAttribute[eGiveItemType]), eAttrType));
if(Item::EquipType::AAA_GRADE == giveItemInfo.m_cAttribute[eGiveItemType])
{
wNewAttribute[eAttrType] += usMinValue + 2;
}
else
{
unsigned short usMaxValue = static_cast<short>(wDropOption *
Item::Grade::GetGradeValue(eArrayType, Item::Grade::VALUE_GRADE,
static_cast<Item::EquipType::Grade>(giveItemInfo.m_cAttribute[eGiveItemType - 1]), eAttrType));
wNewAttribute[eAttrType] += static_cast<short>((usMaxValue + usMinValue) / 2.0f + 0.5f);
}
}
}
bool CreateItemDataFromGiveInfo(Item::CItemMgr& itemMgr, GiveItemInfo& giveItemInfo,
char* szData, unsigned long& dwDataSize_InOut,
unsigned __int64 dwItemUID, Item::ItemPos itemPos)
{
// 일단 기본 아이템 데이터를 넣는다.
const Item::ItemInfo* lpItemInfo = 0;
if (Item::MAX_ITEM_SIZE <= dwDataSize_InOut &&
0 != (lpItemInfo = itemMgr.GetItemInfo(giveItemInfo.m_usPrototypeID)))
{
Item::ItemData* lpItemData = reinterpret_cast<Item::ItemData*>(szData);
lpItemData->m_dwUID = dwItemUID; // 아이템 UID
lpItemData->m_usProtoTypeID = giveItemInfo.m_usPrototypeID; // 아이템 종류 ID
lpItemData->m_ItemPos = itemPos; // 아이템 위치
lpItemData->m_cItemSize = sizeof(Item::ItemData); // 아이템 구조체 크기
lpItemData->m_cNumOrDurability = giveItemInfo.m_cAmount; // 개수 혹은 내구도
if(lpItemInfo->m_DetailData.m_dwFlags & Item::DetailData::EQUIP)
{
// 장비다. 관련 데이터를 좀 더 넣는다.
Item::EquipmentInfo* lpEquipmentInfo =
reinterpret_cast<Item::EquipmentInfo*>(lpItemData + 1);
Item::ItemAttribute* lpItemAttribute =
reinterpret_cast<Item::ItemAttribute*>(lpEquipmentInfo + 1);
const unsigned char cDefaultDurability =
lpItemInfo->m_DetailData.m_cDefaultDurabilityOrStack;
lpEquipmentInfo->m_cUpgradeCnt = 0;
lpEquipmentInfo->m_cReserved1 = 0;
lpEquipmentInfo->m_cUpgradeLevel = 0;
lpEquipmentInfo->m_cDiffMaxSocket = 0;
lpEquipmentInfo->m_cSeasonRecord = 1;
lpEquipmentInfo->m_cSocketNum = 0;
lpEquipmentInfo->m_cAttributeNum = 0;
lpEquipmentInfo->m_cDiffMaxDurability =
(cDefaultDurability <= giveItemInfo.m_cAmount)
? giveItemInfo.m_cAmount - cDefaultDurability : 0;
lpEquipmentInfo->m_cReserved2 = 0;
lpEquipmentInfo->m_cCoreLevel = 0;
lpItemData->m_cItemSize += sizeof(Item::EquipmentInfo);
// 속성을 계산한다. 아이템 타입별로 가질 수 있는 속성이 다르다.
Item::CItemType::ArrayType eArrayType =
Item::CItemType::GetEquipType(lpItemInfo->m_DetailData.m_dwFlags);
short wNewAttribute[Item::Attribute::MAX_ATTRIBUTE_NUM];
std::fill_n(wNewAttribute, int(Item::Attribute::MAX_ATTRIBUTE_NUM), 0);
unsigned short wDropOption = lpItemInfo->m_DetailData.m_wDropOption;
switch(lpItemInfo->m_DetailData.m_cItemType)
{
case Item::ItemType::CON_ARMOUR:
case Item::ItemType::CON_BODY:
case Item::ItemType::DEX_BODY:
case Item::ItemType::DEX_ARMOUR:
case Item::ItemType::CON_HELM:
case Item::ItemType::CON_HEAD:
case Item::ItemType::DEX_HEAD:
case Item::ItemType::DEX_HELM:
// edith 2008.01.14 아이템 옵션추가작업
case Item::ItemType::CON_GLOVE:
case Item::ItemType::DEX_GLOVE:
case Item::ItemType::CON_BOOTS:
case Item::ItemType::DEX_BOOTS:
case Item::ItemType::CON_PELVIS:
case Item::ItemType::DEX_PELVIS:
case Item::ItemType::CON_PROTECT_A:
case Item::ItemType::DEX_PROTECT_A:
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::ARMOR, GiveItemInfo::ARMOR);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::EVADE, GiveItemInfo::EVADE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_HP, GiveItemInfo::MAX_HP);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::HP_REGEN, GiveItemInfo::HP_REGEN);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_MP, GiveItemInfo::MAX_MP);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAGIC_RESIST, GiveItemInfo::MAGIC_RESIST);
break;
case Item::ItemType::DAGGER:
case Item::ItemType::OPP_TALON:
case Item::ItemType::SKILL_A_KNIFE:
case Item::ItemType::ONEHANDED_SWORD:
case Item::ItemType::ONEHANDED_BLUNT:
case Item::ItemType::COM_SWORD:
case Item::ItemType::OPP_HAMMER:
case Item::ItemType::ONEHANDED_AXE:
case Item::ItemType::OPP_SLUSHER:
case Item::ItemType::COM_BLUNT:
case Item::ItemType::OPP_AXE:
case Item::ItemType::BOW:
case Item::ItemType::CROSSBOW:
case Item::ItemType::SKILL_A_ATTACK:
case Item::ItemType::SKILL_A_GUN:
case Item::ItemType::TWOHANDED_SWORD:
case Item::ItemType::TWOHANDED_AXE:
case Item::ItemType::TWOHANDED_BLUNT:
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MIN_DAMAGE, GiveItemInfo::MIN_DAMAGE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_DAMAGE, GiveItemInfo::MAX_DAMAGE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::HIT_RATE, GiveItemInfo::HIT_RATE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::CRITICAL, GiveItemInfo::CRITICAL);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::BLOCK, GiveItemInfo::BLOCK);
break;
case Item::ItemType::STAFF:
case Item::ItemType::OPP_SYTHE:
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_DAMAGE, GiveItemInfo::MAX_DAMAGE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::HIT_RATE, GiveItemInfo::HIT_RATE);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_MP, GiveItemInfo::MAX_MP);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MP_REGEN, GiveItemInfo::MP_REGEN);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::CRITICAL, GiveItemInfo::CRITICAL);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAGIC_POWER, GiveItemInfo::MAGIC_POWER);
break;
case Item::ItemType::SHIELD:
case Item::ItemType::SKILL_A_GUARD:
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_HP, GiveItemInfo::MAX_HP);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::HP_REGEN, GiveItemInfo::HP_REGEN);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MAX_MP, GiveItemInfo::MAX_MP);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::MP_REGEN, GiveItemInfo::MP_REGEN);
AddAttrFromGiveInfo(wNewAttribute, giveItemInfo, eArrayType, wDropOption, Item::Attribute::BLOCK, GiveItemInfo::BLOCK);
break;
}
// 데이터를 다 넣었으니, 속성을 추가한다.
for(int nCount = 0; nCount < Item::Attribute::MAX_ATTRIBUTE_NUM; ++nCount)
{
if(0 < wNewAttribute[nCount])
{
lpItemAttribute->m_cType = nCount;
lpItemAttribute->m_usValue = wNewAttribute[nCount];
++lpItemAttribute;
++lpEquipmentInfo->m_cAttributeNum;
}
}
lpItemData->m_cItemSize +=
lpEquipmentInfo->m_cAttributeNum * sizeof(Item::ItemAttribute);
}
dwDataSize_InOut = lpItemData->m_cItemSize;
return true;
}
return false;
}
}