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

372 lines
12 KiB
C++

#ifndef _ITEM_STRUCTURE_H_
#define _ITEM_STRUCTURE_H_
#include <Creature/CreatureStructure.h>
#include "ItemConstants.h"
namespace Item
{
class CItem;
#pragma pack(1)
// ------------------------------------------------------------------------------------------
// UseLimit, ItemInfo 는 스크립트에만 넣는다.
struct ItemPos
{
unsigned short m_cPos : 4; // 아이템 포지션 (Equip, Inven...) (0~15)
unsigned short m_cIndex : 12; // 아이템 인덱스 (0~4095)
ItemPos() : m_cPos(0), m_cIndex(0) { }
ItemPos(unsigned char cPos, unsigned short usIndex) : m_cPos(cPos), m_cIndex(usIndex) { }
inline void SetPos(unsigned short wIndex) { m_cIndex = wIndex; }
inline void SetPos(unsigned char cXIndex, unsigned char cYIndex, unsigned char cZIndex);
inline void GetPos(unsigned char& cXIndex, unsigned char& cYIndex, unsigned char& cZIndex) const;
inline unsigned char GetXIndex(void) const { return (m_cIndex & 0x00F); }
inline unsigned char GetYIndex(void) const { return (m_cIndex & 0x0F0) >> 4; }
inline unsigned char GetZIndex(void) const { return (m_cIndex & 0xF00) >> 8; }
inline void SetXIndex(unsigned char cXIndex) { m_cIndex = (m_cIndex & 0xFF0) + cXIndex; }
inline void SetYIndex(unsigned char cYIndex) { m_cIndex = (m_cIndex & 0xF0F) + (cYIndex << 4); }
inline void SetZIndex(unsigned char cZIndex) { m_cIndex = (m_cIndex & 0x0FF) + (cZIndex << 8); }
inline bool operator == (const ItemPos& rhs) const { return (m_cPos == rhs.m_cPos && m_cIndex == rhs.m_cIndex); }
};
inline void ItemPos::SetPos(unsigned char cXIndex, unsigned char cYIndex, unsigned char cZIndex)
{
m_cIndex = (cZIndex << 8) + (cYIndex << 4) + cXIndex;
}
inline void ItemPos::GetPos(unsigned char& cXIndex, unsigned char& cYIndex, unsigned char& cZIndex) const
{
cXIndex = (m_cIndex & 0x00F);
cYIndex = (m_cIndex & 0x0F0) >> 4;
cZIndex = (m_cIndex & 0xF00) >> 8;
}
struct ItemData
{
unsigned __int64 m_dwUID; // 아이템 UID
unsigned short m_usProtoTypeID; // 아이템 종류 ID
ItemPos m_ItemPos; // 아이템 위치
unsigned char m_cItemSize; // 아이템 구조체 크기
unsigned char m_cNumOrDurability; // 개수 혹은 내구도
ItemData() { m_dwUID = m_usProtoTypeID = m_cNumOrDurability = 0; m_cItemSize = sizeof(ItemData); }
void DumpInfo(unsigned long dwCID, const char* szExtraString) const;
};
struct ItemAttribute
{
unsigned short m_cType : 4; // 속성 개수 4bit (16가지)
unsigned short m_usValue : 12; // 속성 값 12bit (0 ~ 4096)
ItemAttribute() : m_cType(0), m_usValue(0) { }
ItemAttribute(unsigned char cType, unsigned short usValue) : m_cType(cType), m_usValue(usValue) { }
};
// 뒤에 Socket내용물이 m_cSocketNum만큼, Attribute가 m_cDiffAttributeNum만큼 붙는다.
struct EquipmentInfo
{
enum
{
MAX_UPGRADE_LEVEL = 10, // 최대 제련 레벨
MAX_CORE_LEVEL = 5, // 최대 코어 레벌 (코어란 코어석을 발라 특별한 능력을 부여하는 시스템)
MAX_ATTRIBUTE_PER_GEM = 2, // 보석 하나당 강화되는 최대 속성 수
MAX_ATTRIBUTE_PER_UPGRADE_LEVEL = 2, // 한 단계에 강화되는 최대 속성 수
MAX_UPGRADE_ATTRIBUTE = 6, // 제련으로 인해서 얻을 수 있는 최대 속성 수
MAX_MINSIZE_SOCKET_NUM = 6, // 크기가 1by1인 아이템의 최대 소켓 수
MAX_MINSIZE_ATTRIBUTE_NUM = 6, // 크기가 1by1인 아이템의 최대 속성 수
MAX_SOCKET_NUM = 8, // 일반 아이템의 최대 소켓 수
MAX_SOCKET_ATTRIBUTE_NUM = 16, // 소켓 하나당 최대 속성이 두개까지 달릴 수 있음
// edith 2009.09.16 소켓 개수 수정
// MAX_ATTRIBUTE_NUM = 22, // 일반 아이템의 최대 속성 수
MAX_ATTRIBUTE_NUM = 15, // 일반 아이템의 최대 속성 수
MAX_RUNE_SOCKET_NUM = 2, // 장착할수 있는 룬의 최대 수
MAX_SOCKET_AND_ATTRIBUTE_MINISIZE = (MAX_MINSIZE_SOCKET_NUM * sizeof(char) + MAX_MINSIZE_ATTRIBUTE_NUM * sizeof(ItemAttribute)),
MAX_SOCKET_AND_ATTRIBUTE_SIZE = (MAX_SOCKET_NUM * sizeof(char) + MAX_ATTRIBUTE_NUM * sizeof(ItemAttribute))
};
unsigned short m_cUpgradeCnt : 2; // 재련시 고대의 돌을 연속적 사용한 카운트.
unsigned short m_cReserved1 : 9; // 예약 데이터... (0~511)
short m_cUpgradeLevel : 5; // 업그레이드 단계 (-16 ~ 15)
char m_cDiffMaxSocket : 5; // 상점 아이템 소켓 수 + m_cDiffMaxSocket = 이 아이템의 최대 소켓 수 (-16 ~ 15)
unsigned char m_cSeasonRecord : 3; // 아이템 생성 시기 (0~7) (리밸런싱 전 : 0, 후 : 1, 매찬으로 능력증가 : 2)
unsigned char m_cSocketNum : 4; // 이 아이템의 현재 소켓 수 (0 ~ 15)
unsigned char m_cAttributeNum : 4; // 상점 아이템에 없거나, 수치가 다른 속성 수 (0 ~ 15개)
char m_cDiffMaxDurability; // 상점 아이템과의 최대 내구도 차이.
unsigned char m_cCoreLevel : 4; // 코어의 레벨 (0 ~ 15)
unsigned char m_cReserved2 : 4; // 예약 데이터...(0~124)
EquipmentInfo()
{
m_cUpgradeCnt = m_cReserved1 = m_cUpgradeLevel = m_cDiffMaxSocket = m_cDiffMaxDurability =
m_cSocketNum = m_cAttributeNum = m_cSeasonRecord = m_cCoreLevel = m_cReserved2 = 0;
}
};
#pragma pack()
const unsigned char MAX_ITEM_SIZE = sizeof(ItemData) +
sizeof(EquipmentInfo) + EquipmentInfo::MAX_SOCKET_AND_ATTRIBUTE_SIZE;
struct SpriteData
{
enum { MAX_NAME = 64, MAX_SPRITE_NAME = 32 };
char m_szName[MAX_NAME];
char m_szSpriteName[MAX_SPRITE_NAME];
unsigned short m_nSpriteMinX;
unsigned short m_nSpriteMinY;
unsigned short m_nSpriteMaxX;
unsigned short m_nSpriteMaxY;
SpriteData();
void Initialize();
};
struct StringData
{
enum
{
MAX_FIELD_MODEL_NAME = 32, MAX_EQUIP_MODEL_NAME = 32,
MAX_EFFECT_SOUND_NAME = 32, MAX_TYPE_NAME = 32,
MAX_ITEM_DESCRIBE = 256
};
char m_szFieldModelName[MAX_FIELD_MODEL_NAME];
char m_szEquipModelName[MAX_EQUIP_MODEL_NAME];
char m_szEffectSoundName[MAX_EFFECT_SOUND_NAME];
char m_szTypeName[MAX_TYPE_NAME];
char m_szItemDescribe[MAX_ITEM_DESCRIBE];
StringData();
void Initialize();
};
struct DetailData
{
enum Flags
{
EQUIP = (1 << 0), // 장비할수 있는지 여부
USE_ITEM = (1 << 1), // 사용할 수 있는지 여부
QUICKSLOT_IN = (1 << 2), // 퀵슬롯에 들어갈 수 있는지 여부
STACKABLE = (1 << 3), // 스택할 수 있는지 여부
HELM = (1 << 4), // 투구류
ARMOR = (1 << 5), // 갑옷류
DAGGER = (1 << 6), // 단검류
ONEHANDED = (1 << 7), // 한손 무기류
LONGRANGE = (1 << 8), // 장거리 무기류
TWOHANDED = (1 << 9), // 양손 무기류
STAFF = (1 << 10), // 지팡이류
SHIELD = (1 << 11), // 방패류
//--// start..
NECKLACE = (1 << 12), // 목걸이
RING = (1 << 13), // 반지
RUNE = (1 << 14), // 룬
//--// end..
AVATA = (1 << 15) // 아바타형식
};
unsigned long m_dwPrice; // 기본 가격
unsigned long m_dwBlackPrice; // 암시장용 판매 가격
unsigned long m_dwMedalPrice; // 메달상점용 판매 가격
unsigned short m_wDropOption; // 가치 책정을 위한 값
unsigned char m_cGrade; // 가치 책정값이 0 일때 적용될 등급 //--//
unsigned char m_cCriticalType; // 크리티컬 타입
unsigned char m_cAttackRange; // 공격 거리
unsigned char m_cItemType; // 아이템 종류( namespace Type 참고 )
unsigned char m_cXSize; // 아이템 X크기
unsigned char m_cYSize; // 아이템 Y크기
unsigned char m_cMaxSocketNum; // 최대 소켓수
unsigned char m_cDefaultDurabilityOrStack; // 기본 스택/내구도
unsigned char m_cMaxDurabilityOrStack; // 최대 스택/내구도
unsigned char m_cMinDropLevel; // 드랍하는 몬스터의 최소 레벨
unsigned char m_cMaxDropLevel; // 드랍하는 몬스터의 최대 레벨
unsigned short m_wLowLimitLevel; // 장착 하한선.
unsigned short m_wHighLimitLevel; // 장착 상한선.
bool m_bExchangeAndDrop; // 교환과 드랍이 가능한가?
bool m_bSell; // 팔 수 있는 아이템인가?
bool m_bOptionPrice; // 옵션을 참고해서 가격 책정을 다시 할 것인가?
unsigned long m_dwFlags;
DetailData();
void Initialize();
};
struct EquipAttribute
{
unsigned short m_usAttributeValue[Item::Attribute::MAX_ATTRIBUTE_NUM];
unsigned short m_nAttibuteNum;
EquipAttribute();
void Initialize();
};
struct UseItemInfo
{
Position m_Pos; // 이동 좌표 (순간이동서)
unsigned char m_cZone; // 이동 존 (순간이동서)
unsigned long m_dwAmount; // 양 (경험치쿠폰, 캐쉬북)
unsigned short m_usSkill_ID; // 관련 스킬 아이디 (포션, 스킬북)
unsigned short m_usSkill_LockCount; // 관련 스킬 락카운트 (포션, 스킬북)
unsigned short m_wQuestID; // 시작 퀘스트 아이디 (퀘스트 시작 아이템)
unsigned char m_cLimitRealmPoint; // 공헌 훈장 포인트별 사용 제한
bool m_bForStatueWar; // 국가전(석상전) 시간에만 사용 가능
UseItemInfo();
void Initialize();
};
struct UseLimit
{
enum DeactivatedType
{
STATUS_LIMIT = ( 1 << 0 ),
CLASS_LIMIT = ( 1 << 1 ),
BROKEN_ITEM = ( 1 << 2 )
};
unsigned long m_dwClassLimit;
unsigned char m_cLimitStatus;
unsigned short m_wLimitValue;
UseLimit();
void Initialize();
};
#pragma pack(8)
struct ItemInfo
{
unsigned short m_usProtoTypeID;
DetailData m_DetailData;
UseLimit m_UseLimit;
SpriteData m_SpriteData;
StringData m_StringData;
EquipAttribute m_EquipAttribute;
UseItemInfo m_UseItemInfo;
ItemInfo();
ItemInfo(unsigned short usPrototypeID);
void Initialize();
inline bool operator < (ItemInfo& rhs)
{
return (m_usProtoTypeID < rhs.m_usProtoTypeID);
}
const char* GetItemDescribe(void) const;
};
#pragma pack()
struct ItemGarbage
{
CItem* m_lpItem;
unsigned long m_dwRemainNum;
ItemGarbage(CItem* lpItem, unsigned long dwRemainNum);
};
struct ChemicalInfo
{
unsigned short m_wPickkingItemID;
unsigned short m_wTargetItemID;
unsigned short m_wResultItemID;
unsigned char m_cPickkingItemNum;
unsigned char m_cTargetItemNum;
unsigned char m_cResultItemNum;
unsigned long m_dwItemID; // 아이템 아이디
unsigned short m_usAbilityID; // 잡아이디
unsigned char m_cAbilityLevel;
unsigned short m_usQuestID; // 퀘아이디
unsigned char m_cPercent; // 성공확율
ChemicalInfo();
ChemicalInfo(unsigned short wPickkingItemID, unsigned char cPickkingItemNum,
unsigned short wTargetItemID, unsigned char cTargetItemNum, unsigned int dwItemID, unsigned short usAbilityID, unsigned char cAbilityLevel, unsigned short usQuestID, unsigned char cPercent);
bool operator < (const ChemicalInfo& rhs)
{
if (m_wPickkingItemID == rhs.m_wPickkingItemID)
{
return m_wTargetItemID < rhs.m_wTargetItemID;
}
return m_wPickkingItemID < rhs.m_wPickkingItemID;
}
bool operator == (const ChemicalInfo& rhs)
{
return (m_wPickkingItemID == rhs.m_wPickkingItemID && m_wTargetItemID == rhs.m_wTargetItemID &&
m_cPickkingItemNum == rhs.m_cPickkingItemNum && m_cTargetItemNum == rhs.m_cTargetItemNum);
}
};
namespace Grade
{
struct GradeInfo
{
EquipType::Grade m_eItemGrade;
unsigned char m_cPlus;
EquipType::Grade m_aryAttributeGrade[Attribute::MAX_ATTRIBUTE_NUM];
GradeInfo();
};
enum TableType
{
DROP_MIN_VALUE = 0, // 드랍 그레이드 최소값
DROP_MAX_VALUE = 1, // 드랍 그레이드 최대값
VALUE_GRADE = 2, // 가치 그레이드
MAX_TABLE_TYPE = 3
};
const float GetGradeValue(Item::CItemType::ArrayType eEquipType, Grade::TableType eTableType,
EquipType::Grade eGrade, Attribute::Type eType);
};
};
#endif