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>
877 lines
29 KiB
C++
877 lines
29 KiB
C++
#ifndef _CITEM_CLASS_H_
|
|
#define _CITEM_CLASS_H_
|
|
|
|
#include <limits>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <Network/Packet/PacketStruct/CharItemPacketStruct.h>
|
|
|
|
#include "item/ItemMgr.h"
|
|
|
|
#include "item/ItemStructure.h"
|
|
|
|
// 전방 참조
|
|
class CCharacter;
|
|
|
|
#define DELITEMLOG(x) (void*)0
|
|
//#define DELITEMLOG(x) x
|
|
|
|
namespace Item
|
|
{
|
|
class CItem
|
|
{
|
|
public:
|
|
|
|
CItem();
|
|
CItem(const ItemInfo& itemInfo);
|
|
|
|
// 스크립트로부터 로드한 아이템 데이터를 얻어 온다.
|
|
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);
|
|
|
|
inline void MoveItem(ItemPos itemPos);
|
|
|
|
inline unsigned __int64 GetUID(void) const { return m_ItemData.m_dwUID; }
|
|
inline ItemPos GetPos(void) const { return m_ItemData.m_ItemPos; }
|
|
inline ItemPos GetRealPos(void) const { return m_itemPos_Real; }
|
|
inline void SwapPos(void) { std::swap(m_ItemData.m_ItemPos, m_itemPos_Real); }
|
|
|
|
inline unsigned short GetPrototypeID(void) const { return m_ItemData.m_usProtoTypeID; }
|
|
inline unsigned char GetNumOrDurability(void) const { return m_ItemData.m_cNumOrDurability; }
|
|
inline unsigned char GetMaxNumOrDurability(void) const { return m_cMaxNumOrDurability; }
|
|
inline void SetNumOrDurability(unsigned char cNumOrDurability) { m_ItemData.m_cNumOrDurability = cNumOrDurability; }
|
|
inline void SetMaxNumOrDurability(unsigned char cNumOrDurability) { m_cMaxNumOrDurability = cNumOrDurability; }
|
|
inline void SetStallPrice(unsigned long dwStallPrice) { m_dwStallPrice = dwStallPrice; }
|
|
|
|
inline unsigned long GetStallPrice(void) const { return m_dwStallPrice; }
|
|
inline unsigned long GetBuyBlackPrice(void) const { return m_ItemInfo.m_DetailData.m_dwBlackPrice; }
|
|
inline unsigned long GetBuyMedalPrice(void) const { return m_ItemInfo.m_DetailData.m_dwMedalPrice; }
|
|
|
|
virtual unsigned long GetBuyPrice(void) const;
|
|
virtual unsigned long GetSellPrice(void) const;
|
|
virtual unsigned long GetRepairPrice(void) const;
|
|
virtual unsigned long GetUpgradePrice(void) const;
|
|
virtual unsigned long GetGraftPrice(void) const;
|
|
|
|
inline const char* GetItemTypeName(void) const { return m_ItemInfo.m_StringData.m_szTypeName; }
|
|
|
|
inline bool IsSet(unsigned long dwDetailDataFlag) const { return dwDetailDataFlag == (m_ItemInfo.m_DetailData.m_dwFlags & dwDetailDataFlag); }
|
|
|
|
inline bool GetEnableRepair(void);
|
|
inline bool GetEnableStack(void);
|
|
inline bool GetSocketItem(void);
|
|
inline bool GetRuneItem(void);
|
|
inline bool GetTwohandItem(void);
|
|
inline bool GetEnableEquip(void);
|
|
|
|
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); }
|
|
|
|
// SetUID는 아무때나 함부로 사용하지 마시오!
|
|
inline void SetUID(unsigned __int64 dwItemUID) { m_ItemData.m_dwUID = dwItemUID; }
|
|
|
|
// S 그레이드 제한값 보정(S 그레이드 이외에는 쓰지 마세요. 공식이 정확하지 않습니다. - by hackermz)
|
|
virtual void RevisionLimit() { }
|
|
virtual void RevisionLimit(short* lpattrLimit) { }
|
|
virtual void RevisionLimit(Item::Attribute::Type eAttributeType, short& attrLImit) { }
|
|
|
|
|
|
protected:
|
|
|
|
virtual ~CItem();
|
|
|
|
const ItemInfo& m_ItemInfo; // 스크립트로부터 로드한 아이템 데이터
|
|
ItemData m_ItemData; // DB에 저장되는 아이템 데이터
|
|
|
|
ItemPos m_itemPos_Real; // 임시 공간이 아닌 아이템 위치
|
|
unsigned char m_cMaxNumOrDurability; // 최대 내구도
|
|
unsigned long m_dwStallPrice; // 노점상에서의 가격
|
|
unsigned long m_dwPrice; // 아이템 가격 (옵션에 의해 갱신되지만 내구도를 고려하지는 않은 값)
|
|
|
|
friend class CItemFactory;
|
|
};
|
|
|
|
|
|
class CEquipment : public CItem
|
|
{
|
|
public:
|
|
|
|
enum EQUIPMENT_ERROR
|
|
{
|
|
// 소켓 박기
|
|
S_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_SOCKET_NOT_MAX = 9, // 소켓 개수가 7개가 아니다.
|
|
E_SOCKET_NOT_INST = 10, // 소켓에 인스톨된 보석이 없다.
|
|
|
|
// 룬 설치/제거
|
|
R_SUCCESS = 0, // 룬 설치/제거 성공.
|
|
E_GET_RUNE_FAILED = 9, // 룬 개수가 없을때.
|
|
E_NOT_RUNE = 10, // 룬이 없을때.
|
|
E_NOT_RUNE_SLOT = 11, // 룬에 빈 소켓이 없을때.
|
|
E_NOT_RUNE_LEVEL_LIMIT = 12, // 룬에 레벨제한때 문제에 설치할 수 없을때.
|
|
E_USED_RUNE_SKILL_POINT = 13, // 룬에 추가 스킬 포인트를 사용하고 있어서 제거 할 수 없을때.
|
|
E_NOT_RUNE_SCRIPT_INFO = 14, // 룬에 스크립트 정보를 얻어올수 없을때.
|
|
|
|
// 강화
|
|
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_SCRAP_FAILED = 9, // 고철 생성 실패
|
|
E_SET_SCRAP_FAILED = 10, // 고철 놓기 실패
|
|
E_REMOVE_MINERAL_FAILED = 11, // 광물 제거 실패
|
|
E_UPGRADE_LEVEL_IS_FULL = 12, // 더 이상 업그레이드를 할 수 없음
|
|
E_NOT_ENOUGH_MONEY = 13, // 돈이 부족해서 업그레이드 할 수 없음
|
|
S_BROKEN_EQUIP = 14, // 성공했으나 무기 부서짐 (클라이언트로 보내지는 않는다.)
|
|
|
|
E_NOT_UPGRADE_LEVEL = 15, // 옵션 이식 가능한 제련 업그레이드 레벨이 아님.
|
|
|
|
E_NOT_UPGRADE_AS_OVER = 16, // 고대의 돌 이용 회수 초과.
|
|
E_NOT_UPGRADE_ENDURANCE = 17, // 내구도 회복 아이템 사용 불가.
|
|
E_NOT_UPGRADE_MINENDURANCE = 18, // 제련가능한 내구도 10이 되지 않습니다.
|
|
|
|
// 옵션 이식
|
|
E_WRONG_ATTRIBUTE = 2, // 이식 불가능한 옵션
|
|
E_NOT_EQUAL_KIND = 3, // 다른 종류의 장비
|
|
E_HIGH_GRADE_ORIGINAL = 4, // 원본의 그레이드가 높음
|
|
E_GRAFE_FAILD = 5, // 옵션이식 실패
|
|
|
|
// 보상 판매
|
|
E_WRONG_TYPE = 2, // 보상 판매 대상이 아님
|
|
E_NEW_SEASON_EQUIP = 3, // 새로 드랍됬거나 이미 보상된 장비
|
|
E_LOW_STATUS_EQUIP = 4 // 너무 낮은 수준의 장비
|
|
};
|
|
|
|
enum PASSIVE_TYPE
|
|
{
|
|
PASSIVE_ALWAYS = 0, // 무기에 상관없이 항상 발생하는 패시브
|
|
PASSIVE_THIS_WEAPON = 1, // 해당 무기에 발생하는 패시브
|
|
NONE_PASSIVE_THIS_WEAPON = 2 // 해당 무기에 발생하지 않는 패시브
|
|
};
|
|
|
|
enum RuneApplyType
|
|
{
|
|
RUNE_NONE = 0,
|
|
RUNE_INDEX = (1 << 0), // 하나에 속성.
|
|
RUNE_ALL = (1 << 1), // 모든 속성.
|
|
RUNE_APPLY = (1 << 2), // 속성을 추가.
|
|
RUNE_REMOVE = (1 << 3) // 속성을 삭제.
|
|
};
|
|
|
|
// 아이템을 장비로 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);
|
|
|
|
// 아이템 속성 추가 (속성 변경 후에는 반드시 가격/그레이드 계산을 다시 해줍시다.)
|
|
inline void AddAttribute(Item::Attribute::Type eAttributeType, short nAttributeValue);
|
|
inline void SetAttribute(Item::Attribute::Type eAttributeType, short nAttributeValue);
|
|
|
|
// 3차 밸런스 패치(소켓, 업그레이드 값 제거)0
|
|
inline void RemoveUpgradeAttribute(Item::Attribute::Type eAttributeType);
|
|
inline void RemoveGemAttribute(Item::Attribute::Type eAttributeType);
|
|
|
|
// 아이템 속성을 얻어 온다.
|
|
inline short GetAttribute(Item::Attribute::Type eAttributeType);
|
|
inline void GetAttribute(short* lpAttributeArray_Out, unsigned short nArraySize);
|
|
|
|
// 옵션별 한계값에 도달했는지 체크한다.
|
|
bool CheckAttributeLimit(Item::Attribute::Type eAttributeType, unsigned char cType = 0);
|
|
|
|
inline bool AddSocket(unsigned char cSocket);
|
|
inline void GetSocket(unsigned char* cSockets, unsigned char cArraySize);
|
|
unsigned char GetSocket(unsigned char cIndex) { return m_cSocket[cIndex]; }
|
|
|
|
const Grade::GradeInfo& GetItemGrade(void) const { return m_GradeInfo; }
|
|
|
|
inline void InitializeAttribute(void); // 아이템 정보를 상점값으로 초기화
|
|
BOOL AddRandomOption(Item::EquipType::Grade eGrade, unsigned char cBaseNum, int iMagicChance = 0);
|
|
|
|
// 소켓 설정
|
|
BOOL AddRandomSocket();
|
|
|
|
// 옵션 이식
|
|
EQUIPMENT_ERROR OptionGraft(CEquipment* lpSacrifice, bool bUpgradeLevelLimit, unsigned char cAttributeType,
|
|
unsigned long dwCurrentGold, unsigned long& dwUsedGold);
|
|
|
|
bool CanOptionGraft(Item::CItemType::ArrayType eItemType, Item::Attribute::Type eAttributeType);
|
|
|
|
// 보상 판매
|
|
EQUIPMENT_ERROR Compensation(unsigned char cClass, unsigned char cLevel,
|
|
CharacterStatus status, CEquipment** lppResultEquip, long& lCompensationGold);
|
|
|
|
unsigned char GetUpgradeLevel(void) const { return m_cUpgradeLevel; }
|
|
|
|
unsigned char GetCurrentSocketNum(void) const { return m_cSocketNum; }
|
|
unsigned char GetMaxSocketNum(void) const { return m_cMaxSocket; }
|
|
|
|
// 리밸런싱 이후 생성되는 장비는 이 함수를 호출해준다.
|
|
void SetNewEquip(char cStrong = 0)
|
|
{
|
|
if(cStrong == 2)
|
|
m_cSeasonRecord = 3;
|
|
else if(cStrong == 1)
|
|
m_cSeasonRecord = 2;
|
|
else if(m_cSeasonRecord == 0)
|
|
m_cSeasonRecord = 1;
|
|
}
|
|
unsigned char GetSeasonRecord(void) { return m_cSeasonRecord; }
|
|
|
|
unsigned long GetBuyPrice(void) const;
|
|
unsigned long GetSellPrice(void) const;
|
|
unsigned long GetRepairPrice(void) const;
|
|
unsigned long GetUpgradePrice(void) const;
|
|
unsigned long GetGraftPrice(void) const;
|
|
|
|
unsigned char GetUpgradeCnt(void) { return m_cUpgradeCnt; }
|
|
void SetUpgradeCnt(unsigned char cUpgradeCnt) { m_cUpgradeCnt = cUpgradeCnt; }
|
|
|
|
// 업그레이드 가능 여부 리턴
|
|
bool IsUpgradable(void) const;
|
|
|
|
// 장착아이템에 룬 소켓 개수 체크
|
|
inline unsigned char GetMaxRuneSocket();
|
|
|
|
// 룬을 아이템에 장착 가능한지 체크
|
|
inline unsigned char GetRuneEquipable();
|
|
|
|
// 장착 아이템에 장착제한에 레벨을 얻어온다.
|
|
inline unsigned short GetRuneEquipLimitLevel(void) const;
|
|
|
|
// 룬 아이템을 제거(속성도 같이 제거)
|
|
inline bool SubRuneAttribute(void);
|
|
|
|
// 설치 되어 있는 룬 소켓값을 넘겨준다.
|
|
inline unsigned short GetRuneSocket(unsigned char cIndex)
|
|
{
|
|
if (cIndex >= EquipmentInfo::MAX_RUNE_SOCKET_NUM)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return m_usRuneSocket[cIndex];
|
|
}
|
|
|
|
// 룬 속성을 삭제한 아이템 속성 복사본을 넘겨준다.
|
|
inline void GetSubRuneAttribute(short* psAttribute);
|
|
inline void GetSubRuneAttribute(Item::Attribute::Type eAttributeType, short& sAttribute);
|
|
|
|
// 외부에서 사용할 룬 속성 삭제/추가
|
|
inline void SetRuneAttribute(RuneApplyType enRuneApplyType, unsigned char ucIndex);
|
|
|
|
// 장착 아이템에 있는 모든 룬 아이템에 속성중 스킬포인트 리턴해준다.
|
|
unsigned short GetAllRuneSkillPointCheck();
|
|
|
|
// 룬 아이템이 장착 되어 있으면 스킬 포인트 체크
|
|
bool GetRuneCheckSkill(CCharacter* lpCharacter, Item::ItemPos itemPos, bool bChk = true);
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// ConvertTool에서만 사용되는 함수들 - RebalanceOverItem.cpp 에서 사용
|
|
inline void Repair();
|
|
inline void InitEquip();
|
|
inline void SetEquip();
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// 서버에서만 사용되는 함수들 - ItemServerFunc.cpp 에서 별도 구현
|
|
|
|
EQUIPMENT_ERROR InstallSocket(CItem& Gem);
|
|
EQUIPMENT_ERROR UpgradeItem(CItem& Mineral_InOut, unsigned long dwCurrentGold_In, unsigned long& dwUsedGold_Out, unsigned char& cMaxDur_Out);
|
|
|
|
EQUIPMENT_ERROR InstallRuneSocket(CItem& Rune, bool bEquip, unsigned char cLevel); // 장착 아이템에 룬 소켓 설치.
|
|
|
|
EQUIPMENT_ERROR UnInstallRuneSocket(CItem& Rune, bool bEquip, unsigned char cLevel, unsigned short usSkillPoint); // 장착 아이템에 룬 소켓 제거.
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// 3차 밸런스 패치 관련 함수
|
|
|
|
// S 그레이드 제한값 구하기
|
|
bool GetLimitValue(short* lpattrLimit);
|
|
bool GetLimitValue(Item::Attribute::Type eAttributeType, short& attrLimit);
|
|
|
|
// S 그레이드 제한값 보정(S 그레이드 이외에는 쓰지 마세요. 공식이 정확하지 않습니다. - by hackermz)
|
|
void RevisionLimit();
|
|
void RevisionLimit(short* lpattrLimit);
|
|
void RevisionLimit(Item::Attribute::Type eAttributeType, short& attrLImit);
|
|
|
|
// 그레이드 책정
|
|
void CalculateItemGrade(void);
|
|
|
|
|
|
protected:
|
|
|
|
enum ApplyType
|
|
{
|
|
APPLY = 1, // 값 바꾸지 말 것
|
|
REMOVE = -1 // 값 바꾸지 말 것
|
|
};
|
|
|
|
CEquipment(const ItemInfo& itemInfo);
|
|
virtual ~CEquipment();
|
|
|
|
inline void InitializeGemAttribute(void); // 소켓 정보로 소켓 속성을 초기화
|
|
inline void InitializeUpgradeAttribute(void); // 업그레이드 단계로 업그레이드 속성을 초기화
|
|
|
|
inline void ApplyGemAttribute(ApplyType eApplyType); // 소켓 속성을 적용
|
|
inline void ApplyUpgradeAttribute(ApplyType eApplyType); // 업그레이드 속성을 적용
|
|
inline void ApplyRuneAttribute(ApplyType eApplyType); // 룬 아이템 속성을 적용
|
|
|
|
void CalculateItemPrice(void); // 가격 책정
|
|
|
|
unsigned char m_cSocket[EquipmentInfo::MAX_SOCKET_NUM]; // 아이템 소켓 정보
|
|
ItemAttribute m_SocketAttribute[EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM]; // 아이템 소켓으로 박은 속성
|
|
ItemAttribute m_UpgradeAttribute[EquipmentInfo::MAX_UPGRADE_ATTRIBUTE]; // 아이템 업그레이드시 붙는 속성
|
|
unsigned short m_usRuneSocket[EquipmentInfo::MAX_RUNE_SOCKET_NUM]; // 룬 소켓
|
|
|
|
short m_wAttribute[Attribute::MAX_ATTRIBUTE_NUM]; // 최종적으로 계산된 아이템 속성 (스크립트 + DB + ...)
|
|
|
|
unsigned char m_cUpgradeLevel; // 업그레이드 단계
|
|
unsigned char m_cSocketNum; // 현재 소켓 개수
|
|
unsigned char m_cMaxSocket; // 최대 소켓 개수
|
|
unsigned char m_cMaxAttribute; // 최대 속성 개수
|
|
|
|
unsigned char m_cSeasonRecord; // 아이템 생성 시기
|
|
|
|
Grade::GradeInfo m_GradeInfo; // 그레이드 정보
|
|
|
|
unsigned char m_cUpgradeCnt;
|
|
|
|
friend class CItemFactory;
|
|
friend class CItemType;
|
|
};
|
|
|
|
class CUseItem : public CItem
|
|
{
|
|
public:
|
|
|
|
inline static CUseItem* DowncastToUseItem(CItem* lpItem);
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// 서버에서만 사용되는 함수들 - ItemServerFunc.cpp 에서 별도 구현
|
|
|
|
bool Use(CCharacter* lpSender, CCharacter* lpRecver, unsigned short& wError);
|
|
|
|
protected:
|
|
|
|
CUseItem(const ItemInfo& itemInfo);
|
|
virtual ~CUseItem();
|
|
|
|
bool UsePotion(CCharacter* lpSender, CCharacter* lpRecver);
|
|
|
|
friend class CItemFactory;
|
|
};
|
|
};
|
|
|
|
|
|
inline void Item::CItem::MoveItem(ItemPos itemPos)
|
|
{
|
|
if (TakeType::TS_STALL == itemPos.m_cPos)
|
|
{
|
|
m_itemPos_Real = itemPos;
|
|
}
|
|
else
|
|
{
|
|
m_ItemData.m_ItemPos = itemPos;
|
|
if (TakeType::TS_TEMP != itemPos.m_cPos)
|
|
{
|
|
m_itemPos_Real = itemPos;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline Item::CEquipment* Item::CEquipment::DowncastToEquipment(Item::CItem* lpItem)
|
|
{
|
|
if (NULL == lpItem) { return NULL; }
|
|
return lpItem->IsSet(DetailData::EQUIP) ?
|
|
static_cast<CEquipment*>(lpItem) : NULL;
|
|
}
|
|
|
|
inline void Item::CEquipment::AddAttribute(Item::Attribute::Type eAttributeType, short nAttributeValue)
|
|
{
|
|
/*
|
|
// 룬아이템에 속성 추가
|
|
if (eAttributeType == Attribute::RUNE && 0 != nAttributeValue)
|
|
{
|
|
unsigned short usRuneID = nAttributeValue + EtcItemID::RUNE_START_ID;
|
|
|
|
const ItemInfo* lpRuneInfo = CItemMgr::GetInstance().GetItemInfo(usRuneID);
|
|
if (NULL != lpRuneInfo)
|
|
{
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (0 != m_usRuneSocket[cIndex])
|
|
{
|
|
m_usRuneSocket[cIndex] = usRuneID;
|
|
|
|
for (int nIndex = 0; nIndex < Item::Attribute::MAX_ATTRIBUTE_NUM; ++nIndex)
|
|
{
|
|
if (Item::EquipType::S_GRADE != GetItemGrade().m_aryAttributeGrade[nIndex])
|
|
{
|
|
m_wAttribute[nIndex] += lpRuneInfo->m_EquipAttribute.m_usAttributeValue[nIndex];
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
if (Item::EquipType::S_GRADE != GetItemGrade().m_aryAttributeGrade[eAttributeType])
|
|
{
|
|
m_wAttribute[eAttributeType] += nAttributeValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::SetAttribute(Item::Attribute::Type eAttributeType, short nAttributeValue)
|
|
{
|
|
/*
|
|
// 룬아이템에 속성 추가
|
|
if (eAttributeType == Attribute::RUNE && 0 != nAttributeValue)
|
|
{
|
|
unsigned short usRuneID = nAttributeValue + EtcItemID::RUNE_START_ID;
|
|
|
|
const ItemInfo* lpRuneInfo = CItemMgr::GetInstance().GetItemInfo(usRuneID);
|
|
if (NULL != lpRuneInfo)
|
|
{
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (0 != m_usRuneSocket[cIndex])
|
|
{
|
|
m_usRuneSocket[cIndex] = usRuneID;
|
|
|
|
for (int nIndex = 0; nIndex < Item::Attribute::MAX_ATTRIBUTE_NUM; ++nIndex)
|
|
{
|
|
m_wAttribute[nIndex] = lpRuneInfo->m_EquipAttribute.m_usAttributeValue[nIndex];
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
m_wAttribute[eAttributeType] = nAttributeValue;
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::RemoveUpgradeAttribute(Item::Attribute::Type eAttributeType)
|
|
{
|
|
ItemAttribute* first = m_UpgradeAttribute;
|
|
ItemAttribute* last = m_UpgradeAttribute + EquipmentInfo::MAX_UPGRADE_ATTRIBUTE;
|
|
|
|
for (;first != last; ++first)
|
|
{
|
|
if(eAttributeType == static_cast<Item::Attribute::Type>(first->m_cType))
|
|
{
|
|
first->m_usValue = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::RemoveGemAttribute(Item::Attribute::Type eAttributeType)
|
|
{
|
|
ItemAttribute* first = m_SocketAttribute;
|
|
ItemAttribute* last = m_SocketAttribute + EquipmentInfo::MAX_UPGRADE_ATTRIBUTE;
|
|
|
|
for (;first != last; ++first)
|
|
{
|
|
if(eAttributeType == static_cast<Item::Attribute::Type>(first->m_cType))
|
|
{
|
|
first->m_usValue = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline bool Item::CEquipment::SubRuneAttribute(void)
|
|
{
|
|
// 룬 아이템 제거
|
|
for (unsigned char cRune = 0; cRune <= EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cRune)
|
|
{
|
|
if (m_usRuneSocket[cRune])
|
|
{
|
|
unsigned short usItemId = m_usRuneSocket[cRune];
|
|
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(usItemId);
|
|
|
|
if (itemInfo)
|
|
{
|
|
for (unsigned char cIndex = 0; cIndex < Item::Attribute::MAX_ATTRIBUTE_NUM; ++cIndex)
|
|
{
|
|
m_wAttribute[cIndex] -= itemInfo->m_EquipAttribute.m_usAttributeValue[cIndex];
|
|
}
|
|
}
|
|
|
|
m_usRuneSocket[cRune] = 0;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
inline short Item::CEquipment::GetAttribute(Item::Attribute::Type eAttributeType)
|
|
{
|
|
return m_wAttribute[eAttributeType];
|
|
}
|
|
|
|
inline 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;
|
|
|
|
for (int nIndex = 0; nIndex < nCopyNum; ++nIndex)
|
|
{
|
|
*(lpAttributeArray_Out + nIndex) = GetAttribute(static_cast<Item::Attribute::Type>(nIndex));
|
|
}
|
|
}
|
|
|
|
inline bool Item::CEquipment::AddSocket(unsigned char cSocket)
|
|
{
|
|
if (m_cSocketNum < m_cMaxSocket && 0 == m_cSocket[m_cSocketNum])
|
|
{
|
|
m_cSocket[m_cSocketNum] = cSocket;
|
|
++m_cSocketNum;
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
inline void Item::CEquipment::GetSocket(unsigned char* cSockets, unsigned char cArraySize)
|
|
{
|
|
unsigned short nCopyNum = cArraySize < Item::EquipmentInfo::MAX_SOCKET_NUM
|
|
? cArraySize : Item::EquipmentInfo::MAX_SOCKET_NUM;
|
|
unsigned char* lpSocketPastEnd = m_cSocket + nCopyNum;
|
|
std::copy(m_cSocket, lpSocketPastEnd , cSockets);
|
|
}
|
|
|
|
inline void Item::CEquipment::InitializeAttribute(void)
|
|
{
|
|
for (unsigned int nIndex = 0; nIndex < Item::Attribute::MAX_ATTRIBUTE_NUM; ++nIndex)
|
|
{
|
|
m_wAttribute[nIndex] = m_ItemInfo.m_EquipAttribute.m_usAttributeValue[nIndex];
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::InitializeGemAttribute(void)
|
|
{
|
|
std::fill_n(m_SocketAttribute, int(EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM), ItemAttribute());
|
|
|
|
// 설치된 소켓을 가지고 속성과 값을 설정
|
|
CItemType::SetInstallGemAttribute(this);
|
|
}
|
|
|
|
inline void Item::CEquipment::InitializeUpgradeAttribute(void)
|
|
{
|
|
std::fill_n(m_UpgradeAttribute, int(EquipmentInfo::MAX_UPGRADE_ATTRIBUTE), ItemAttribute());
|
|
|
|
// 아이템 업그레이드 단계값을 가지고 속성과 값을 설정
|
|
CItemType::SetUpgradeItemAttribute(this);
|
|
}
|
|
|
|
inline void Item::CEquipment::ApplyGemAttribute(ApplyType eApplyType)
|
|
{
|
|
ItemAttribute* first = m_SocketAttribute;
|
|
ItemAttribute* last = m_SocketAttribute + EquipmentInfo::MAX_SOCKET_ATTRIBUTE_NUM;
|
|
|
|
for (;first != last; ++first)
|
|
{
|
|
AddAttribute(static_cast<Item::Attribute::Type>(first->m_cType), first->m_usValue * eApplyType);
|
|
}
|
|
}
|
|
|
|
inline unsigned char Item::CEquipment::GetMaxRuneSocket()
|
|
{
|
|
// 장착아이템에 룬 소켓 개수 체크
|
|
return Item::CItemMgr::GetInstance().GetMaxRuneSocket(static_cast<ItemType::Type>(GetItemInfo().m_DetailData.m_cItemType));
|
|
}
|
|
|
|
inline unsigned char Item::CEquipment::GetRuneEquipable()
|
|
{
|
|
// 장착아이템에 룬 소켓 빈공간 체크
|
|
unsigned char cRuneSocketCnt = Item::CItemMgr::GetInstance().GetMaxRuneSocket(static_cast<ItemType::Type>(GetItemInfo().m_DetailData.m_cItemType));
|
|
|
|
if (!cRuneSocketCnt)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (!m_usRuneSocket[0])
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
if (!m_usRuneSocket[1] && cRuneSocketCnt == EquipmentInfo::MAX_RUNE_SOCKET_NUM)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline void Item::CEquipment::ApplyUpgradeAttribute(ApplyType eApplyType)
|
|
{
|
|
ItemAttribute* first = m_UpgradeAttribute;
|
|
ItemAttribute* last = m_UpgradeAttribute + EquipmentInfo::MAX_UPGRADE_ATTRIBUTE;
|
|
|
|
for (;first != last; ++first)
|
|
{
|
|
AddAttribute(static_cast<Item::Attribute::Type>(first->m_cType), first->m_usValue * eApplyType);
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::ApplyRuneAttribute(ApplyType eApplyType)
|
|
{
|
|
// 룬아이템에 속성 추가/삭제
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (m_usRuneSocket[cIndex])
|
|
{
|
|
unsigned short usItemId = m_usRuneSocket[cIndex];
|
|
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(usItemId);
|
|
|
|
if (itemInfo)
|
|
{
|
|
for (unsigned char cAttribute = 0; cAttribute < Item::Attribute::MAX_ATTRIBUTE_NUM; ++cAttribute)
|
|
{
|
|
m_wAttribute[cAttribute] += itemInfo->m_EquipAttribute.m_usAttributeValue[cAttribute]*eApplyType;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::GetSubRuneAttribute(short* psAttribute)
|
|
{
|
|
// 룬 속성을 삭제한 아이템 속성 복사본을 넘겨준다.
|
|
memcpy(psAttribute, m_wAttribute, sizeof(m_wAttribute));
|
|
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (m_usRuneSocket[cIndex])
|
|
{
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(m_usRuneSocket[cIndex]);
|
|
|
|
if (itemInfo)
|
|
{
|
|
for (unsigned char cAttribute = 0; cAttribute < Item::Attribute::MAX_ATTRIBUTE_NUM; ++cAttribute)
|
|
{
|
|
psAttribute[cAttribute] -= itemInfo->m_EquipAttribute.m_usAttributeValue[cAttribute];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::GetSubRuneAttribute(Item::Attribute::Type eAttributeType, short& sAttribute)
|
|
{
|
|
sAttribute = m_wAttribute[eAttributeType];
|
|
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (m_usRuneSocket[cIndex])
|
|
{
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(m_usRuneSocket[cIndex]);
|
|
|
|
if (itemInfo)
|
|
{
|
|
sAttribute -= itemInfo->m_EquipAttribute.m_usAttributeValue[eAttributeType];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void Item::CEquipment::SetRuneAttribute(RuneApplyType enRuneApplyType, unsigned char ucIndex)
|
|
{
|
|
// 외부에서 사용할 룬 속성 삭제/추가.
|
|
|
|
if (enRuneApplyType&RuneApplyType::RUNE_INDEX && enRuneApplyType&RuneApplyType::RUNE_REMOVE)
|
|
{
|
|
for (unsigned char ucRuneIndex = 0; ucRuneIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ucRuneIndex++)
|
|
{
|
|
if (m_usRuneSocket[ucRuneIndex])
|
|
{
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(m_usRuneSocket[ucRuneIndex]);
|
|
|
|
if (itemInfo)
|
|
{
|
|
m_wAttribute[ucIndex] -= itemInfo->m_EquipAttribute.m_usAttributeValue[ucIndex];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (enRuneApplyType&RuneApplyType::RUNE_ALL && enRuneApplyType&RuneApplyType::RUNE_REMOVE)
|
|
{
|
|
ApplyRuneAttribute(REMOVE);
|
|
}
|
|
else if (enRuneApplyType&RuneApplyType::RUNE_INDEX && enRuneApplyType&RuneApplyType::RUNE_APPLY)
|
|
{
|
|
for (unsigned char ucRuneIndex = 0; ucRuneIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ucRuneIndex++)
|
|
{
|
|
if (m_usRuneSocket[ucRuneIndex])
|
|
{
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(m_usRuneSocket[ucRuneIndex]);
|
|
|
|
if (itemInfo)
|
|
{
|
|
m_wAttribute[ucIndex] += itemInfo->m_EquipAttribute.m_usAttributeValue[ucIndex];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (enRuneApplyType&RuneApplyType::RUNE_ALL && enRuneApplyType&RuneApplyType::RUNE_APPLY)
|
|
{
|
|
ApplyRuneAttribute(APPLY);
|
|
}
|
|
}
|
|
|
|
inline unsigned short Item::CEquipment::GetRuneEquipLimitLevel(void) const
|
|
{
|
|
// 장착 아이템에 장착제한에 레벨을 얻어온다.
|
|
unsigned short usResult = 0;
|
|
|
|
for (unsigned char cIndex = 0; cIndex < EquipmentInfo::MAX_RUNE_SOCKET_NUM; ++cIndex)
|
|
{
|
|
if (m_usRuneSocket[cIndex])
|
|
{
|
|
unsigned short usItemId = m_usRuneSocket[cIndex];
|
|
|
|
const ItemInfo* itemInfo = CItemMgr::GetInstance().GetItemInfo(usItemId);
|
|
|
|
if (itemInfo)
|
|
{
|
|
if (itemInfo->m_UseLimit.m_cLimitStatus==Item::StatusLimit::LEVEL)
|
|
{
|
|
if (usResult<itemInfo->m_UseLimit.m_wLimitValue)
|
|
{
|
|
usResult = itemInfo->m_UseLimit.m_wLimitValue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return usResult;
|
|
}
|
|
|
|
inline Item::CUseItem* Item::CUseItem::DowncastToUseItem(CItem* lpItem)
|
|
{
|
|
if (NULL == lpItem) { return NULL; }
|
|
return lpItem->IsSet(DetailData::USE_ITEM) ?
|
|
static_cast<CUseItem*>(lpItem) : NULL;
|
|
}
|
|
|
|
inline bool Item::CItem::GetEnableRepair(void)
|
|
{
|
|
unsigned long dwFlags = GetItemInfo().m_DetailData.m_dwFlags;
|
|
return ((dwFlags & Item::DetailData::EQUIP) && !(dwFlags & Item::DetailData::STACKABLE));
|
|
}
|
|
|
|
inline bool Item::CItem::GetEnableStack(void)
|
|
{
|
|
return (GetItemInfo().m_DetailData.m_dwFlags & Item::DetailData::STACKABLE) ? true : false;
|
|
}
|
|
|
|
inline bool Item::CItem::GetEnableEquip(void)
|
|
{
|
|
return (GetItemInfo().m_DetailData.m_dwFlags & Item::DetailData::EQUIP);
|
|
}
|
|
|
|
inline bool Item::CItem::GetSocketItem(void)
|
|
{
|
|
return (GetItemInfo().m_DetailData.m_cItemType == Item::ItemType::GEM);
|
|
}
|
|
|
|
inline bool Item::CItem::GetRuneItem(void)
|
|
{
|
|
return (GetItemInfo().m_DetailData.m_cItemType == Item::ItemType::RUNE);
|
|
}
|
|
|
|
inline bool Item::CItem::GetTwohandItem(void)
|
|
{
|
|
unsigned char cItemType = GetItemInfo().m_DetailData.m_cItemType;
|
|
return (cItemType == Item::ItemType::BOW ||
|
|
cItemType == Item::ItemType::CROSSBOW ||
|
|
cItemType == Item::ItemType::STAFF ||
|
|
cItemType == Item::ItemType::TWOHANDED_AXE ||
|
|
cItemType == Item::ItemType::TWOHANDED_BLUNT ||
|
|
cItemType == Item::ItemType::TWOHANDED_SWORD ||
|
|
cItemType == Item::ItemType::OPP_SYTHE);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------------------
|
|
// ConvertTool에서만 사용되는 함수들 - RebalanceOverItem.cpp 에서 사용
|
|
inline void Item::CEquipment::Repair()
|
|
{
|
|
SetNumOrDurability(GetMaxNumOrDurability());
|
|
CalculateItemPrice();
|
|
}
|
|
|
|
inline void Item::CEquipment::InitEquip()
|
|
{
|
|
// 옵션 이식을 하기전에 룬 추가 옵션을 삭제한다.
|
|
RuneApplyType enRuneApplyType = static_cast<RuneApplyType>(RUNE_ALL | RUNE_REMOVE);
|
|
|
|
SetRuneAttribute(enRuneApplyType, 0);
|
|
|
|
// 제련 단계는 초기화된다. (옵션은 남는다.)
|
|
m_cUpgradeLevel = 0;
|
|
InitializeUpgradeAttribute();
|
|
|
|
// 소켓도 초기화된다. (보석은 모두 제거되지만 옵션은 남는다.)
|
|
m_cSocketNum = 0;
|
|
std::fill_n(m_cSocket, unsigned char(Item::EquipmentInfo::MAX_SOCKET_NUM), 0);
|
|
InitializeGemAttribute();
|
|
m_cMaxSocket = m_ItemInfo.m_DetailData.m_cMaxSocketNum;
|
|
}
|
|
|
|
inline void Item::CEquipment::SetEquip()
|
|
{
|
|
// 룬 속성을 다시 추가한다.
|
|
RuneApplyType enRuneApplyType = static_cast<RuneApplyType>(RUNE_ALL | RUNE_APPLY);
|
|
|
|
SetRuneAttribute(enRuneApplyType, 0);
|
|
}
|
|
|
|
#endif |