newhere
-
Posts
13 -
Joined
-
Last visited
-
Feedback
0%
Content Type
Forums
Store
Third Party - Providers Directory
Feature Plan
Release Notes
Docs
Events
Posts posted by newhere
-
-
I have no calculation for 1/5 and 6/7 bonus
they just add to the sash like in the weapon. no function for calculation.
so i need to find the item attribute add to sash thing
and write it like
if 25% sash
item_attr /100*25
i think.
-
thanks for help but my problem was that the sash absorbs 100% of the bonus not like 25%.
"Its absorbing the 100% of the 1/5 and 6/7 Bonus."
-
thanks for your answer. but i dont know.
i have like this:
ITEM_MAX_ACCEDRAIN = 25,
ITEM_MIN_ACCEDRAIN = 20,
References
Spoilerif ((pBaseItem->GetRefinedVnum() == 0) && (pBaseItem->GetSocket(0) < ITEM_MAX_ACCEDRAIN) && (GetAcceRefineGrade(pBaseItem->GetVnum()) == 4))
{
if (pBaseItem->GetSocket(0) < ITEM_MIN_ACCEDRAIN) {
ChatPacket(CHAT_TYPE_INFO, LC_TEXT("ACCE_COMBINE_ABSORB_TO_LOW"));
return;
}
uppMax = true;
result_vnum = pBaseItem->GetVnum();
}
else {
result_vnum = pBaseItem->GetRefinedVnum();
} -
hey, thanks for your answer.
i dont have acce.cpp or acce.h
item_lenght.h
Spoiler#ifndef __INC_METIN2_ITEM_LENGTH_H__
#define __INC_METIN2_ITEM_LENGTH_H__#include "CommonDefines.h"
enum EItemMisc
{
ITEM_NAME_MAX_LEN = 24,
ITEM_VALUES_MAX_NUM = 6,
ITEM_SMALL_DESCR_MAX_LEN = 256,
ITEM_LIMIT_MAX_NUM = 2,
ITEM_APPLY_MAX_NUM = 3,
ITEM_SOCKET_MAX_NUM = 3,
ITEM_MAX_COUNT = 200,ITEM_ATTRIBUTE_NORM_NUM = 5,
ITEM_ATTRIBUTE_RARE_NUM = 2,ITEM_ATTRIBUTE_NORM_START = 0,
ITEM_ATTRIBUTE_NORM_END = ITEM_ATTRIBUTE_NORM_START + ITEM_ATTRIBUTE_NORM_NUM,ITEM_ATTRIBUTE_RARE_START = ITEM_ATTRIBUTE_NORM_END,
ITEM_ATTRIBUTE_RARE_END = ITEM_ATTRIBUTE_RARE_START + ITEM_ATTRIBUTE_RARE_NUM,ITEM_ATTRIBUTE_MAX_NUM = ITEM_ATTRIBUTE_RARE_END, // 7
ITEM_ATTRIBUTE_MAX_LEVEL = 5,
ITEM_AWARD_WHY_MAX_LEN = 50,REFINE_MATERIAL_MAX_NUM = 5,
ITEM_ELK_VNUM = 50026,
#ifdef __COSTUME_ACCE__
ITEM_MAX_ACCEDRAIN = 25,
ITEM_MIN_ACCEDRAIN = 20,
#endif
};const BYTE ITEM_SOCKET_REMAIN_SEC = 0;
enum EItemValueIdice
{
ITEM_VALUE_DRAGON_SOUL_POLL_OUT_BONUS_IDX = 0,
ITEM_VALUE_CHARGING_AMOUNT_IDX = 0,
ITEM_VALUE_SECONDARY_COIN_UNIT_IDX = 0,
};
enum EItemDragonSoulSockets
{
ITEM_SOCKET_DRAGON_SOUL_ACTIVE_IDX = 2,
ITEM_SOCKET_CHARGING_AMOUNT_IDX = 2,
};
// 헐 이거 미친거 아니야?
// 나중에 소켓 확장하면 어쩌려고 이지랄 -_-;;;
enum EItemUniqueSockets
{
ITEM_SOCKET_UNIQUE_SAVE_TIME = ITEM_SOCKET_MAX_NUM - 2,
ITEM_SOCKET_UNIQUE_REMAIN_TIME = ITEM_SOCKET_MAX_NUM - 1
};enum EItemTypes
{
ITEM_NONE, //0
ITEM_WEAPON, //1//무기
ITEM_ARMOR, //2//갑옷
ITEM_USE, //3//아이템 사용
ITEM_AUTOUSE, //4
ITEM_MATERIAL, //5
ITEM_SPECIAL, //6 //스페셜 아이템
ITEM_TOOL, //7
ITEM_LOTTERY, //8//복권
ITEM_ELK, //9//돈
ITEM_METIN, //10
ITEM_CONTAINER, //11
ITEM_FISH, //12//낚시
ITEM_ROD, //13
ITEM_RESOURCE, //14
ITEM_CAMPFIRE, //15
ITEM_UNIQUE, //16
ITEM_SKILLBOOK, //17
ITEM_QUEST, //18
ITEM_POLYMORPH, //19
ITEM_TREASURE_BOX, //20//보물상자
ITEM_TREASURE_KEY, //21//보물상자 열쇠
ITEM_SKILLFORGET, //22
ITEM_GIFTBOX, //23
ITEM_PICK, //24
ITEM_HAIR, //25//머리
ITEM_TOTEM, //26//토템
ITEM_BLEND, //27//생성될때 랜덤하게 속성이 붙는 약물
ITEM_COSTUME, //28//코스츔 아이템 (2011년 8월 추가된 코스츔 시스템용 아이템)
ITEM_DS, //29 //용혼석
ITEM_SPECIAL_DS, //30 // 특수한 용혼석 (DS_SLOT에 착용하는 UNIQUE 아이템이라 생각하면 됨)
ITEM_EXTRACT, //31 추출도구.
ITEM_SECONDARY_COIN, //32 ?? 명도전??
ITEM_RING, //33 반지
ITEM_BELT, //34 벨트
#ifdef COMPANION_SYSTEM
ITEM_COMPANION,
#endif
#ifdef SHININGSYSTEM
ITEM_SHINING, //36 벨트
#endif
};enum EMetinSubTypes
{
METIN_NORMAL,
METIN_GOLD,
};enum EWeaponSubTypes
{
WEAPON_SWORD,
WEAPON_DAGGER,
WEAPON_BOW,
WEAPON_TWO_HANDED,
WEAPON_BELL,
WEAPON_FAN,
WEAPON_ARROW,
WEAPON_MOUNT_SPEAR,
#ifdef ENABLE_WOLFMAN_CHARACTER
WEAPON_CLAW,
#endif
WEAPON_NUM_TYPES,
};enum EArmorSubTypes
{
ARMOR_BODY,
ARMOR_HEAD,
ARMOR_SHIELD,
ARMOR_WRIST,
ARMOR_FOOTS,
ARMOR_NECK,
ARMOR_EAR,
ARMOR_NUM_TYPES
};enum ECostumeSubTypes
{
COSTUME_BODY = ARMOR_BODY, // [중요!!] ECostumeSubTypes enum value는 종류별로 EArmorSubTypes의 그것과 같아야 함.
COSTUME_HAIR = ARMOR_HEAD, // 이는 코스츔 아이템에 추가 속성을 붙이겠다는 사업부의 요청에 따라서 기존 로직을 활용하기 위함임.
#ifdef __COSTUME_ACCE__
COSTUME_ACCE,
#endif
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
COSTUME_MOUNT = 3,
#endif
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
COSTUME_WEAPON = 4,
#endif
COSTUME_NUM_TYPES,
};
#ifdef __COSTUME_ACCE__
enum {
ABSORB,
COMBINE,
};enum {
ACCE_SLOT_LEFT,
ACCE_SLOT_RIGHT,
ACCE_SLOT_RESULT,
ACCE_SLOT_MAX_NUM,
};
#endif
enum EDragonSoulSubType
{
DS_SLOT1,
DS_SLOT2,
DS_SLOT3,
DS_SLOT4,
DS_SLOT5,
DS_SLOT6,
DS_SLOT_MAX,
};enum EDragonSoulGradeTypes
{
DRAGON_SOUL_GRADE_NORMAL,
DRAGON_SOUL_GRADE_BRILLIANT,
DRAGON_SOUL_GRADE_RARE,
DRAGON_SOUL_GRADE_ANCIENT,
DRAGON_SOUL_GRADE_LEGENDARY,
DRAGON_SOUL_GRADE_MAX,};
enum EDragonSoulStepTypes
{
DRAGON_SOUL_STEP_LOWEST,
DRAGON_SOUL_STEP_LOW,
DRAGON_SOUL_STEP_MID,
DRAGON_SOUL_STEP_HIGH,
DRAGON_SOUL_STEP_HIGHEST,
DRAGON_SOUL_STEP_MAX,
};
#define DRAGON_SOUL_STRENGTH_MAX 7enum EDSInventoryMaxNum
{
DRAGON_SOUL_INVENTORY_MAX_NUM = DS_SLOT_MAX * DRAGON_SOUL_GRADE_MAX * DRAGON_SOUL_BOX_SIZE,
};#ifdef SHININGSYSTEM
enum EShiningSubTypes
{
SHINING_WEAPON,
SHINING_ARMOR,
SHINING_SPECIAL,
};
#endifenum EFishSubTypes
{
FISH_ALIVE,
FISH_DEAD,
};enum EResourceSubTypes
{
RESOURCE_FISHBONE,
RESOURCE_WATERSTONEPIECE,
RESOURCE_WATERSTONE,
RESOURCE_BLOOD_PEARL,
RESOURCE_BLUE_PEARL,
RESOURCE_WHITE_PEARL,
RESOURCE_BUCKET,
RESOURCE_CRYSTAL,
RESOURCE_GEM,
RESOURCE_STONE,
RESOURCE_METIN,
RESOURCE_ORE,
};enum EUniqueSubTypes
{
UNIQUE_NONE,
UNIQUE_BOOK,
UNIQUE_SPECIAL_RIDE,
UNIQUE_SPECIAL_MOUNT_RIDE,
};enum EUseSubTypes
{
USE_POTION, // 0
USE_TALISMAN,
USE_TUNING,
USE_MOVE,
USE_TREASURE_BOX,
USE_MONEYBAG,
USE_BAIT,
USE_ABILITY_UP,
USE_AFFECT,
USE_CREATE_STONE,
USE_SPECIAL, // 10
USE_POTION_NODELAY,
USE_CLEAR,
USE_INVISIBILITY,
USE_DETACHMENT,
USE_BUCKET,
USE_POTION_CONTINUE,
USE_CLEAN_SOCKET,
USE_CHANGE_ATTRIBUTE,
USE_ADD_ATTRIBUTE,
USE_ADD_ACCESSORY_SOCKET, // 20
USE_PUT_INTO_ACCESSORY_SOCKET,
USE_ADD_ATTRIBUTE2,
USE_RECIPE,
USE_CHANGE_ATTRIBUTE2,
USE_BIND,
USE_UNBIND,
USE_TIME_CHARGE_PER,
USE_TIME_CHARGE_FIX, // 28
USE_PUT_INTO_BELT_SOCKET, // 29 벨트 소켓에 사용할 수 있는 아이템
USE_PUT_INTO_RING_SOCKET, // 30 반지 소켓에 사용할 수 있는 아이템 (유니크 반지 말고, 새로 추가된 반지 슬롯)
USE_CHANGE_COSTUME_ATTR, // 31
USE_RESET_COSTUME_ATTR, // 32
#ifdef __CHANGE_LOOK_SYSTEM__
USE_RESET_LOOK_VNUM,
#endif
};enum EExtractSubTypes
{
EXTRACT_DRAGON_SOUL,
EXTRACT_DRAGON_HEART,
};enum EAutoUseSubTypes
{
AUTOUSE_POTION,
AUTOUSE_ABILITY_UP,
AUTOUSE_BOMB,
AUTOUSE_GOLD,
AUTOUSE_MONEYBAG,
AUTOUSE_TREASURE_BOX
};enum EMaterialSubTypes
{
MATERIAL_LEATHER,
MATERIAL_BLOOD,
MATERIAL_ROOT,
MATERIAL_NEEDLE,
MATERIAL_JEWEL,
MATERIAL_DS_REFINE_NORMAL,
MATERIAL_DS_REFINE_BLESSED,
MATERIAL_DS_REFINE_HOLLY,
};enum ESpecialSubTypes
{
SPECIAL_MAP,
SPECIAL_KEY,
SPECIAL_DOC,
SPECIAL_SPIRIT,
};enum EToolSubTypes
{
TOOL_FISHING_ROD
};enum ELotterySubTypes
{
LOTTERY_TICKET,
LOTTERY_INSTANT
};enum EItemFlag
{
ITEM_FLAG_REFINEABLE = (1 << 0),
ITEM_FLAG_SAVE = (1 << 1),
ITEM_FLAG_STACKABLE = (1 << 2), // 여러개 합칠 수 있음
ITEM_FLAG_COUNT_PER_1GOLD = (1 << 3),
ITEM_FLAG_SLOW_QUERY = (1 << 4),
ITEM_FLAG_UNUSED01 = (1 << 5), // UNUSED
ITEM_FLAG_UNIQUE = (1 << 6),
ITEM_FLAG_MAKECOUNT = (1 << 7),
ITEM_FLAG_IRREMOVABLE = (1 << 8),
ITEM_FLAG_CONFIRM_WHEN_USE = (1 << 9),
ITEM_FLAG_QUEST_USE = (1 << 10),
ITEM_FLAG_QUEST_USE_MULTIPLE = (1 << 11),
ITEM_FLAG_QUEST_GIVE = (1 << 12),
ITEM_FLAG_LOG = (1 << 13),
ITEM_FLAG_APPLICABLE = (1 << 14),
};enum EItemAntiFlag
{
ITEM_ANTIFLAG_FEMALE = (1 << 0), // 여성 사용 불가
ITEM_ANTIFLAG_MALE = (1 << 1), // 남성 사용 불가
ITEM_ANTIFLAG_WARRIOR = (1 << 2), // 무사 사용 불가
ITEM_ANTIFLAG_ASSASSIN = (1 << 3), // 자객 사용 불가
ITEM_ANTIFLAG_SURA = (1 << 4), // 수라 사용 불가
ITEM_ANTIFLAG_SHAMAN = (1 << 5), // 무당 사용 불가
ITEM_ANTIFLAG_GET = (1 << 6), // 집을 수 없음
ITEM_ANTIFLAG_DROP = (1 << 7), // 버릴 수 없음
ITEM_ANTIFLAG_SELL = (1 << 8), // 팔 수 없음
ITEM_ANTIFLAG_EMPIRE_A = (1 << 9), // A 제국 사용 불가
ITEM_ANTIFLAG_EMPIRE_B = (1 << 10), // B 제국 사용 불가
ITEM_ANTIFLAG_EMPIRE_C = (1 << 11), // C 제국 사용 불가
ITEM_ANTIFLAG_SAVE = (1 << 12), // 저장되지 않음
ITEM_ANTIFLAG_GIVE = (1 << 13), // 거래 불가
ITEM_ANTIFLAG_PKDROP = (1 << 14), // PK시 떨어지지 않음
ITEM_ANTIFLAG_STACK = (1 << 15), // 합칠 수 없음
ITEM_ANTIFLAG_MYSHOP = (1 << 16), // 개인 상점에 올릴 수 없음
ITEM_ANTIFLAG_SAFEBOX = (1 << 17), // 창고에 넣을 수 없음
#ifdef ENABLE_WOLFMAN_CHARACTER
ITEM_ANTIFLAG_WOLFMAN = (1 << 18), // 수인족 사용 불가
#endif
};enum EItemWearableFlag
{
WEARABLE_BODY = (1 << 0),
WEARABLE_HEAD = (1 << 1),
WEARABLE_FOOTS = (1 << 2),
WEARABLE_WRIST = (1 << 3),
WEARABLE_WEAPON = (1 << 4),
WEARABLE_NECK = (1 << 5),
WEARABLE_EAR = (1 << 6),
WEARABLE_UNIQUE = (1 << 7),
WEARABLE_SHIELD = (1 << 8),
WEARABLE_ARROW = (1 << 9),
WEARABLE_HAIR = (1 << 10),
WEARABLE_ABILITY = (1 << 11),
WEARABLE_COSTUME_BODY = (1 << 12),
};enum ELimitTypes
{
LIMIT_NONE,LIMIT_LEVEL,
LIMIT_STR,
LIMIT_DEX,
LIMIT_INT,
LIMIT_CON,
LIMIT_PCBANG,/// 착용 여부와 상관 없이 실시간으로 시간 차감 (socket0에 소멸 시간이 박힘: unix_timestamp 타입)
LIMIT_REAL_TIME,/// 아이템을 맨 처음 사용(혹은 착용) 한 순간부터 리얼타임 타이머 시작
/// 최초 사용 전에는 socket0에 사용가능시간(초단위, 0이면 프로토의 limit value값 사용) 값이 쓰여있다가
/// 아이템 사용시 socket1에 사용 횟수가 박히고 socket0에 unix_timestamp 타입의 소멸시간이 박힘.
LIMIT_REAL_TIME_START_FIRST_USE,/// 아이템을 착용 중일 때만 사용 시간이 차감되는 아이템
/// socket0에 남은 시간이 초단위로 박힘. (아이템 최초 사용시 해당 값이 0이면 프로토의 limit value값을 socket0에 복사)
LIMIT_TIMER_BASED_ON_WEAR,LIMIT_MAX_NUM
};enum EAttrAddonTypes
{
ATTR_ADDON_NONE,
// positive values are reserved for set
ATTR_DAMAGE_ADDON = -1,
};enum ERefineType
{
REFINE_TYPE_NORMAL,
REFINE_TYPE_NOT_USED1,
REFINE_TYPE_SCROLL,
REFINE_TYPE_HYUNIRON,
REFINE_TYPE_MONEY_ONLY,
REFINE_TYPE_MUSIN,
REFINE_TYPE_BDRAGON,
};#endif
-
Hey, i have problem with Sash.
Its absorbing the 100% of the 1/5 and 6/7 Bonus.
Like in this Thread. But i dont know what/how to change in item.cpp maybe you can help me.
Is it here?
attrVal = int(float(attrVal) / 100.0f * float(GetSocket(0)));// <= 0 ? 1 : int(float(attrVal) / 100.0f * float(GetSocket(0)));
item.cpp full:
Spoiler#include "stdafx.h"
#include "utils.h"
#include "config.h"
#include "char.h"
#include "desc.h"
#include "sectree_manager.h"
#include "packet.h"
#include "mob_manager.h"
#include "protocol.h"
#include "log.h"
#include "skill.h"
#include "unique_item.h"
#include "profiler.h"
#include "marriage.h"
#include "item_addon.h"
#include "dev_log.h"
#include "locale_service.h"
#include "item.h"
#include "item_manager.h"
#include "affect.h"
#include "DragonSoul.h"
#include "buff_on_attributes.h"
#include "belt_inventory_helper.h"
#ifdef SHOP_SEARCH
#include "shop_search.h"
#endif
#include "../../common/VnumHelper.h"
#include "../../common/CommonDefines.h"CItem::CItem(DWORD dwVnum)
: m_dwVnum(dwVnum), m_bWindow(0), m_dwID(0), m_bEquipped(false), m_dwVID(0), m_wCell(0), m_dwCount(0), m_lFlag(0), m_dwLastOwnerPID(0),
m_bExchanging(false), m_pkDestroyEvent(NULL), m_pkExpireEvent(NULL), m_pkUniqueExpireEvent(NULL),
m_pkTimerBasedOnWearExpireEvent(NULL), m_pkRealTimeExpireEvent(NULL),
m_pkAccessorySocketExpireEvent(NULL), m_pkOwnershipEvent(NULL), m_dwOwnershipPID(0), m_bSkipSave(false), m_isLocked(false),
m_dwMaskVnum(0), m_dwSIGVnum (0)
#ifdef __CHANGE_LOOK_SYSTEM__
, m_dwLook(0)
#endif
{
memset( &m_alSockets, 0, sizeof(m_alSockets) );
memset( &m_aAttr, 0, sizeof(m_aAttr) );
}CItem::~CItem()
{
Destroy();
}void CItem::Initialize()
{
CEntity::Initialize(ENTITY_ITEM);m_bWindow = RESERVED_WINDOW;
m_pOwner = NULL;
m_dwID = 0;
m_bEquipped = false;
m_dwVID = m_wCell = m_dwCount = m_lFlag = 0;
m_pProto = NULL;
m_bExchanging = false;
memset(&m_alSockets, 0, sizeof(m_alSockets));
memset(&m_aAttr, 0, sizeof(m_aAttr));m_pkDestroyEvent = NULL;
m_pkOwnershipEvent = NULL;
m_dwOwnershipPID = 0;
m_pkUniqueExpireEvent = NULL;
m_pkTimerBasedOnWearExpireEvent = NULL;
m_pkRealTimeExpireEvent = NULL;m_pkAccessorySocketExpireEvent = NULL;
#ifdef OFFLINE_SHOP
m_dwRealID = 0;
#endif
m_bSkipSave = false;
m_dwLastOwnerPID = 0;
#ifdef __CHANGE_LOOK_SYSTEM__
m_dwLook = 0;
#endif
}void CItem::Destroy()
{
event_cancel(&m_pkDestroyEvent);
event_cancel(&m_pkOwnershipEvent);
event_cancel(&m_pkUniqueExpireEvent);
event_cancel(&m_pkTimerBasedOnWearExpireEvent);
event_cancel(&m_pkRealTimeExpireEvent);
event_cancel(&m_pkAccessorySocketExpireEvent);CEntity::Destroy();
if (GetSectree())
GetSectree()->RemoveEntity(this);
}EVENTFUNC(item_destroy_event)
{
item_event_info* info = dynamic_cast<item_event_info*>( event->info );if ( info == NULL )
{
sys_err( "item_destroy_event> <Factor> Null pointer" );
return 0;
}LPITEM pkItem = info->item;
if (pkItem->GetOwner())
sys_err("item_destroy_event: Owner exist. (item %s owner %s)", pkItem->GetName(), pkItem->GetOwner()->GetName());pkItem->SetDestroyEvent(NULL);
M2_DESTROY_ITEM(pkItem);
return 0;
}void CItem::SetDestroyEvent(LPEVENT pkEvent)
{
m_pkDestroyEvent = pkEvent;
}void CItem::StartDestroyEvent(int iSec)
{
if (m_pkDestroyEvent)
return;item_event_info* info = AllocEventInfo<item_event_info>();
info->item = this;SetDestroyEvent(event_create(item_destroy_event, info, PASSES_PER_SEC(iSec)));
}void CItem::EncodeInsertPacket(LPENTITY ent)
{
LPDESC d;if (!(d = ent->GetDesc()))
return;const PIXEL_POSITION & c_pos = GetXYZ();
struct packet_item_ground_add pack;
pack.bHeader = HEADER_GC_ITEM_GROUND_ADD;
pack.x = c_pos.x;
pack.y = c_pos.y;
pack.z = c_pos.z;
pack.dwVnum = GetVnum();
pack.dwVID = m_dwVID;
//pack.count = m_dwCount;
#ifdef ENABLE_EXTENDED_ITEMNAME_ON_GROUND
for (size_t i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
pack.alSockets = GetSocket(i);thecore_memcpy(pack.aAttrs, GetAttributes(), sizeof(pack.aAttrs));
#endifd->Packet(&pack, sizeof(pack));
if (m_pkOwnershipEvent != NULL)
{
item_event_info * info = dynamic_cast<item_event_info *>(m_pkOwnershipEvent->info);if ( info == NULL )
{
sys_err( "CItem::EncodeInsertPacket> <Factor> Null pointer" );
return;
}TPacketGCItemOwnership p;
p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
p.dwVID = m_dwVID;
strlcpy(p.szName, info->szOwnerName, sizeof(p.szName));d->Packet(&p, sizeof(TPacketGCItemOwnership));
}
}void CItem::EncodeRemovePacket(LPENTITY ent)
{
LPDESC d;if (!(d = ent->GetDesc()))
return;struct packet_item_ground_del pack;
pack.bHeader = HEADER_GC_ITEM_GROUND_DEL;
pack.dwVID = m_dwVID;d->Packet(&pack, sizeof(pack));
sys_log(2, "Item::EncodeRemovePacket %s to %s", GetName(), ((LPCHARACTER) ent)->GetName());
}void CItem::SetProto(const TItemTable * table)
{
assert(table != NULL);
m_pProto = table;
SetFlag(m_pProto->dwFlags);
}#ifdef ENABLE_EXTENDED_ITEMNAME_ON_GROUND
const char * CItem::GetName()
{
static char szItemName[128];
memset(szItemName, 0, sizeof(szItemName));
if (GetProto())
{
int len = 0;
switch (GetType())
{
case ITEM_POLYMORPH:
{
const DWORD dwMobVnum = GetSocket(0);
const CMob* pMob = CMobManager::instance().Get(dwMobVnum);
if (pMob)
len = snprintf(szItemName, sizeof(szItemName), "%s", pMob->m_table.szLocaleName);break;
}
case ITEM_SKILLBOOK:
case ITEM_SKILLFORGET:
{
const DWORD dwSkillVnum = (GetVnum() == ITEM_SKILLBOOK_VNUM || GetVnum() == ITEM_SKILLFORGET_VNUM) ? GetSocket(0) : 0;
const CSkillProto* pSkill = (dwSkillVnum != 0) ? CSkillManager::instance().Get(dwSkillVnum) : NULL;
if (pSkill)
len = snprintf(szItemName, sizeof(szItemName), "%s", pSkill->szName);break;
}
}
len += snprintf(szItemName + len, sizeof(szItemName) - len, (len>0)?" %s":"%s", GetProto()->szLocaleName);
}return szItemName;
}
#endifvoid CItem::UsePacketEncode(LPCHARACTER ch, LPCHARACTER victim, struct packet_item_use *packet)
{
if (!GetVnum())
return;packet->header = HEADER_GC_ITEM_USE;
packet->ch_vid = ch->GetVID();
packet->victim_vid = victim->GetVID();
packet->Cell = TItemPos(GetWindow(), m_wCell);
packet->vnum = GetVnum();
}void CItem::RemoveFlag(long bit)
{
REMOVE_BIT(m_lFlag, bit);
}void CItem::AddFlag(long bit)
{
SET_BIT(m_lFlag, bit);
}void CItem::UpdatePacket()
{
if (!m_pOwner || !m_pOwner->GetDesc())
return;TPacketGCItemUpdate pack;
pack.header = HEADER_GC_ITEM_UPDATE;
pack.Cell = TItemPos(GetWindow(), m_wCell);
#ifdef __CHANGE_LOOK_SYSTEM__
pack.dwVnum = m_dwLook;
#endif
pack.count = m_dwCount;for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
pack.alSockets = m_alSockets;thecore_memcpy(pack.aAttr, GetAttributes(), sizeof(pack.aAttr));
sys_log(2, "UpdatePacket %s -> %s", GetName(), m_pOwner->GetName());
m_pOwner->GetDesc()->Packet(&pack, sizeof(pack));
}DWORD CItem::GetCount()
{
if (GetType() == ITEM_ELK) return MIN(m_dwCount, INT_MAX);
else
{
return MIN(m_dwCount, g_bItemCountLimit);
}
}bool CItem::SetCount(DWORD count)
{
if (GetType() == ITEM_ELK)
{
m_dwCount = MIN(count, INT_MAX);
}
else
{
m_dwCount = MIN(count, g_bItemCountLimit);
}if (count == 0 && m_pOwner)
{
if (GetSubType() == USE_ABILITY_UP || GetSubType() == USE_POTION || GetVnum() == 70020)
{
LPCHARACTER pOwner = GetOwner();
WORD wCell = GetCell();RemoveFromCharacter();
if (!IsDragonSoul())
{
LPITEM pItem = pOwner->FindSpecifyItem(GetVnum());if (NULL != pItem)
{
pOwner->ChainQuickslotItem(pItem, QUICKSLOT_TYPE_ITEM, wCell);
}
else
{
#ifdef ENABLE_5_INVENTORY
pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, wCell, 750);
#else
pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, wCell, 255);
#endif
}
}M2_DESTROY_ITEM(this);
}
else
{
if (!IsDragonSoul())
{
#ifdef ENABLE_5_INVENTORY
m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, m_wCell, 750);
#else
m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, m_wCell, 255);
#endif
}
M2_DESTROY_ITEM(RemoveFromCharacter());
}return false;
}UpdatePacket();
Save();
return true;
}LPITEM CItem::RemoveFromCharacter()
{
if (!m_pOwner)
{
sys_err("Item::RemoveFromCharacter owner null");
return (this);
}LPCHARACTER pOwner = m_pOwner;
if (m_bEquipped)
{
Unequip();
//pOwner->UpdatePacket();SetWindow(RESERVED_WINDOW);
Save();
return (this);
}
else
{
if (GetWindow() != SAFEBOX && GetWindow() != MALL)
{
if (IsDragonSoul())
{
if (m_wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
sys_err("CItem::RemoveFromCharacter: pos >= DRAGON_SOUL_INVENTORY_MAX_NUM");
else
pOwner->SetItem(TItemPos(m_bWindow, m_wCell), NULL);
}
else
{
TItemPos cell(INVENTORY, m_wCell);if (false == cell.IsDefaultInventoryPosition() && false == cell.IsBeltInventoryPosition())
sys_err("CItem::RemoveFromCharacter: Invalid Item Position");
else
{
pOwner->SetItem(cell, NULL);
}
}
}m_pOwner = NULL;
m_wCell = 0;SetWindow(RESERVED_WINDOW);
#ifdef OFFLINE_SHOP
if(!GetRealID())
#endif
Save();
return (this);
}
}#ifdef __HIGHLIGHT_SYSTEM__
bool CItem::AddToCharacter(LPCHARACTER ch, TItemPos Cell, bool isHighLight)
#else
bool CItem::AddToCharacter(LPCHARACTER ch, TItemPos Cell)
#endif
{
assert(GetSectree() == NULL);
assert(m_pOwner == NULL);
WORD pos = Cell.cell;
BYTE window_type = Cell.window_type;if (INVENTORY == window_type)
{
if (m_wCell >= INVENTORY_MAX_NUM && BELT_INVENTORY_SLOT_START > m_wCell)
{
sys_err("CItem::AddToCharacter: cell overflow: %s to %s cell %d", m_pProto->szName, ch->GetName(), m_wCell);
return false;
}
}
else if (DRAGON_SOUL_INVENTORY == window_type)
{
if (m_wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
{
sys_err("CItem::AddToCharacter: cell overflow: %s to %s cell %d", m_pProto->szName, ch->GetName(), m_wCell);
return false;
}
}if (ch->GetDesc())
m_dwLastOwnerPID = ch->GetPlayerID();event_cancel(&m_pkDestroyEvent);
#ifdef __HIGHLIGHT_SYSTEM__
ch->SetItem(TItemPos(window_type, pos), this, isHighLight);
#else
ch->SetItem(TItemPos(window_type, pos), this);
#endif
m_pOwner = ch;Save();
return true;
}LPITEM CItem::RemoveFromGround()
{
if (GetSectree())
{
SetOwnership(NULL);GetSectree()->RemoveEntity(this);
ViewCleanup();
Save();
}return (this);
}bool CItem::AddToGround(long lMapIndex, const PIXEL_POSITION & pos, bool skipOwnerCheck)
{
if (0 == lMapIndex)
{
sys_err("wrong map index argument: %d", lMapIndex);
return false;
}if (GetSectree())
{
sys_err("sectree already assigned");
return false;
}if (!skipOwnerCheck && m_pOwner)
{
sys_err("owner pointer not null");
return false;
}LPSECTREE tree = SECTREE_MANAGER::instance().Get(lMapIndex, pos.x, pos.y);
if (!tree)
{
sys_err("cannot find sectree by %dx%d", pos.x, pos.y);
return false;
}//tree->Touch();
SetWindow(GROUND);
SetXYZ(pos.x, pos.y, pos.z);
tree->InsertEntity(this);
UpdateSectree();
Save();
return true;
}bool CItem::DistanceValid(LPCHARACTER ch)
{
if (!GetSectree())
return false;int iDist = DISTANCE_APPROX(GetX() - ch->GetX(), GetY() - ch->GetY());
if (iDist > 300)
return false;return true;
}bool CItem::CanUsedBy(LPCHARACTER ch)
{
// Anti flag check
switch (ch->GetJob())
{
case JOB_WARRIOR:
if (GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR)
return false;
break;case JOB_ASSASSIN:
if (GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN)
return false;
break;case JOB_SHAMAN:
if (GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN)
return false;
break;case JOB_SURA:
if (GetAntiFlag() & ITEM_ANTIFLAG_SURA)
return false;
break;
#ifdef ENABLE_WOLFMAN_CHARACTER
case JOB_WOLFMAN:
if (GetAntiFlag() & ITEM_ANTIFLAG_WOLFMAN)
return false;
break;
#endif
}return true;
}
int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell)
{
// 코스츔 아이템(ITEM_COSTUME)은 WearFlag 없어도 됨. (sub type으로 착용위치 구분. 귀찮게 또 wear flag 줄 필요가 있나..)
// 용혼석(ITEM_DS, ITEM_SPECIAL_DS)도 SUB_TYPE으로 구분. 신규 반지, 벨트는 ITEM_TYPE으로 구분
#ifdef SHININGSYSTEM
if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType() && ITEM_SHINING != GetType())
return -1;
#else
if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType())
return -1;
#endif
// 용혼석 슬롯을 WEAR로 처리할 수가 없어서(WEAR는 최대 32개까지 가능한데 용혼석을 추가하면 32가 넘는다.)
// 인벤토리의 특정 위치((INVENTORY_MAX_NUM + WEAR_MAX_NUM)부터 (INVENTORY_MAX_NUM + WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX - 1)까지)를
// 용혼석 슬롯으로 정함.
// return 할 때에, INVENTORY_MAX_NUM을 뺀 이유는,
// 본래 WearCell이 INVENTORY_MAX_NUM를 빼고 return 하기 때문.
if (GetType() == ITEM_DS || GetType() == ITEM_SPECIAL_DS)
{
if (iCandidateCell < 0)
{
return WEAR_MAX_NUM + GetSubType();
}
else
{
for (int i = 0; i < DRAGON_SOUL_DECK_MAX_NUM; i++)
{
if (WEAR_MAX_NUM + i * DS_SLOT_MAX + GetSubType() == iCandidateCell)
{
return iCandidateCell;
}
}
return -1;
}
}
else if (GetType() == ITEM_COSTUME)
{
if (GetSubType() == COSTUME_BODY)
return WEAR_COSTUME_BODY;
else if (GetSubType() == COSTUME_HAIR)
return WEAR_COSTUME_HAIR;
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
else if (GetSubType() == COSTUME_MOUNT)
return WEAR_COSTUME_MOUNT;
#endif
#ifdef __COSTUME_ACCE__
else if (GetSubType() == COSTUME_ACCE)
return WEAR_COSTUME_ACCE;
#endif
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
else if (GetSubType() == COSTUME_WEAPON)
return WEAR_COSTUME_WEAPON;
#endif
}
#if !defined(ENABLE_MOUNT_COSTUME_SYSTEM) && !defined(__COSTUME_ACCE__)
else if (GetType() == ITEM_RING)
{
if (ch->GetWear(WEAR_RING1))
return WEAR_RING2;
else
return WEAR_RING1;
}
#endif
else if (GetType() == ITEM_BELT)
return WEAR_BELT;
else if (GetWearFlag() & WEARABLE_BODY)
return WEAR_BODY;
else if (GetWearFlag() & WEARABLE_HEAD)
return WEAR_HEAD;
else if (GetWearFlag() & WEARABLE_FOOTS)
return WEAR_FOOTS;
else if (GetWearFlag() & WEARABLE_WRIST)
return WEAR_WRIST;
else if (GetWearFlag() & WEARABLE_WEAPON)
return WEAR_WEAPON;
else if (GetWearFlag() & WEARABLE_SHIELD)
return WEAR_SHIELD;
else if (GetWearFlag() & WEARABLE_NECK)
return WEAR_NECK;
else if (GetWearFlag() & WEARABLE_EAR)
return WEAR_EAR;
else if (GetWearFlag() & WEARABLE_ARROW)
return WEAR_ARROW;
else if (GetWearFlag() & WEARABLE_UNIQUE)
{
if (ch->GetWear(WEAR_UNIQUE1))
return WEAR_UNIQUE2;
else
return WEAR_UNIQUE1;
}
#ifdef SHININGSYSTEM
else if (GetType() == ITEM_SHINING)
{
if (GetSubType() == SHINING_WEAPON) {
for (int i = WEAR_SHINING_WEAPON_1; i <= WEAR_SHINING_WEAPON_3; i++)
{
if (!ch->GetWear(i))
return i;
}
return WEAR_SHINING_WEAPON_1;
}
else if (GetSubType() == SHINING_ARMOR) {
if (ch->GetWear(WEAR_SHINING_ARMOR_1))
return WEAR_SHINING_ARMOR_2;
else
return WEAR_SHINING_ARMOR_1;
}
else if (GetSubType() == SHINING_SPECIAL) {
return WEAR_SHINING_SPECIAL;
}
}
#endif
// 수집 퀘스트를 위한 아이템이 박히는곳으로 한번 박히면 절대 E수 없다.
else if (GetWearFlag() & WEARABLE_ABILITY)
{
if (!ch->GetWear(WEAR_ABILITY1))
{
return WEAR_ABILITY1;
}
else if (!ch->GetWear(WEAR_ABILITY2))
{
return WEAR_ABILITY2;
}
else if (!ch->GetWear(WEAR_ABILITY3))
{
return WEAR_ABILITY3;
}
else if (!ch->GetWear(WEAR_ABILITY4))
{
return WEAR_ABILITY4;
}
else if (!ch->GetWear(WEAR_ABILITY5))
{
return WEAR_ABILITY5;
}
else if (!ch->GetWear(WEAR_ABILITY6))
{
return WEAR_ABILITY6;
}
else if (!ch->GetWear(WEAR_ABILITY7))
{
return WEAR_ABILITY7;
}
else if (!ch->GetWear(WEAR_ABILITY8))
{
return WEAR_ABILITY8;
}
else
{
return -1;
}
}
return -1;
}void CItem::ModifyPoints(bool bAdd)
{
int accessoryGrade;// 무기와 갑옷만 소켓을 적용시킨다.
if (false == IsAccessoryForSocket())
{
if (m_pProto->bType == ITEM_WEAPON || m_pProto->bType == ITEM_ARMOR)
{
// 소켓이 속성강화에 사용되는 경우 적용하지 않는다 (ARMOR_WRIST ARMOR_NECK ARMOR_EAR)
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
DWORD dwVnum;if ((dwVnum = GetSocket(i)) <= 2)
continue;TItemTable * p = ITEM_MANAGER::instance().GetTable(dwVnum);
if (!p)
{
sys_err("cannot find table by vnum %u", dwVnum);
continue;
}if (ITEM_METIN == p->bType)
{
//m_pOwner->ApplyPoint(p->alValues[0], bAdd ? p->alValues[1] : -p->alValues[1]);
for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (p->aApplies.bType == APPLY_NONE)
continue;if (p->aApplies.bType == APPLY_SKILL)
m_pOwner->ApplyPoint(p->aApplies.bType, bAdd ? p->aApplies.lValue : p->aApplies.lValue ^ 0x00800000);
else
m_pOwner->ApplyPoint(p->aApplies.bType, bAdd ? p->aApplies.lValue : -p->aApplies.lValue);
}
}
}
}accessoryGrade = 0;
}
else
{
accessoryGrade = MIN(GetAccessorySocketGrade(), ITEM_ACCESSORY_SOCKET_MAX_NUM);
}for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (m_pProto->aApplies.bType == APPLY_NONE)
continue;long value = m_pProto->aApplies.lValue;
if (m_pProto->aApplies.bType == APPLY_SKILL)
{
m_pOwner->ApplyPoint(m_pProto->aApplies.bType, bAdd ? value : value ^ 0x00800000);
}
else
{
if (0 != accessoryGrade)
value += MAX(accessoryGrade, value * aiAccessorySocketEffectivePct[accessoryGrade] / 100);m_pOwner->ApplyPoint(m_pProto->aApplies.bType, bAdd ? value : -value);
}
}
// 초승달의 반지, 할로윈 사탕, 행복의 반지, 영원한 사랑의 펜던트의 경우
// 기존의 하드 코딩으로 강제로 속성을 부여했지만,
// 그 부분을 제거하고 special item group 테이블에서 속성을 부여하도록 변경하였다.
// 하지만 하드 코딩되어있을 때 생성된 아이템이 남아있을 수도 있어서 특수처리 해놓는다.
// 이 아이템들의 경우, 밑에 ITEM_UNIQUE일 때의 처리로 속성이 부여되기 때문에,
// 아이템에 박혀있는 attribute는 적용하지 않고 넘어간다.
#ifdef __COSTUME_ACCE__
if (ITEM_COSTUME == GetType() && COSTUME_ACCE == GetSubType())
{
TItemTable * p = ITEM_MANAGER::instance().GetTable(GetSocket(1));if (p) {
for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (p->aApplies.bType == APPLY_NONE)
continue;int value = p->aApplies.lValue;
if (value < 0)
value = 1;
else
value = int(float(value) / 100.0f * float(GetSocket(0))) <= 0 ? 1 : int(float(value) / 100.0f * float(GetSocket(0)));if (p->aApplies.bType == APPLY_SKILL)
{
m_pOwner->ApplyPoint(p->aApplies.bType, bAdd ? value : value ^ 0x00800000);
}
else
{
m_pOwner->ApplyPoint(p->aApplies.bType, bAdd ? value : -value);
}
}
}
}
#endif
if (true == CItemVnumHelper::IsRamadanMoonRing(GetVnum()) || true == CItemVnumHelper::IsHalloweenCandy(GetVnum())
|| true == CItemVnumHelper::IsHappinessRing(GetVnum()) || true == CItemVnumHelper::IsLovePendant(GetVnum()))
{
// Do not anything.
}
else
{
for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
{
if (GetAttributeType(i))
{
const TPlayerItemAttribute& ia = GetAttribute(i);
short attrVal = ia.sValue;
#ifdef __COSTUME_ACCE__
if (ITEM_COSTUME == GetType() && COSTUME_ACCE == GetSubType())
{
if (attrVal < 0)
attrVal = 1;
else
attrVal = int(float(attrVal) / 100.0f * float(GetSocket(0)));// <= 0 ? 1 : int(float(attrVal) / 100.0f * float(GetSocket(0)));
}
#endif
if (ia.bType == APPLY_SKILL)
m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : ia.sValue ^ 0x00800000);
else
m_pOwner->ApplyPoint(ia.bType, bAdd ? ia.sValue : -ia.sValue);
}
}
}switch (m_pProto->bType)
{
case ITEM_PICK:
case ITEM_ROD:
{
if (bAdd)
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, GetVnum());
}
else
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, 0);
}
}
break;case ITEM_WEAPON:
{
#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
if (0 != m_pOwner->GetWear(WEAR_COSTUME_WEAPON))
break;
#endifif (bAdd)
{
#ifdef __CHANGE_LOOK_SYSTEM__
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, GetItemLook() > 0 ? GetItemLook() : GetVnum());
#else
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, GetVnum());
#endif
}
else
{
if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
m_pOwner->SetPart(PART_WEAPON, 0);
}
}
break;case ITEM_ARMOR:
{
// 코스츔 body를 입고있다면 armor는 벗던 입던 상관 없이 비주얼에 영향을 주면 안 됨.
if (0 != m_pOwner->GetWear(WEAR_COSTUME_BODY))
break;if (GetSubType() == ARMOR_BODY || GetSubType() == ARMOR_HEAD || GetSubType() == ARMOR_FOOTS || GetSubType() == ARMOR_SHIELD)
{
if (bAdd)
{
#ifdef __CHANGE_LOOK_SYSTEM__
if (GetProto()->bSubType == ARMOR_BODY)
m_pOwner->SetPart(PART_MAIN, GetItemLook() > 0 ? GetItemLook() : GetVnum());
#else
if (GetProto()->bSubType == ARMOR_BODY)
m_pOwner->SetPart(PART_MAIN, GetVnum());
#endif
}
else
{
if (GetProto()->bSubType == ARMOR_BODY)
m_pOwner->SetPart(PART_MAIN, m_pOwner->GetOriginalPart(PART_MAIN));
}
}
}
break;// 코스츔 아이템 입었을 때 캐릭터 parts 정보 세팅. 기존 스타일대로 추가함..
case ITEM_COSTUME:
{
DWORD toSetValue = this->GetVnum();
EParts toSetPart = PART_MAX_NUM;// 갑옷 코스츔
if (GetSubType() == COSTUME_BODY)
{
toSetPart = PART_MAIN;if (false == bAdd)
{
// 코스츔 갑옷을 벗었을 때 원래 갑옷을 입고 있었다면 그 갑옷으로 look 세팅, 입지 않았다면 default look
#ifdef __CHANGE_LOOK_SYSTEM__
CItem* pArmor = m_pOwner->GetWear(WEAR_BODY);
#else
const CItem* pArmor = m_pOwner->GetWear(WEAR_BODY);
#endif
#ifdef __CHANGE_LOOK_SYSTEM__
toSetValue = (NULL != pArmor) ? pArmor->GetItemLook() > 0 ? pArmor->GetItemLook() : pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN);
#else
toSetValue = (NULL != pArmor) ? pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN);
#endif
}}
// 헤어 코스츔
else if (GetSubType() == COSTUME_HAIR)
{
toSetPart = PART_HAIR;// 코스츔 헤어는 shape값을 item proto의 value3에 세팅하도록 함. 특별한 이유는 없고 기존 갑옷(ARMOR_BODY)의 shape값이 프로토의 value3에 있어서 헤어도 같이 value3으로 함.
// [NOTE] 갑옷은 아이템 vnum을 보내고 헤어는 shape(value3)값을 보내는 이유는.. 기존 시스템이 그렇게 되어있음...
toSetValue = (true == bAdd) ? this->GetValue(3) : 0;
}#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
else if (GetSubType() == COSTUME_MOUNT)
{
// not need to do a thing in here
}
#endif#ifdef ENABLE_WEAPON_COSTUME_SYSTEM
else if (GetSubType() == COSTUME_WEAPON)
{
toSetPart = PART_WEAPON;
if (false == bAdd)
{
#ifdef __CHANGE_LOOK_SYSTEM__
CItem* pWeapon = m_pOwner->GetWear(WEAR_WEAPON);
#else
const CItem* pWeapon = m_pOwner->GetWear(WEAR_WEAPON);
#endif
#ifdef __CHANGE_LOOK_SYSTEM__
toSetValue = (NULL != pWeapon) ? pWeapon->GetItemLook() > 0 ? pWeapon->GetItemLook() : pWeapon->GetVnum() : m_pOwner->GetOriginalPart(PART_WEAPON);
#else
toSetValue = (NULL != pWeapon) ? pWeapon->GetVnum() : m_pOwner->GetOriginalPart(PART_WEAPON);
#endif
}
}
#endif
#ifdef __COSTUME_ACCE__
else if (GetSubType() == COSTUME_ACCE) {
toSetPart = PART_ACCE;
toSetValue = (true == bAdd) ? this->GetVnum() : 0;
}
#endifif (PART_MAX_NUM != toSetPart)
{
m_pOwner->SetPart((BYTE)toSetPart, toSetValue);
m_pOwner->UpdatePacket();
}
}
break;
case ITEM_UNIQUE:
{
if (0 != GetSIGVnum())
{
const CSpecialItemGroup* pItemGroup = ITEM_MANAGER::instance().GetSpecialItemGroup(GetSIGVnum());
if (NULL == pItemGroup)
break;
DWORD dwAttrVnum = pItemGroup->GetAttrVnum(GetVnum());
const CSpecialAttrGroup* pAttrGroup = ITEM_MANAGER::instance().GetSpecialAttrGroup(dwAttrVnum);
if (NULL == pAttrGroup)
break;
for (itertype (pAttrGroup->m_vecAttrs) it = pAttrGroup->m_vecAttrs.begin(); it != pAttrGroup->m_vecAttrs.end(); it++)
{
m_pOwner->ApplyPoint(it->apply_type, bAdd ? it->apply_value : -it->apply_value);
}
}
}
break;
}
}bool CItem::IsEquipable() const
{
switch (this->GetType())
{
case ITEM_COSTUME:
case ITEM_ARMOR:
case ITEM_WEAPON:
case ITEM_ROD:
case ITEM_PICK:
case ITEM_UNIQUE:
case ITEM_DS:
case ITEM_SPECIAL_DS:
case ITEM_RING:
case ITEM_BELT:
#ifdef SHININGSYSTEM
case ITEM_SHINING:
#endif
return true;
}return false;
}#define ENABLE_IMMUNE_FIX
// return false on error state
#ifdef ENABLE_5_INVENTORY
bool CItem::EquipTo(LPCHARACTER ch, WORD bWearCell)
#else
bool CItem::EquipTo(LPCHARACTER ch, BYTE bWearCell)
#endif
{
if (!ch)
{
sys_err("EquipTo: nil character");
return false;
}// 용혼석 슬롯 index는 WEAR_MAX_NUM 보다 큼.
if (IsDragonSoul())
{
if (bWearCell < WEAR_MAX_NUM || bWearCell >= WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX)
{
sys_err("EquipTo: invalid dragon soul cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetSubType(), bWearCell - WEAR_MAX_NUM);
return false;
}
}
else
{
if (bWearCell >= WEAR_MAX_NUM)
{
sys_err("EquipTo: invalid wear cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetWearFlag(), bWearCell);
return false;
}
}if (ch->GetWear(bWearCell))
{
sys_err("EquipTo: item already exist (this: #%d %s cell: %d %s)", GetOriginalVnum(), GetName(), bWearCell, ch->GetWear(bWearCell)->GetName());
return false;
}if (GetOwner())
RemoveFromCharacter();ch->SetWear(bWearCell, this); // 여기서 패킷 나감
m_pOwner = ch;
m_bEquipped = true;
m_wCell = INVENTORY_MAX_NUM + bWearCell;#ifndef ENABLE_IMMUNE_FIX
DWORD dwImmuneFlag = 0;for (int i = 0; i < WEAR_MAX_NUM; ++i)
{
if (m_pOwner->GetWear(i))
{
// m_pOwner->ChatPacket(CHAT_TYPE_INFO, "unequip immuneflag(%u)", m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); // always 0
SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag);
}
}m_pOwner->SetImmuneFlag(dwImmuneFlag);
#endifif (IsDragonSoul())
{
DSManager::instance().ActivateDragonSoul(this);
}
else
{
ModifyPoints(true);
StartUniqueExpireEvent();
if (-1 != GetProto()->cLimitTimerBasedOnWearIndex)
StartTimerBasedOnWearExpireEvent();// ACCESSORY_REFINE
StartAccessorySocketExpireEvent();
// END_OF_ACCESSORY_REFINE
}ch->BuffOnAttr_AddBuffsFromItem(this);
m_pOwner->ComputeBattlePoints();
m_pOwner->UpdatePacket();
Save();
return (true);
}bool CItem::Unequip()
{
if (!m_pOwner || GetCell() < INVENTORY_MAX_NUM)
{
// ITEM_OWNER_INVALID_PTR_BUG
sys_err("%s %u m_pOwner %p, GetCell %d",
GetName(), GetID(), get_pointer(m_pOwner), GetCell());
// END_OF_ITEM_OWNER_INVALID_PTR_BUG
return false;
}if (this != m_pOwner->GetWear(GetCell() - INVENTORY_MAX_NUM))
{
sys_err("m_pOwner->GetWear() != this");
return false;
}//신규 말 아이템 제거시 처리
if (IsRideItem())
ClearMountAttributeAndAffect();if (IsDragonSoul())
{
DSManager::instance().DeactivateDragonSoul(this);
}
else
{
ModifyPoints(false);
}StopUniqueExpireEvent();
if (-1 != GetProto()->cLimitTimerBasedOnWearIndex)
StopTimerBasedOnWearExpireEvent();// ACCESSORY_REFINE
StopAccessorySocketExpireEvent();
// END_OF_ACCESSORY_REFINE
m_pOwner->BuffOnAttr_RemoveBuffsFromItem(this);m_pOwner->SetWear(GetCell() - INVENTORY_MAX_NUM, NULL);
#ifndef ENABLE_IMMUNE_FIX
DWORD dwImmuneFlag = 0;for (int i = 0; i < WEAR_MAX_NUM; ++i)
{
if (m_pOwner->GetWear(i))
{
// m_pOwner->ChatPacket(CHAT_TYPE_INFO, "unequip immuneflag(%u)", m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); // always 0
SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag);
}
}m_pOwner->SetImmuneFlag(dwImmuneFlag);
#endifm_pOwner->ComputeBattlePoints();
m_pOwner->UpdatePacket();
m_pOwner = NULL;
m_wCell = 0;
m_bEquipped = false;return true;
}long CItem::GetValue(DWORD idx)
{
assert(idx < ITEM_VALUES_MAX_NUM);
return GetProto()->alValues[idx];
}void CItem::SetExchanging(bool bOn)
{
m_bExchanging = bOn;
}void CItem::Save()
{
if (m_bSkipSave)
return;ITEM_MANAGER::instance().DelayedSave(this);
}bool CItem::CreateSocket(BYTE bSlot, BYTE bGold)
{
assert(bSlot < ITEM_SOCKET_MAX_NUM);if (m_alSockets[bSlot] != 0)
{
sys_err("Item::CreateSocket : socket already exist %s %d", GetName(), bSlot);
return false;
}if (bGold)
m_alSockets[bSlot] = 2;
else
m_alSockets[bSlot] = 1;UpdatePacket();
Save();
return true;
}void CItem::SetSockets(const long * c_al)
{
thecore_memcpy(m_alSockets, c_al, sizeof(m_alSockets));
Save();
}void CItem::SetSocket(int i, long v, bool bLog)
{
assert(i < ITEM_SOCKET_MAX_NUM);
m_alSockets = v;
UpdatePacket();
Save();
if (bLog)
{
#ifdef ENABLE_NEWSTUFF
if (g_iDbLogLevel>=LOG_LEVEL_MAX)
#endif
LogManager::instance().ItemLog(i, v, 0, GetID(), "SET_SOCKET", "", "", GetOriginalVnum());
}
}#ifdef ENABLE_YANG_LIMIT
long long CItem::GetGold()
#else
int CItem::GetGold()
#endif
{
if (IS_SET(GetFlag(), ITEM_FLAG_COUNT_PER_1GOLD))
{
if (GetProto()->dwGold == 0)
return GetCount();
else
return GetCount() / GetProto()->dwGold;
}
else
return GetProto()->dwGold;
}#ifdef ENABLE_YANG_LIMIT
long long CItem::GetShopBuyPrice()
#else
int CItem::GetShopBuyPrice()
#endif
{
return GetProto()->dwShopBuyPrice;
}bool CItem::IsOwnership(LPCHARACTER ch)
{
if (!m_pkOwnershipEvent)
return true;return m_dwOwnershipPID == ch->GetPlayerID() ? true : false;
}EVENTFUNC(ownership_event)
{
item_event_info* info = dynamic_cast<item_event_info*>( event->info );if ( info == NULL )
{
sys_err( "ownership_event> <Factor> Null pointer" );
return 0;
}LPITEM pkItem = info->item;
pkItem->SetOwnershipEvent(NULL);
TPacketGCItemOwnership p;
p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
p.dwVID = pkItem->GetVID();
p.szName[0] = '\0';pkItem->PacketAround(&p, sizeof(p));
return 0;
}void CItem::SetOwnershipEvent(LPEVENT pkEvent)
{
m_pkOwnershipEvent = pkEvent;
}void CItem::SetOwnership(LPCHARACTER ch, int iSec)
{
if (!ch)
{
if (m_pkOwnershipEvent)
{
event_cancel(&m_pkOwnershipEvent);
m_dwOwnershipPID = 0;TPacketGCItemOwnership p;
p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
p.dwVID = m_dwVID;
p.szName[0] = '\0';PacketAround(&p, sizeof(p));
}
return;
}if (m_pkOwnershipEvent)
return;if (iSec <= 10)
iSec = 30;m_dwOwnershipPID = ch->GetPlayerID();
item_event_info* info = AllocEventInfo<item_event_info>();
strlcpy(info->szOwnerName, ch->GetName(), sizeof(info->szOwnerName));
info->item = this;SetOwnershipEvent(event_create(ownership_event, info, PASSES_PER_SEC(iSec)));
TPacketGCItemOwnership p;
p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
p.dwVID = m_dwVID;
strlcpy(p.szName, ch->GetName(), sizeof(p.szName));PacketAround(&p, sizeof(p));
}int CItem::GetSocketCount()
{
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
{
if (GetSocket(i) == 0)
return i;
}
return ITEM_SOCKET_MAX_NUM;
}bool CItem::AddSocket()
{
int count = GetSocketCount();
if (count == ITEM_SOCKET_MAX_NUM)
return false;
m_alSockets[count] = 1;
return true;
}void CItem::AlterToSocketItem(int iSocketCount)
{
if (iSocketCount >= ITEM_SOCKET_MAX_NUM)
{
sys_log(0, "Invalid Socket Count %d, set to maximum", ITEM_SOCKET_MAX_NUM);
iSocketCount = ITEM_SOCKET_MAX_NUM;
}for (int i = 0; i < iSocketCount; ++i)
SetSocket(i, 1);
}void CItem::AlterToMagicItem()
{
int idx = GetAttributeSetIndex();if (idx < 0)
return;// Appeariance Second Third
// Weapon 50 20 5
// Armor 30 10 2
// Acc 20 10 1int iSecondPct;
int iThirdPct;switch (GetType())
{
case ITEM_WEAPON:
iSecondPct = 20;
iThirdPct = 5;
break;case ITEM_ARMOR:
case ITEM_COSTUME:
if (GetSubType() == ARMOR_BODY)
{
iSecondPct = 10;
iThirdPct = 2;
}
else
{
iSecondPct = 10;
iThirdPct = 1;
}
break;default:
return;
}// 100% 확률로 좋은 속성 하나
PutAttribute(aiItemMagicAttributePercentHigh);if (number(1, 100) <= iSecondPct)
PutAttribute(aiItemMagicAttributePercentLow);if (number(1, 100) <= iThirdPct)
PutAttribute(aiItemMagicAttributePercentLow);
}DWORD CItem::GetRefineFromVnum()
{
return ITEM_MANAGER::instance().GetRefineFromVnum(GetVnum());
}int CItem::GetRefineLevel()
{
const char* name = GetBaseName();
char* p = const_cast<char*>(strrchr(name, '+'));if (!p)
return 0;int rtn = 0;
str_to_number(rtn, p+1);const char* locale_name = GetName();
p = const_cast<char*>(strrchr(locale_name, '+'));if (p)
{
int locale_rtn = 0;
str_to_number(locale_rtn, p+1);
if (locale_rtn != rtn)
{
sys_err("refine_level_based_on_NAME(%d) is not equal to refine_level_based_on_LOCALE_NAME(%d).", rtn, locale_rtn);
}
}return rtn;
}bool CItem::IsPolymorphItem()
{
return GetType() == ITEM_POLYMORPH;
}EVENTFUNC(unique_expire_event)
{
item_event_info* info = dynamic_cast<item_event_info*>( event->info );if ( info == NULL )
{
sys_err( "unique_expire_event> <Factor> Null pointer" );
return 0;
}LPITEM pkItem = info->item;
if (pkItem->GetValue(2) == 0)
{
if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) <= 1)
{
sys_log(0, "UNIQUE_ITEM: expire %s %u", pkItem->GetName(), pkItem->GetID());
pkItem->SetUniqueExpireEvent(NULL);
ITEM_MANAGER::instance().RemoveItem(pkItem, "UNIQUE_EXPIRE");
return 0;
}
else
{
pkItem->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - 1);
return PASSES_PER_SEC(60);
}
}
else
{
time_t cur = get_global_time();if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) <= cur)
{
pkItem->SetUniqueExpireEvent(NULL);
ITEM_MANAGER::instance().RemoveItem(pkItem, "UNIQUE_EXPIRE");
return 0;
}
else
{
// 게임 내에 시간제 아이템들이 빠릿빠릿하게 사라지지 않는 버그가 있어
// 수정
// by rtsummit
if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur < 600)
return PASSES_PER_SEC(pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur);
else
return PASSES_PER_SEC(600);
}
}
}// 시간 후불제
// timer를 시작할 때에 시간 차감하는 것이 아니라,
// timer가 발화할 때에 timer가 동작한 시간 만큼 시간 차감을 한다.
EVENTFUNC(timer_based_on_wear_expire_event)
{
item_event_info* info = dynamic_cast<item_event_info*>( event->info );if ( info == NULL )
{
sys_err( "expire_event <Factor> Null pointer" );
return 0;
}LPITEM pkItem = info->item;
int remain_time = pkItem->GetSocket(ITEM_SOCKET_REMAIN_SEC) - processing_time/passes_per_sec;
if (remain_time <= 0)
{
sys_log(0, "ITEM EXPIRED : expired %s %u", pkItem->GetName(), pkItem->GetID());
pkItem->SetTimerBasedOnWearExpireEvent(NULL);
pkItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, 0);// 일단 timer based on wear 용혼석은 시간 다 되었다고 없애지 않는다.
if (pkItem->IsDragonSoul())
{
DSManager::instance().DeactivateDragonSoul(pkItem);
}
else
{
ITEM_MANAGER::instance().RemoveItem(pkItem, "TIMER_BASED_ON_WEAR_EXPIRE");
}
return 0;
}
pkItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, remain_time);
return PASSES_PER_SEC (MIN (60, remain_time));
}void CItem::SetUniqueExpireEvent(LPEVENT pkEvent)
{
m_pkUniqueExpireEvent = pkEvent;
}void CItem::SetTimerBasedOnWearExpireEvent(LPEVENT pkEvent)
{
m_pkTimerBasedOnWearExpireEvent = pkEvent;
}EVENTFUNC(real_time_expire_event)
{
const item_vid_event_info* info = reinterpret_cast<const item_vid_event_info*>(event->info);if (NULL == info)
return 0;const LPITEM item = ITEM_MANAGER::instance().FindByVID( info->item_vid );
if (NULL == item)
return 0;const time_t current = get_global_time();
if (current > item->GetSocket(0))
{
switch (item->GetVnum())
{
if(item->IsNewMountItem())
{
if (item->GetSocket(2) != 0)
item->ClearMountAttributeAndAffect();
}
break;
}
#ifdef SHOP_SEARCH
if (item->GetOwner() && CShopSearchHelper::IsGlass(item->GetVnum()))
CShopSearchHelper::Close(item->GetVnum(), item->GetOwner());
#endif
ITEM_MANAGER::instance().RemoveItem(item, "REAL_TIME_EXPIRE");return 0;
}return PASSES_PER_SEC(1);
}void CItem::StartRealTimeExpireEvent()
{
if (m_pkRealTimeExpireEvent)
return;
for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
{
if (LIMIT_REAL_TIME == GetProto()->aLimits.bType || LIMIT_REAL_TIME_START_FIRST_USE == GetProto()->aLimits.bType)
{
item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
info->item_vid = GetVID();m_pkRealTimeExpireEvent = event_create( real_time_expire_event, info, PASSES_PER_SEC(1));
sys_log(0, "REAL_TIME_EXPIRE: StartRealTimeExpireEvent");
return;
}
}
}bool CItem::IsRealTimeItem()
{
if(!GetProto())
return false;
for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
{
if (LIMIT_REAL_TIME == GetProto()->aLimits.bType)
return true;
}
return false;
}void CItem::StartUniqueExpireEvent()
{
if (GetType() != ITEM_UNIQUE)
return;if (m_pkUniqueExpireEvent)
return;//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
if (IsRealTimeItem())
return;// HARD CODING
if (GetVnum() == UNIQUE_ITEM_HIDE_ALIGNMENT_TITLE)
m_pOwner->ShowAlignment(false);int iSec = GetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME);
if (iSec == 0)
iSec = 60;
else
iSec = MIN(iSec, 60);SetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME, 0);
item_event_info* info = AllocEventInfo<item_event_info>();
info->item = this;SetUniqueExpireEvent(event_create(unique_expire_event, info, PASSES_PER_SEC(iSec)));
}// 시간 후불제
// timer_based_on_wear_expire_event 설명 참조
void CItem::StartTimerBasedOnWearExpireEvent()
{
if (m_pkTimerBasedOnWearExpireEvent)
return;//기간제 아이템일 경우 시간제 아이템은 동작하지 않는다
if (IsRealTimeItem())
return;if (-1 == GetProto()->cLimitTimerBasedOnWearIndex)
return;int iSec = GetSocket(0);
// 남은 시간을 분단위로 끊기 위해...
if (0 != iSec)
{
iSec %= 60;
if (0 == iSec)
iSec = 60;
}item_event_info* info = AllocEventInfo<item_event_info>();
info->item = this;SetTimerBasedOnWearExpireEvent(event_create(timer_based_on_wear_expire_event, info, PASSES_PER_SEC(iSec)));
}void CItem::StopUniqueExpireEvent()
{
if (!m_pkUniqueExpireEvent)
return;if (GetValue(2) != 0) // 게임시간제 이외의 아이템은 UniqueExpireEvent를 중단할 수 없다.
return;// HARD CODING
if (GetVnum() == UNIQUE_ITEM_HIDE_ALIGNMENT_TITLE)
m_pOwner->ShowAlignment(true);SetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME, event_time(m_pkUniqueExpireEvent) / passes_per_sec);
event_cancel(&m_pkUniqueExpireEvent);ITEM_MANAGER::instance().SaveSingleItem(this);
}void CItem::StopTimerBasedOnWearExpireEvent()
{
if (!m_pkTimerBasedOnWearExpireEvent)
return;int remain_time = GetSocket(ITEM_SOCKET_REMAIN_SEC) - event_processing_time(m_pkTimerBasedOnWearExpireEvent) / passes_per_sec;
SetSocket(ITEM_SOCKET_REMAIN_SEC, remain_time);
event_cancel(&m_pkTimerBasedOnWearExpireEvent);ITEM_MANAGER::instance().SaveSingleItem(this);
}void CItem::ApplyAddon(int iAddonType)
{
CItemAddonManager::instance().ApplyAddonTo(iAddonType, this);
}int CItem::GetSpecialGroup() const
{
return ITEM_MANAGER::instance().GetSpecialGroupFromItem(GetVnum());
}//
// 악세서리 소켓 처리.
//
bool CItem::IsAccessoryForSocket()
{
return (m_pProto->bType == ITEM_ARMOR && (m_pProto->bSubType == ARMOR_WRIST || m_pProto->bSubType == ARMOR_NECK || m_pProto->bSubType == ARMOR_EAR)) ||
(m_pProto->bType == ITEM_BELT); // 2013년 2월 새로 추가된 '벨트' 아이템의 경우 기획팀에서 악세서리 소켓 시스템을 그대로 이용하자고 함.
}void CItem::SetAccessorySocketGrade(int iGrade)
{
SetSocket(0, MINMAX(0, iGrade, GetAccessorySocketMaxGrade()));int iDownTime = aiAccessorySocketDegradeTime[GetAccessorySocketGrade()];
//if (test_server)
// iDownTime /= 60;SetAccessorySocketDownGradeTime(iDownTime);
}void CItem::SetAccessorySocketMaxGrade(int iMaxGrade)
{
SetSocket(1, MINMAX(0, iMaxGrade, ITEM_ACCESSORY_SOCKET_MAX_NUM));
}void CItem::SetAccessorySocketDownGradeTime(DWORD time)
{
SetSocket(2, time);if (test_server && GetOwner())
GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s에서 소켓 빠질때까지 남은 시간 %d"), GetName(), time);
}EVENTFUNC(accessory_socket_expire_event)
{
item_vid_event_info* info = dynamic_cast<item_vid_event_info*>( event->info );if ( info == NULL )
{
sys_err( "accessory_socket_expire_event> <Factor> Null pointer" );
return 0;
}LPITEM item = ITEM_MANAGER::instance().FindByVID(info->item_vid);
if (item->GetAccessorySocketDownGradeTime() <= 1)
{
degrade:
item->SetAccessorySocketExpireEvent(NULL);
item->AccessorySocketDegrade();
return 0;
}
else
{
int iTime = item->GetAccessorySocketDownGradeTime() - 60;if (iTime <= 1)
goto degrade;item->SetAccessorySocketDownGradeTime(iTime);
if (iTime > 60)
return PASSES_PER_SEC(60);
else
return PASSES_PER_SEC(iTime);
}
}void CItem::StartAccessorySocketExpireEvent()
{
if (!IsAccessoryForSocket())
return;if (m_pkAccessorySocketExpireEvent)
return;if (GetAccessorySocketMaxGrade() == 0)
return;if (GetAccessorySocketGrade() == 0)
return;int iSec = GetAccessorySocketDownGradeTime();
SetAccessorySocketExpireEvent(NULL);if (iSec <= 1)
iSec = 5;
else
iSec = MIN(iSec, 60);item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
info->item_vid = GetVID();SetAccessorySocketExpireEvent(event_create(accessory_socket_expire_event, info, PASSES_PER_SEC(iSec)));
}void CItem::StopAccessorySocketExpireEvent()
{
if (!m_pkAccessorySocketExpireEvent)
return;if (!IsAccessoryForSocket())
return;int new_time = GetAccessorySocketDownGradeTime() - (60 - event_time(m_pkAccessorySocketExpireEvent) / passes_per_sec);
event_cancel(&m_pkAccessorySocketExpireEvent);
if (new_time <= 1)
{
AccessorySocketDegrade();
}
else
{
SetAccessorySocketDownGradeTime(new_time);
}
}bool CItem::IsRideItem()
{
if (ITEM_UNIQUE == GetType() && UNIQUE_SPECIAL_RIDE == GetSubType())
return true;
if (ITEM_UNIQUE == GetType() && UNIQUE_SPECIAL_MOUNT_RIDE == GetSubType())
return true;
#ifdef ENABLE_MOUNT_COSTUME_SYSTEM
if (ITEM_COSTUME == GetType() && COSTUME_MOUNT == GetSubType())
return true;
#endif
return false;
}bool CItem::IsRamadanRing()
{
if (GetVnum() == UNIQUE_ITEM_RAMADAN_RING)
return true;
return false;
}void CItem::ClearMountAttributeAndAffect()
{
LPCHARACTER ch = GetOwner();ch->RemoveAffect(AFFECT_MOUNT);
ch->RemoveAffect(AFFECT_MOUNT_BONUS);ch->MountVnum(0);
ch->PointChange(POINT_ST, 0);
ch->PointChange(POINT_DX, 0);
ch->PointChange(POINT_HT, 0);
ch->PointChange(POINT_IQ, 0);
}// fixme
// 이거 지금은 안쓴데... 근데 혹시나 싶어서 남겨둠.
// by rtsummit
bool CItem::IsNewMountItem()
{
switch(GetVnum())
{
case 76000: case 76001: case 76002: case 76003:
case 76004: case 76005: case 76006: case 76007:
case 76008: case 76009: case 76010: case 76011:
case 76012: case 76013: case 76014:
return true;
}
return false;
}void CItem::SetAccessorySocketExpireEvent(LPEVENT pkEvent)
{
m_pkAccessorySocketExpireEvent = pkEvent;
}void CItem::AccessorySocketDegrade()
{
if (GetAccessorySocketGrade() > 0)
{
LPCHARACTER ch = GetOwner();if (ch)
{
ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s에 박혀있던 보석이 사라집니다."), GetName());
}ModifyPoints(false);
SetAccessorySocketGrade(GetAccessorySocketGrade()-1);
ModifyPoints(true);int iDownTime = aiAccessorySocketDegradeTime[GetAccessorySocketGrade()];
if (test_server)
iDownTime /= 60;SetAccessorySocketDownGradeTime(iDownTime);
if (iDownTime)
StartAccessorySocketExpireEvent();
}
}// ring에 item을 박을 수 있는지 여부를 체크해서 리턴
static const bool CanPutIntoRing(LPITEM ring, LPITEM item)
{
//const DWORD vnum = item->GetVnum();
return false;
}bool CItem::CanPutInto(LPITEM item)
{
if (item->GetType() == ITEM_BELT)
return this->GetSubType() == USE_PUT_INTO_BELT_SOCKET;else if(item->GetType() == ITEM_RING)
return CanPutIntoRing(item, this);else if (item->GetType() != ITEM_ARMOR)
return false;DWORD vnum = item->GetVnum();
struct JewelAccessoryInfo
{
DWORD jewel;
DWORD wrist;
DWORD neck;
DWORD ear;
};
const static JewelAccessoryInfo infos[] = {
{ 50634, 14420, 16220, 17220 },
{ 50635, 14500, 16500, 17500 },
{ 50636, 14520, 16520, 17520 },
{ 50637, 14540, 16540, 17540 },
{ 50638, 14560, 16560, 17560 },
{ 50639, 14570, 16570, 17570 },
};DWORD item_type = (item->GetVnum() / 10) * 10;
for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++)
{
const JewelAccessoryInfo& info = infos;
switch(item->GetSubType())
{
case ARMOR_WRIST:
if (info.wrist == item_type)
{
if (info.jewel == GetVnum())
{
return true;
}
else
{
return false;
}
}
break;
case ARMOR_NECK:
if (info.neck == item_type)
{
if (info.jewel == GetVnum())
{
return true;
}
else
{
return false;
}
}
break;
case ARMOR_EAR:
if (info.ear == item_type)
{
if (info.jewel == GetVnum())
{
return true;
}
else
{
return false;
}
}
break;
}
}
if (item->GetSubType() == ARMOR_WRIST)
vnum -= 14000;
else if (item->GetSubType() == ARMOR_NECK)
vnum -= 16000;
else if (item->GetSubType() == ARMOR_EAR)
vnum -= 17000;
else
return false;DWORD type = vnum / 20;
if (type < 0 || type > 11)
{
type = (vnum - 170) / 20;if (50623 + type != GetVnum())
return false;
else
return true;
}
else if (item->GetVnum() >= 16210 && item->GetVnum() <= 16219)
{
if (50625 != GetVnum())
return false;
else
return true;
}
else if (item->GetVnum() >= 16230 && item->GetVnum() <= 16239)
{
if (50626 != GetVnum())
return false;
else
return true;
}return 50623 + type == GetVnum();
}// PC_BANG_ITEM_ADD
bool CItem::IsPCBangItem()
{
for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
{
if (m_pProto->aLimits.bType == LIMIT_PCBANG)
return true;
}
return false;
}
// END_PC_BANG_ITEM_ADDbool CItem::CheckItemUseLevel(int nLevel)
{
for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
{
if (this->m_pProto->aLimits.bType == LIMIT_LEVEL)
{
if (this->m_pProto->aLimits.lValue > nLevel) return false;
else return true;
}
}
return true;
}long CItem::FindApplyValue(BYTE bApplyType)
{
if (m_pProto == NULL)
return 0;for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
{
if (m_pProto->aApplies.bType == bApplyType)
return m_pProto->aApplies.lValue;
}return 0;
}void CItem::CopySocketTo(LPITEM pItem)
{
for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
pItem->m_alSockets = m_alSockets;
}
}int CItem::GetAccessorySocketGrade()
{
return MINMAX(0, GetSocket(0), GetAccessorySocketMaxGrade());
}int CItem::GetAccessorySocketMaxGrade()
{
return MINMAX(0, GetSocket(1), ITEM_ACCESSORY_SOCKET_MAX_NUM);
}int CItem::GetAccessorySocketDownGradeTime()
{
return MINMAX(0, GetSocket(2), aiAccessorySocketDegradeTime[GetAccessorySocketGrade()]);
}void CItem::AttrLog()
{
const char * pszIP = NULL;if (GetOwner() && GetOwner()->GetDesc())
pszIP = GetOwner()->GetDesc()->GetHostName();for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
{
if (m_alSockets)
{
#ifdef ENABLE_NEWSTUFF
if (g_iDbLogLevel>=LOG_LEVEL_MAX)
#endif
LogManager::instance().ItemLog(i, m_alSockets, 0, GetID(), "INFO_SOCKET", "", pszIP ? pszIP : "", GetOriginalVnum());
}
}for (int i = 0; i<ITEM_ATTRIBUTE_MAX_NUM; ++i)
{
int type = m_aAttr.bType;
int value = m_aAttr.sValue;if (type)
{
#ifdef ENABLE_NEWSTUFF
if (g_iDbLogLevel>=LOG_LEVEL_MAX)
#endif
LogManager::instance().ItemLog(i, type, value, GetID(), "INFO_ATTR", "", pszIP ? pszIP : "", GetOriginalVnum());
}
}
}int CItem::GetLevelLimit()
{
for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
{
if (this->m_pProto->aLimits.bType == LIMIT_LEVEL)
{
return this->m_pProto->aLimits.lValue;
}
}
return 0;
}bool CItem::OnAfterCreatedItem()
{
// 아이템을 한 번이라도 사용했다면, 그 이후엔 사용 중이지 않아도 시간이 차감되는 방식
if (-1 != this->GetProto()->cLimitRealTimeFirstUseIndex)
{
// Socket1에 아이템의 사용 횟수가 기록되어 있으니, 한 번이라도 사용한 아이템은 타이머를 시작한다.
if (0 != GetSocket(1))
{
StartRealTimeExpireEvent();
}
}return true;
}
#ifdef __AUCTION__// 경매장
// window를 경매장으로 한다.bool CItem::MoveToAuction()
{
LPCHARACTER owner = GetOwner();
if (owner == NULL)
{
sys_err ("Item those owner is not exist cannot regist in auction");
return false;
}if (GetWindow() == AUCTION)
{
sys_err ("Item is already in auction.");
}SetWindow(AUCTION);
owner->SetItem(m_bCell, NULL);
Save();
ITEM_MANAGER::instance().FlushDelayedSave(this);return true;
}void CItem::CopyToRawData (TPlayerItem* new_item)
{
if (new_item != NULL)
return;new_item->id = m_dwID;
new_item->window = m_bWindow;
new_item->pos = m_bCell;
new_item->count = m_dwCount;new_item->vnum = GetVnum();
thecore_memcpy (new_item->alSockets, m_alSockets, sizeof (m_alSockets));
thecore_memcpy (new_item->aAttr, m_aAttr, sizeof (m_aAttr));new_item->owner = m_pOwner->GetPlayerID();
}
#endifbool CItem::IsDragonSoul()
{
return GetType() == ITEM_DS;
}int CItem::GiveMoreTime_Per(float fPercent)
{
if (IsDragonSoul())
{
DWORD duration = DSManager::instance().GetDuration(this);
DWORD remain_sec = GetSocket(ITEM_SOCKET_REMAIN_SEC);
DWORD given_time = fPercent * duration / 100u;
if (remain_sec == duration)
return false;
if ((given_time + remain_sec) >= duration)
{
SetSocket(ITEM_SOCKET_REMAIN_SEC, duration);
return duration - remain_sec;
}
else
{
SetSocket(ITEM_SOCKET_REMAIN_SEC, given_time + remain_sec);
return given_time;
}
}
// 우선 용혼석에 관해서만 하도록 한다.
else
return 0;
}int CItem::GiveMoreTime_Fix(DWORD dwTime)
{
if (IsDragonSoul())
{
DWORD duration = DSManager::instance().GetDuration(this);
DWORD remain_sec = GetSocket(ITEM_SOCKET_REMAIN_SEC);
if (remain_sec == duration)
return false;
if ((dwTime + remain_sec) >= duration)
{
SetSocket(ITEM_SOCKET_REMAIN_SEC, duration);
return duration - remain_sec;
}
else
{
SetSocket(ITEM_SOCKET_REMAIN_SEC, dwTime + remain_sec);
return dwTime;
}
}
// 우선 용혼석에 관해서만 하도록 한다.
else
return 0;
}
int CItem::GetDuration()
{
if(!GetProto())
return -1;for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
{
if (LIMIT_REAL_TIME == GetProto()->aLimits.bType)
return GetProto()->aLimits.lValue;
}if (GetProto()->cLimitTimerBasedOnWearIndex >= 0)
{
BYTE cLTBOWI = GetProto()->cLimitTimerBasedOnWearIndex;
return GetProto()->aLimits[cLTBOWI].lValue;
}return -1;
}bool CItem::IsSameSpecialGroup(const LPITEM item) const
{
// 서로 VNUM이 같다면 같은 그룹인 것으로 간주
if (this->GetVnum() == item->GetVnum())
return true;if (GetSpecialGroup() && (item->GetSpecialGroup() == GetSpecialGroup()))
return true;return false;
}#ifdef __CHANGE_LOOK_SYSTEM__
void CItem::SetItemLook(DWORD look)
{
m_dwLook = look;
UpdatePacket();
ITEM_MANAGER::instance().SaveSingleItem(this);
Save();
}
#endif -
Thanks for your answer. This will help me a lot cause im noob at this part.
The thing with the Guild mark symbols is a good example for what i asked
-
Hey, i have a simple Question.
I bought game and db long time ago.
There were some Accounts/Players at the beginning i deleted manual (no code) only in player/player etc.
is there a way to check or clean stuff like this?
i mean how can i clean a db?
-
vor 1 Stunde schrieb CHMarvin:
Check def OnMouseLeftButtonUp and def __PutItem in game.py
Problem was in def __PutItem after added the auto refine
Fixed now!
Thanks let me know if you need something
-
Can someone maybe help me?
I can send all datas if needed
-
Hey, i cant trade with players if i take the item and drag it on player.
with the trade button i can trade with the player.
Maybe someone have an idea what i have to check for this...
https://metin2.download/picture/1i4qE2DNFJV0aPiWKbchIcWg4OczQSDT/.gif
no sysser information
-
sorry but still need help
-
Hey, im here
1- Cause i dont know/find where i can change the position of my closed Questscrolls
https://metin2.download/picture/r3F9504x09DVmF8K988YXgTtGTP6KMUj/.gif
for example i would like to have them on top middle...but i dont know the py data for it...
2-i have Gaya on my Serverfiles since beginning. Everything working...but my Client have a display bug
New Chars start with 999,999 Clientside shown but really they have ZERO ... I checked hole client for datas with"Gaya" "Gem" "999,999".. i think...
Would be nice if you can help me
Sash absorbing 100%
in Community Support - Questions & Answers
Posted
maybe here: if (ABSORB == GetAcceWindowType())
if (ABSORB == GetAcceWindowType())
{
if (m_pointsInstant.pAcceSlots[ACCE_SLOT_RIGHT] != WORD_MAX && m_pointsInstant.pAcceSlots[ACCE_SLOT_LEFT] != WORD_MAX)
{
LPITEM pkAcce = GetItem(TItemPos(INVENTORY, m_pointsInstant.pAcceSlots[ACCE_SLOT_LEFT]));
LPITEM pkWeaponToAbsorb = GetItem(TItemPos(INVENTORY, m_pointsInstant.pAcceSlots[ACCE_SLOT_RIGHT]));
LPITEM pShowItem = ITEM_MANAGER::instance().CreateItem(pkAcce->GetVnum(), 1, 0, false, -1, true);
pkWeaponToAbsorb->CopyAttributeTo(pShowItem);
pShowItem->SetSocket(0, pkAcce->GetSocket(0));
pShowItem->SetSocket(1, pkWeaponToAbsorb->GetVnum());
TPacketGCAcce pack;
pack.header = HEADER_GC_ACCE;
pack.subheader = ACCE_SUBHEADER_GC_SET_ITEM;
pack.size = sizeof(TPacketGCAcce) + sizeof(TPacketGCItemSet);
TPacketGCItemSet pack_sub;
pack_sub.header = 0;
pack_sub.Cell = TItemPos(ACCEREFINE, (WORD)ACCE_SLOT_RESULT);
pack_sub.vnum = pShowItem->GetVnum();
pack_sub.count = (BYTE)pShowItem->GetCount();
pack_sub.flags = pShowItem->GetFlag();
pack_sub.anti_flags = pShowItem->GetAntiFlag();
thecore_memcpy(pack_sub.alSockets, pShowItem->GetSockets(), sizeof(pack_sub.alSockets));
thecore_memcpy(pack_sub.aAttr, pShowItem->GetAttributes(), sizeof(pack_sub.aAttr));
GetDesc()->BufferedPacket(&pack, sizeof(TPacketGCAcce));
GetDesc()->Packet(&pack_sub, sizeof(TPacketGCItemSet));
M2_DESTROY_ITEM(pShowItem);
}
char_item.cpp