Files
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

354 lines
14 KiB
C++

#ifndef _CITEM_CLASS_H_
#define _CITEM_CLASS_H_
#include <limits>
#include <algorithm>
#include "ItemStructure.h"
// 전방 참조
namespace Skill
{
struct ProtoType;
}
namespace Item
{
class CItem
{
public:
CItem();
CItem(unsigned __int64 dwItemUID, const ItemInfo& itemInfo); // Create Item
virtual ~CItem();
// 스크립트로부터 로드한 아이템 데이터를 얻어 온다.
const ItemInfo& GetItemInfo() const { return m_ItemInfo; }
// Desc : 아이템 정보를 char버퍼로 기록한다.
// In : 버퍼, 버퍼 크기
// Out : (Return)성공 여부, nBufferLength_InOut - 기록한 크기
virtual bool SerializeOut(char* lpSerializeItem_Out, size_t& nBufferLength_InOut);
// Desc : char버퍼로부터 아이템 정보를 읽어 온다.
// In : 버퍼, 버퍼 크기
// Out : (Return)성공 여부, nBufferLength_InOut - 사용한 버퍼 크기
virtual bool SerializeIn(const char* lpSerializeItem_In, size_t& nBufferLength_InOut);
// Move Item
inline void MoveItem(ItemPos itemPos) { m_ItemData.m_ItemPos = itemPos; }
// 아이템 가변 정보.
inline unsigned __int64 GetUID() const { return m_ItemData.m_dwUID; }
inline ItemPos GetPos() const { return m_ItemData.m_ItemPos; }
inline ItemPos GetRealPos() const { return m_itemPos_Real; }
inline unsigned short GetPrototypeID() const { return m_ItemData.m_usProtoTypeID; }
inline unsigned char GetNumOrDurability() const { return m_ItemData.m_cNumOrDurability; }
inline unsigned char GetMaxNumOrDurability() const { return m_cMaxNumOrDurability; }
inline void SetNumOrDurability(unsigned char cNumOrDurability) { m_ItemData.m_cNumOrDurability = cNumOrDurability; }
inline void SetStallPrice(unsigned long dwStallPrice) { m_dwStallPrice = dwStallPrice; }
inline unsigned long GetBuyPrice() const { return (0 == m_dwStallPrice) ? m_ItemInfo.m_DetailData.m_dwPrice : m_dwStallPrice; }
inline unsigned long GetBuyBlackPrice() const { return m_ItemInfo.m_DetailData.m_dwBlackPrice; }
inline unsigned long GetSellPrice() const;
inline unsigned long GetRepairPrice() const;
inline const char* GetItemTypeName() const;
inline unsigned char GetOptionLimit() const { return m_ItemInfo.m_DetailData.m_cOptionLimit; }
inline bool IsSet(unsigned long dwDetailDataFlag) const { return dwDetailDataFlag == (m_ItemInfo.m_DetailData.m_dwFlags & dwDetailDataFlag); }
// 재일이가 추가한 것
inline bool GetEnableRepair();
inline bool GetEnableStack();
inline bool GetSocketItem();
inline bool GetTwohandItem();
inline bool GetEnableEquip();
inline void SetItemPos(unsigned short wItemPos) { m_ItemData.m_ItemPos.m_cPos = wItemPos; }
inline unsigned short GetItemPos(void) { return m_ItemData.m_ItemPos.m_cPos; }
inline void SetPos(unsigned char cXIndex, unsigned char cYIndex, unsigned char cZIndex) { m_ItemData.m_ItemPos.SetPos(cXIndex, cYIndex, cZIndex); }
inline void SetXIndex(unsigned char cXIndex) { m_ItemData.m_ItemPos.SetXIndex(cXIndex); }
inline void SetYIndex(unsigned char cYIndex) { m_ItemData.m_ItemPos.SetYIndex(cYIndex); }
inline void SetZIndex(unsigned char cZIndex) { m_ItemData.m_ItemPos.SetZIndex(cZIndex); }
inline void SetPos(unsigned short wIndex) { m_ItemData.m_ItemPos.SetPos(wIndex); }
protected:
const ItemInfo& m_ItemInfo; // 스크립트로부터 로드한 아이템 데이터
ItemData m_ItemData; // DB에 저장되는 아이템 데이터
ItemPos m_itemPos_Real; // 임시 공간이 아닌 아이템 위치
unsigned char m_cMaxNumOrDurability; // 최대 내구도
unsigned long m_dwStallPrice; // 노점상에서의 가격
};
class CEquipment : public CItem
{
public:
enum EQUIPMENT_ERROR
{
E_SUCCESS = 0, // 성공
E_SERVER_ERROR = 1, // 서버 에러
E_GET_EQUIP_FAILED = 2, // 장비 얻기 실패
E_GET_GEM_FAILED = 3, // 젬 얻기 실패
E_NOT_EQUIP = 4, // 장비 아이템 아님
E_NOT_GEM = 5, // 젬 아이템 아님
E_REMOVE_GEM_FAILED = 6, // 젬 제거 실패
E_SOCKET_IS_FULL = 7, // 소켓 슬롯 초과
E_OVER_MAX_SOCKET = 8, // 최대 소켓 초과
E_GET_MINERAL_FAILED = 3,
E_NOT_MINERAL = 5,
E_NOT_MATCH_MINERAL_TYPE = 6,
E_NOT_ENOUGH_MINERAL = 7,
E_REMOVE_EQUIP_FAILED = 8,
E_CREATE_ITEM_FAILED = 9,
E_REMOVE_MINERAL_FAILED = 10
};
CEquipment(unsigned __int64 dwItemUID, const ItemInfo& itemInfo);
virtual ~CEquipment();
// 아이템을 장비로 Downcast한다.
inline static CEquipment* DowncastToEquipment(CItem* lpItem);
// Desc : 아이템 정보를 char버퍼로 기록한다.
// In : 버퍼, 버퍼 크기
// Out : (Return)성공 여부, nBufferLength_InOut - 기록한 크기
virtual bool SerializeOut(char* lpSerializeItem_Out, size_t& nBufferLength_InOut);
// Desc : char버퍼로부터 아이템 정보를 읽어 온다.
// In : 버퍼, 버퍼 크기
// Out : (Return)성공 여부, nBufferLength_InOut - 사용한 버퍼 크기
virtual bool SerializeIn(const char* lpSerializeItem_In, size_t& nBufferLength_InOut);
// 아이템 속성을 임의로 바꾸기 위함.
void AddAttribute(Item::Attribute::Type eAttributeType, unsigned short nAttributeValue) { m_usAttribute[eAttributeType] += nAttributeValue; }
inline void AddAttribute(const short* lpAttributeArray_In, unsigned short nArraySize);
// 아이템 속성을 얻어 온다.
unsigned short GetAttribute(Item::Attribute::Type eAttributeType) { return m_usAttribute[eAttributeType]; }
inline void GetAttribute(short* lpAttributeArray_Out, unsigned short nArraySize);
// Desc : InstallSocket -
// 소켓에 보석을 박는 순서. 1. 보석을 찾는다. 2. 장비를 찾아서 벗는다.
// 3. 장비에 보석을 박는다. 4. 보석을 없앤다. 5. 장비를 다시 입는다.
EQUIPMENT_ERROR InstallSocket(CItem& Gem);
// Desc : UpgradeItem -
EQUIPMENT_ERROR UpgradeItem(CItem& Mineral);
void InitializeAttribute();
unsigned char m_cSocket[Item::EquipmentInfo::MAX_SOCKET_NUM]; // 아이템 소켓 정보
short m_usAttribute[Item::Attribute::MAX_ATTRIBUTE_NUM]; // 아이템 속성
unsigned short m_usRuneSocket; // 룬 소켓
unsigned char m_cMaterialType; // 재질값
unsigned char m_cMaxSocket; // 최대 소켓 개수
unsigned char m_cSocketNum; // 소켓 개수
unsigned char m_cMaxAttribute; // 최대 속성 개수
unsigned char m_cReserved; // 예약된 공간
unsigned char m_cReserved2; // 예약된 공간
};
class CUseItem : public CItem
{
public:
CUseItem(unsigned __int64 dwItemUID, const ItemInfo& itemInfo);
virtual ~CUseItem();
inline static CUseItem* DowncastToUseItem(CItem* lpItem);
bool Use();
};
class CSkillItem : public CItem
{
public:
CSkillItem();
virtual ~CSkillItem() { }
inline void SetProtoTypeID(unsigned short usProtoTypeID) { m_ItemData.m_usProtoTypeID = usProtoTypeID; }
inline unsigned char GetMaxNumOrDurability() const { return m_cMaxDurability; }
inline void SetMaxNumOrDurability(unsigned char cMaxNumOrDurability) { m_cMaxDurability = cMaxNumOrDurability; }
bool SetSkillInfo(const Skill::ProtoType *lpSkillInfo);
protected:
ItemInfo m_ItemInfoInstance;
unsigned char m_cMaxDurability; // 최대 내구도
};
};
inline const char* Item::CItem::GetItemTypeName() const
{
switch (m_ItemInfo.m_DetailData.m_cItemType)
{
case Item::CItemType::HELM: return "투구";
case Item::CItemType::SHIRT: return "셔츠";
case Item::CItemType::TUNIC: return "튜닉";
case Item::CItemType::ARMOUR: return "아머";
case Item::CItemType::GLOVE: return "장갑";
case Item::CItemType::BOOTS: return "부츠";
case Item::CItemType::SWORD: return "한손검";
case Item::CItemType::BLUNT: return "한손둔기";
case Item::CItemType::AXE: return "한손도끼";
case Item::CItemType::TWOHANDED_BLUNT: return "양손둔기";
case Item::CItemType::TWOHANDED_AXE: return "양손도끼";
case Item::CItemType::TWOHANDED_SWORD: return "양손검";
case Item::CItemType::BOW: return "";
case Item::CItemType::CROSSBOW: return "석궁";
case Item::CItemType::STAFF: return "스태프";
case Item::CItemType::DAGGER: return "단검";
case Item::CItemType::SHIELD: return "방패";
case Item::CItemType::CLOAK: return "망토";
case Item::CItemType::RING: return "반지";
case Item::CItemType::NECKLACE: return "목걸이";
case Item::CItemType::POTION: return "물약";
case Item::CItemType::POISON: return "독약";
case Item::CItemType::TRAP: return "트랩";
case Item::CItemType::SKILLBOOK: return "스킬북";
case Item::CItemType::GEM: return "보석류";
case Item::CItemType::RUNE: return "";
case Item::CItemType::MATERIAL: return "메테리얼";
case Item::CItemType::AMMO: return "소모품";
case Item::CItemType::ETC: return "기타";
case Item::CItemType::HEAD: return "헤드아머";
case Item::CItemType::BODY: return "바디아머";
case Item::CItemType::PROTECT_A: return "프로텍트암";
case Item::CItemType::PELVIS: return "펠비스아머";
case Item::CItemType::COM_BLUNT: return "컴배턴트 둔기";
case Item::CItemType::COM_SWORD: return "컴배턴트 검";
case Item::CItemType::OPP_HAMMER: return "오피세이터 둔기";
case Item::CItemType::OPP_AXE: return "오피세이터 도끼";
case Item::CItemType::OPP_SLUSHER: return "오피세이터 슬러셔";
case Item::CItemType::OPP_TALON: return "오피세이터 탈룬";
case Item::CItemType::OPP_SYTHE: return "오피세이터 사이드";
case Item::CItemType::SKILL_A_GUARD: return "가드암";
case Item::CItemType::SKILL_A_ATTACK: return "어택암";
case Item::CItemType::SKILL_A_GUN: return "건암";
case Item::CItemType::SKILL_A_KNIFE: return "나이프암";
case Item::CItemType::ACCESSORY: return "악세서리";
case Item::CItemType::ARROW: return "화살";
case Item::CItemType::BOLT: return "볼트";
}
return NULL;
}
inline unsigned long Item::CItem::GetSellPrice() const
{
if (0 != m_dwStallPrice) { return m_dwStallPrice; }
unsigned long dwSellPrice = m_ItemInfo.m_DetailData.m_dwPrice;
unsigned long dwFlags = m_ItemInfo.m_DetailData.m_dwFlags;
if(IsSet(DetailData::EQUIP))
{
dwSellPrice = IsSet(DetailData::STACKABLE) ?
dwSellPrice / 2 : (dwSellPrice * m_ItemData.m_cNumOrDurability / m_cMaxNumOrDurability / 2);
}
else
{
dwSellPrice = (Item::CItemType::SKILLBOOK == m_ItemInfo.m_DetailData.m_cItemType) ?
dwSellPrice / 4 : dwSellPrice / 2;
}
return (0 == dwSellPrice) ? 1 : dwSellPrice;
}
inline unsigned long Item::CItem::GetRepairPrice() const
{
unsigned long dwRepairPrice = (m_ItemInfo.m_DetailData.m_dwPrice *
(m_cMaxNumOrDurability - m_ItemData.m_cNumOrDurability) / m_cMaxNumOrDurability / 2);
return (0 == dwRepairPrice) ? 1 : dwRepairPrice;
}
inline Item::CEquipment* Item::CEquipment::DowncastToEquipment(Item::CItem* lpItem)
{
return lpItem->IsSet(DetailData::EQUIP) ?
static_cast<CEquipment*>(lpItem) : NULL;
}
void Item::CEquipment::AddAttribute(const short* lpAttributeArray_In, unsigned short nArraySize)
{
unsigned short nCopyNum = nArraySize < Item::Attribute::MAX_ATTRIBUTE_NUM
? nArraySize : Item::Attribute::MAX_ATTRIBUTE_NUM;
while(0 <= --nCopyNum) { m_usAttribute[nCopyNum] += lpAttributeArray_In[nCopyNum]; }
}
void Item::CEquipment::GetAttribute(short* lpAttributeArray_Out, unsigned short nArraySize)
{
unsigned short nCopyNum = nArraySize < Item::Attribute::MAX_ATTRIBUTE_NUM
? nArraySize : Item::Attribute::MAX_ATTRIBUTE_NUM;
short* lpAttributePastEnd = m_usAttribute + nCopyNum;
std::copy(m_usAttribute, lpAttributePastEnd, lpAttributeArray_Out);
}
inline Item::CUseItem* Item::CUseItem::DowncastToUseItem(CItem* lpItem)
{
return lpItem->IsSet(DetailData::USE_ITEM) ?
static_cast<CUseItem*>(lpItem) : NULL;
}
// 재일이가 추가 한 것
inline bool Item::CItem::GetEnableRepair()
{
unsigned long dwFlags = GetItemInfo().m_DetailData.m_dwFlags;
if((dwFlags & Item::DetailData::EQUIP) && !(dwFlags & Item::DetailData::STACKABLE))
return true;
return false;
}
inline bool Item::CItem::GetEnableStack()
{
if(GetItemInfo().m_DetailData.m_dwFlags & Item::DetailData::STACKABLE)
return true;
return false;
}
inline bool Item::CItem::GetEnableEquip()
{
if(GetItemInfo().m_DetailData.m_dwFlags & Item::DetailData::EQUIP)
return true;
return false;
}
inline bool Item::CItem::GetSocketItem()
{
unsigned char cItemType = GetItemInfo().m_DetailData.m_cItemType;
if(cItemType == Item::CItemType::GEM || cItemType == Item::CItemType::RUNE)
return true;
return false;
}
inline bool Item::CItem::GetTwohandItem()
{
unsigned char cItemType = GetItemInfo().m_DetailData.m_cItemType;
if(cItemType == Item::CItemType::BOW || cItemType == Item::CItemType::CROSSBOW ||
cItemType == Item::CItemType::STAFF || cItemType == Item::CItemType::TWOHANDED_AXE ||
cItemType == Item::CItemType::TWOHANDED_BLUNT || cItemType == Item::CItemType::TWOHANDED_SWORD ||
cItemType == Item::CItemType::OPP_SYTHE)
return true;
return false;
}
#endif