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>
354 lines
14 KiB
C++
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 |