Guest User

Untitled

a guest
May 9th, 2025
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 56.74 KB | None | 0 0
  1. #include "stdafx.h"
  2. #include "utils.h"
  3. #include "config.h"
  4. #include "char.h"
  5. #include "desc.h"
  6. #include "sectree_manager.h"
  7. #include "packet.h"
  8. #include "protocol.h"
  9. #include "log.h"
  10. #include "skill.h"
  11. #include "unique_item.h"
  12. #include "profiler.h"
  13. #include "marriage.h"
  14. #include "item_addon.h"
  15. #include "locale_service.h"
  16. #include "item.h"
  17. #include "item_manager.h"
  18. #include "affect.h"
  19. #include "DragonSoul.h"
  20. #include "buff_on_attributes.h"
  21. #include "belt_inventory_helper.h"
  22. #include "../../common/VnumHelper.h"
  23. // #include "../../common/length.h"
  24. #include "../../common/CommonDefines.h"
  25. #include "../../common/service.h"
  26.  
  27. using namespace std;
  28. #include <iostream>
  29.  
  30. CItem::CItem(DWORD dwVnum)
  31.     : m_pProto(nullptr)  // Initialize in the same order as in item.h
  32.     , m_bIsDeleted(false) // dracaryS
  33.     , m_dwVnum(dwVnum)
  34. #if defined(__BL_TRANSMUTATION__)
  35.     , m_dwTransmutationVnum(0)
  36. #endif
  37.     , m_pOwner(nullptr)
  38.     , m_bWindow(0)
  39.     , m_dwID(0)
  40.     , m_bEquipped(false)
  41.     , m_dwVID(0)
  42.     , m_wCell(0)
  43.     , m_dwCount(0)
  44.     , m_lFlag(0)
  45.     , m_dwLastOwnerPID(0)
  46.     , m_bExchanging(false)
  47.     , m_pkDestroyEvent(nullptr)
  48.     , m_pkExpireEvent(nullptr)
  49.     , m_pkUniqueExpireEvent(nullptr)
  50.     , m_pkTimerBasedOnWearExpireEvent(nullptr)
  51.     , m_pkRealTimeExpireEvent(nullptr)
  52.     , m_pkAccessorySocketExpireEvent(nullptr)
  53.     , m_pkOwnershipEvent(nullptr)
  54.     , m_dwOwnershipPID(0)
  55.     , m_bSkipSave(false)
  56.     , m_isLocked(false)
  57.     , m_dwMaskVnum(0)
  58.     , m_dwSIGVnum(0)
  59. #if defined(__SOUL_SYSTEM__)
  60.     , m_pkSoulTimerUseEvent(nullptr)
  61. #endif
  62.     , m_bIsChangingAttr(false)
  63. {
  64.     memset(&m_alSockets, 0, sizeof(m_alSockets));
  65.     memset(&m_aAttr, 0, sizeof(m_aAttr));
  66. }
  67.  
  68. CItem::~CItem()
  69. {
  70.     Destroy();
  71.  
  72.     m_bIsDeleted = true; // dracaryS
  73.  
  74.     ITEM_MANAGER::instance().RemoveFromDelayedSave(this); // @fixme323
  75. }
  76.  
  77. void CItem::Initialize()
  78. {
  79.     CEntity::Initialize(ENTITY_ITEM);
  80.  
  81.     m_bIsDeleted = false; // dracaryS
  82.  
  83.     m_bWindow = RESERVED_WINDOW;
  84.     m_pOwner = NULL;
  85.     m_dwID = 0;
  86.     m_bEquipped = false;
  87.     m_dwVID = m_wCell = m_dwCount = m_lFlag = 0;
  88.     m_pProto = NULL;
  89.     m_bExchanging = false;
  90.     memset(&m_alSockets, 0, sizeof(m_alSockets));
  91.     memset(&m_aAttr, 0, sizeof(m_aAttr));
  92.  
  93.     m_pkDestroyEvent = NULL;
  94.     m_pkOwnershipEvent = NULL;
  95.     m_dwOwnershipPID = 0;
  96.     m_pkUniqueExpireEvent = NULL;
  97.     m_pkTimerBasedOnWearExpireEvent = NULL;
  98.     m_pkRealTimeExpireEvent = NULL;
  99.  
  100.     m_pkAccessorySocketExpireEvent = NULL;
  101. #if defined(__SOUL_SYSTEM__)
  102.     m_pkSoulTimerUseEvent = nullptr;
  103. #endif
  104.  
  105.     m_bSkipSave = false;
  106.     m_bIsChangingAttr = false;
  107.     m_dwLastOwnerPID = 0;
  108. }
  109.  
  110. void CItem::Destroy()
  111. {
  112.     event_cancel(&m_pkDestroyEvent);
  113.     event_cancel(&m_pkOwnershipEvent);
  114.     event_cancel(&m_pkUniqueExpireEvent);
  115.     event_cancel(&m_pkTimerBasedOnWearExpireEvent);
  116.     event_cancel(&m_pkRealTimeExpireEvent);
  117.     event_cancel(&m_pkAccessorySocketExpireEvent);
  118. #if defined(__SOUL_SYSTEM__)
  119.     event_cancel(&m_pkSoulTimerUseEvent);
  120. #endif
  121.  
  122.     CEntity::Destroy();
  123.  
  124.     if (GetSectree())
  125.         GetSectree()->RemoveEntity(this);
  126. }
  127.  
  128. EVENTFUNC(item_destroy_event)
  129. {
  130.     item_vid_event_info* info = dynamic_cast<item_vid_event_info*>( event->info );
  131.  
  132.     if ( info == NULL )
  133.     {
  134.         sys_err( "item_destroy_event> <Factor> Null pointer" );
  135.         return 0;
  136.     }
  137.  
  138.     const LPITEM pkItem = ITEM_MANAGER::instance().FindByVID(info->item_vid);
  139.     if (!pkItem)
  140.         return 0;
  141.  
  142.     if (pkItem->GetOwner())
  143.         sys_err("item_destroy_event: Owner exist. %s owner pid %d", pkItem->GetName(), pkItem->GetLastOwnerPID());
  144.  
  145.  
  146.     pkItem->SetDestroyEvent(NULL);
  147.     M2_DESTROY_ITEM(pkItem);
  148.     return 0;
  149. }
  150.  
  151. void CItem::SetDestroyEvent(LPEVENT pkEvent)
  152. {
  153.     m_pkDestroyEvent = pkEvent;
  154. }
  155.  
  156. void CItem::StartDestroyEvent(int iSec)
  157. {
  158.     if (m_pkDestroyEvent)
  159.         return;
  160.  
  161.     item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
  162.     info->item_vid = GetVID();
  163.  
  164.     SetDestroyEvent(event_create(item_destroy_event, info, PASSES_PER_SEC(iSec)));
  165. }
  166.  
  167. void CItem::EncodeInsertPacket(LPENTITY ent)
  168. {
  169.     LPDESC d;
  170.  
  171.     if (!(d = ent->GetDesc()))
  172.         return;
  173.  
  174.     const PIXEL_POSITION & c_pos = GetXYZ();
  175.  
  176.     struct packet_item_ground_add pack;
  177.  
  178.     pack.bHeader    = HEADER_GC_ITEM_GROUND_ADD;
  179.     pack.x      = c_pos.x;
  180.     pack.y      = c_pos.y;
  181.     pack.z      = c_pos.z;
  182.     pack.dwVnum     = GetVnum();
  183.     pack.dwVID      = m_dwVID;
  184.     //pack.count    = m_dwCount;
  185.  
  186.     for (int i = 0; i <ITEM_SOCKET_MAX_NUM; ++i)
  187.         pack.alSockets[i] = GetSocket(i);
  188.  
  189. #ifdef __ITEM_GROUND_ONLY_OWNER__
  190.     LPCHARACTER ch = d->GetCharacter();
  191.     if (!ch)
  192.         return;
  193.     else if (m_dwOwnershipPID != 0 && m_dwOwnershipPID != ch->GetPlayerID())
  194.         return;
  195. #endif
  196.  
  197.     d->Packet(&pack, sizeof(pack));
  198.  
  199.     if (m_pkOwnershipEvent != NULL)
  200.     {
  201.         item_event_info * info = dynamic_cast<item_event_info *>(m_pkOwnershipEvent->info);
  202.  
  203.         if ( info == NULL )
  204.         {
  205.             sys_err( "CItem::EncodeInsertPacket> <Factor> Null pointer" );
  206.             return;
  207.         }
  208.  
  209.         TPacketGCItemOwnership p;
  210.  
  211.         p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
  212.         p.dwVID = m_dwVID;
  213.         strlcpy(p.szName, info->szOwnerName, sizeof(p.szName));
  214.  
  215.         d->Packet(&p, sizeof(TPacketGCItemOwnership));
  216.     }
  217. }
  218.  
  219. void CItem::EncodeRemovePacket(LPENTITY ent)
  220. {
  221.     LPDESC d;
  222.  
  223.     if (!(d = ent->GetDesc()))
  224.         return;
  225.  
  226.     struct packet_item_ground_del pack;
  227.  
  228.     pack.bHeader    = HEADER_GC_ITEM_GROUND_DEL;
  229.     pack.dwVID      = m_dwVID;
  230.  
  231.     d->Packet(&pack, sizeof(pack));
  232.     sys_log(2, "Item::EncodeRemovePacket %s to %s", GetName(), ((LPCHARACTER) ent)->GetName());
  233. }
  234.  
  235. void CItem::SetProto(const TItemTable * table)
  236. {
  237.     assert(table != NULL);
  238.     m_pProto = table;
  239.     SetFlag(m_pProto->dwFlags);
  240. }
  241.  
  242. void CItem::UsePacketEncode(LPCHARACTER ch, LPCHARACTER victim, struct packet_item_use *packet)
  243. {
  244.     if (!GetVnum())
  245.         return;
  246.  
  247.     packet->header  = HEADER_GC_ITEM_USE;
  248.     packet->ch_vid  = ch->GetVID();
  249.     packet->victim_vid  = victim->GetVID();
  250.     packet->Cell = TItemPos(GetWindow(), m_wCell);
  251.     packet->vnum    = GetVnum();
  252. }
  253.  
  254. void CItem::RemoveFlag(long bit)
  255. {
  256.     REMOVE_BIT(m_lFlag, bit);
  257. }
  258.  
  259. void CItem::AddFlag(long bit)
  260. {
  261.     SET_BIT(m_lFlag, bit);
  262. }
  263.  
  264. void CItem::UpdatePacket()
  265. {
  266.     if (!m_pOwner || !m_pOwner->GetDesc())
  267.         return;
  268.  
  269.     if (IsChangingAttr())
  270.         return;
  271.  
  272.     TPacketGCItemUpdate pack;
  273.  
  274.     pack.header = HEADER_GC_ITEM_UPDATE;
  275.     pack.Cell = TItemPos(GetWindow(), m_wCell);
  276.     pack.count  = m_dwCount;
  277.  
  278.     for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
  279.         pack.alSockets[i] = m_alSockets[i];
  280.  
  281.     thecore_memcpy(pack.aAttr, GetAttributes(), sizeof(pack.aAttr));
  282. #if defined(__BL_TRANSMUTATION__)
  283.     pack.dwTransmutationVnum = GetTransmutationVnum();
  284. #endif
  285.  
  286.     sys_log(2, "UpdatePacket %s -> %s", GetName(), m_pOwner->GetName());
  287.     m_pOwner->GetDesc()->Packet(&pack, sizeof(pack));
  288. }
  289.  
  290. DWORD CItem::GetCount()
  291. {
  292. #ifdef ENABLE_CHEQUE_SYSTEM
  293.     if (GetType() == ITEM_ELK || GetType() == ITEM_CHEQUE) return MIN(m_dwCount, INT_MAX);
  294. #else
  295.     if (GetType() == ITEM_ELK) return MIN(m_dwCount, INT_MAX);
  296. #endif
  297.     else
  298.     {
  299.         return MIN(m_dwCount, g_bItemCountLimit);
  300.     }
  301. }
  302.  
  303. bool CItem::SetCount(DWORD count)
  304. {
  305. #ifdef ENABLE_CHEQUE_SYSTEM
  306.     if (GetType() == ITEM_ELK || GetType() == ITEM_CHEQUE)
  307. #else
  308.     if (GetType() == ITEM_ELK)
  309. #endif
  310.     {
  311.         m_dwCount = MIN(count, INT_MAX);
  312.     }
  313.     else
  314.     {
  315.         m_dwCount = MIN(count, g_bItemCountLimit);
  316.     }
  317.  
  318.     if (count == 0 && m_pOwner)
  319.     {
  320.         if (GetSubType() == USE_ABILITY_UP || GetSubType() == USE_POTION || GetVnum() == 70020)
  321.         {
  322.             LPCHARACTER pOwner = GetOwner();
  323.             WORD wCell = GetCell();
  324.  
  325.             RemoveFromCharacter();
  326.  
  327.             if (!IsDragonSoul())
  328.             {
  329.                 LPITEM pItem = pOwner->FindSpecifyItem(GetVnum());
  330.  
  331.                 if (NULL != pItem)
  332.                 {
  333.                     pOwner->ChainQuickslotItem(pItem, QUICKSLOT_TYPE_ITEM, wCell);
  334.                 }
  335.                 else
  336.                 {
  337.                     pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, wCell, 255);
  338.                 }
  339.             }
  340.  
  341.             M2_DESTROY_ITEM(this);
  342.         }
  343.         else
  344.         {
  345.             if (!IsDragonSoul())
  346.             {
  347.                 m_pOwner->SyncQuickslot(QUICKSLOT_TYPE_ITEM, m_wCell, 255);
  348.             }
  349.             M2_DESTROY_ITEM(RemoveFromCharacter());
  350.         }
  351.  
  352.         return false;
  353.     }
  354.     else if (count == 0 && !m_pOwner) // @fixme345 (experimental full flush)
  355.         ITEM_MANAGER::instance().SaveSingleItem(this);
  356.  
  357.     UpdatePacket();
  358.  
  359.     Save();
  360.     return true;
  361. }
  362.  
  363. LPITEM CItem::RemoveFromCharacter()
  364. {
  365.     if (!m_pOwner)
  366.     {
  367.         sys_err("Item::RemoveFromCharacter owner null");
  368.         return (this);
  369.     }
  370.  
  371.     LPCHARACTER pOwner = m_pOwner;
  372.  
  373.     if (m_bEquipped)   
  374.     {
  375.         Unequip();
  376.  
  377.         SetWindow(RESERVED_WINDOW);
  378.         Save();
  379.         return (this);
  380.     }
  381.     else
  382.     {
  383.         if (GetWindow() != SAFEBOX && GetWindow() != MALL)
  384.         {
  385.             if (IsDragonSoul())
  386.             {
  387.                 if (m_wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
  388.                     sys_err("CItem::RemoveFromCharacter: pos >= DRAGON_SOUL_INVENTORY_MAX_NUM");
  389.                 else
  390.                     pOwner->SetItem(TItemPos(m_bWindow, m_wCell), NULL);
  391.             }
  392. #ifdef ENABLE_SWITCHBOT_WORLDARD
  393.             else if (GetWindow() == SWITCHBOT)
  394.             {
  395.                 if (m_wCell >= SWITCHBOT_SLOT_MAX)
  396.                     sys_err("CItem::RemoveFromCharacter: pos >= SWITCHBOT_SLOT_MAX");
  397.                 else
  398.                     pOwner->SetItem(TItemPos(m_bWindow, m_wCell), NULL);
  399.             }
  400. #endif
  401.             else
  402.             {
  403.                 TItemPos cell(INVENTORY, m_wCell);
  404.  
  405.                 if (false == cell.IsDefaultInventoryPosition() && false == cell.IsBeltInventoryPosition())
  406.                     sys_err("CItem::RemoveFromCharacter: Invalid Item Position");
  407.                 else
  408.                 {
  409.                     pOwner->SetItem(cell, NULL);
  410.                 }
  411.             }
  412.         }
  413.  
  414.         m_pOwner = NULL;
  415.         m_wCell = 0;
  416.  
  417.         SetWindow(RESERVED_WINDOW);
  418.         Save();
  419.         return (this);
  420.     }
  421. }
  422.  
  423. #if defined(__BL_ENABLE_PICKUP_ITEM_EFFECT__)
  424. bool CItem::AddToCharacter(LPCHARACTER ch, TItemPos Cell, bool bHighlight)
  425. #else
  426. bool CItem::AddToCharacter(LPCHARACTER ch, TItemPos Cell)
  427. #endif
  428. {
  429.     assert(GetSectree() == NULL);
  430.     assert(m_pOwner == NULL);
  431.  
  432.     WORD pos = Cell.cell;
  433.     BYTE window_type = Cell.window_type;
  434.  
  435.     if (INVENTORY == window_type)
  436.     {
  437.         if (m_wCell >= INVENTORY_MAX_NUM && BELT_INVENTORY_SLOT_START > m_wCell)
  438.         {
  439.             sys_err("CItem::AddToCharacter: cell overflow: %s to %s cell %d", m_pProto->szName, ch->GetName(), m_wCell);
  440.             return false;
  441.         }
  442.     }
  443.     else if (DRAGON_SOUL_INVENTORY == window_type)
  444.     {
  445.         if (m_wCell >= DRAGON_SOUL_INVENTORY_MAX_NUM)
  446.         {
  447.             sys_err("CItem::AddToCharacter: cell overflow: %s to %s cell %d", m_pProto->szName, ch->GetName(), m_wCell);
  448.             return false;
  449.         }
  450.     }
  451. #ifdef ENABLE_SWITCHBOT_WORLDARD
  452.     else if (SWITCHBOT == window_type)
  453.     {
  454.         if (m_wCell >= SWITCHBOT_SLOT_MAX){
  455.             sys_err("CItem::AddToCharacter: cell overflow: %s to %s cell %d", m_pProto->szName, ch->GetName(), m_wCell);
  456.             return false;
  457.         }
  458.     }
  459. #endif
  460.  
  461. #ifdef __BL_ENABLE_PICKUP_ITEM_EFFECT__
  462.     if (bHighlight)
  463.         bHighlight = this->GetLastOwnerPID() != ch->GetPlayerID();
  464. #endif
  465.  
  466.     if (ch->GetDesc())
  467.         m_dwLastOwnerPID = ch->GetPlayerID();
  468.  
  469. #ifdef ENABLE_ACCE_SYSTEM
  470.     if ((GetType() == ITEM_COSTUME) && (GetSubType() == COSTUME_ACCE) && (GetSocket(ACCE_ABSORPTION_SOCKET) == 0))
  471.     {
  472.         long lVal = GetValue(ACCE_GRADE_VALUE_FIELD);
  473.         switch (lVal)
  474.         {
  475.         case 2:
  476.             lVal = ACCE_GRADE_2_ABS;
  477.             break;
  478.         case 3:
  479.             lVal = ACCE_GRADE_3_ABS;
  480.             break;
  481.         case 4:
  482.             lVal = number(ACCE_GRADE_4_ABS_MIN, ACCE_GRADE_4_ABS_MAX_COMB);
  483.             break;
  484.         default:
  485.             lVal = ACCE_GRADE_1_ABS;
  486.             break;
  487.         }
  488.         SetSocket(ACCE_ABSORPTION_SOCKET, lVal);
  489.     }
  490. #endif
  491.     event_cancel(&m_pkDestroyEvent);
  492.  
  493. #if defined(__BL_ENABLE_PICKUP_ITEM_EFFECT__)
  494.     ch->SetItem(TItemPos(window_type, pos), this, bHighlight);
  495. #else
  496.     ch->SetItem(TItemPos(window_type, pos), this);
  497. #endif
  498.     m_pOwner = ch;
  499.  
  500.     Save();
  501.     return true;
  502. }
  503.  
  504. LPITEM CItem::RemoveFromGround()
  505. {
  506.     if (GetSectree())
  507.     {
  508.         SetOwnership(NULL);
  509.  
  510.         GetSectree()->RemoveEntity(this);
  511.  
  512.         ViewCleanup();
  513.  
  514.         Save();
  515.     }
  516.  
  517.     return (this);
  518. }
  519.  
  520. bool CItem::AddToGround(long lMapIndex, const PIXEL_POSITION & pos, bool skipOwnerCheck)
  521. {
  522.     if (0 == lMapIndex)
  523.     {
  524.         sys_err("wrong map index argument: %d", lMapIndex);
  525.         return false;
  526.     }
  527.  
  528.     if (GetSectree())
  529.     {
  530.         sys_err("sectree already assigned");
  531.         return false;
  532.     }
  533.  
  534.     if (!skipOwnerCheck && m_pOwner)
  535.     {
  536.         sys_err("owner pointer not null");
  537.         return false;
  538.     }
  539.  
  540.     LPSECTREE tree = SECTREE_MANAGER::instance().Get(lMapIndex, pos.x, pos.y);
  541.  
  542.     if (!tree)
  543.     {
  544.         sys_err("cannot find sectree by %dx%d", pos.x, pos.y);
  545.         return false;
  546.     }
  547.  
  548.     SetWindow(GROUND);
  549.     SetXYZ(pos.x, pos.y, pos.z);
  550.     tree->InsertEntity(this);
  551.     UpdateSectree();
  552.     Save();
  553.     return true;
  554. }
  555.  
  556. bool CItem::DistanceValid(LPCHARACTER ch)
  557. {
  558.     if (!GetSectree())
  559.         return false;
  560.  
  561.     int iDist = DISTANCE_APPROX(GetX() - ch->GetX(), GetY() - ch->GetY());
  562.  
  563.     if (iDist > 300)
  564.         return false;
  565.  
  566.     return true;
  567. }
  568.  
  569. bool CItem::CanUsedBy(LPCHARACTER ch)
  570. {
  571.     // Anti flag check
  572.     switch (ch->GetJob())
  573.     {
  574.         case JOB_WARRIOR:
  575.             if (GetAntiFlag() & ITEM_ANTIFLAG_WARRIOR)
  576.                 return false;
  577.             break;
  578.  
  579.         case JOB_ASSASSIN:
  580.             if (GetAntiFlag() & ITEM_ANTIFLAG_ASSASSIN)
  581.                 return false;
  582.             break;
  583.  
  584.         case JOB_SHAMAN:
  585.             if (GetAntiFlag() & ITEM_ANTIFLAG_SHAMAN)
  586.                 return false;
  587.             break;
  588.  
  589.         case JOB_SURA:
  590.             if (GetAntiFlag() & ITEM_ANTIFLAG_SURA)
  591.                 return false;
  592.             break;
  593. #ifdef ENABLE_WOLFMAN_CHARACTER
  594.         case JOB_WOLFMAN:
  595.             if (GetAntiFlag() & ITEM_ANTIFLAG_WOLFMAN)
  596.                 return false;
  597.             break;
  598. #endif
  599.     }
  600.  
  601.     return true;
  602. }
  603.  
  604. int CItem::FindEquipCell(LPCHARACTER ch, int iCandidateCell)
  605. {
  606. #ifdef __PET_SYSTEM__
  607.     if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType() && ITEM_NORMAL_PET != GetType())
  608. #else
  609.     if ((0 == GetWearFlag() || ITEM_TOTEM == GetType()) && ITEM_COSTUME != GetType() && ITEM_DS != GetType() && ITEM_SPECIAL_DS != GetType() && ITEM_RING != GetType() && ITEM_BELT != GetType())
  610. #endif
  611.         return -1;
  612.  
  613.     if (GetType() == ITEM_DS || GetType() == ITEM_SPECIAL_DS)
  614.     {
  615.         if (iCandidateCell < 0)
  616.         {
  617.             return WEAR_MAX_NUM + GetSubType();
  618.         }
  619.         else
  620.         {
  621.             for (int i = 0; i < DRAGON_SOUL_DECK_MAX_NUM; i++)
  622.             {
  623.                 if (WEAR_MAX_NUM + i * DS_SLOT_MAX + GetSubType() == iCandidateCell)
  624.                 {
  625.                     return iCandidateCell;
  626.                 }
  627.             }
  628.             return -1;
  629.         }
  630.     }
  631.     else if (GetType() == ITEM_COSTUME)
  632.     {
  633.         if (GetSubType() == COSTUME_BODY)
  634.             return WEAR_COSTUME_BODY;
  635.         else if (GetSubType() == COSTUME_HAIR)
  636.             return WEAR_COSTUME_HAIR;
  637. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  638.         else if (GetSubType() == COSTUME_MOUNT)
  639.             return WEAR_COSTUME_MOUNT;
  640. #endif
  641. #ifdef ENABLE_ACCE_SYSTEM
  642.         else if (GetSubType() == COSTUME_ACCE)
  643.             return WEAR_COSTUME_ACCE;
  644. #endif
  645. #ifdef ENABLE_WEAPON_COSTUME_SYSTEM
  646.         else if (GetSubType() == COSTUME_WEAPON)
  647.             return WEAR_COSTUME_WEAPON;
  648. #endif
  649.     }
  650. #if !defined(ENABLE_MOUNT_COSTUME_SYSTEM) && !defined(ENABLE_ACCE_SYSTEM)
  651.     else if (GetType() == ITEM_RING)
  652.     {
  653.         if (ch->GetWear(WEAR_RING1))
  654.             return WEAR_RING2;
  655.         else
  656.             return WEAR_RING1;
  657.     }
  658. #endif
  659.     else if (GetType() == ITEM_BELT)
  660.         return WEAR_BELT;
  661. // #ifdef __PET_SYSTEM__
  662.     // else if (GetType() == ITEM_NORMAL_PET)
  663.         // return WEAR_NORMAL_PET;
  664. // #endif
  665.     else if (GetWearFlag() & WEARABLE_BODY)
  666.         return WEAR_BODY;
  667.     else if (GetWearFlag() & WEARABLE_HEAD)
  668.         return WEAR_HEAD;
  669.     else if (GetWearFlag() & WEARABLE_FOOTS)
  670.         return WEAR_FOOTS;
  671.     else if (GetWearFlag() & WEARABLE_WRIST)
  672.         return WEAR_WRIST;
  673.     else if (GetWearFlag() & WEARABLE_WEAPON)
  674.         return WEAR_WEAPON;
  675.     else if (GetWearFlag() & WEARABLE_SHIELD)
  676.         return WEAR_SHIELD;
  677.     else if (GetWearFlag() & WEARABLE_NECK)
  678.         return WEAR_NECK;
  679.     else if (GetWearFlag() & WEARABLE_EAR)
  680.         return WEAR_EAR;
  681.     else if (GetWearFlag() & WEARABLE_ARROW)
  682.         return WEAR_ARROW;
  683.     else if (GetWearFlag() & WEARABLE_UNIQUE)
  684.     {
  685.         if (ch->GetWear(WEAR_UNIQUE1))
  686.             return WEAR_UNIQUE2;
  687.         else
  688.             return WEAR_UNIQUE1;
  689.     }
  690.  
  691.    
  692.     else if (GetWearFlag() & WEARABLE_ABILITY)
  693.     {
  694.         if (!ch->GetWear(WEAR_ABILITY1))
  695.         {
  696.             return WEAR_ABILITY1;
  697.         }
  698.         else if (!ch->GetWear(WEAR_ABILITY2))
  699.         {
  700.             return WEAR_ABILITY2;
  701.         }
  702.         else if (!ch->GetWear(WEAR_ABILITY3))
  703.         {
  704.             return WEAR_ABILITY3;
  705.         }
  706.         else if (!ch->GetWear(WEAR_ABILITY4))
  707.         {
  708.             return WEAR_ABILITY4;
  709.         }
  710.         else if (!ch->GetWear(WEAR_ABILITY5))
  711.         {
  712.             return WEAR_ABILITY5;
  713.         }
  714.         else if (!ch->GetWear(WEAR_ABILITY6))
  715.         {
  716.             return WEAR_ABILITY6;
  717.         }
  718.         else if (!ch->GetWear(WEAR_ABILITY7))
  719.         {
  720.             return WEAR_ABILITY7;
  721.         }
  722.         else if (!ch->GetWear(WEAR_ABILITY8))
  723.         {
  724.             return WEAR_ABILITY8;
  725.         }
  726.         else
  727.         {
  728.             return -1;
  729.         }
  730.     }
  731.     return -1;
  732. }
  733.  
  734. void CItem::ModifyPoints(bool bAdd)
  735. {
  736.     int accessoryGrade;
  737.  
  738.     if (false == IsAccessoryForSocket())
  739.     {
  740.         if (m_pProto->bType == ITEM_WEAPON || m_pProto->bType == ITEM_ARMOR)
  741.         {
  742.             for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
  743.             {
  744.                 DWORD dwVnum;
  745.  
  746.                 if ((dwVnum = GetSocket(i)) <= 2)
  747.                     continue;
  748.  
  749.                 TItemTable * p = ITEM_MANAGER::instance().GetTable(dwVnum);
  750.  
  751.                 if (!p)
  752.                 {
  753.                     sys_err("cannot find table by vnum %u", dwVnum);
  754.                     continue;
  755.                 }
  756.  
  757.                 if (ITEM_METIN == p->bType)
  758.                 {
  759.                     //m_pOwner->ApplyPoint(p->alValues[0], bAdd ? p->alValues[1] : -p->alValues[1]);
  760.                     for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
  761.                     {
  762.                         if (p->aApplies[i].bType == APPLY_NONE)
  763.                             continue;
  764.  
  765.                         if (p->aApplies[i].bType == APPLY_SKILL)
  766.                             m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : p->aApplies[i].lValue ^ 0x00800000);
  767.                         else
  768.                             m_pOwner->ApplyPoint(p->aApplies[i].bType, bAdd ? p->aApplies[i].lValue : -p->aApplies[i].lValue);
  769.                     }
  770.                 }
  771.             }
  772.         }
  773.  
  774.         accessoryGrade = 0;
  775.     }
  776.     else
  777.     {
  778.         accessoryGrade = MIN(GetAccessorySocketGrade(), ITEM_ACCESSORY_SOCKET_MAX_NUM);
  779.     }
  780.  
  781. #ifdef ENABLE_ACCE_SYSTEM
  782.     if ((GetType() == ITEM_COSTUME) && (GetSubType() == COSTUME_ACCE) && (GetSocket(ACCE_ABSORBED_SOCKET)))
  783.     {
  784.         TItemTable * pkItemAbsorbed = ITEM_MANAGER::instance().GetTable(GetSocket(ACCE_ABSORBED_SOCKET));
  785.         if (pkItemAbsorbed)
  786.         {
  787.             if ((pkItemAbsorbed->bType == ITEM_ARMOR) && (pkItemAbsorbed->bSubType == ARMOR_BODY))
  788.             {
  789.                 // basic defense value from armor
  790.                 auto lDefGrade = CalcAcceBonus(pkItemAbsorbed->alValues[1] + (pkItemAbsorbed->alValues[5] * 2));
  791.                 m_pOwner->ApplyPoint(APPLY_DEF_GRADE_BONUS, bAdd ? lDefGrade : -lDefGrade);
  792.                 // basic magic defense value from armor
  793.                 auto lDefMagicBonus = CalcAcceBonus(pkItemAbsorbed->alValues[0]);
  794.                 m_pOwner->ApplyPoint(APPLY_MAGIC_DEF_GRADE, bAdd ? lDefMagicBonus : -lDefMagicBonus);
  795.             }
  796.             else if (pkItemAbsorbed->bType == ITEM_WEAPON)
  797.             {
  798.                 // basic attack value from weapon
  799.                 if (pkItemAbsorbed->alValues[3] + pkItemAbsorbed->alValues[4] > 0)
  800.                 {
  801.                     auto lAttGrade = CalcAcceBonus(pkItemAbsorbed->alValues[4] + pkItemAbsorbed->alValues[5]);
  802.                     if (pkItemAbsorbed->alValues[3] > pkItemAbsorbed->alValues[4])
  803.                         lAttGrade = CalcAcceBonus(pkItemAbsorbed->alValues[3] + pkItemAbsorbed->alValues[5]);
  804.                     m_pOwner->ApplyPoint(APPLY_ATT_GRADE_BONUS, bAdd ? lAttGrade : -lAttGrade);
  805.                 }
  806.                 // basic magic attack value from weapon
  807.                 if (pkItemAbsorbed->alValues[1] + pkItemAbsorbed->alValues[2] > 0)
  808.                 {
  809.                     long lAttMagicGrade = CalcAcceBonus(pkItemAbsorbed->alValues[2] + pkItemAbsorbed->alValues[5]);
  810.                     if (pkItemAbsorbed->alValues[1] > pkItemAbsorbed->alValues[2])
  811.                         lAttMagicGrade = CalcAcceBonus(pkItemAbsorbed->alValues[1] + pkItemAbsorbed->alValues[5]);
  812.                     m_pOwner->ApplyPoint(APPLY_MAGIC_ATT_GRADE, bAdd ? lAttMagicGrade : -lAttMagicGrade);
  813.                 }
  814.             }
  815.         }
  816.     }
  817. #endif
  818.  
  819.     for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
  820.     {
  821.         const auto& apply = m_pProto->aApplies[i];
  822.  
  823. // #ifdef __PET_SYSTEM__
  824.         // if(IsPetItem())
  825.             // continue;
  826. // #endif
  827.  
  828.         if (apply.bType == APPLY_NONE)
  829.             continue;
  830.  
  831.     #ifdef ENABLE_MOUNT_LIKE_HORSE
  832.         if (IsMount())
  833.             continue;
  834.     #endif
  835.  
  836.         long value = apply.lValue;
  837.  
  838.         if (apply.bType == APPLY_SKILL)
  839.         {
  840.             m_pOwner->ApplyPoint(apply.bType, bAdd ? value : value ^ 0x00800000);
  841.         }
  842.         else
  843.         {
  844.             if (accessoryGrade > 0)
  845.             {
  846.                 long totalBonus = 0;
  847.                 for (int j = 0; j < accessoryGrade; ++j)
  848.                 {
  849.                     totalBonus += MAX(1, apply.lValue * aiAccessorySocketEffectivePct[j + 1] / 100);
  850.                 }
  851.                 value += totalBonus;
  852.             }
  853.  
  854.             m_pOwner->ApplyPoint(apply.bType, bAdd ? value : -value);
  855.         }
  856.     }
  857.  
  858. #ifdef ENABLE_ACCE_COSTUME_SYSTEM
  859.     if (GetType() == ITEM_COSTUME && GetSubType() == COSTUME_ACCE)
  860.     {
  861.         TItemTable * pkItemAbsorbed = ITEM_MANAGER::instance().GetTable(GetSocket(ACCE_ABSORBED_SOCKET));
  862.         if (pkItemAbsorbed)
  863.         {
  864.             for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
  865.             {
  866.                 if (pkItemAbsorbed->aApplies[i].bType == APPLY_NONE)
  867.                     continue;
  868.                 int value = CalcAcceBonus(pkItemAbsorbed->aApplies[i].lValue);
  869.                 if (pkItemAbsorbed->aApplies[i].bType == APPLY_SKILL)
  870.                     m_pOwner->ApplyPoint(pkItemAbsorbed->aApplies[i].bType, bAdd ? value : value ^ 0x00800000);
  871.                 else
  872.                 {
  873.                     if (0 != accessoryGrade && i < ITEM_APPLY_MAX_NUM - 1) // @fixme170
  874.                         value += MAX(accessoryGrade, value * aiAccessorySocketEffectivePct[accessoryGrade] / 100);
  875.                     m_pOwner->ApplyPoint(pkItemAbsorbed->aApplies[i].bType, bAdd ? value : -value);
  876.                 }
  877.             }
  878.         }
  879.     }
  880. #endif
  881.  
  882.     if (true == CItemVnumHelper::IsRamadanMoonRing(GetVnum()) || true == CItemVnumHelper::IsHalloweenCandy(GetVnum())
  883.         || true == CItemVnumHelper::IsHappinessRing(GetVnum()) || true == CItemVnumHelper::IsLovePendant(GetVnum()))
  884.     {
  885.         // Do not anything.
  886.     }
  887.     else
  888.     {
  889.         for (int i = 0; i < ITEM_ATTRIBUTE_MAX_NUM; ++i)
  890.         {
  891.             if (GetAttributeType(i))
  892.             {
  893.                 const TPlayerItemAttribute &ia = GetAttribute(i);
  894.                 auto value = ia.sValue;
  895. #ifdef ENABLE_ACCE_SYSTEM
  896.                 if (GetType() == ITEM_COSTUME && GetSubType() == COSTUME_ACCE)
  897.                     value = CalcAcceBonus(value);
  898. #endif
  899.                 if (ia.bType == APPLY_SKILL)
  900.                     m_pOwner->ApplyPoint(ia.bType, bAdd ? value : value ^ 0x00800000);
  901.                 else
  902.                     m_pOwner->ApplyPoint(ia.bType, bAdd ? value : -value);
  903.             }
  904.         }
  905.     }
  906.  
  907.     switch (m_pProto->bType)
  908.     {
  909.         case ITEM_PICK:
  910.         case ITEM_ROD:
  911.             {
  912.                 if (bAdd)
  913.                 {
  914.                     if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
  915.                         m_pOwner->SetPart(PART_WEAPON, GetVnum());
  916.                 }
  917.                 else
  918.                 {
  919.                     if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
  920.                         m_pOwner->SetPart(PART_WEAPON, 0);
  921.                 }
  922.             }
  923.             break;
  924.            
  925.         case ITEM_WEAPON:
  926.             {
  927. #ifdef ENABLE_WEAPON_COSTUME_SYSTEM
  928.                 if (m_pOwner->GetWear(WEAR_COSTUME_WEAPON) != 0)
  929.                     break;
  930. #endif
  931.                 if (bAdd)
  932.                 {
  933. #if defined(__BL_TRANSMUTATION__)
  934.                     if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
  935.                     {
  936.                         const WORD wVnum = static_cast<WORD>(GetVnum());
  937.                         // m_pOwner->ChatPacket(CHAT_TYPE_INFO, "wVnum %d .", wVnum);
  938.                         const WORD wTransmutationVnum = static_cast<WORD>(GetTransmutationVnum());
  939.                         // m_pOwner->ChatPacket(CHAT_TYPE_INFO, "wTransmutationVnum %d .", wTransmutationVnum);
  940.                         m_pOwner->SetPart(PART_WEAPON, wTransmutationVnum != 0 ? wTransmutationVnum : wVnum);
  941.                         // m_pOwner->ChatPacket(CHAT_TYPE_INFO, "ternary %d .", wTransmutationVnum != 0 ? wTransmutationVnum : wVnum);
  942.                     }
  943. #else
  944.                     if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
  945.                         m_pOwner->SetPart(PART_WEAPON, static_cast<WORD>(GetVnum()));
  946. #endif
  947.                 }
  948.                 else
  949.                 {
  950.                     if (m_wCell == INVENTORY_MAX_NUM + WEAR_WEAPON)
  951. #ifdef ENABLE_WEAPON_COSTUME_SYSTEM
  952.                         m_pOwner->SetPart(PART_WEAPON, 0);
  953. #else
  954.                         m_pOwner->SetPart(PART_WEAPON, m_pOwner->GetOriginalPart(PART_WEAPON));
  955. #endif
  956.                 }
  957.             }
  958.             break;
  959.  
  960.         case ITEM_ARMOR:
  961.             {
  962.                 if (0 != m_pOwner->GetWear(WEAR_COSTUME_BODY))
  963.                     break;
  964.  
  965.                 if (GetSubType() == ARMOR_BODY || GetSubType() == ARMOR_HEAD || GetSubType() == ARMOR_FOOTS || GetSubType() == ARMOR_SHIELD)
  966.                 {
  967.                     if (bAdd)
  968.                     {
  969. #if defined(__BL_TRANSMUTATION__)
  970.                         if (GetProto()->bSubType == ARMOR_BODY)
  971.                         {
  972.                             const WORD wVnum = static_cast<WORD>(GetVnum());
  973.                             const WORD wTransmutationVnum = static_cast<WORD>(GetTransmutationVnum());
  974.                             m_pOwner->SetPart(PART_MAIN, wTransmutationVnum != 0 ? wTransmutationVnum : wVnum);
  975.                         }
  976. #else
  977.                         if (GetProto()->bSubType == ARMOR_BODY)
  978.                             m_pOwner->SetPart(PART_MAIN, static_cast<WORD>(GetVnum()));
  979. #endif
  980.                     }
  981.                     else
  982.                     {
  983.                         if (GetProto()->bSubType == ARMOR_BODY)
  984.                             m_pOwner->SetPart(PART_MAIN, m_pOwner->GetOriginalPart(PART_MAIN));
  985.                     }
  986.                 }
  987.             }
  988.             break;
  989.        
  990.         case ITEM_COSTUME:
  991.             {
  992.                 DWORD toSetValue = this->GetVnum();
  993.                 EParts toSetPart = PART_MAX_NUM;
  994.                
  995.                 if (GetSubType() == COSTUME_BODY)
  996.                 {
  997.                     toSetPart = PART_MAIN;
  998.                     if (false == bAdd)
  999.                     {
  1000.                         const CItem* pArmor = m_pOwner->GetWear(WEAR_BODY);
  1001. #if defined(__BL_TRANSMUTATION__)
  1002.                         if (pArmor != NULL)
  1003.                         {
  1004.                             const DWORD dwVnum = pArmor->GetVnum();
  1005.                             const DWORD dwTransmutationVnum = pArmor->GetTransmutationVnum();
  1006.                             toSetValue = dwTransmutationVnum != 0 ? dwTransmutationVnum : dwVnum;
  1007.                         }
  1008.                         else
  1009.                         {
  1010.                             toSetValue = m_pOwner->GetOriginalPart(PART_MAIN);
  1011.                         }
  1012. #else
  1013.                         toSetValue = (NULL != pArmor) ? pArmor->GetVnum() : m_pOwner->GetOriginalPart(PART_MAIN);
  1014. #endif
  1015.                     }
  1016.                 }
  1017.  
  1018.                 else if (GetSubType() == COSTUME_HAIR)
  1019.                 {
  1020.                     toSetPart = PART_HAIR;
  1021.                     toSetValue = (true == bAdd) ? this->GetValue(3) : 0;
  1022.                 }
  1023.  
  1024. #ifdef ENABLE_ACCE_SYSTEM
  1025.                 else if (GetSubType() == COSTUME_ACCE)
  1026.                 {
  1027.                     toSetValue -= 85000;
  1028.                     // if (GetSocket(ACCE_ABSORPTION_SOCKET) >= ACCE_EFFECT_FROM_ABS)
  1029.                         // toSetValue += 2000;
  1030.  
  1031.                     toSetValue = (bAdd == true) ? toSetValue : 0;
  1032.                     toSetPart = PART_ACCE;
  1033.                 }
  1034. #endif
  1035.  
  1036. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  1037.                 else if (GetSubType() == COSTUME_MOUNT)
  1038.                 {
  1039.                     // not need to do a thing in here
  1040.                 }
  1041. #endif
  1042.  
  1043. #ifdef ENABLE_WEAPON_COSTUME_SYSTEM
  1044.                 else if (GetSubType() == COSTUME_WEAPON)
  1045.                 {
  1046.                     toSetPart = PART_WEAPON;
  1047.                     if (false == bAdd)
  1048.                     {
  1049.                         const CItem* pWeapon = m_pOwner->GetWear(WEAR_WEAPON);
  1050.                         toSetValue = (NULL != pWeapon) ? pWeapon->GetVnum() : m_pOwner->GetOriginalPart(PART_WEAPON);
  1051.                     }
  1052.                 }
  1053. #endif
  1054.  
  1055.                 if (PART_MAX_NUM != toSetPart)
  1056.                 {
  1057.                     m_pOwner->SetPart((BYTE)toSetPart, toSetValue);
  1058.                     m_pOwner->UpdatePacket();
  1059.                 }
  1060.             }
  1061.             break;
  1062.  
  1063.         case ITEM_UNIQUE:
  1064.             {
  1065.                 if (0 != GetSIGVnum())
  1066.                 {
  1067.                     const CSpecialItemGroup* pItemGroup = ITEM_MANAGER::instance().GetSpecialItemGroup(GetSIGVnum());
  1068.                     if (NULL == pItemGroup)
  1069.                         break;
  1070.                     DWORD dwAttrVnum = pItemGroup->GetAttrVnum(GetVnum());
  1071.                     const CSpecialAttrGroup* pAttrGroup = ITEM_MANAGER::instance().GetSpecialAttrGroup(dwAttrVnum);
  1072.                     if (NULL == pAttrGroup)
  1073.                         break;
  1074.                     for (itertype (pAttrGroup->m_vecAttrs) it = pAttrGroup->m_vecAttrs.begin(); it != pAttrGroup->m_vecAttrs.end(); it++)
  1075.                     {
  1076.                         m_pOwner->ApplyPoint(it->apply_type, bAdd ? it->apply_value : -it->apply_value);
  1077.                     }
  1078.                 }
  1079.             }
  1080.             break;
  1081.     }
  1082. }
  1083.  
  1084. bool CItem::IsEquipable() const
  1085. {
  1086.     switch (this->GetType())
  1087.     {
  1088.     case ITEM_COSTUME:
  1089.     case ITEM_ARMOR:
  1090.     case ITEM_WEAPON:
  1091.     case ITEM_ROD:
  1092.     case ITEM_PICK:
  1093.     case ITEM_UNIQUE:
  1094.     case ITEM_DS:
  1095.     case ITEM_SPECIAL_DS:
  1096.     case ITEM_RING:
  1097.     case ITEM_BELT:
  1098. // #ifdef __PET_SYSTEM__
  1099.     // case ITEM_NORMAL_PET:
  1100. // #endif
  1101.         return true;
  1102.     }
  1103.  
  1104.     return false;
  1105. }
  1106.  
  1107. #define ENABLE_IMMUNE_FIX
  1108. // return false on error state
  1109. bool CItem::EquipTo(LPCHARACTER ch, BYTE bWearCell)
  1110. {
  1111.     if (!ch)
  1112.     {
  1113.         sys_err("EquipTo: nil character");
  1114.         return false;
  1115.     }
  1116.  
  1117.    
  1118.     if (IsDragonSoul())
  1119.     {
  1120.         if (bWearCell < WEAR_MAX_NUM || bWearCell >= WEAR_MAX_NUM + DRAGON_SOUL_DECK_MAX_NUM * DS_SLOT_MAX)
  1121.         {
  1122.             sys_err("EquipTo: invalid dragon soul cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetSubType(), bWearCell - WEAR_MAX_NUM);
  1123.             return false;
  1124.         }
  1125.     }
  1126.     else
  1127.     {
  1128.         if (bWearCell >= WEAR_MAX_NUM)
  1129.         {
  1130.             sys_err("EquipTo: invalid wear cell (this: #%d %s wearflag: %d cell: %d)", GetOriginalVnum(), GetName(), GetWearFlag(), bWearCell);
  1131.             return false;
  1132.         }
  1133.     }
  1134.  
  1135.     if (ch->GetWear(bWearCell))
  1136.     {
  1137.         sys_err("EquipTo: item already exist (this: #%d %s cell: %d %s)", GetOriginalVnum(), GetName(), bWearCell, ch->GetWear(bWearCell)->GetName());
  1138.         return false;
  1139.     }
  1140.  
  1141.     if (GetOwner())
  1142.         RemoveFromCharacter();
  1143.  
  1144.     ch->SetWear(bWearCell, this);
  1145.  
  1146.     m_pOwner = ch;
  1147.     m_bEquipped = true;
  1148.     m_wCell = INVENTORY_MAX_NUM + bWearCell;
  1149.  
  1150. #ifndef ENABLE_IMMUNE_FIX
  1151.     DWORD dwImmuneFlag = 0;
  1152.  
  1153.     for (int i = 0; i < WEAR_MAX_NUM; ++i)
  1154.     {
  1155.         if (m_pOwner->GetWear(i))
  1156.         {
  1157.             // m_pOwner->ChatPacket(CHAT_TYPE_INFO, "unequip immuneflag(%u)", m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); // always 0
  1158.             SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag);
  1159.         }
  1160.     }
  1161.  
  1162.     m_pOwner->SetImmuneFlag(dwImmuneFlag);
  1163. #endif
  1164.  
  1165.     if (IsDragonSoul())
  1166.     {
  1167.         DSManager::instance().ActivateDragonSoul(this);
  1168. #ifdef __DS_SET__
  1169.         ch->DragonSoul_HandleSetBonus();
  1170. #endif
  1171.     }
  1172.     else
  1173.     {
  1174.         ModifyPoints(true);
  1175.         StartUniqueExpireEvent();
  1176.         if (-1 != GetProto()->cLimitTimerBasedOnWearIndex)
  1177.             StartTimerBasedOnWearExpireEvent();
  1178.  
  1179.         // ACCESSORY_REFINE
  1180.         StartAccessorySocketExpireEvent();
  1181.         // END_OF_ACCESSORY_REFINE
  1182.     }
  1183.  
  1184.     ch->BuffOnAttr_AddBuffsFromItem(this);
  1185.  
  1186. // #ifdef __PET_SYSTEM__
  1187.     // if (IsPetItem())
  1188.         // ch->PetSummon(this);
  1189. // #endif
  1190.  
  1191.     m_pOwner->ComputeBattlePoints();
  1192.  
  1193.     m_pOwner->UpdatePacket();
  1194.  
  1195.     Save();
  1196.  
  1197.     return (true);
  1198. }
  1199.  
  1200. bool CItem::Unequip()
  1201. {
  1202.     if (!m_pOwner || GetCell() < INVENTORY_MAX_NUM)
  1203.     {
  1204.         // ITEM_OWNER_INVALID_PTR_BUG
  1205.         sys_err("%s %u m_pOwner %p, GetCell %d",
  1206.                 GetName(), GetID(), get_pointer(m_pOwner), GetCell());
  1207.         // END_OF_ITEM_OWNER_INVALID_PTR_BUG
  1208.         return false;
  1209.     }
  1210.  
  1211.     if (this != m_pOwner->GetWear(GetCell() - INVENTORY_MAX_NUM))
  1212.     {
  1213.         sys_err("m_pOwner->GetWear() != this");
  1214.         return false;
  1215.     }
  1216.  
  1217. // #ifdef __PET_SYSTEM__
  1218.     // if (IsPetItem())
  1219.         // m_pOwner->PetUnsummon(this);
  1220. // #endif
  1221.  
  1222.     if (IsRideItem())
  1223.         ClearMountAttributeAndAffect();
  1224.  
  1225.     if (IsDragonSoul())
  1226.     {
  1227.         DSManager::instance().DeactivateDragonSoul(this);
  1228.     }
  1229.     else
  1230.     {
  1231.         ModifyPoints(false);
  1232.     }
  1233.  
  1234.     StopUniqueExpireEvent();
  1235.  
  1236.     if (-1 != GetProto()->cLimitTimerBasedOnWearIndex)
  1237.         StopTimerBasedOnWearExpireEvent();
  1238.  
  1239.     // ACCESSORY_REFINE
  1240.     StopAccessorySocketExpireEvent();
  1241.     // END_OF_ACCESSORY_REFINE
  1242.  
  1243.     m_pOwner->BuffOnAttr_RemoveBuffsFromItem(this);
  1244.  
  1245.     m_pOwner->SetWear(GetCell() - INVENTORY_MAX_NUM, NULL);
  1246.  
  1247. #ifndef ENABLE_IMMUNE_FIX
  1248.     DWORD dwImmuneFlag = 0;
  1249.  
  1250.     for (int i = 0; i < WEAR_MAX_NUM; ++i)
  1251.     {
  1252.         if (m_pOwner->GetWear(i))
  1253.         {
  1254.             // m_pOwner->ChatPacket(CHAT_TYPE_INFO, "unequip immuneflag(%u)", m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag); // always 0
  1255.             SET_BIT(dwImmuneFlag, m_pOwner->GetWear(i)->m_pProto->dwImmuneFlag);
  1256.         }
  1257.     }
  1258.  
  1259.     m_pOwner->SetImmuneFlag(dwImmuneFlag);
  1260. #endif
  1261.  
  1262.     m_pOwner->ComputeBattlePoints();
  1263.  
  1264.     m_pOwner->UpdatePacket();
  1265.  
  1266.     m_pOwner = NULL;
  1267.     m_wCell = 0;
  1268.     m_bEquipped = false;
  1269.  
  1270.     return true;
  1271. }
  1272.  
  1273. long CItem::GetValue(DWORD idx)
  1274. {
  1275.     assert(idx < ITEM_VALUES_MAX_NUM);
  1276.     return GetProto()->alValues[idx];
  1277. }
  1278.  
  1279. void CItem::SetExchanging(bool bOn)
  1280. {
  1281.     m_bExchanging = bOn;
  1282. }
  1283.  
  1284. void CItem::Save()
  1285. {
  1286.     if (m_bSkipSave)
  1287.         return;
  1288.  
  1289.     ITEM_MANAGER::instance().DelayedSave(this);
  1290. }
  1291.  
  1292. bool CItem::CreateSocket(BYTE bSlot, BYTE bGold)
  1293. {
  1294.     assert(bSlot < ITEM_SOCKET_MAX_NUM);
  1295.  
  1296.     if (m_alSockets[bSlot] != 0)
  1297.     {
  1298.         sys_err("Item::CreateSocket : socket already exist %s %d", GetName(), bSlot);
  1299.         return false;
  1300.     }
  1301.  
  1302.     if (bGold)
  1303.         m_alSockets[bSlot] = 2;
  1304.     else
  1305.         m_alSockets[bSlot] = 1;
  1306.  
  1307.     UpdatePacket();
  1308.  
  1309.     Save();
  1310.     return true;
  1311. }
  1312.  
  1313. void CItem::SetSockets(const long * c_al)
  1314. {
  1315.     thecore_memcpy(m_alSockets, c_al, sizeof(m_alSockets));
  1316.     Save();
  1317. }
  1318.  
  1319. void CItem::SetSocket(int i, long v, bool bLog)
  1320. {
  1321.     assert(i < ITEM_SOCKET_MAX_NUM);
  1322.     m_alSockets[i] = v;
  1323.     UpdatePacket();
  1324.     Save();
  1325.     if (bLog)
  1326.     {
  1327. #ifdef ENABLE_NEWSTUFF
  1328.         if (g_iDbLogLevel>=LOG_LEVEL_MAX)
  1329. #endif
  1330.         LogManager::instance().ItemLog(i, v, 0, GetID(), "SET_SOCKET", "", "", GetOriginalVnum());
  1331.     }
  1332. }
  1333.  
  1334. // int CItem::GetGold()
  1335. long long CItem::GetGold()
  1336. {
  1337.     if (IS_SET(GetFlag(), ITEM_FLAG_COUNT_PER_1GOLD))
  1338.     {
  1339.         if (GetProto()->dwGold == 0)
  1340.             return GetCount();
  1341.         else
  1342.             return GetCount() / GetProto()->dwGold;
  1343.     }
  1344.     else
  1345.         return GetProto()->dwGold;
  1346. }
  1347.  
  1348. // int CItem::GetShopBuyPrice()
  1349. long long CItem::GetShopBuyPrice()
  1350. {
  1351.     return GetProto()->dwShopBuyPrice;
  1352. }
  1353.  
  1354. bool CItem::IsOwnership(LPCHARACTER ch)
  1355. {
  1356.     if (!m_pkOwnershipEvent)
  1357.         return true;
  1358.  
  1359.     return m_dwOwnershipPID == ch->GetPlayerID() ? true : false;
  1360. }
  1361.  
  1362. EVENTFUNC(ownership_event)
  1363. {
  1364.     item_event_info* info = dynamic_cast<item_event_info*>( event->info );
  1365.  
  1366.     if ( info == NULL )
  1367.     {
  1368.         sys_err( "ownership_event> <Factor> Null pointer" );
  1369.         return 0;
  1370.     }
  1371.  
  1372.     LPITEM pkItem = info->item;
  1373.  
  1374.     pkItem->SetOwnershipEvent(NULL);
  1375.  
  1376. #ifdef __ITEM_GROUND_ONLY_OWNER__
  1377.     pkItem->ViewReencode();
  1378. #else
  1379.     TPacketGCItemOwnership p;
  1380.     p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
  1381.     p.dwVID = pkItem->GetVID();
  1382.     p.szName[0] = '\0';
  1383.  
  1384.     pkItem->PacketAround(&p, sizeof(p));
  1385. #endif
  1386.     return 0;
  1387. }
  1388.  
  1389. void CItem::SetOwnershipEvent(LPEVENT pkEvent)
  1390. {
  1391.     m_pkOwnershipEvent = pkEvent;
  1392. #ifdef __ITEM_GROUND_ONLY_OWNER__
  1393.     if (!m_pkOwnershipEvent)
  1394.         m_dwOwnershipPID = 0;
  1395. #endif
  1396. }
  1397.  
  1398. void CItem::SetOwnership(LPCHARACTER ch, int iSec)
  1399. {
  1400.     if (!ch)
  1401.     {
  1402.         if (m_pkOwnershipEvent)
  1403.         {
  1404.             event_cancel(&m_pkOwnershipEvent);
  1405.             m_dwOwnershipPID = 0;
  1406.  
  1407.             if(!GetOwner()) // fix about if item not on ground if has owner skip packet around//dracaryS
  1408.             {
  1409.                 TPacketGCItemOwnership p;
  1410.                 p.bHeader   = HEADER_GC_ITEM_OWNERSHIP;
  1411.                 p.dwVID = m_dwVID;
  1412.                 p.szName[0] = '\0';
  1413.                 PacketAround(&p, sizeof(p));
  1414.             }
  1415.         }
  1416.         return;
  1417.     }
  1418.  
  1419.     if (m_pkOwnershipEvent)
  1420.         return;
  1421.  
  1422.     if (iSec <= 10)
  1423.         iSec = 30;
  1424.  
  1425.     m_dwOwnershipPID = ch->GetPlayerID();
  1426.  
  1427.     item_event_info* info = AllocEventInfo<item_event_info>();
  1428.     strlcpy(info->szOwnerName, ch->GetName(), sizeof(info->szOwnerName));
  1429.     info->item = this;
  1430.  
  1431.     SetOwnershipEvent(event_create(ownership_event, info, PASSES_PER_SEC(iSec)));
  1432.  
  1433.     TPacketGCItemOwnership p;
  1434.  
  1435.     p.bHeader = HEADER_GC_ITEM_OWNERSHIP;
  1436.     p.dwVID = m_dwVID;
  1437.     strlcpy(p.szName, ch->GetName(), sizeof(p.szName));
  1438.  
  1439.     PacketAround(&p, sizeof(p));
  1440. }
  1441.  
  1442. int CItem::GetSocketCount()
  1443. {
  1444.     for (int i = 0; i < ITEM_SOCKET_MAX_NUM; i++)
  1445.     {
  1446.         if (GetSocket(i) == 0)
  1447.             return i;
  1448.     }
  1449.     return ITEM_SOCKET_MAX_NUM;
  1450. }
  1451.  
  1452. bool CItem::AddSocket()
  1453. {
  1454.     int count = GetSocketCount();
  1455.     if (count == ITEM_SOCKET_MAX_NUM)
  1456.         return false;
  1457.     m_alSockets[count] = 1;
  1458.     return true;
  1459. }
  1460.  
  1461. void CItem::AlterToSocketItem(int iSocketCount)
  1462. {
  1463.     if (iSocketCount >= ITEM_SOCKET_MAX_NUM)
  1464.     {
  1465.         sys_log(0, "Invalid Socket Count %d, set to maximum", ITEM_SOCKET_MAX_NUM);
  1466.         iSocketCount = ITEM_SOCKET_MAX_NUM;
  1467.     }
  1468.  
  1469.     for (int i = 0; i < iSocketCount; ++i)
  1470.         SetSocket(i, 1);
  1471. }
  1472.  
  1473. void CItem::AlterToMagicItem()
  1474. {
  1475.     int idx = GetAttributeSetIndex();
  1476.  
  1477.     if (idx < 0)
  1478.         return;
  1479.  
  1480.     // Appearance Second Third
  1481.     // Weapon 50        20   5
  1482.     // Armor  30        10   2
  1483.     // Acc  20      10   1
  1484.  
  1485.     int iSecondPct;
  1486.     int iThirdPct;
  1487.  
  1488.     switch (GetType())
  1489.     {
  1490.         case ITEM_WEAPON:
  1491.             iSecondPct = 20;
  1492.             iThirdPct = 5;
  1493.             break;
  1494.  
  1495.         case ITEM_ARMOR:
  1496.         case ITEM_COSTUME:
  1497.             if (GetSubType() == ARMOR_BODY)
  1498.             {
  1499.                 iSecondPct = 10;
  1500.                 iThirdPct = 2;
  1501.             }
  1502.             else
  1503.             {
  1504.                 iSecondPct = 10;
  1505.                 iThirdPct = 1;
  1506.             }
  1507.             break;
  1508.  
  1509.         default:
  1510.             return;
  1511.     }
  1512.  
  1513.    
  1514.     PutAttribute(aiItemMagicAttributePercentHigh);
  1515.  
  1516.     if (number(1, 100) <= iSecondPct)
  1517.         PutAttribute(aiItemMagicAttributePercentLow);
  1518.  
  1519.     if (number(1, 100) <= iThirdPct)
  1520.         PutAttribute(aiItemMagicAttributePercentLow);
  1521. }
  1522.  
  1523. DWORD CItem::GetRefineFromVnum()
  1524. {
  1525.     return ITEM_MANAGER::instance().GetRefineFromVnum(GetVnum());
  1526. }
  1527.  
  1528. int CItem::GetRefineLevel()
  1529. {
  1530.     const char* name = GetBaseName();
  1531.     char* p = const_cast<char*>(strrchr(name, '+'));
  1532.  
  1533.     if (!p)
  1534.         return 0;
  1535.  
  1536.     int rtn = 0;
  1537.     str_to_number(rtn, p+1);
  1538.  
  1539.     const char* locale_name = GetName();
  1540.     p = const_cast<char*>(strrchr(locale_name, '+'));
  1541.  
  1542.     if (p)
  1543.     {
  1544.         int locale_rtn = 0;
  1545.         str_to_number(locale_rtn, p+1);
  1546.         if (locale_rtn != rtn)
  1547.         {
  1548.             sys_err("refine_level_based_on_NAME(%d) is not equal to refine_level_based_on_LOCALE_NAME(%d).", rtn, locale_rtn);
  1549.         }
  1550.     }
  1551.  
  1552.     return rtn;
  1553. }
  1554.  
  1555. bool CItem::IsPolymorphItem()
  1556. {
  1557.     return GetType() == ITEM_POLYMORPH;
  1558. }
  1559.  
  1560. #if defined(__BL_OFFICIAL_LOOT_FILTER__)
  1561. long CItem::GetWearingLevelLimit() const
  1562. {
  1563.     if (m_pProto)
  1564.     {
  1565.         for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
  1566.             if (m_pProto->aLimits[i].bType == LIMIT_LEVEL)
  1567.                 return m_pProto->aLimits[i].lValue;
  1568.     }
  1569.    
  1570.     return 0;
  1571. }
  1572.  
  1573. bool CItem::IsHairDye() const
  1574. {
  1575.     switch (GetVnum())
  1576.     {
  1577.     case 70202:
  1578.     case 70203:
  1579.     case 70204:
  1580.     case 70205:
  1581.     case 70206:
  1582.         return true;
  1583.     default:
  1584.         return false;
  1585.     }
  1586. }
  1587. #endif
  1588.  
  1589. EVENTFUNC(unique_expire_event)
  1590. {
  1591.     item_event_info* info = dynamic_cast<item_event_info*>( event->info );
  1592.  
  1593.     if (!info)
  1594.     {
  1595.         sys_err( "unique_expire_event> <Factor> Null pointer" );
  1596.         return 0;
  1597.     }
  1598.  
  1599.     LPITEM pkItem = info->item;
  1600.  
  1601.     if (pkItem->GetValue(2) == 0)
  1602.     {
  1603.         if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) <= 1)
  1604.         {
  1605.             sys_log(0, "UNIQUE_ITEM: expire %s %u", pkItem->GetName(), pkItem->GetID());
  1606.             pkItem->SetUniqueExpireEvent(NULL);
  1607.             ITEM_MANAGER::instance().RemoveItem(pkItem, "UNIQUE_EXPIRE");
  1608.             return 0;
  1609.         }
  1610.         else
  1611.         {
  1612.             pkItem->SetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME, pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - 1);
  1613.             return PASSES_PER_SEC(60);
  1614.         }
  1615.     }
  1616.     else
  1617.     {
  1618.         time_t cur = get_global_time();
  1619.  
  1620.         if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) <= cur)
  1621.         {
  1622.             pkItem->SetUniqueExpireEvent(NULL);
  1623.             ITEM_MANAGER::instance().RemoveItem(pkItem, "UNIQUE_EXPIRE");
  1624.             return 0;
  1625.         }
  1626.         else
  1627.         {
  1628.            
  1629.            
  1630.             // by rtsummit
  1631.             if (pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur < 600)
  1632.                 return PASSES_PER_SEC(pkItem->GetSocket(ITEM_SOCKET_UNIQUE_REMAIN_TIME) - cur);
  1633.             else
  1634.                 return PASSES_PER_SEC(600);
  1635.         }
  1636.     }
  1637. }
  1638.  
  1639. EVENTFUNC(timer_based_on_wear_expire_event)
  1640. {
  1641.     item_event_info* info = dynamic_cast<item_event_info*>( event->info );
  1642.  
  1643.     if (!info)
  1644.     {
  1645.         sys_err( "expire_event <Factor> Null pointer" );
  1646.         return 0;
  1647.     }
  1648.  
  1649.     LPITEM pkItem = info->item;
  1650.     int remain_time = pkItem->GetSocket(ITEM_SOCKET_REMAIN_SEC) - processing_time/passes_per_sec;
  1651.     if (remain_time <= 0)
  1652.     {
  1653.         sys_log(0, "ITEM EXPIRED : expired %s %u", pkItem->GetName(), pkItem->GetID());
  1654.         pkItem->SetTimerBasedOnWearExpireEvent(NULL);
  1655.         pkItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, 0);
  1656.  
  1657.        
  1658.         if (pkItem->IsDragonSoul())
  1659.         {
  1660.             DSManager::instance().DeactivateDragonSoul(pkItem);
  1661.         }
  1662.         else
  1663.         {
  1664.             ITEM_MANAGER::instance().RemoveItem(pkItem, "TIMER_BASED_ON_WEAR_EXPIRE");
  1665.         }
  1666.         return 0;
  1667.     }
  1668.     pkItem->SetSocket(ITEM_SOCKET_REMAIN_SEC, remain_time);
  1669.     return PASSES_PER_SEC (MIN (60, remain_time));
  1670. }
  1671.  
  1672. void CItem::SetUniqueExpireEvent(LPEVENT pkEvent)
  1673. {
  1674.     m_pkUniqueExpireEvent = pkEvent;
  1675. }
  1676.  
  1677. void CItem::SetTimerBasedOnWearExpireEvent(LPEVENT pkEvent)
  1678. {
  1679.     m_pkTimerBasedOnWearExpireEvent = pkEvent;
  1680. }
  1681.  
  1682. EVENTFUNC(real_time_expire_event)
  1683. {
  1684.     const item_vid_event_info* info = reinterpret_cast<const item_vid_event_info*>(event->info);
  1685.  
  1686.     if (!info)
  1687.         return 0;
  1688.  
  1689.     const LPITEM item = ITEM_MANAGER::instance().FindByVID( info->item_vid );
  1690.  
  1691.     if (!item)
  1692.         return 0;
  1693.  
  1694.     const time_t current = get_global_time();
  1695.  
  1696.     if (current > item->GetSocket(0))
  1697.     {
  1698.         // if(item->IsNewMountItem())
  1699.         // {
  1700.             // if (item->GetSocket(2) != 0)
  1701.                 // item->ClearMountAttributeAndAffect();
  1702.         // }
  1703.  
  1704.         ITEM_MANAGER::instance().RemoveItem(item, "REAL_TIME_EXPIRE");
  1705.  
  1706.         return 0;
  1707.     }
  1708.  
  1709.     return PASSES_PER_SEC(1);
  1710. }
  1711.  
  1712. void CItem::StartRealTimeExpireEvent()
  1713. {
  1714.     if (m_pkRealTimeExpireEvent)
  1715.         return;
  1716.     for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
  1717.     {
  1718.         if (LIMIT_REAL_TIME == GetProto()->aLimits[i].bType || LIMIT_REAL_TIME_START_FIRST_USE == GetProto()->aLimits[i].bType)
  1719.         {
  1720.             item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
  1721.             info->item_vid = GetVID();
  1722.  
  1723.             m_pkRealTimeExpireEvent = event_create( real_time_expire_event, info, PASSES_PER_SEC(1));
  1724.  
  1725.             sys_log(0, "REAL_TIME_EXPIRE: StartRealTimeExpireEvent");
  1726.  
  1727.             return;
  1728.         }
  1729.     }
  1730. }
  1731.  
  1732. bool CItem::IsRealTimeItem()
  1733. {
  1734.     if(!GetProto())
  1735.         return false;
  1736.     for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
  1737.     {
  1738.         if (LIMIT_REAL_TIME == GetProto()->aLimits[i].bType)
  1739.             return true;
  1740.     }
  1741.     return false;
  1742. }
  1743.  
  1744. void CItem::StartUniqueExpireEvent()
  1745. {
  1746.     if (GetType() != ITEM_UNIQUE)
  1747.         return;
  1748.  
  1749.     if (m_pkUniqueExpireEvent)
  1750.         return;
  1751.  
  1752.    
  1753.     if (IsRealTimeItem())
  1754.         return;
  1755.  
  1756. // #ifndef ENABLE_EXPIRATION_TIME //ENABLE_PVP_TALISMAN
  1757.     // if(GetVnum() == PVP_TALISMAN_VNUM)
  1758.         // return;
  1759. // #endif
  1760.  
  1761.     // HARD CODING
  1762.     if (GetVnum() == UNIQUE_ITEM_HIDE_ALIGNMENT_TITLE)
  1763.         m_pOwner->ShowAlignment(false);
  1764.  
  1765.     int iSec = GetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME);
  1766.  
  1767.     if (iSec == 0)
  1768.         iSec = 60;
  1769.     else
  1770.         iSec = MIN(iSec, 60);
  1771.  
  1772.     SetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME, 0);
  1773.  
  1774.     item_event_info* info = AllocEventInfo<item_event_info>();
  1775.     info->item = this;
  1776.  
  1777.     SetUniqueExpireEvent(event_create(unique_expire_event, info, PASSES_PER_SEC(iSec)));
  1778. }
  1779.  
  1780.  
  1781. // timer_based_on_wear_expire_event 설명 참조
  1782. void CItem::StartTimerBasedOnWearExpireEvent()
  1783. {
  1784.     if (m_pkTimerBasedOnWearExpireEvent)
  1785.         return;
  1786.  
  1787.    
  1788.     if (IsRealTimeItem())
  1789.         return;
  1790.  
  1791.     if (-1 == GetProto()->cLimitTimerBasedOnWearIndex)
  1792.         return;
  1793.  
  1794.     int iSec = GetSocket(0);
  1795.  
  1796.    
  1797.     if (0 != iSec)
  1798.     {
  1799.         iSec %= 60;
  1800.         if (0 == iSec)
  1801.             iSec = 60;
  1802.     }
  1803.  
  1804.     item_event_info* info = AllocEventInfo<item_event_info>();
  1805.     info->item = this;
  1806.  
  1807.     SetTimerBasedOnWearExpireEvent(event_create(timer_based_on_wear_expire_event, info, PASSES_PER_SEC(iSec)));
  1808. }
  1809.  
  1810. void CItem::StopUniqueExpireEvent()
  1811. {
  1812.     if (!m_pkUniqueExpireEvent)
  1813.         return;
  1814.  
  1815.     if (GetValue(2) != 0)
  1816.         return;
  1817.  
  1818.     // HARD CODING
  1819.     if (GetVnum() == UNIQUE_ITEM_HIDE_ALIGNMENT_TITLE)
  1820.         m_pOwner->ShowAlignment(true);
  1821.  
  1822.     SetSocket(ITEM_SOCKET_UNIQUE_SAVE_TIME, event_time(m_pkUniqueExpireEvent) / passes_per_sec);
  1823.     event_cancel(&m_pkUniqueExpireEvent);
  1824.  
  1825.     ITEM_MANAGER::instance().SaveSingleItem(this);
  1826. }
  1827.  
  1828. void CItem::StopTimerBasedOnWearExpireEvent()
  1829. {
  1830.     if (!m_pkTimerBasedOnWearExpireEvent)
  1831.         return;
  1832.  
  1833.     int remain_time = GetSocket(ITEM_SOCKET_REMAIN_SEC) - event_processing_time(m_pkTimerBasedOnWearExpireEvent) / passes_per_sec;
  1834.  
  1835.     SetSocket(ITEM_SOCKET_REMAIN_SEC, remain_time);
  1836.     event_cancel(&m_pkTimerBasedOnWearExpireEvent);
  1837.  
  1838.     ITEM_MANAGER::instance().SaveSingleItem(this);
  1839. }
  1840.  
  1841. #ifdef ENABLE_SWITCHBOT_WORLDARD
  1842. void CItem::ApplyAddon(int iAddonType, bool switchbot)
  1843. #else
  1844. void CItem::ApplyAddon(int iAddonType)
  1845. #endif
  1846. {
  1847. #ifdef ENABLE_SWITCHBOT_WORLDARD
  1848.     CItemAddonManager::instance().ApplyAddonTo(iAddonType, this, switchbot);
  1849. #else
  1850.     CItemAddonManager::instance().ApplyAddonTo(iAddonType, this);
  1851. #endif
  1852. }
  1853.  
  1854. int CItem::GetSpecialGroup() const
  1855. {
  1856.     return ITEM_MANAGER::instance().GetSpecialGroupFromItem(GetVnum());
  1857. }
  1858.  
  1859. bool CItem::IsAccessoryForSocket()
  1860. {
  1861.     if (!m_pProto)
  1862.     {
  1863.         sys_err("CItem::IsAccessoryForSocket() ? null m_pProto, vnum: %u", GetVnum());
  1864.         return false;
  1865.     }
  1866.  
  1867.     return (m_pProto->bType == ITEM_ARMOR &&
  1868.         (m_pProto->bSubType == ARMOR_WRIST || m_pProto->bSubType == ARMOR_NECK || m_pProto->bSubType == ARMOR_EAR)) ||
  1869.         (m_pProto->bType == ITEM_BELT);
  1870. }
  1871.  
  1872. void CItem::SetAccessorySocketGrade(int iGrade)
  1873. {
  1874.     SetSocket(0, MINMAX(0, iGrade, GetAccessorySocketMaxGrade()));
  1875.  
  1876.     int iDownTime = aiAccessorySocketDegradeTime[GetAccessorySocketGrade()];
  1877.  
  1878.     SetAccessorySocketDownGradeTime(iDownTime);
  1879. }
  1880.  
  1881. void CItem::SetAccessorySocketMaxGrade(int iMaxGrade)
  1882. {
  1883.     SetSocket(1, MINMAX(0, iMaxGrade, ITEM_ACCESSORY_SOCKET_MAX_NUM));
  1884. }
  1885.  
  1886. void CItem::SetAccessorySocketDownGradeTime(DWORD time)
  1887. {
  1888.     SetSocket(2, time);
  1889.  
  1890.     if (test_server && GetOwner())
  1891.         GetOwner()->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s에서 소켓 빠질때까지 남은 시간 %d"), GetName(), time);
  1892. }
  1893.  
  1894. EVENTFUNC(accessory_socket_expire_event)
  1895. {
  1896.     item_vid_event_info* info = dynamic_cast<item_vid_event_info*>( event->info );
  1897.  
  1898.     if (!info)
  1899.     {
  1900.         sys_err( "accessory_socket_expire_event> <Factor> Null pointer" );
  1901.         return 0;
  1902.     }
  1903.  
  1904.     LPITEM item = ITEM_MANAGER::instance().FindByVID(info->item_vid);
  1905.  
  1906.     if (item->GetAccessorySocketDownGradeTime() <= 1)
  1907.     {
  1908. degrade:
  1909.         item->SetAccessorySocketExpireEvent(NULL);
  1910.         item->AccessorySocketDegrade();
  1911.         return 0;
  1912.     }
  1913.     else
  1914.     {
  1915.         int iTime = item->GetAccessorySocketDownGradeTime() - 60;
  1916.  
  1917.         if (iTime <= 1)
  1918.             goto degrade;
  1919.  
  1920.         item->SetAccessorySocketDownGradeTime(iTime);
  1921.  
  1922.         if (iTime > 60)
  1923.             return PASSES_PER_SEC(60);
  1924.         else
  1925.             return PASSES_PER_SEC(iTime);
  1926.     }
  1927. }
  1928.  
  1929. void CItem::StartAccessorySocketExpireEvent()
  1930. {
  1931.     if (!IsAccessoryForSocket())
  1932.         return;
  1933.  
  1934.     if (m_pkAccessorySocketExpireEvent)
  1935.         return;
  1936.  
  1937.     if (GetAccessorySocketMaxGrade() == 0)
  1938.         return;
  1939.  
  1940.     if (GetAccessorySocketGrade() == 0)
  1941.         return;
  1942.  
  1943.     int iSec = GetAccessorySocketDownGradeTime();
  1944.     SetAccessorySocketExpireEvent(NULL);
  1945.  
  1946.     if (iSec <= 1)
  1947.         iSec = 5;
  1948.     else
  1949.         iSec = MIN(iSec, 60);
  1950.  
  1951.     item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
  1952.     info->item_vid = GetVID();
  1953.  
  1954.     SetAccessorySocketExpireEvent(event_create(accessory_socket_expire_event, info, PASSES_PER_SEC(iSec)));
  1955. }
  1956.  
  1957. void CItem::StopAccessorySocketExpireEvent()
  1958. {
  1959.     if (!m_pkAccessorySocketExpireEvent)
  1960.         return;
  1961.  
  1962.     if (!IsAccessoryForSocket())
  1963.         return;
  1964.  
  1965.     int new_time = GetAccessorySocketDownGradeTime() - (60 - event_time(m_pkAccessorySocketExpireEvent) / passes_per_sec);
  1966.  
  1967.     event_cancel(&m_pkAccessorySocketExpireEvent);
  1968.  
  1969.     if (new_time <= 1)
  1970.     {
  1971.         AccessorySocketDegrade();
  1972.     }
  1973.     else
  1974.     {
  1975.         SetAccessorySocketDownGradeTime(new_time);
  1976.     }
  1977. }
  1978.  
  1979. #ifdef SWAP_ITEM_TASKBAR_FIX
  1980. bool CItem::IsQuickslotRestricted() const
  1981. {
  1982.     switch(GetType())
  1983.     {
  1984.         case ITEM_WEAPON:
  1985.         case ITEM_ARMOR:
  1986.             return true;
  1987.  
  1988.         case ITEM_COSTUME:
  1989.             switch(GetSubType())
  1990.             {
  1991.                 case COSTUME_BODY:
  1992.                 case COSTUME_HAIR:
  1993.                 case COSTUME_WEAPON:
  1994.                 #ifdef ENABLE_ACCE_SYSTEM
  1995.                 case COSTUME_ACCE:
  1996.                 #endif
  1997.                     return true;
  1998.                 default:
  1999.                     break;
  2000.             }
  2001.             break;
  2002.  
  2003.         default:
  2004.             break;
  2005.     }
  2006.  
  2007.     return false;
  2008. }
  2009. #endif
  2010.  
  2011. bool CItem::IsRideItem()
  2012. {
  2013.     if (ITEM_UNIQUE == GetType() && UNIQUE_SPECIAL_RIDE == GetSubType())
  2014.         return true;
  2015.     if (ITEM_UNIQUE == GetType() && UNIQUE_SPECIAL_MOUNT_RIDE == GetSubType())
  2016.         return true;
  2017. #ifdef ENABLE_MOUNT_COSTUME_SYSTEM
  2018.     if (ITEM_COSTUME == GetType() && COSTUME_MOUNT == GetSubType())
  2019.         return true;
  2020. #endif
  2021.     return false;
  2022. }
  2023.  
  2024. bool CItem::IsRamadanRing()
  2025. {
  2026.     if (GetVnum() == UNIQUE_ITEM_RAMADAN_RING)
  2027.         return true;
  2028.     return false;
  2029. }
  2030.  
  2031. // #ifdef __PET_SYSTEM__
  2032. // bool CItem::IsPetItem()
  2033. // {
  2034.     // if (GetType() == ITEM_NORMAL_PET)
  2035.         // return true;
  2036.    
  2037.     // return false;
  2038. // }
  2039. // #endif
  2040.  
  2041. void CItem::ClearMountAttributeAndAffect()
  2042. {
  2043.     LPCHARACTER ch = GetOwner();
  2044.  
  2045.     ch->RemoveAffect(AFFECT_MOUNT);
  2046.     ch->RemoveAffect(AFFECT_MOUNT_BONUS);
  2047.  
  2048.     ch->MountVnum(0);
  2049.  
  2050.     ch->PointChange(POINT_ST, 0);
  2051.     ch->PointChange(POINT_DX, 0);
  2052.     ch->PointChange(POINT_HT, 0);
  2053.     ch->PointChange(POINT_IQ, 0);
  2054. }
  2055.  
  2056. // fixme
  2057.  
  2058. // by rtsummit
  2059. bool CItem::IsNewMountItem()
  2060. {
  2061.     switch(GetVnum())
  2062.     {
  2063.         case 76000: case 76001: case 76002: case 76003:
  2064.         case 76004: case 76005: case 76006: case 76007:
  2065.         case 76008: case 76009: case 76010: case 76011:
  2066.         case 76012: case 76013: case 76014:
  2067.             return true;
  2068.     }
  2069.     return false;
  2070. }
  2071.  
  2072. void CItem::SetAccessorySocketExpireEvent(LPEVENT pkEvent)
  2073. {
  2074.     m_pkAccessorySocketExpireEvent = pkEvent;
  2075. }
  2076.  
  2077. void CItem::AccessorySocketDegrade()
  2078. {
  2079.     if (GetAccessorySocketGrade() > 0)
  2080.     {
  2081.         LPCHARACTER ch = GetOwner();
  2082.  
  2083.         if (ch)
  2084.         {
  2085.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("%s에 박혀있던 보석이 사라집니다."), GetName());
  2086.         }
  2087.  
  2088.         ModifyPoints(false);
  2089.         SetAccessorySocketGrade(GetAccessorySocketGrade()-1);
  2090.         ModifyPoints(true);
  2091.  
  2092.         int iDownTime = aiAccessorySocketDegradeTime[GetAccessorySocketGrade()];
  2093.  
  2094.         if (test_server)
  2095.             iDownTime /= 60;
  2096.  
  2097.         SetAccessorySocketDownGradeTime(iDownTime);
  2098.  
  2099.         if (iDownTime)
  2100.             StartAccessorySocketExpireEvent();
  2101.     }
  2102. }
  2103.  
  2104.  
  2105. static const bool CanPutIntoRing(LPITEM ring, LPITEM item)
  2106. {
  2107.     //const DWORD vnum = item->GetVnum();
  2108.     return false;
  2109. }
  2110.  
  2111. /*
  2112. bool CItem::CanPutInto(LPITEM item)
  2113. {
  2114.     if (item->GetType() == ITEM_BELT)
  2115.         return this->GetSubType() == USE_PUT_INTO_BELT_SOCKET;
  2116.  
  2117.     else if(item->GetType() == ITEM_RING)
  2118.         return CanPutIntoRing(item, this);
  2119.  
  2120.     else if (item->GetType() != ITEM_ARMOR)
  2121.         return false;
  2122.  
  2123.     DWORD vnum = item->GetVnum();
  2124.  
  2125.     struct JewelAccessoryInfo
  2126.     {
  2127.         DWORD jewel;
  2128.         DWORD wrist;
  2129.         DWORD neck;
  2130.         DWORD ear;
  2131.     };
  2132.     const static JewelAccessoryInfo infos[] = {
  2133.         { 50634, 14420, 16220, 17220 },
  2134.         { 50635, 14500, 16500, 17500 },
  2135.         { 50636, 14520, 16520, 17520 },
  2136.         { 50637, 14540, 16540, 17540 },
  2137.         { 50638, 14560, 16560, 17560 },
  2138.         { 50639, 14570, 16570, 17570 },
  2139.     };
  2140.  
  2141.     DWORD item_type = (item->GetVnum() / 10) * 10;
  2142.     for (size_t i = 0; i < sizeof(infos) / sizeof(infos[0]); i++)
  2143.     {
  2144.         const JewelAccessoryInfo& info = infos[i];
  2145.         switch(item->GetSubType())
  2146.         {
  2147.         case ARMOR_WRIST:
  2148.             if (info.wrist == item_type)
  2149.             {
  2150.                 if (info.jewel == GetVnum())
  2151.                 {
  2152.                     return true;
  2153.                 }
  2154.                 else
  2155.                 {
  2156.                     return false;
  2157.                 }
  2158.             }
  2159.             break;
  2160.         case ARMOR_NECK:
  2161.             if (info.neck == item_type)
  2162.             {
  2163.                 if (info.jewel == GetVnum())
  2164.                 {
  2165.                     return true;
  2166.                 }
  2167.                 else
  2168.                 {
  2169.                     return false;
  2170.                 }
  2171.             }
  2172.             break;
  2173.         case ARMOR_EAR:
  2174.             if (info.ear == item_type)
  2175.             {
  2176.                 if (info.jewel == GetVnum())
  2177.                 {
  2178.                     return true;
  2179.                 }
  2180.                 else
  2181.                 {
  2182.                     return false;
  2183.                 }
  2184.             }
  2185.             break;
  2186.         }
  2187.     }
  2188.     if (item->GetSubType() == ARMOR_WRIST)
  2189.         vnum -= 14000;
  2190.     else if (item->GetSubType() == ARMOR_NECK)
  2191.         vnum -= 16000;
  2192.     else if (item->GetSubType() == ARMOR_EAR)
  2193.         vnum -= 17000;
  2194.     else
  2195.         return false;
  2196.  
  2197.     DWORD type = vnum / 20;
  2198.  
  2199.     if (type < 0 || type > 11)
  2200.     {
  2201.         type = (vnum - 170) / 20;
  2202.  
  2203.         if (50623 + type != GetVnum())
  2204.             return false;
  2205.         else
  2206.             return true;
  2207.     }
  2208.     else if (item->GetVnum() >= 16210 && item->GetVnum() <= 16219)
  2209.     {
  2210.         if (50625 != GetVnum())
  2211.             return false;
  2212.         else
  2213.             return true;
  2214.     }
  2215.     else if (item->GetVnum() >= 16230 && item->GetVnum() <= 16239)
  2216.     {
  2217.         if (50626 != GetVnum())
  2218.             return false;
  2219.         else
  2220.             return true;
  2221.     }
  2222.  
  2223.     return 50623 + type == GetVnum();
  2224. }
  2225. */
  2226. bool CItem::CanPutInto(LPITEM item)
  2227. {
  2228.     if (item->GetType() == ITEM_BELT)
  2229.         return this->GetSubType() == USE_PUT_INTO_BELT_SOCKET;
  2230.  
  2231.     else if(item->GetType() == ITEM_RING)
  2232.         return CanPutIntoRing(item, this);
  2233.  
  2234.     else if (item->GetType() != ITEM_ARMOR)
  2235.         return false;
  2236.    
  2237.     DWORD item_sub_type = item->GetSubType();
  2238.     if (item_sub_type != ARMOR_WRIST && item_sub_type != ARMOR_NECK && item_sub_type != ARMOR_EAR)
  2239.     {
  2240.         return false;
  2241.     }
  2242.  
  2243.     // ORE
  2244.     switch(this->GetVnum())
  2245.     {
  2246.         case 50623: case 50624: case 50625: case 50626:
  2247.         case 50627: case 50628: case 50629: case 50630:
  2248.         case 50631: case 50632: case 50633: case 50634:
  2249.         case 50635: case 50636: case 50637: case 50638:
  2250.             return true;
  2251.     }
  2252.     return false;
  2253. }
  2254.  
  2255. // PC_BANG_ITEM_ADD
  2256. bool CItem::IsPCBangItem()
  2257. {
  2258.     for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
  2259.     {
  2260.         if (m_pProto->aLimits[i].bType == LIMIT_PCBANG)
  2261.             return true;
  2262.     }
  2263.     return false;
  2264. }
  2265. // END_PC_BANG_ITEM_ADD
  2266.  
  2267. bool CItem::CheckItemUseLevel(int nLevel)
  2268. {
  2269.     for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
  2270.     {
  2271.         if (this->m_pProto->aLimits[i].bType == LIMIT_LEVEL)
  2272.         {
  2273.             if (this->m_pProto->aLimits[i].lValue > nLevel) return false;
  2274.             else return true;
  2275.         }
  2276.     }
  2277.     return true;
  2278. }
  2279.  
  2280. long CItem::FindApplyValue(BYTE bApplyType)
  2281. {
  2282.     if (m_pProto == NULL)
  2283.         return 0;
  2284.  
  2285.     for (int i = 0; i < ITEM_APPLY_MAX_NUM; ++i)
  2286.     {
  2287.         if (m_pProto->aApplies[i].bType == bApplyType)
  2288.             return m_pProto->aApplies[i].lValue;
  2289.     }
  2290.  
  2291.     return 0;
  2292. }
  2293.  
  2294. void CItem::CopySocketTo(LPITEM pItem)
  2295. {
  2296.     for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
  2297.     {
  2298.         pItem->m_alSockets[i] = m_alSockets[i];
  2299.     }
  2300. }
  2301.  
  2302. int CItem::GetAccessorySocketGrade()
  2303. {
  2304.     return MINMAX(0, GetSocket(0), GetAccessorySocketMaxGrade());
  2305. }
  2306.  
  2307. int CItem::GetAccessorySocketMaxGrade()
  2308. {
  2309.     return MINMAX(0, GetSocket(1), ITEM_ACCESSORY_SOCKET_MAX_NUM);
  2310. }
  2311.  
  2312. int CItem::GetAccessorySocketDownGradeTime()
  2313. {
  2314.     return MINMAX(0, GetSocket(2), aiAccessorySocketDegradeTime[GetAccessorySocketGrade()]);
  2315. }
  2316.  
  2317. void CItem::AttrLog()
  2318. {
  2319.     const char * pszIP = NULL;
  2320.  
  2321.     if (GetOwner() && GetOwner()->GetDesc())
  2322.         pszIP = GetOwner()->GetDesc()->GetHostName();
  2323.  
  2324.     for (int i = 0; i < ITEM_SOCKET_MAX_NUM; ++i)
  2325.     {
  2326.         if (m_alSockets[i])
  2327.         {
  2328. #ifdef ENABLE_NEWSTUFF
  2329.             if (g_iDbLogLevel>=LOG_LEVEL_MAX)
  2330. #endif
  2331.             LogManager::instance().ItemLog(i, m_alSockets[i], 0, GetID(), "INFO_SOCKET", "", pszIP ? pszIP : "", GetOriginalVnum());
  2332.         }
  2333.     }
  2334.  
  2335.     for (int i = 0; i<ITEM_ATTRIBUTE_MAX_NUM; ++i)
  2336.     {
  2337.         int type    = m_aAttr[i].bType;
  2338.         int value   = m_aAttr[i].sValue;
  2339.  
  2340.         if (type)
  2341.         {
  2342. #ifdef ENABLE_NEWSTUFF
  2343.             if (g_iDbLogLevel>=LOG_LEVEL_MAX)
  2344. #endif
  2345.             LogManager::instance().ItemLog(i, type, value, GetID(), "INFO_ATTR", "", pszIP ? pszIP : "", GetOriginalVnum());
  2346.         }
  2347.     }
  2348. }
  2349.  
  2350. int CItem::GetLevelLimit()
  2351. {
  2352.     for (int i = 0; i < ITEM_LIMIT_MAX_NUM; ++i)
  2353.     {
  2354.         if (this->m_pProto->aLimits[i].bType == LIMIT_LEVEL)
  2355.         {
  2356.             return this->m_pProto->aLimits[i].lValue;
  2357.         }
  2358.     }
  2359.     return 0;
  2360. }
  2361.  
  2362. bool CItem::OnAfterCreatedItem()
  2363. {
  2364. #if defined(__SOUL_SYSTEM__)
  2365.     if (GetType() == ITEM_SOUL && GetLimitValue(1) != 0)
  2366.         StartSoulTimerUseEvent();
  2367. #endif
  2368.  
  2369.     if (-1 != this->GetProto()->cLimitRealTimeFirstUseIndex)
  2370.     {
  2371.        
  2372.         if (0 != GetSocket(1))
  2373.         {
  2374.             StartRealTimeExpireEvent();
  2375.         }
  2376.     }
  2377.  
  2378.     return true;
  2379. }
  2380.  
  2381. bool CItem::IsDragonSoul()
  2382. {
  2383.     return GetType() == ITEM_DS;
  2384. }
  2385.  
  2386. int CItem::GiveMoreTime_Per(float fPercent)
  2387. {
  2388.     if (IsDragonSoul())
  2389.     {
  2390.         DWORD duration = DSManager::instance().GetDuration(this);
  2391.         DWORD remain_sec = GetSocket(ITEM_SOCKET_REMAIN_SEC);
  2392.         DWORD given_time = fPercent * duration / 100u;
  2393.         if (remain_sec == duration)
  2394.             return false;
  2395.         if ((given_time + remain_sec) >= duration)
  2396.         {
  2397.             SetSocket(ITEM_SOCKET_REMAIN_SEC, duration);
  2398.             return duration - remain_sec;
  2399.         }
  2400.         else
  2401.         {
  2402.             SetSocket(ITEM_SOCKET_REMAIN_SEC, given_time + remain_sec);
  2403.             return given_time;
  2404.         }
  2405.     }
  2406.    
  2407.     else
  2408.         return 0;
  2409. }
  2410.  
  2411. int CItem::GiveMoreTime_Fix(DWORD dwTime)
  2412. {
  2413.     if (IsDragonSoul())
  2414.     {
  2415.         DWORD duration = DSManager::instance().GetDuration(this);
  2416.         DWORD remain_sec = GetSocket(ITEM_SOCKET_REMAIN_SEC);
  2417.         if (remain_sec == duration)
  2418.             return false;
  2419.         if ((dwTime + remain_sec) >= duration)
  2420.         {
  2421.             SetSocket(ITEM_SOCKET_REMAIN_SEC, duration);
  2422.             return duration - remain_sec;
  2423.         }
  2424.         else
  2425.         {
  2426.             SetSocket(ITEM_SOCKET_REMAIN_SEC, dwTime + remain_sec);
  2427.             return dwTime;
  2428.         }
  2429.     }
  2430.    
  2431.     else
  2432.         return 0;
  2433. }
  2434.  
  2435. #if defined(__BL_TRANSMUTATION__)
  2436. void CItem::SetTransmutationVnum(DWORD blVnum)
  2437. {
  2438.     m_dwTransmutationVnum = blVnum;
  2439.     Save();
  2440. }
  2441.  
  2442. DWORD CItem::GetTransmutationVnum() const
  2443. {
  2444.     return m_dwTransmutationVnum;
  2445. }
  2446. #endif
  2447.  
  2448. int CItem::GetDuration()
  2449. {
  2450.     if(!GetProto())
  2451.         return -1;
  2452.  
  2453.     for (int i=0 ; i < ITEM_LIMIT_MAX_NUM ; i++)
  2454.     {
  2455.         if (LIMIT_REAL_TIME == GetProto()->aLimits[i].bType)
  2456.             return GetProto()->aLimits[i].lValue;
  2457.     }
  2458.  
  2459.     if (GetProto()->cLimitTimerBasedOnWearIndex >= 0)
  2460.     {
  2461.         BYTE cLTBOWI = GetProto()->cLimitTimerBasedOnWearIndex;
  2462.         return GetProto()->aLimits[cLTBOWI].lValue;
  2463.     }
  2464.  
  2465.     return -1;
  2466. }
  2467.  
  2468. /*
  2469. bool CItem::IsSameSpecialGroup(const LPITEM item) const
  2470. {
  2471.    
  2472.     if (this->GetVnum() == item->GetVnum())
  2473.         return true;
  2474.  
  2475.     if (GetSpecialGroup() && (item->GetSpecialGroup() == GetSpecialGroup()))
  2476.         return true;
  2477.  
  2478.     return false;
  2479. }
  2480. */
  2481.  
  2482. bool CItem::IsSameSpecialGroup(const LPITEM item) const
  2483. {
  2484.     if (this->GetVnum() == item->GetVnum())
  2485.         return true;
  2486.  
  2487.     if (GetSpecialGroup() && (item->GetSpecialGroup() == GetSpecialGroup())){
  2488.         TItemTable * p = ITEM_MANAGER::instance().GetTable(GetSpecialGroup());
  2489.         if (!p)
  2490.             return true;
  2491.  
  2492.         if (p->bType != ITEM_GIFTBOX)
  2493.             return true;
  2494.     }
  2495.  
  2496.     return false;
  2497. }
  2498.  
  2499. /*
  2500. #if defined(__MULTI_LANGUAGE_SYSTEM__) && !defined(__ITEM_DROP_RENEWAL__)
  2501. const char* CItem::GetName()
  2502. {
  2503.     uint8_t locale = LOCALE_GR;
  2504.     if (m_pOwner) {
  2505.         if (m_pOwner->GetDesc() && m_pOwner->GetDesc()->IsPhase(PHASE_GAME))
  2506.             locale = m_pOwner->GetDesc()->GetLanguage();
  2507.     }
  2508.  
  2509.     return m_pProto ? LC_LOCALE_ITEM_TEXT(GetVnum(), locale) : NULL;
  2510. }
  2511. #endif
  2512. */
  2513.  
  2514. #if defined(__SOUL_SYSTEM__)
  2515. EVENTFUNC(soul_timer_use_event)
  2516. {
  2517.     const item_vid_event_info* info = reinterpret_cast<const item_vid_event_info*>(event->info);
  2518.     if (info == nullptr)
  2519.         return 0;
  2520.  
  2521.     LPITEM item = ITEM_MANAGER::instance().FindByVID(info->item_vid);
  2522.     if (item == nullptr)
  2523.         return 0;
  2524.  
  2525.     auto data = item->GetSocket(2);
  2526.     if (data == 0)
  2527.         data = item->GetValue(2);
  2528.  
  2529.     auto keep_time = data / 10000;
  2530.     auto max_time = item->GetLimitValue(1);
  2531.     auto min_time = 60;
  2532.     auto remain_count = data % 10000;
  2533.  
  2534.     if (keep_time % min_time == 0 && keep_time > 0 && item->GetSocket(1) != TRUE)
  2535.         if (const auto& ch = item->GetOwner())
  2536.             ch->ChatPacket(CHAT_TYPE_INFO, LC_TEXT("[Soul System] Use %s to receive the effect."), item->GetName());
  2537.  
  2538.     if (keep_time >= max_time)
  2539.         return 0;
  2540.  
  2541.     auto new_data = ((keep_time + 1) * 10000) + remain_count;
  2542.     item->SetSocket(2, new_data, false /* log */);
  2543.  
  2544.     return PASSES_PER_SEC(test_server ? 1 : 60);
  2545. }
  2546.  
  2547. void CItem::StartSoulTimerUseEvent()
  2548. {
  2549.     if (m_pkSoulTimerUseEvent)
  2550.         return;
  2551.  
  2552.     item_vid_event_info* info = AllocEventInfo<item_vid_event_info>();
  2553.     info->item_vid = GetVID();
  2554.     m_pkSoulTimerUseEvent = event_create(soul_timer_use_event, info, PASSES_PER_SEC(test_server ? 1 : 60));
  2555. }
  2556.  
  2557. void CItem::ResetSoulTimerUseEvent()
  2558. {
  2559.     if (m_pkSoulTimerUseEvent)
  2560.         event_cancel(&m_pkSoulTimerUseEvent);
  2561.  
  2562.     StartSoulTimerUseEvent();
  2563. }
  2564. #endif
  2565.  
Add Comment
Please, Sign In to add comment