Files
Leviathan/Server/GameServer/Game/Struct/StructItem.h
T
2026-06-01 12:46:52 +02:00

429 lines
25 KiB
C++

#pragma once
#include <mmo/ArObject.h>
#include <toolkit/ILock.h>
#include "StructBase.h"
#include "GameType.h"
#include "ItemInstance.h"
#include "StructGold.h"
#include "GameDBManager.h"
#include <list>
#include <time.h>
struct StructItem : GameObject
{
struct ITEM_PICKUP_ORDER
{
AR_HANDLE hPlayer[ 3 ];
int nPartyID[ 3 ];
};
// PreviousUID에 따른 정렬을 쉽게 하기 위해 필요한 구조체
struct INDEX_FINDER
{
StructItem * pItem;
INDEX_FINDER( StructItem * _pItem ) : pItem( _pItem ){}
bool operator ==( ItemUID uid )
{
return uid == pItem->GetPreviousUID();
}
};
enum _TARGET_TYPE
{
TARGET_TYPE_PLAYER = 0,
TARGET_TYPE_SUMMON = 1,
TARGET_TYPE_MONSTER = 2,
TARGET_TYPE_NPC = 3,
TARGET_TYPE_UNKNOWN = 4
};
static StructItem* AllocItem( ItemUID uid,
ItemBase::ItemCode code,
const __int64 & cnt = 1,
ItemInstance::GenerateCode info = ItemInstance::BY_UNKNOWN,
int level = -1,
int enhance = -1,
int flag = -1,
ItemBase::ItemCode socket_0 = 0,
ItemBase::ItemCode socket_1 = 0,
ItemBase::ItemCode socket_2 = 0,
ItemBase::ItemCode socket_3 = 0,
int awaken_sid = 0,
int identified_sid = 0,
int remain_time = -1,
const unsigned char & elemental_effect_type = 0,
const time_t & elemental_effect_expire_time = 0,
const int elemental_effect_attack_point = 0,
const int elemental_effect_magic_point = 0,
const ItemBase::ItemCode appearance_code = 0,
int summon_code = 0,
int extra_item_effect = 0); // Fraun Sky Accessories 7/12/2025
static StructItem* FindItem( AR_HANDLE handle );
static StructItem* AllocGold( const StructGold & gold, ItemInstance::GenerateCode gcode = ItemInstance::BY_UNKNOWN );
static void InitItemSystem();
static void DeInitItemSystem();
#define PendFreeItem( p ) PendFreeItem_( p, __FILE__, __LINE__ )
static void PendFreeItem_( StructItem* p, const char* function, const int line ); // 지워 달라고 요청. (모았다 주기적으로 한꺼번에 delete 한다)
friend struct StructPlayer;
virtual bool IsDeleteable();
static bool RegisterItemBase( const ItemBaseServer & base );
static ItemBase::ItemCode GetItemCode( const char *szItemName );
static bool IsValidItemCode( ItemBase::ItemCode code );
static bool RegisterConvertingInfo( ItemBase::ItemCode _key, ItemBase::ItemCode _value );
AR_HANDLE GetHandle() const { return m_hHandle; }
virtual bool IsItem() const { return true; }
inline bool IsBow() const { return ( GetItemBase().nClass == ItemBase::CLASS_LIGHT_BOW || GetItemBase().nClass == ItemBase::CLASS_HEAVY_BOW ); }
inline bool IsCrossBow() const { return GetItemBase().nClass == ItemBase::CLASS_CROSSBOW; }
// Bullet 류는 화살 뿐만 아니라 화살통을 포함한다.
inline bool IsBullet() const { return GetItemBase().nGroup == ItemBase::GROUP_BULLET; }
inline bool IsBelt() const { return GetItemBase().nGroup == ItemBase::GROUP_BELT; }
inline bool IsEquipment() const { return GetItemBase().nType == ItemBase::TYPE_ARMOR; }
inline bool IsCard() const { return GetItemBase().nType == ItemBase::TYPE_CARD; }
inline bool IsChaosStone() const { return GetItemBase().nCode == 804000; }
inline bool IsCharm() const { return GetItemBase().nType == ItemBase::TYPE_CHARM; }
inline bool IsCollection() const { return GetItemBase().nType == ItemBase::TYPE_COLLECTION; }
inline bool IsWeapon() const { return GetItemGroup() == ItemBase::GROUP_WEAPON; }
inline bool IsAccessory() const { return GetItemGroup() == ItemBase::GROUP_ACCESSORY; }
inline bool IsItemCard() const { return GetItemGroup() == ItemBase::GROUP_ITEMCARD; }
inline bool IsWarpItem() const { return GetItemBase().Flag.IsOn( ItemBase::FLAG_WARP ); }
inline bool IsSummonCard() const { return GetItemGroup() == ItemBase::GROUP_SUMMONCARD; }
inline bool IsPetCage() const { return GetItemGroup() == ItemBase::GROUP_PET_CAGE; }
inline bool IsSkillCard() const { return GetItemGroup() == ItemBase::GROUP_SKILLCARD; }
inline bool IsSpellCard() const { return GetItemGroup() == ItemBase::GROUP_SPELLCARD; }
inline bool IsCube() const { return GetItemBase().nType == ItemBase::TYPE_CUBE; }
inline bool IsSupplyItem() const { return GetItemBase().nType == ItemBase::TYPE_SUPPLY; }
inline bool IsUsingItem() const { return GetItemBase().nType == ItemBase::TYPE_USE || GetItemBase().nType == ItemBase::TYPE_USE_CARD; }
inline bool IsArmor() const { return GetItemBase().nGroup == ItemBase::GROUP_ARMOR ; }
inline bool IsStrikeCube() const { return GetItemGroup() == ItemBase::GROUP_STRIKE_CUBE; }
inline bool IsDefenceCube() const { return GetItemGroup() == ItemBase::GROUP_DEFENCE_CUBE; }
inline bool IsSkillCube() const { return GetItemGroup() == ItemBase::GROUP_SKILL_CUBE; }
inline bool IsArtifact() const { return GetItemGroup() == ItemBase::GROUP_ARTIFACT; }
//AziaMafia SkinPet
inline bool IsSkin1() const { return GetItemGroup() == ItemBase::GROUP_SKIN1; }
inline bool IsSkin2() const { return GetItemGroup() == ItemBase::GROUP_SKIN2; }
inline bool IsSkin3() const { return GetItemGroup() == ItemBase::GROUP_SKIN3; }
//AziaMafia PetSlot armure Set
inline bool IsHelmet() const { return GetItemGroup() == ItemBase::GROUP_HELM; }
inline bool IsGloves() const { return GetItemGroup() == ItemBase::GROUP_GLOVE; }
inline bool IsBoots() const { return GetItemGroup() == ItemBase::GROUP_BOOTS; }
//accesoire
inline bool IsEarRing() const { return GetItemClass() == ItemBase::CLASS_EARRING; }
inline bool IsRing() const { return GetItemClass() == ItemBase::CLASS_RING; }
inline bool IsAmulet() const { return GetItemClass() == ItemBase::CLASS_ARMULET; }
inline bool IsEquipmentOnBelt() const { return GetItemGroup() == ItemBase::GROUP_EQUIPMENT_ON_BELT; }
inline bool IsFarmPass() const { return GetItemBase().nClass == ItemBase::CLASS_FARM_PASS; }
inline bool IsRefreshStone() const { return GetItemCode() == 800000; } // 하드코드 -_-
inline bool IsEtherealStone() const { return GetItemBase().nClass == ItemBase::CLASS_ETHEREAL_STONE;}
inline bool IsShield() const { return GetItemBase().nClass == ItemBase::CLASS_SHIELD; }
inline bool IsTwoHandItem() const { return GetItemBase().WearType == ItemBase::WEAR_TWOHAND; }
inline bool IsDonatable() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_DONATE ); }
inline bool IsNeedTarget() const { return GetBaseFlag().IsOn( ItemBase::FLAG_TARGET_USE ); }
inline bool IsCashItem() const { return GetBaseFlag().IsOn( ItemBase::FLAG_CASHITEM ); }
inline bool IsTradable() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_TRADE ); } // 뭐가 좀;;
inline bool IsDropable() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_DROP ); } // 역시 좀;;
inline bool IsUsableMoving() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_MOVING ); } // 으음;;
inline bool IsUsableSit() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_SIT ); } // 으음;;
inline bool IsUsableInSiegeOrRaid() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_RAID_SIEGE ); } // 아... 막 가는거다;;
inline bool IsUsableInSecroute() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_SECROUTE ); } // 젠장 왜 사용 불가 플래그냐고...
inline bool IsUsableInEventmap() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_EVENTMAP ); } // 역시 긍정 문으로 바꾸는 것이...;;
inline bool IsUsableInHuntaholic() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_HUNTAHOLIC ); } // ...
inline bool IsUsableInOnlyHuntaholic() const { return GetBaseFlag().IsOn( ItemBase::FLAG_USABLE_IN_ONLY_HUNTAHOLIC ); }
inline bool IsUsableInDeathmatch() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_DEATHMATCH ); }
inline bool IsUsableInOnlyDeathmatch() const { return GetBaseFlag().IsOn( ItemBase::FLAG_USABLE_IN_ONLY_DEATHMATCH ); }
inline bool IsErasable() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_NOT_ERASABLE ); }
inline bool IsUsableOnOnlySit() const { return GetBaseFlag().IsOn( ItemBase::FLAG_USABLE_ON_ONLY_SIT ); }
inline bool IsUsableInSecretDungeon() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_SECRET_DUNGEON ); }
inline bool IsUsableInBattleArena() const { return !GetBaseFlag().IsOn( ItemBase::FLAG_CANT_USE_IN_BATTLE_ARENA ); }
inline bool IsRandomizable() const { return GetBaseFlag().IsOn( ItemBase::FLAG_RANDOMIZABLE ); }
// 중첩기준: 중첩 가능한 플래그, 소환수가 들어 있지 않고, 스킬카드면 장비되있지 않아야 함.
bool IsJoinable() const
{
return GetBaseFlag().IsOn( ItemBase::FLAG_JOIN )
&& !GetInstanceFlag().IsOn( ItemInstance::ITEM_FLAG_SUMMON )
&& !( IsSkillCard() && ( GetBindedPlayerSID() || GetBindedSummonSID() ) );
}
void CopyFrom( StructItem* pFrom );
const bool IsReplaceable( const ItemBase::ItemCode code, const bool reset_remain_time );
const char* GetName() const;
std::string GetNameInGame(); // 게임상 이름 반환 (게임에서 못 보는 이름인 '< >' 태그 삭제된 이름으로 반환)
inline void SetPickupOrder( const ITEM_PICKUP_ORDER& ItemPickupOrder ) { s_memcpy( &m_ItemPickupOrder, sizeof( m_ItemPickupOrder ), &ItemPickupOrder, sizeof( m_ItemPickupOrder ) ); }
inline const ITEM_PICKUP_ORDER& GetPickupOrder() const { return m_ItemPickupOrder; }
// ItemUID 는 DB 에 저장할 필요가 있을때 발급된다.
// 이는 플레이어의 인벤토리에 포함될때를 의미하며 해서 StructPlayer 에서 할당해준다.
bool SetItemUID( ItemUID uid );
ItemUID GetItemUID() const { return m_Instance.UID; }
bool ChangeItemCode( const ItemBase::ItemCode code );
bool ChangeAdditionalItemEffect( const ItemBase::ItemCode code, const int nItemEffectID ); // Fraun Sky Accessories 7/12/2025
// PreviuosUID는 아이템이 StructInventory 구조체 하에서 관리될 때 벡터형태의 메모리 구조의 단점을 어느정도 커버하기위해 사용된다.
// 구체적으로는 발급은 StructInventory::push 로직내에서 처리되고, 데이터의 관리는 StructInventory내의 각 함수들에 의해 이루어진다.
inline void SetPreviousUID( ItemUID uid ) { m_Instance.PreviousUID = uid; }
inline ItemUID GetPreviousUID() { return m_Instance.PreviousUID; }
inline AR_HANDLE GetOwnerHandle() const { return m_Instance.OwnerHandle; }
inline void SetOwnerInfo( AR_HANDLE handle, int UID, int nAccountID ) { m_Instance.OwnerHandle = handle; m_Instance.nOwnerUID = UID; m_nAccountID = nAccountID; memset( &m_ItemPickupOrder, 0, sizeof( m_ItemPickupOrder ) ); }
inline int GetOwnerUID() const { return m_Instance.nOwnerUID; }
inline int GetAccountID() const { return m_nAccountID; }
inline int GetAuctionID() const { return m_Instance.nAuctionID; }
inline void SetAuctionID( int nAuctionID ) { m_Instance.nAuctionID = nAuctionID; }
inline int GetItemKeepingID() const { return m_Instance.nItemKeepingID; }
inline void SetItemKeepingID( int nItemKeepingID ) { m_Instance.nItemKeepingID = nItemKeepingID; }
inline void SetIdx( int nIdx ) { m_Instance.nIdx = nIdx; }
inline int GetIdx() const { return m_Instance.nIdx; }
inline bool IsVirtualItem() const { return m_bIsVirtualItem; }
inline void SetVirtualItem() { m_bIsVirtualItem = true; }
inline void SetOwnSummonInfo( AR_HANDLE handle, int UID ) { m_Instance.OwnSummonHandle = handle; m_Instance.nOwnSummonUID = UID; }
inline int GetOwnSummonUID() const { return m_Instance.nOwnSummonUID; }
inline AR_HANDLE GetOwnSummonHandle() const { return m_Instance.OwnSummonHandle; }
inline int GetItemAdditionalEffect() const { return m_Instance.nAdditionalItemEffect; } // Fraun Sky Accessories 7/12/2025
inline bool IsInStorage() const { return ( GetAccountID() && !GetOwnerUID() && GetItemCode() != 0 ); } // gold 아이템은 안친다.-_-
inline bool IsInInventory() const { return ( !GetAccountID() && GetOwnerUID() ); }
inline void SetWearInfo( ItemBase::ItemWearType wear_info, const bool bSkipDBUpdate = false )
{
m_Instance.nWearInfo = wear_info;
if( !bSkipDBUpdate )
TurnOnUpdateFlag();
}
inline ItemBase::ItemWearType GetWearInfo() const { return m_Instance.nWearInfo; } // 1000 이상일경우 소환수에 장착된것임.
void SetBindedCreatureHandle( AR_HANDLE target ) { m_hBindedTarget = target; }
AR_HANDLE GetBindedCreatureHandle() const { return m_hBindedTarget; }
ItemBase::ItemCode GetItemCode() const { return m_Instance.Code; }
const ItemBaseServer & GetItemBase() const { return *m_pItemBase; }
float GetWeight( const __int64 & cnt ) const { return cnt * GetItemBase().fWeight; }
float GetWeight() const { return GetCount() * GetItemBase().fWeight; }
ItemBase::ITEM_TYPE GetItemType() const { return static_cast< ItemBase::ITEM_TYPE >( GetItemBase().nType ); }
ItemBase::ItemClass GetItemClass() const { return GetItemBase().nClass; }
bool IsWearable() const;
ItemBase::ItemWearType GetWearType() const { return GetItemBase().WearType; }
int GetMaxSocketCount() const;
int GetUsingSocketCount() const;
ItemBase::ItemCode GetSocketCode( unsigned idx ) const { return m_Instance.Socket[idx]; }
void SetSocketCode( unsigned idx, ItemBase::ItemCode code ) { m_Instance.Socket[idx] = code; }
void SetSummonCode( int _nSummonCode ) { m_Instance.nSummonCode = _nSummonCode; }
int GetSummonCode() const;
int GetStateCode() const { return m_pItemBase->nStateCode; }
int GetStateLevel() const { return m_pItemBase->nStateLevel; }
AR_TIME GetStateTime() const { return m_pItemBase->nStateTime; }
AR_TIME GetCoolTime() const { return m_pItemBase->nCoolTime * 100; }
int GetCoolTimeGroup() const { return m_pItemBase->nCoolTimeGroup; }
// 소환수 카드 전용
void SetSummonSID( int sid, const bool bSkipDBUpdate = false )
{
if( !bSkipDBUpdate )
TurnOnUpdateFlag();
m_Instance.Socket[0] = sid;
}
int GetSummonSID() const { return static_cast< int >( m_Instance.Socket[0] ); }
void SetSummonStruct( struct StructSummon* pSummon ) { m_pSummon = pSummon; }
struct StructSummon* GetSummonStruct() const { return m_pSummon; }
// 펫 우리 전용
void SetPetSID( const int sid ) { m_Instance.Socket[0] = sid; TurnOnUpdateFlag(); }
const int GetPetSID() const { return static_cast< int >( m_Instance.Socket[0] ); }
void SetPetCode( const int code ) { m_Instance.Socket[1] = code; TurnOnUpdateFlag(); }
const int GetPetCode() const { return static_cast< int >( m_Instance.Socket[1] ); }
void SetPetStruct( struct StructPet * pPet ) { m_pPet = pPet; }
struct StructPet * GetPetStruct() const { return m_pPet; }
void SetEventDropFlag( bool bFlag ) { m_bIsEventDrop = bFlag; }
bool GetEventDropFlag() const { return m_bIsEventDrop; }
// (스킬카드일경우) 누구에게 바인딩 되었는지?
int GetSkillId() const { return m_pItemBase->nSkillID; } // TODO : 스킬카드일경우 스킬 번호 알려줘야함
bool IsBinded() const { return !!m_hBindedTarget; }
void SetBindTarget( struct StructCreature *pTarget, const bool bSkipDBUpdate = false );
int GetBindedPlayerSID() const { return static_cast< int >( m_Instance.Socket[0] ); }
int GetBindedSummonSID() const { return static_cast< int >( m_Instance.Socket[1] ); }
bool IsGold() const { return !GetItemCode(); }
void SetCount( const __int64 & c ) { m_Instance.nCount = c; TurnOnUpdateFlag(); }
const __int64 GetCount() const { return m_Instance.nCount; }
unsigned char GetItemGrade() const { return GetItemBase().nGrade; }
int GetItemRank() const { return GetItemBase().nRank; }
int GetItemLevel( bool toDB = false ) const { return toDB ? m_Instance.nLevel : m_Instance.nLevel % 100; }
void SetItemLevel( int level ) { m_Instance.nLevel = GetItemEnhanceChance() * 100 + level; TurnOnUpdateFlag(); }
int GetItemEnhance() const { return m_Instance.nEnhance; }
void SetItemEnhance( int enhance );
short GetItemEnhanceChance() const { return ( ( m_Instance.nLevel - GetItemLevel() ) / 100 ); }
void SetItemEnhanceChance(float chance) { m_Instance.nLevel = GetItemLevel() + chance * 100; TurnOnUpdateFlag(); }
// 에테리얼 내구도 관련
const int ProcEtherealDurabilityConsumption( const int nBaseConsumption, const c_fixed10 & fConsumeRate, const c_fixed10 & fEnvironmentalConsumeRate );
const int GetCurrentEtherealDurability() const { return m_Instance.nCurrentEtherealDurability; }
void SetCurrentEtherealDurability( const int nDurability ) { m_Instance.nCurrentEtherealDurability = std::min( std::max( nDurability, 0 ), GetMaxEtherealDurability() ); TurnOnUpdateFlag(); }
void AddCurrentEtherealDurability( const int nAdd )
{
// 오버 플로우 체크
__int64 nNewEtherealDurability = GetCurrentEtherealDurability();
nNewEtherealDurability += nAdd;
if( nNewEtherealDurability > INT_MAX )
{
assert( 0 );
nNewEtherealDurability = INT_MAX;
}
SetCurrentEtherealDurability( int( nNewEtherealDurability ) );
}
const int GetMaxEtherealDurability() const;
int GetCurrentEndurance() const { return m_Instance.nCurrentEndurance; }
void SetCurrentEndurance( int n );
int GetMaxEndurance() const;
// 레벨제한
int GetLevelLimit() const;
// 권장레벨
int GetRecommendLevel() const;
AR_UNIT GetItemAttackRange() const { return AR_UNIT( GetItemBase().nRange ); }
int GetItemGroup() const { return GetItemBase().nGroup; }
ItemBase::BaseFlag GetBaseFlag() const { return GetItemBase().Flag; }
inline ItemInstance::InstanceFlag & GetInstanceFlag() { return m_Instance.Flag; }
inline const ItemInstance::InstanceFlag & GetInstanceFlag() const { return m_Instance.Flag; }
void SetInstanceFlagOn( int idx );
void SetInstanceFlagOff( int idx );
bool IsQuestItem() { return GetBaseFlag().IsOn( ItemBase::FLAG_QUEST ); }
bool IsQuestDistributeItem() { return GetBaseFlag().IsOn( ItemBase::FLAG_QUEST_DISTRIBUTE ); }
inline ItemInstance::GenerateCode GetGenerateCode() const { return m_Instance.GenerateInfo; }
// 기간제 아이템 관련
bool IsExpireItem() const;
time_t GetExpireTime() const { return m_Instance.tExpire; } // 단위 : 초
void SetRemainTime( time_t t ) { m_Instance.tExpire = t; }
// 기간제 속성 이펙트 관련
const unsigned short SetElementalEffect( const unsigned char & cType, const time_t & tExpire );
const unsigned short SetElementalEffectAttackPoint( const int nAttackPoint );
const unsigned short SetElementalEffectMagicPoint( const int nMagicPoint );
void ClearElementalEffect();
// tElementalEffectExpire가 0일 경우는 무제한
inline const unsigned char GetElementalEffectType() const { return ( ( !m_Instance.tElementalEffectExpire || m_Instance.tElementalEffectExpire >= time( NULL ) ) ? m_Instance.cElementalEffectType : 0 ); }
const time_t & GetElementalEffectExpireTime() const { return m_Instance.tElementalEffectExpire; }
const int GetElementalEffectAttackPoint() const { return m_Instance.nElementalEffectAttackPoint; }
const int GetElementalEffectMagicPoint() const { return m_Instance.nElementalEffectMagicPoint; }
// 형상 변환 관련
const ItemBase::ItemCode GetAppearanceCode() const { return m_Instance.nAppearanceCode; }
const bool SetAppearanceCode( const ItemBase::ItemCode nAppearanceCode ) { m_Instance.nAppearanceCode = nAppearanceCode; return true; }
// 이하는 구현을 위해 존재하는 인터페이스임.
void DBQuery( GameDBManager::DBProc *pWork );
void onEndQuery();
volatile size_t GetDBQueryCount() { return m_lQueryList.size(); }
inline bool IsNeedUpdateToDB() { return ( m_nDBUpdateFlag != 0 ); }
inline void TurnOffDbUpdateFlag() { InterlockedExchange( &m_nDBUpdateFlag, 0 ); }
inline void TurnOnUpdateFlag() { InterlockedIncrement( &m_nDBUpdateFlag ); }
inline void SetDropTime( AR_TIME t ) { m_nDropTime = t; }
inline AR_TIME GetDropTime() { return m_nDropTime; }
static ItemBaseServer & GetItemBase( ItemBase::ItemCode c );
// 세트 아이템 전용
int GetSetItemID() { return m_pItemBase->nSetID; }
int GetSetItemPartFlag() { return m_pItemBase->nSetPartFlag; }
// 아이템 랜덤 옵션 관련 함수들 (각성, 아이템옵션랜덤화)
inline int GetRandomOptionType( ItemInstance::RANDOM_TYPE eType, int nIndex ) const { return m_Instance.RandomOption[ eType ].OptionInfo[ nIndex ].nType; }
inline c_fixed10 GetRandomOptionValue1( ItemInstance::RANDOM_TYPE eType, int nIndex ) const { return m_Instance.RandomOption[ eType ].OptionInfo[ nIndex ].fValue1; }
inline c_fixed10 GetRandomOptionValue2( ItemInstance::RANDOM_TYPE eType, int nIndex ) const { return m_Instance.RandomOption[ eType ].OptionInfo[ nIndex ].fValue2; }
inline int GetRandomSID( ItemInstance::RANDOM_TYPE eType ) const { return m_Instance.RandomOption[ eType ].nSID; }
inline void SetRandomSID( ItemInstance::RANDOM_TYPE eType, int nSID ) { m_Instance.RandomOption[ eType ].nSID = nSID; }
inline bool IsRandomOptionItem( ItemInstance::RANDOM_TYPE eType ) const { return !!m_Instance.RandomOption[ eType ].nSID; }
bool SetRandomOption( ItemInstance::RANDOM_TYPE eType, ItemInstance::RANDOM_OPTION & RandomOption );
ItemInstance::RANDOM_OPTION* GetRandomOption( ItemInstance::RANDOM_TYPE eType );
inline int GetAwakenOptionType( int nIndex ) const { return GetRandomOptionType( ItemInstance::AWAKEN, nIndex ); }
inline c_fixed10 GetAwakenOptionValue1( int nIndex ) const { return GetRandomOptionValue1( ItemInstance::AWAKEN, nIndex ); }
inline c_fixed10 GetAwakenOptionValue2( int nIndex ) const { return GetRandomOptionValue2( ItemInstance::AWAKEN, nIndex ); }
inline int GetAwakenSID() const { return GetRandomSID( ItemInstance::AWAKEN ); }
inline void SetAwakenSID( int nSID ) { return SetRandomSID( ItemInstance::AWAKEN, nSID ); }
inline bool IsAwaken() const { return IsRandomOptionItem( ItemInstance::AWAKEN ); }
inline bool SetAwakenOption( ItemInstance::RANDOM_OPTION & AwakenOption ) { return SetRandomOption( ItemInstance::AWAKEN, AwakenOption ); }
inline int GetIdentifiedOptionType( int nIndex ) const { return GetRandomOptionType( ItemInstance::IDENTIFIED, nIndex ); }
inline c_fixed10 GetIdentifiedOptionValue1( int nIndex ) const { return GetRandomOptionValue1( ItemInstance::IDENTIFIED, nIndex ); }
inline c_fixed10 GetIdentifiedOptionValue2( int nIndex ) const { return GetRandomOptionValue2( ItemInstance::IDENTIFIED, nIndex ); }
inline int GetIdentifiedSID() const { return GetRandomSID( ItemInstance::IDENTIFIED ); }
inline void SetIdentifiedSID( int nSID ) { return SetRandomSID( ItemInstance::IDENTIFIED, nSID ); }
inline bool IsIdentified() const { return IsRandomOptionItem( ItemInstance::IDENTIFIED ); }
inline bool SetIdentifiedOption( ItemInstance::RANDOM_OPTION & IdentifiedOption ) { return SetRandomOption( ItemInstance::IDENTIFIED, IdentifiedOption ); }
protected:
static void deletePendingItem();
static void freeItem( StructItem* p );
// ArScheduler 에서 StructItem 을 지우기 위해 존재함.
// alloc/free 메커니즘에 관한 확실한 이해 전에는 수정 말것!
virtual bool ProcDelete();
AR_HANDLE m_hHandle;
ItemInstance m_Instance;
int m_nAccountID;
unsigned m_unInventoryIndex; // 리스트에서의 위치
bool m_bIsEventDrop;
bool m_bIsVirtualItem;
volatile long m_nDBUpdateFlag;
ItemBaseServer* m_pItemBase;
struct StructSummon * m_pSummon;
struct StructPet * m_pPet;
AR_HANDLE m_hBindedTarget; // 스킬카드일경우
AR_TIME m_nDropTime;
ITEM_PICKUP_ORDER m_ItemPickupOrder; // 아이템 집는 순서.
XCriticalSection m_bQueryLock;
std::list< GameDBManager::DBProc* > m_lQueryList;
const char* m_deleteFunction;
int m_deleteLine;
StructItem( AR_HANDLE handle );
virtual ~StructItem();
};